長いScrollViewレイアウトの一番上までスクロールする方法は?


162

私のアプリの一部では、ユーザーに名前のリストが表示され、適切と思われるようにグループ化するように求められます。

(注、ListViewコードはそのままAndroid Viewsチュートリアルからコピーされました。私はまだ自分のニーズに合わせてカスタマイズしていません。これを機能させる方法を理解しようとしています。)

基本レイアウトは、RelativeLayoutを含むScrollView(以下のコードでは「groupsScrollView」と呼ばれます)を含むLinearLayoutです。ボタンとテキストをいくつか用意し、その下にあるListViewに名前のリストを表示します。これはすべて、表示されている画面領域よりも高いため、ユーザーは垂直方向にスクロールしてすべてを見ることができます。

これはすべて、ページが読み込まれるときを除いて、すべて美しく機能します。ただし、ページの中央にある常に、ListViewの上部にプリスクロールされます。ユーザーが何をすべきかを指示するために作成したテキストとボタンが表示されません。

画面をつかんで上にスクロールすることもできますが、これは問題なく機能しますが、すでに一番上までスクロールした状態で画面をロードしたいと思います。新しく読み込まれたページの上部を表示するために、ユーザーが上にスクロールする必要はありません。しかし、プログラムで画面の最上部までスクロールしようとしたすべてが失敗しました。

これが私のonCreateメソッドです:

protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.groups);

    mainScrollView = (ScrollView)findViewById(R.id.groupsScrollView);

    //get the Bundle out of the Intent...
    Bundle extras = getIntent().getExtras();
    mNames = extras.getStringArray("mNames");

    setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item, mNames));

    ListView lv = getListView();
    lv.setTextFilterEnabled(true);

    //This is the line I'm having issues with
    mainScrollView.pageScroll(View.FOCUS_UP);

    lv.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View view,
            int position, long id) {
          // When clicked, show a toast with the TextView text
          Toast.makeText(getApplicationContext(), ((TextView) view).getText(),
              Toast.LENGTH_SHORT).show();
        }
      });
}

「mainScrollView.pageScroll(View.FOCUS_UP);」という行が問題です。エラーは発生しませんが、何も実行されないようです。scrollTo(0,0)、scrollDirection(View.FOCUS_UPを試しました)、そして私が考えることができる他のすべて。

エラーが発生しないので、これらのスクロールコマンドは実際には機能しているが、それらを含むScrollViewまたはRelativeLayoutの上部ではなく、ListViewの上部にスクロールしていると想定する必要があります。これは、Google独自のscrollTo(int x、int y)メソッドの説明で確認されているようです。「このバージョンでは、スクロールも子の境界に固定されます。」

長い質問をさらに長くするには、ScrollView内に含まれる画面に一連のビューをロードし、プログラムでページ全体をスクロールしてユーザーが操作できるようにする方法を教えてください。

ありがとう!

回答:


264

試す

mainScrollView.fullScroll(ScrollView.FOCUS_UP);

うまくいくはずです。


私のためにも働く。:D
Muntasir Aonik 2017年

1
ScrollView#fullScroll()が現在のフォーカスを変更することがわかりました。EditTextでテストしました。
illusionJJ

175

同じ問題、おそらく何らかのバグがありました。

fullScroll(ScrollView.FOCUS_UP)他の答えからでもうまくいきませんでした。 ダイアログが表示された直後
、私にとってはうまく機能したものだけが電話をかけていましたscroll_view.smoothScrollTo(0,0)


これは最初はうまくいきましたが、後で何度も何度も試しましたが、このアプローチでは満足のいく結果が得られませんでした。
JaydeepW 2013

16
私はscroll_view.smoothScrollTo(0,0)から解決します。そのとき、リストビューがスクロールビューの横にある場合、fullScroll(ScrollView.FOCUS_UP)は機能しません。
Kirtikumar A. 2013

1
scroll_view.smoothScrollTo(0,0)は、mainScrollView.fullScroll(ScrollView.FOCUS_UP);よりもうまく機能しました。ありがとう!
marienke 2014年

2
ほとんどのデバイスではfullScroll(ScrollView.FOCUS_UP)が機能しましたが、Nexus 5とテキストサイズを大きくしたデバイスでは、fullSscrollがアクションバーの下に移動され、smoothScrollTo(0,0)はすべてのデバイスでより適切に機能しました。
jt-gilkeson 2015

これにはfullScroll()、移動後も選択された項目が選択されたままになるという利点があります。を使用するfullScroll()と、スクロールビューの最初のアイテムは、スクロールが上に移動する前に選択したアイテムとは関係なく、私の場合は毎回再選択されました。
GeertVc 2017年

97

私は同じ問題を抱えていて、これで修正されました。お役に立てば幸いです。

listView.setFocusable(false);

3
これもグリッドビューの正しい解決策です。同じビューグループに複数のビュー要素がある場合、特にリストまたはグリッドビューの上にある別のリストビューがある場合に発生します。アダプターがUIスレッドに通知するため、ビューが再作成され、最初の要素までスクロールします。listView.setFocusable(false)/ gridView.setFocusable(false)を呼び出すだけです。xmlファイルから実行すると、機能しません。
omersem

このソリューションは私の場合にも機能しました。NestedScrollView内にRecyclerViewがあったため、自動スクロールダウンでした。ありがとう!
Nilesh Rathore

アダプタを設定する前にこれを追加する必要がありましたが、その後は魅力のように機能します。ありがとう
コミュニティ

完璧な説明!!
ボルハ・ロペス

説明についてはMiguelと特にomersemの両方に感謝します。特にXMLで設定すると機能しないという部分については、頭痛の
種を減らしました

53

scrollViewObject.fullScroll(ScrollView.FOCUS_UP)これは正常に機能しますが、この行の問題だけは、scrollViewObjectにデータが入力されているときにすぐに呼び出されることです。データが入力されるまで数ミリ秒待つ必要があります。このコードを試してください:

scrollViewObject.postDelayed(new Runnable() {
    @Override
    public void run() {
        scroll.fullScroll(ScrollView.FOCUS_UP);
    }
}, 600);

または

 scrollViewObject.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        scrollViewObject.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        scrollViewObject.fullScroll(View.FOCUS_UP);
    }
});

scrollviewがページの一番下までスクロールするはずだったのと同じ問題を処理していましたが、直してしまいました!
Machine Tribe

1
「マジック」x待機するミリ秒数を推測する代わりに、Viewオブジェクトは、ウィジェットがUIにレンダリングされるとランナブルをポストする、使用可能なpost(Runnable)メソッドを提供します。
Ryan

@Ryan:ポスト(Runnableを)は常にネクサス5(Genymotion)に私のために動作しません
DIKA

post(Runnable)が機能しない可能性があるのは、ビューインフローテーションステップの後にデータをフェッチした場合、最初に上にスクロールすると機能し、次にデータがビューに入力されるためです。したがって、データを設定したプロセスの後でpostDelayed(Runnable、dummyMillis)を使用するか、またはscroll.fullScroll(ScrollView.FOCUS_UP)を使用する必要があります。
oguzhan 2017

静的なミリを与える最初のソリューションは悪いアプローチです。
Malwinder Singh

35

これらすべての有効なソリューションの主な問題は、スクロールがまだ画面に描画されていないときにスクロールを上に移動しようとしていることです。

スクロールビューが画面に表示されるまで待ってから、これらのソリューションのいずれかで上に移動する必要があります。遅延を気にしないので、これは遅延後よりも優れたソリューションです。

    // Wait until my scrollView is ready
    scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            // Ready, move up
            scrollView.fullScroll(View.FOCUS_UP);
        }
    });

7
素晴らしい解決策- onGlobalLayoutメソッド呼び出しの 最後にグローバルリスナーを削除することを忘れないでくださいscrollView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
Nilhcem

30

非常に簡単

    ScrollView scroll = (ScrollView) findViewById(R.id.addresses_scroll);
    scroll.setFocusableInTouchMode(true);
    scroll.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);

3
私にとっては機能しませんでした(3行目)、解決策は次のとおりです:scroll.fullScroll(View.FOCUS_UP); (最初の2行を含む)
medskill 2017年

@medskill、こんにちは、これらをxmlファイルに記述しましたか?これはでのみ機能することを私は思いonCreate()ます。
不明

@ imknownJ.Kimuはxmlファイルで私のために機能します
Paglian

これでうまくいきました。2行目と3行目の両方が必要です。私にとってはXMLでは機能しません。
2018

2
できればキスします!これに1〜2時間費やしました。2つのリストビューが読み込まれるのを待っており、それらに集中したくない場合に最適です。それをonResume()に追加しました。
John T

24

同じ問題に直面しましたView FlipperまたはDialog内でScrollviewを使用している場合、ケース scrollViewObject.fullScroll(ScrollView.FOCUS_UP)がfalseを返すため、ケース scrollViewObject.smoothScrollTo(0, 0)が機能します

上にスクロールフォーカス


19
 final ScrollView scrollview = (ScrollView)findViewById(R.id.selected_place_layout_scrollview);

         scrollview.post(new Runnable() { 
                public void run() { 
                    scrollview.scrollTo(0, 0); 
                } 
            }); 

9
runOnUiThread( new Runnable(){
   @Override
   public void run(){
      mainScrollView.fullScroll(ScrollView.FOCUS_UP);
   }
}


6

これはscrollviewの強制スクロールです:

            scrollView.post(new Runnable() {
                @Override
                public void run() {
                    scrollView.scrollTo(0, 0);
                    scrollView.pageScroll(View.FOCUS_UP);
                    scrollView.smoothScrollTo(0,0);
                }
            });

4
scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        // Ready, move up
        scrollView.fullScroll(View.FOCUS_UP);
    }
});

1

Kotlinで問題を次のように修正しました:

scrollview.isFocusableInTouchMode = true
scrollview.fullScroll(View.FOCUS_UP)
scrollview.smoothScrollTo(0,0)

0
@SuppressWarnings({ "deprecation", "unchecked" })
public void swipeTopToBottom(AppiumDriver<MobileElement> driver) 
                    throws InterruptedException {
       Dimension dimensions = driver.manage().window().getSize();
        Double screenHeightStart = dimensions.getHeight() * 0.30;
        int scrollStart = screenHeightStart.intValue();
        System.out.println("s="+scrollStart);
        Double screenHeightEnd = dimensions.getHeight()*0.90;
        int scrollEnd = screenHeightEnd.intValue();
        driver.swipe(0,scrollStart,0,scrollEnd,2000);
        CommonUtils.threadWait(driver, 3000);
    }

これは確実に実行されます
Ajeet Gour 2017

この回答がどのように問題を解決するかについて簡単に説明してください。
AyberkÖzgür2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.