15

RecyclerViewを使用してチャットアプリケーションを作成しようとしています。私はLinearLayoutManagersetReverseLayout(true)と使用しています。RecyclerViewをスクロールして挿入する

データセットstart =最新のメッセージである下端までスクロールされ、新しいメッセージがデータセットに挿入されると、アイテムはリストの下部に期待通りに表示されます(ビューがスクロールされます)。新しいアイテムのためのスペースを確保するために)。

私が持っている問題は、古いメッセージを見るためにスクロールしたときです。新しいメッセージがデータセットの先頭に挿入されると、そのメッセージはビューポートの範囲外にあるためレンダリングされなくても、メッセージの高さは約1つ上にスクロールされます。

ビューを下にスクロールするとスクロール動作を維持できますが、古いメッセージにスクロールしたときにスクロール動作を無効にするにはどうすればよいですか。

はUPDATE:私は私が同様に作られたレポに加工修正を犯しhttps://github.com/ehehhh/RecyclerViewProblem

UPDATE 2: は、私はまた、この問題が再現される小さなアプリケーションを、作られました。

関連するコード(願わくは):

compile 'com.android.support:recyclerview-v7:24.2.0' 

XML:

<android.support.v7.widget.RecyclerView 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:clipToPadding="false" 
      android:paddingBottom="8dp" 
      android:paddingTop="8dp" 
      app:layout_behavior="@string/appbar_scrolling_view_behavior"/> 

RecyclerView初期化コード:

layoutManager = new LinearLayoutManager(context); 
layoutManager.setOrientation(LinearLayoutManager.VERTICAL); 
layoutManager.setReverseLayout(true); 
recyclerView.setLayoutManager(layoutManager); 
recyclerView.setScrollContainer(true); 
recyclerView.setLayoutAnimation(null); 
recyclerView.setItemAnimator(null); 
adapter = new ChatAdapter(...); 
recyclerView.setAdapter(adapter); 

アダプタ

public class ChatAdapter extends RecyclerView.Adapter<ChatViewHolder> { 

    private List<MessageWrapper> dataset; 

    public ChatAdapter(List<MessageWrapper> dataset, ...) { 
     this.dataset = dataset; 
     setHasStableIds(true); 
    } 

    ... 

    @Override 
    public long getItemId(int position) { 
     return dataset.get(position).getId(); 
    } 

    @Override 
    public int getItemCount() { 
     return dataset.size(); 
    } 

    public void datasetChanged(List<MessageWrapper> dataset) { 
     this.dataset = dataset; 
     notifyDataSetChanged(); 
    } 
} 

新しいアイテムがデータセットに追加されたとき、私はちょうどアダプタでdatasetChangedメソッドを呼び出します。あなたはアイテムが を変更知っているあなたがた働いたものを、この特定のケースでは

notifyItemInserted(position) 

を使用できるかどうnotifyDataSetChangedが冗長で使用してリサイクラービューで

+0

あなたはデータセット全体を更新するのですか? または新しい行を挿入するだけですか? –

+0

リストの先頭に項目を追加してから、 'notifyDatasetChanged()'を呼び出します。 – ehehhh

+0

@ehehhh私はsetStackFromEnd(true)と同じ問題がありますか?それについての手がかりは? – ADM

答えて

4

notifyItemInserted(0); 

または

notifyItemRangeInserted(positionStart, newItems.size() - 1) 

この範囲内のビューのみを再バインドします

チェック https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#notifyItemInserted(int)

+0

あなたの答えをありがとう、私はあなたの方法を試して、行動は同じままです。なぜなら、基本的にデルタを「裏で」計算し、 'notifyItemRangeInserted()'を呼び出すか、自動的に必要なものを呼び出す 'setHasStableIds(true)'を使用しているからです。 – ehehhh

+0

setHasStableIds(false)を試してみました。ちょうど好奇心から試して何か変わったのですか? –

+0

はい、私は同じ結果を得ています。 – ehehhh

0

私は同様の問題がありました。私はチャットアプリケーションを作っていました。私のRecyclerViewは常に上から行を表示していました。最後に挿入されたメッセージを表示するために、下に行くことを望みました。これはrecyclerView.scrollToPosition(messages.size()-1)ChildEventListenerに追加、私のために働いていたものです:

public class MainActivity extends AppCompatActivity { 

    private RecyclerView recyclerView; 
    private MessageAdapter mMessageAdapter; 
    private List<Message> messages; 

    private FirebaseDatabase mFirebaseDatabase; 
    private DatabaseReference mMessagesDatabaseRef; 

    .... 


    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     mFirebaseDatabase = FirebaseDatabase.getInstance(); 
     mMessagesDatabaseRef = mFirebaseDatabase.getReference().child("messages"); 


     recyclerView = (RecyclerView) findViewById(R.id.recycler_view); 


     // Initialize message ListView and its adapter 
     messages = new ArrayList<>(); 
     mMessageAdapter = new MessageAdapter(messages); 



     RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext()); 
     recyclerView.setLayoutManager(mLayoutManager); 

     recyclerView.setAdapter(mMessageAdapter); 

     ..... 

     mMessagesDatabaseRef.addChildEventListener(new ChildEventListener() { 
      @Override 
      public void onChildAdded(DataSnapshot dataSnapshot, String s) { 


       messages.add(dataSnapshot.getValue(Message.class)); 

       recyclerView.scrollToPosition(messages.size()-1); 
       mMessageAdapter.notifyDataSetChanged(); 

      } 

      ...... 


     }); 

    } 



} 
関連する問題