Android - Horizo​​ntalScrollView在键盘打开时向右滚动

时间:2015-10-15 19:07:30

标签: android android-layout android-softkeyboard horizontalscrollview

我的应用程序的总体布局就位,其中包括水平滚动视图。 我正在做的是在滚动视图中添加32个片段(通过两个按钮和一个editText扩展为垂直线性布局。它们将成为均衡器的控件)。

问题是,当我尝试编辑其中一个editText时,滚动视图一直向右滚动 - 因此您无法看到您正在键入的内容,并且必须一直滚动回到该条目才能查看它。

这是主要的xml布局。它将屏幕分成4个象限,水平滚动视图位于右下角:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    tools:context=".MainActivity"
    android:focusable="true"
    android:focusableInTouchMode="true">

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:padding="4dp"
        android:orientation="vertical"
        android:layout_weight="2"
        >
        <TextView android:text="Hello World!" android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:layout_weight="4"
        android:padding="4dp"
        android:orientation="vertical"
        android:background="#FF0000"
        >
        <TextView android:text="Hello World!"      android:layout_width="wrap_content"
            android:layout_height="wrap_content" />


        <HorizontalScrollView
            android:id="@+id/hsv_eqControls"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:padding="2dp"
            android:background="#FFFFFF"
            android:descendantFocusability="beforeDescendants"
            android:focusable="true"
            android:focusableInTouchMode="true"
            >

            <LinearLayout
                android:id="@+id/layout_eqControls"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:orientation="horizontal">

            </LinearLayout>

        </HorizontalScrollView>
    </LinearLayout>

</LinearLayout>

这就是我在滚动视图中添加的内容

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="3dp"
    android:orientation="vertical">
    <Button
        android:id="@+id/btn_eqUp"
        android:layout_width="60dp"
        android:layout_height="60dp" />
    <EditText
        android:id="@+id/etext_eq"
        android:layout_width="60dp"
        android:layout_height="wrap_content"
        android:inputType="numberDecimal|numberSigned"
        android:textAlignment="center"
        android:layout_gravity="center_horizontal"
        android:background="#EEEEEE"
        android:hint="32dB"/>
    <Button
        android:id="@+id/btn_eqDown"
        android:layout_width="60dp"
        android:layout_height="60dp" />
    <TextView
        android:id="@+id/vtext_eqLabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAlignment="center"
        android:layout_gravity="center"
        android:text="1"/>
</LinearLayout>

这是我为填充滚动视图而运行的代码:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // View eqControls = findViewById(R.id.hsv_eqControls);

        FragmentTransaction ft = getFragmentManager().beginTransaction();
        for(int i = 1; i < 33; i++)
        {
            ft.add(R.id.layout_eqControls, new FragmentEQ(), "ch"+i);
        }

        ft.commit();
        getFragmentManager().executePendingTransactions();
        for(int i = 1; i < 33; i++)
        {
            FragmentEQ feq = (FragmentEQ) getFragmentManager().findFragmentByTag("ch"+i);
            if(feq != null)
                feq.setChannel(i);
        }

    }
}

这是我片段的代码:

public class FragmentEQ extends Fragment {
    protected int _channel = 0;
    protected ViewGroup _parent;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                            Bundle savedInstanceState)
    {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.activity_fragment_eq, container, false);
        TextView label = (TextView) view.findViewById(R.id.vtext_eqLabel);

        label.setText(Integer.toString(_channel));
        return view;
    }

    public int getChannel() { return _channel; }

    public void setChannel(int i)
    {
        _channel = i;
    }
}

我尝试过创建自定义Horizo​​ntalScrollView,并将scrollTo()和onRequestFocusInDescendants()重写为无效的空白方法,但这不会改变任何内容。

public class EQScrollView extends HorizontalScrollView {

    public EQScrollView( Context context, AttributeSet attrs)
    {
        super(context, attrs);
        setSmoothScrollingEnabled(false);
    }

    @Override
    public void scrollTo(int x, int y)
    {

    }

    @Override
    public boolean onRequestFocusInDescendants(int x, Rect y)
    {

        return false;
    }

}

3 个答案:

答案 0 :(得分:1)

我刚遇到这个问题,对我来说只有在android:inputType中未设置EditText时才会滚动到最后。如果你删除它,那么问题应该消失。

仅使用.setInputType(InputType.TYPE_CLASS_NUMBER);即可生成此错误。

不可否认,这不是一个解决办法,但值得注意的原因。

答案 1 :(得分:1)

使用“设置原始输入类型”:

setRawInputType(InputType.TYPE_CLASS_NUMBER);

首先为我解决了这个问题。在意识到某些数字键盘不提供十进制输入后,我最终使用EditText的标准文本输入,扩展Horizo​​ntalScrollView并覆盖“onRequestFocusInDescendants”,“requestChildRectangleOnScreen”和“getFocusables”,如下所示:

public class HorizontalScrollViewEx extends HorizontalScrollView {
    public HorizontalScrollViewEx(Context context) {
        super(context);
    }

    public HorizontalScrollViewEx(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public HorizontalScrollViewEx(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public HorizontalScrollViewEx(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
        return true;
    }

    @Override
    public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
        return true;
    }

    @Override
    public ArrayList<View> getFocusables(int direction) {
        return new ArrayList<View>();
    }
}

答案 2 :(得分:0)

Horizo​​ntalScrollView总是在我尝试单击EditText时滚动到右侧

我通过以下方式解决了类似问题:

在我的情况下

    <HorizontalScrollView
        android:id="@+id/id_HorizontalScrollView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/border_left_black_bold">

            <android.support.v7.widget.RecyclerView
                android:id="@+id/id_RecyclerView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
    </HorizontalScrollView>
  • RecyclerView的项目视图:
<LinearLayout>
    <EditText
        android:id="@+id/id_edit"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="@drawable/border_right_black"
        android:gravity="center"
        android:inputType="number" />
<LinearLayout/>
  • 我的解决方案

自定义Horizo​​ntalScrollView并覆盖requestChildRectangleOnScreen方法

    @Override
    public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
        return true;
    }
    @Override
    protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {
        return 0;
    }

根本原因

让我们回到Android源代码。

  1. 弹出软键盘时。布局的大小已更改View.java protected void onLayout(boolean changed, int left, int top, int right, int bottom)
    /**
     * Called from layout when this view should
     * assign a size and position to each of its children.
     * ....
     */
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    }
  1. 然后 Horizo​​ntalScrollView.java protected void onLayout(boolean changed, int left, int top, int right, int bottom)

在这种方法中,mIsLayoutDirty = false;

  1. Horizo​​ntalScrollView.java public void requestChildFocus(View child, View focused)

  2. Horizo​​ntalScrollView.java private void scrollToChild(View child)

  3. Horizo​​ntalScrollView.java

int scrollDelta = computeScrollDeltaToGetChildRectOnScreen(mTempRect);
if(scrollDelta!=0){
    scrollBy(scrollDelta, 0);
}