web-dev-qa-db-ja.com

Android水平スクロールビューの位置の設定

水平スクロールビューの位置を、押したボタンに対応するように設定しようとしています。これを使用して失敗に設定しようとしました:

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番目のボタン(画面外)が押された場合、新しいビューを設定して、水平スクロールビューが右端になり、左端から開始するようにします。

水平スクロールビューの位置を設定するにはどうすればよいですか?

16
Nick

現在、ボタンの位置ではなく、Horizo​​ntalScrollViewの左上隅にスクロールしようとしています。次のように、ボタンの(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を返す を意味します。レイアウトが完全に初期化される前にスクロール位置を設定しようとしても効果がないため、hsv.scrollTo()の少し後にonCreate()を呼び出す必要があります。

機能しているように見える1つのオプションは、コードを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);
}
_

ただし、この関数はアクティビティがフォーカスを取得または失うたびに呼び出されるため、意図したよりも頻繁にスクロール位置を更新してしまう可能性があります。

よりエレガントな解決策は、Horizo​​ntalScrollViewをサブクラス化し、ビューが初期化されたことがわかった後、onMeasure()にスクロール位置を設定することです。これを行うために、レイアウトを2つのファイルに分割し、MyHorizo​​ntalScrollViewという名前の新しいクラスを追加しました。

_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());
    }
}
_

MyHorizo​​ntalScrollViewが作成されると、ボタンレイアウトが自動的に拡張および追加されます。次に、super onMeasure()を呼び出した後(レイアウトの初期化が完了したことがわかるように)、スクロール位置を設定します。

これは新しいmain.xmlです。新しいMyHorizo​​ntalScrollViewのみが含まれますが、線形レイアウトまたは相対レイアウト内に簡単に配置して、他のビュー要素を追加できます。 (_com.theisenp.test_をMyHorizo​​ntalScrollViewが配置されているパッケージの名前に置き換えます):

_<?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" />
_

そして、これはMyHorizo​​ntalScrollViewによって自動的に拡張される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>
_
34
theisenp

これは古い質問ですが、最近同じ問題に遭遇し、さらに別の、しかしそれほど複雑ではない解決策を見つけました。

元の質問の特定のレイアウトファイルを想定し、特定のレイアウトでアクティビティが開始された場合、水平スクロールビューをボタン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);
            }
        });
    }
}
11
Tomasz Nguyen