鴻蒙輸入框被軟鍵盤(pán)遮擋的解決辦法
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
處理前后對(duì)比

問(wèn)題現(xiàn)狀
安卓上面,輸入框被軟鍵盤(pán)遮擋,很簡(jiǎn)單
- xml 配置
- android:windowSoftInputMode="adjustPan"
- 或者,java 配置
- getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
這樣,軟鍵盤(pán)彈出后,輸入框就會(huì)自動(dòng)上移。
鴻蒙上也有類(lèi)似的設(shè)置,但是貌似沒(méi)效果:
- getWindow().setInputPanelDisplayType(WindowManager.LayoutConfig.INPUT_ADJUST_PAN);
解決過(guò)程
原理:
布局文件用ScrollView包起來(lái)
監(jiān)聽(tīng)根布局大小變化,變小了,證明輸入法彈出了。
滾動(dòng)ScrollView,使當(dāng)前焦點(diǎn)控件顯示在軟鍵盤(pán)上方。
核心代碼:
- 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];//焦點(diǎn)控件的左上角
- 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();//不包括狀態(tài)欄(手機(jī)時(shí)間、wifi顯示的那一部分,) 2211,狀態(tài)欄是129,加起來(lái)就是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) {
- //包括標(biāo)題欄,但不包括狀態(tài)欄。默認(rèn) 大小 (0,129,1080,2340),top=129即狀態(tài)欄 , height=2211。 同android的decorView
- Rect decorRect = new Rect();
- component.getWindowVisibleRect(decorRect);
- Timber.d("onRefreshed() called with: rect = [ %s ]", decorRect);
- if (decorRect.getHeight() == 0) {
- //剛進(jìn)入界面可能為0
- return;
- }
- int softHeight = screenHeight - decorRect.getHeight();
- Timber.d("onRefreshed() called with: softHeight = [ %s ]", softHeight);
- if (softHeight > 100) {//當(dāng)輸入法高度大于100判定為輸入法打開(kāi)了
- if (myTask != null) {
- mainHandler.removeTask(myTask);
- myTask = null;
- }
- mainHandler.postTask(myTask = new MyTask(softHeight, root, decorRect), 100);
- }
- }
- });
- }
- }
完整代碼見(jiàn)文末
特別說(shuō)明: 滾動(dòng)操作為什么要delay 100毫秒?因?yàn)辄c(diǎn)擊一個(gè)輸入框Component.LayoutRefreshedListener有時(shí)會(huì)反復(fù)調(diào)用多次,而且間隔時(shí)間小于10毫秒,所以會(huì)造成滾動(dòng)距離不準(zhǔn)確。用postTask之后,每次調(diào)用的時(shí)候會(huì)把之前的task remove掉,以最新的一次為準(zhǔn)。
計(jì)算滾動(dòng)距離
其中上面的大紅框是decorRect(即當(dāng)前Ability可視區(qū)域),下面的大黑框是輸入法顯示區(qū)域。其中,軟鍵盤(pán)彈出后,輸入框被軟鍵盤(pán)擋住,圖中的小紅框。
所以,要滾動(dòng)的距離就是圖中的C=A-B。

可以?xún)?yōu)化的點(diǎn):
如果是Dialog中的輸入框,當(dāng)前的計(jì)算方法是否正確?
如果不用ScrollView,還有別的解決辦法嗎?
抽取出工具類(lèi)或工具方法,代碼復(fù)用。
文章相關(guān)附件可以點(diǎn)擊下面的原文鏈接前往下載
原文鏈接:https://harmonyos.51cto.com/posts/4776
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)