EditText AdjustResize强制内容超出视图

时间:2017-02-08 09:40:25

标签: java android android-layout android-edittext android-softkeyboard

我目前正在开发一个简单的Notes应用程序,用户可以在其中输入标题和笔记内容。我希望实现的是当用户点击音符内容(EditText)时,软键盘出现,只有音符内容EditText缩小(调整大小),而其他所有内容都保持在同一位置。

我目前的实施情况如下:

清单:

<activity android:theme="@style/AppTheme"
        android:name=".AddActivity"
        android:label="@string/add_record"
        android:windowSoftInputMode="adjustResize"
        android:parentActivityName=".MainActivity"
        android:excludeFromRecents="true"/>

XML - 添加活动

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/add_record"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="20dp">

    <EditText
        android:id="@+id/title_edittext"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="@string/enter_title"
        android:inputType="textCapSentences"
        android:textColor="@color/fontPrimary"
        android:theme="@style/EditTextCustomCursor">

        <requestFocus />
    </EditText>

    <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/modify_scrollview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:fitsSystemWindows="false"
        android:isScrollContainer="false"
        android:fillViewport="true">

        <EditText
            android:id="@+id/note_edittext"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@null"
            android:ellipsize="end"
            android:gravity="top|left"
            android:hint="@string/enter_note"
            android:inputType="textCapSentences|textMultiLine"
            android:paddingLeft="5dp"
            android:scrollHorizontally="false"
            android:textColor="@color/fontPrimary"
            android:theme="@style/EditTextCustomCursor" />
    </ScrollView>

</LinearLayout>

Java - 添加活动

private int screenHeight;
private int actionBarHeight = 350;
private int keyboardHeight;

...

private void setupListeners() {

    final LinearLayout layout = (LinearLayout) findViewById(R.id.add_record);
    layout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

        @Override
        public void onGlobalLayout() {
            Rect r = new Rect();
            layout.getWindowVisibleDisplayFrame(r);

            screenHeight = layout.getRootView().getHeight();
            keyboardHeight = screenHeight - (r.bottom - r.top);
            Log.d("Keyboard Size", "Size: " + keyboardHeight);

        }
    });

    KeyboardVisibilityEvent.setEventListener(
            AddActivity.this,
            new KeyboardVisibilityEventListener() {
                @Override
                public void onVisibilityChanged(boolean isOpen) {

                    if (isOpen) {
                        Log.d("KB", "openKeyboard");
                        scrollView.setLayoutParams(new LinearLayout.LayoutParams(
                                LinearLayout.LayoutParams.FILL_PARENT, screenHeight - actionBarHeight - keyboardHeight));
                    } else {
                        Log.d("KB", "closeKeyboard");
                        scrollView.setLayoutParams(new LinearLayout.LayoutParams(
                                LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT));
                    }
                }
            });
}

这是使用键盘库(https://github.com/yshrsmz/KeyboardVisibilityEvent)来检测键盘何时打开或关闭。这非常有效,高度/布局可以根据我想要的样子进行调整,但前提是用户单击EditText的顶部。如果用户点击EditText的底部(如果他们输入了长注),那么整个布局会被推高,在页面底部留下很大的间隙。

因此,有什么方法可以让用户点击EditText / ScrollView中的任何位置,因为它只调整一个EditText的高度,并将另一个EditText保留在屏幕顶部,而不会将其推出并支持SupportActionBar观点?此外,ScrollView用于实现屏幕右侧的垂直滚动条 - 如果只使用EditText可以实现相同的行为,那么我将完全删除ScrollView。

编辑添加照片

图片1:长注释内容(注释内容的底部位于scrollView的底部(在滚动之前无法看到))

Clicking top half of note EditText

图片2:同样的注意事项,但点击底部,强制顶部的EditText和支持ActionBar离开视图,同时在底部留下间隙。

Clicking bottom half of note EditText

说明:F高亮显示(在图像2中),它是EditText / ScrollView的底部,因此您可以看到在软键盘顶部和EditText / ScrollView底部之间创建的大间隙

所需行为:单击底部EditText中的任何位置只应调整该特定EditText的大小,以便为软键盘腾出空间,并确保此EditText位于软键盘上方,以便用户可以看到他们正在键入的内容,而顶部的EditText保留在整个地方都是一样的。

2 个答案:

答案 0 :(得分:1)

因为你在滚动视图中添加了edittext。为什么你甚至需要滚动视图?当键盘弹出导致此行为时,滚动视图具有转到特定行的属性。如果你真的想使用scrollview,那么将主布局添加为scrollview。在那里添加一个直接子项,即线性布局,并添加该线性布局中的所有内容。

答案 1 :(得分:0)

通过执行以下操作,我设法解决了大部分问题:

  • 删除ScrollView
  • 对EditText进行子类化(以接收关闭键盘按钮)
  • 添加高度变化监听器
  • 将滚动条属性添加到EditText

清单:

<activity android:theme="@style/AppTheme"
        android:name=".AddActivity"
        android:label="@string/add_record"
        android:windowSoftInputMode="adjustNothing"
        android:parentActivityName=".MainActivity"
        android:excludeFromRecents="true"/>

XML - 添加活动:

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/add_record"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="20dp"
    android:windowSoftInputMode="stateHidden">

    <EditText
        android:id="@+id/title_edittext"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="@string/enter_title"
        android:inputType="textCapSentences"
        android:textColor="@color/fontPrimary"
        android:theme="@style/EditTextCustomCursor">

        <requestFocus />
    </EditText>

    <com.securenotes.ExtendedEditText
        android:id="@+id/note_edittext"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@null"
        android:ellipsize="end"
        android:gravity="top|left"
        android:hint="@string/enter_note"
        android:inputType="textCapSentences|textMultiLine"
        android:lines="50"
        android:maxLines="20"
        android:minLines="5"
        android:paddingLeft="5dp"
        android:scrollHorizontally="false"
        android:scrollbars="vertical"
        android:textColor="@color/fontPrimary"
        android:theme="@style/EditTextCustomCursor" />

</LinearLayout>

Java - 添加活动:

private Boolean initialStart = true;
private Boolean isOpened = false;

...

private void setupListeners() {

    final View activityRootView = getWindow().getDecorView().findViewById(android.R.id.content);
    activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {

            int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
            Log.d("KB", "HeightDiff: " + heightDiff);
            if (heightDiff > 100) { // 99% of the time the height diff will be due to a keyboard.

                if (!isOpened && initialStart) {
                    Log.d("KB", "1) openKeyboard");
                    //Do two things, make the view top visible and the editText smaller
                    noteEditText.setLines(15);
                    noteEditText.requestLayout();
                    initialStart = false;
                    isOpened = true;
                } else if (!isOpened && noteEditText.hasFocus()) {
                    Log.d("KB", "2) openKeyboard");
                    //Do two things, make the view top visible and the editText smaller
                    noteEditText.setLines(15);
                    noteEditText.requestLayout();
                    isOpened = true;
                }
            }
        }
    });

    noteEditText.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.d("KB", "EditText onClick");
            isOpened = false;
        }
    });

    noteEditText.setOnKeyListener(new View.OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
                Log.d("KB", "closeKeyboard");
                noteEditText.setLines(50);
                noteEditText.requestLayout();
            }
            return false;
        }
    });
}

Java - Subclassed EditText:

    public class ExtendedEditText extends EditText {

    public ExtendedEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

    }

    public ExtendedEditText(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    public ExtendedEditText(Context context) {
        super(context);

    }

    @Override
    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
            dispatchKeyEvent(event);
            return false;
        }
        return super.onKeyPreIme(keyCode, event);
    }

}

然而,剩下的一个问题是,如果用户正在滚动EditText,有时它会将其检测为单击而不是滚动,以便键盘可见,并且布局(行数)会更改。我查看了onScrollChangeListener但是这需要API 23并且我当前的最小值是15 - 有没有办法解释滚动和EditText上的实际点击之间的区别?