
回复
添加资源
添加资源将有机会获得更多曝光,你也可以直接关联已上传资源 去关联
@toc
-----> 喵叔catuncle / TestTextField <-----
因为后来代码更新了,所以文章内容只是解决问题的一个思路。以代码为准!
理论上讲通过自定义Adapter,可以适配所有的情况
处理前 | 处理前后 |
---|---|
![]() |
![]() |
安卓上面,输入框被软键盘遮挡,很简单
xml 配置
android:windowSoftInputMode="adjustPan"
或者,java 配置
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
这样,软键盘弹出后,输入框就会自动上移。
鸿蒙上也有类似的设置,但是貌似没效果:
getWindow().setInputPanelDisplayType(WindowManager.LayoutConfig.INPUT_ADJUST_PAN);
public class MainAbilitySlice extends AbilitySlice {
private EventHandler mainHandler = new EventHandler(EventRunner.getMainEventRunner());
private MyTask myTask = null;
class MyTask implements Runnable {
private final int softHeight;
private final ScrollView root;
private final Rect decorRect;
public MyTask(int softHeight, ScrollView root, Rect decorRect) {
this.softHeight = softHeight;
this.root = root;
this.decorRect = decorRect;
}
@Override
public void run() {
Timber.d("onRefreshed() called with: softHeight = [ %s ]", softHeight);
Component focusView = root.findFocus();
int focusTop = focusView.getLocationOnScreen()[1];//焦点控件的左上角
root.fluentScrollByY(focusTop + focusView.getHeight() - decorRect.top - decorRect.getHeight() + 100);
}
}
@Override
public void onStart(Intent intent) {
super.onStart(intent);
getWindow().setInputPanelDisplayType(WindowManager.LayoutConfig.INPUT_ADJUST_PAN);
super.setUIContent(ResourceTable.Layout_ability_main);
Optional<Display> display = DisplayManager.getInstance().getDefaultDisplay(getContext());
Point pt = new Point();
display.get().getSize(pt);
int screenHeight = pt.getPointYToInt();//不包括状态栏(手机时间、wifi显示的那一部分,) 2211,状态栏是129,加起来就是2340
Timber.d("onRefreshed() called with: screenHeight = [ %s ]", screenHeight);
ScrollView root = (ScrollView) findComponentById(ResourceTable.Id_root);
root.setLayoutRefreshedListener(new Component.LayoutRefreshedListener() {
@Override
public void onRefreshed(Component component) {
//包括标题栏,但不包括状态栏。默认 大小 (0,129,1080,2340),top=129即状态栏 , height=2211。 同android的decorView
Rect decorRect = new Rect();
component.getWindowVisibleRect(decorRect);
Timber.d("onRefreshed() called with: rect = [ %s ]", decorRect);
if (decorRect.getHeight() == 0) {
//刚进入界面可能为0
return;
}
int softHeight = screenHeight - decorRect.getHeight();
Timber.d("onRefreshed() called with: softHeight = [ %s ]", softHeight);
if (softHeight > 100) {//当输入法高度大于100判定为输入法打开了
if (myTask != null) {
mainHandler.removeTask(myTask);
myTask = null;
}
mainHandler.postTask(myTask = new MyTask(softHeight, root, decorRect), 100);
}
}
});
}
}
----> 完整代码见文末 <----
特别说明: 滚动操作为什么要delay 100毫秒?因为点击一个输入框Component.LayoutRefreshedListener
有时会反复调用多次,而且间隔时间小于10毫秒,所以会造成滚动距离不准确。用postTask之后,每次调用的时候会把之前的task remove掉,以最新的一次为准。
其中上面的大红框是decorRect(即当前Ability可视区域),下面的大黑框是输入法显示区域。其中,软键盘弹出后,输入框被软键盘挡住,图中的小红框。
所以,要滚动的距离就是图中的C=A-B
。
自动上移TextField。监听软键盘显示、隐藏。
我已经预定义了
ScrollViewTFHAdapter
、DirectionTFHAdapter
处理根布局为ScrollView
、DirectionalLayout
的情况。预定义了
DlgTFHAdapter
处理CommonDialog
的情况(通过debug发现CommonDialog的根布局也是ScrollView,但是Dialog有一些特殊情,所以通过继承ScrollViewTFHAdapter来实现)