[解決済み] NestedScrollView内のRecyclerViewが途中でスクロールを開始する原因
質問
NestedScrollViewの中にRecyclerViewを追加すると、スクロールの挙動がおかしくなるのですが。
何が起こるかというと、スクロールビューに画面に表示できる以上の行があるときはいつでも、アクティビティが起動されるとすぐに、NestedScrollViewはトップからのオフセットで開始します(画像1)。スクロールビュー内のアイテムが少なく、一度に表示できる場合は、このようなことは起こりません(画像2)。
サポートライブラリのバージョン23.2.0を使用しています。
画像1 : WRONG - 上からオフセットで始まります。
画像2 : CORRECT - リサイクラービューのアイテムが少ない。
以下に私のレイアウトコードを貼り付けます。
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Title:"
style="@style/TextAppearance.AppCompat.Caption"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/bodyPadding"
style="@style/TextAppearance.AppCompat.Body1"
android:text="Neque porro quisquam est qui dolorem ipsum"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Subtitle:"
style="@style/TextAppearance.AppCompat.Caption"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/TextAppearance.AppCompat.Body1"
android:padding="@dimen/bodyPadding"
android:text="Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit..."/>
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/rv"
android:focusable="false"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
私は何かを見逃しているのでしょうか?誰かこれを修正する方法を知っていますか?
アップデート 1
Activityの初期化時に以下のコードを配置すると、正常に動作するようになりました。
sv.post(new Runnable() {
@Override
public void run() {
sv.scrollTo(0,0);
}
});
svはNestedScrollViewへの参照ですが、かなりハックされているように見えます。
アップデート 2
リクエストに応えて、私のアダプターコードを紹介します。
public abstract class ArrayAdapter<T, VH extends RecyclerView.ViewHolder>
extends RecyclerView.Adapter<VH> {
private List<T> mObjects;
public ArrayAdapter(final List<T> objects) {
mObjects = objects;
}
/**
* Adds the specified object at the end of the array.
*
* @param object The object to add at the end of the array.
*/
public void add(final T object) {
mObjects.add(object);
notifyItemInserted(getItemCount() - 1);
}
/**
* Remove all elements from the list.
*/
public void clear() {
final int size = getItemCount();
mObjects.clear();
notifyItemRangeRemoved(0, size);
}
@Override
public int getItemCount() {
return mObjects.size();
}
public T getItem(final int position) {
return mObjects.get(position);
}
public long getItemId(final int position) {
return position;
}
/**
* Returns the position of the specified item in the array.
*
* @param item The item to retrieve the position of.
* @return The position of the specified item.
*/
public int getPosition(final T item) {
return mObjects.indexOf(item);
}
/**
* Inserts the specified object at the specified index in the array.
*
* @param object The object to insert into the array.
* @param index The index at which the object must be inserted.
*/
public void insert(final T object, int index) {
mObjects.add(index, object);
notifyItemInserted(index);
}
/**
* Removes the specified object from the array.
*
* @param object The object to remove.
*/
public void remove(T object) {
final int position = getPosition(object);
mObjects.remove(object);
notifyItemRemoved(position);
}
/**
* Sorts the content of this adapter using the specified comparator.
*
* @param comparator The comparator used to sort the objects contained in this adapter.
*/
public void sort(Comparator<? super T> comparator) {
Collections.sort(mObjects, comparator);
notifyItemRangeChanged(0, getItemCount());
}
}
そして、これが私のViewHolderです。
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView txt;
public ViewHolder(View itemView) {
super(itemView);
txt = (TextView) itemView;
}
public void render(String text) {
txt.setText(text);
}
}
そして、RecyclerViewの各項目のレイアウトです(これは単に
android.R.layout.simple_spinner_item
- のみです。この画面はこのバグの例を示すためだけのものです)。
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
style="?android:attr/spinnerItemStyle"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:textAlignment="inherit"/>
どのように解決するのですか?
私は、このような問題を設定することによって解決しました。
<ImageView ...
android:focusableInTouchMode="true"/>
をRecyclerViewの上にある私のビューに設定してください(不要なスクロールの後に隠されました)。このプロパティをRecyclerViewの上にあるLinearLayoutか、RecyclerViewのコンテナであるLinearLayoutに設定してみてください(別のケースで役に立ちました)。
NestedScrollViewのソースを見ると、onRequestFocusInDescendantsで最初の可能な子にフォーカスしようとし、RecyclerViewだけがフォーカス可能であれば、それが勝ちになるようです。
編集 (Waranに感謝): そして、スムーズなスクロールのために、以下の設定を忘れないでください。
yourRecyclerView.setNestedScrollingEnabled(false);
関連
-
[解決済み】Android "ビュー階層を作成した元のスレッドだけが、そのビューに触れることができる"
-
android.os の NetworkOnMainThreadException。
-
AndroidエミュレーターのADBサーバーがACKしない問題
-
Gradle のエラーです。gradle-core.jar (com.android.tools.build:gradle-core:x.x.x) を見つけられませんでした。
-
Androidで発生した問題、解決策とヒント
-
android studioが "The activity must be exported or contain an intent-filter" と表示され実行される。
-
指定された子にはすでに親がいます。まず、その子の親に対して removeView() をコールする必要があります。
-
例外「指定された子にはすでに親がいます」の解決方法。removeViewを呼び出す必要があります" の解決方法(ソースコード付き例)
-
Androidで、onTouchEventでダブルクリックを実装し、ダブルクリックイベントとして判定する方法
-
view.getRootView()の本当の意味とテストについて
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
adb シェルがデバイスのオフラインを求めるプロンプトを表示する
-
aapt2エラー:ログを確認する(具体的な原因の探り方)
-
cygwinのダウンロード、インストールチュートリアル、およびCDTの「makeプログラムがパスに見つからない」バグの解消
-
アプリはGoogle検索でインデックスされません Androidmanifestのクソみたいな黄色い警告
-
repo: コマンドが見つかりません
-
Android TextViewにandroid:ellipsize=endのバグがある。
-
view.getRootView()の本当の意味とテストについて
-
Androidの美しいSeekBarスタイルのカスタマイズ
-
Androidカスタムドロップダウンリストボックスコントロール
-
android studioが新しいプロジェクトを作成しますが、プロジェクトの同期に成功するまでデザインエディタが使用できません。