安卓设置水平滚动视图的位置

18

我正在尝试设置水平滚动视图的位置,使其与被点击的按钮对应。我已经尝试使用以下方式进行设置,但未成功:

HorizontalScrollView hsv = (HorizontalScrollView)findViewById(R.id.ScrollView);
int x, y;
x = hsv.getLeft();
y = hsv.getTop();
hsv.scrollTo(x, y);

这不会产生任何结果,滚动视图不受影响。 XML代码:

 <HorizontalScrollView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/ScrollView"
        android:layout_width="fill_parent"
        android:layout_height="50dp"
        android:layout_alignParentBottom="true"
        android:background="@null"
        android:scrollbars="none" >

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="horizontal" >

            <Button
                android:layout_width="100dp"
                android:layout_height="fill_parent"
                android:layout_marginBottom="-5dp"
                android:text="btn0" 
                android:id="@+id/btn0"
                android:background="@drawable/yellow_btn" />

            <Button
                android:layout_width="100dp"
                android:layout_height="fill_parent"
                android:layout_marginBottom="-5dp"
                android:background="@drawable/yellow_btn"
                android:text="bnt1"
                android:id="@+id/btn1" />

            <Button
                android:layout_width="100dp"
                android:layout_height="fill_parent"
                android:layout_marginBottom="-5dp"
                android:background="@drawable/yellow_btn"
                android:text="btn2"
                android:id="@+id/btn2" />

            <Button
                android:layout_width="100dp"
                android:layout_height="fill_parent"
                android:layout_marginBottom="-5dp"
                android:background="@drawable/yellow_btn"
                android:text="btn3"
                android:id="@+id/btn3" />

      <Button
                android:layout_width="100dp"
                android:layout_height="fill_parent"
                android:layout_marginBottom="-5dp"
                android:background="@drawable/yellow_btn"
                android:text="btn4"
                android:id="@+id/btn4" />

      <Button
                android:layout_width="100dp"
                android:layout_height="fill_parent"
                android:layout_marginBottom="-5dp"
                android:background="@drawable/yellow_btn"
                android:text="btn5"
                android:id="@+id/btn5" />

        </LinearLayout>
    </HorizontalScrollView>

如果当新活动启动时,第5个按钮被按下(位于屏幕外),我希望设置新视图,使水平滚动视图完全靠右,而不是从左侧开始。

我该如何设置水平滚动视图的位置?

2个回答

35

目前您正在尝试将HorizontalScrollView滚动到左上角,而不是按钮的位置。 尝试像这样滚动到按钮的(x,y)位置:

HorizontalScrollView hsv = (HorizontalScrollView) findViewById(R.id.ScrollView);
Button button = (Button) findViewById(R.id.btn5);
int x, y;
x = button.getLeft();
y = button.getTop();
hsv.scrollTo(x, y);

编辑:

如果将此代码放在onCreate()中,它将无法像您期望的那样运行。即使您已经调用了setContentView(),布局也还没有被测量和初始化。这意味着getLeft()getTop()方法都会返回0。在完全初始化布局之前尝试设置滚动位置没有效果,因此您需要在onCreate()之后的某个时间调用hsv.scrollTo()

似乎可行的一个选项是将代码放置在onWindowFocusChanged()中:

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);

    HorizontalScrollView hsv = (HorizontalScrollView) findViewById(R.id.ScrollView);
    Button button = (Button) findViewById(R.id.btn5);
    int x, y;
    x = button.getLeft();
    y = button.getTop();
    hsv.scrollTo(x, y);
}
然而,该函数在每次Activity获得或失去焦点时都会被调用,因此您可能会比预期的更频繁地更新滚动位置。 一种更优雅的解决方案是子类化HorizontalScrollView并在onMeasure()中设置滚动位置,在视图已初始化后执行此操作。为此,我将您的布局拆分为两个文件,并添加了一个名为MyHorizontalScrollView的新类:
package com.theisenp.test;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.HorizontalScrollView;

public class MyHorizontalScrollView extends HorizontalScrollView {

    public MyHorizontalScrollView(Context context) {
        super(context);
        addButtons(context);
    }

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

    /**
     * Inflates the layout containing the buttons and adds them to the ScrollView
     * @param context
     */
    private void addButtons(Context context) {
        View buttons = inflate(context, R.layout.buttons, null);
        addView(buttons);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        //Find button 5 and scroll to its location
        View button = findViewById(R.id.btn5);
        scrollTo(button.getLeft(), button.getTop());
    }
}

当创建 MyHorizontalScrollView 时,它会自动膨胀并添加按钮布局。然后在调用 super 的 onMeasure() (以便它知道布局已经完成初始化) 后,它会设置滚动位置。

这是新的 main.xml。它只包含了新的 MyHorizontalScrollView,但你可以很容易地将其放入线性或相对布局中,并添加其他视图元素。(您需要用 MyHorizontalScrollView 所在的包的名称替换“com.theisenp.test”):

<?xml version="1.0" encoding="utf-8"?>
<com.theisenp.test.MyHorizontalScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ScrollView"
android:layout_width="fill_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:background="@null"
android:scrollbars="none" />

这是由MyHorizontalScrollView自动填充的buttons.xml布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:orientation="horizontal" >

    <Button
    android:id="@+id/btn0"
    android:layout_width="100dp"
    android:layout_height="fill_parent"
    android:layout_marginBottom="-5dp"
    android:text="btn0" />

    <Button
    android:id="@+id/btn1"
    android:layout_width="100dp"
    android:layout_height="fill_parent"
    android:layout_marginBottom="-5dp"
    android:text="bnt1" />

    <Button
    android:id="@+id/btn2"
    android:layout_width="100dp"
    android:layout_height="fill_parent"
    android:layout_marginBottom="-5dp"
    android:text="btn2" />

    <Button
    android:id="@+id/btn3"
    android:layout_width="100dp"
    android:layout_height="fill_parent"
    android:layout_marginBottom="-5dp"
    android:text="btn3" />

    <Button
    android:id="@+id/btn4"
    android:layout_width="100dp"
    android:layout_height="fill_parent"
    android:layout_marginBottom="-5dp"
    android:text="btn4" />

    <Button
    android:id="@+id/btn5"
    android:layout_width="100dp"
    android:layout_height="fill_parent"
    android:layout_marginBottom="-5dp"
    android:text="btn5" />

</LinearLayout>

我已经尝试过将其放置在设置布局后的oncreate中,但没有任何反应。还有其他想法吗? - Nick
我已经编辑了我的答案,并添加了解决方案的完整说明。 - theisenp

16
尽管这是一个老问题,但最近我遇到了相同的问题,并找到了另一个解决方案,而且比较简单。
假设原始问题中给定了布局文件,并且如果使用该布局启动活动,则需要滚动水平滚动视图到按钮5。
为了实现滚动到按钮5,请在活动的onCreate()方法中放置以下代码:
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Some code such as layout inflation.

        final HorizontalScrollView hsv = (HorizontalScrollView) findViewById(R.id.ScrollView);

        // Scrolling to button 5.
        hsv.post(new Runnable() {
            @Override
            public void run() {
                // Get the button.
                View button = findViewById(R.id.btn5);

                // Locate the button.
                int x, y;
                x = button.getLeft();
                y = button.getTop();

                // Scroll to the button.
                hsv.scrollTo(x, y);
            }
        });
    }
}

这是一个简单得多的解决方案。 - lintmachine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接