特定の期間ごとにアイテムを追加するRecyclerViewがあります。オブジェクトを追加するとき、リストアイテムが500(以上)の場合、最初のアイテムが削除され、新しいアイテムが追加されます。
RecyclerViewがこれ以上下にスクロールできない場合は!recyclerView.canScrollVertically(1);
を使用し、新しいアイテムを追加した後、RecyclerViewは最後の位置にsmoothScroolToPosition()
します。
どこに問題がありますか?さて、ReyclerViewが古いアイテムを削除するときに中央(下ではなく上)にある場合、突然いくつかの位置にジャンプします。 RecyclerViewが位置をジャンプしないようにし、上部のアイテムを削除したときの位置に留まるようにしたい
layoutManager.setStackFromEnd(true);
を使ってみましたが、うまくいきませんでした
助言がありますか?
一部のコード(無関係なコードは削除されます)。 RecyclerViewが中央からリストアイテムを表示してVOLUME_UPを押すと、問題が再現します。
public class ActivityMain extends ActionBarActivity {
public static final int MAX_LOG_ITEMS = 500;
private RecyclerView mRecyclerView;
private AdapterLog mRecyclerAdapter;
private boolean mAutoScroll = true;
private DataReceiver mDataReceiver;
private Handler mLogHandler = new Handler() {
@Override public void handleMessage(Message msg) {
switch (msg.what){
case DataReceiver.CAT_LOGS:
List<Log> catLogs = (List<Log>) msg.obj;
updateLogs(catLogs);
break;
case DataReceiver .CLEAR_LOGS:
if (mRecyclerAdapter.getItemCount() > MAX_LOG_ITEMS)
mRecyclerAdapter.removeFirstItems(mRecyclerAdapter.getItemCount() - MAX_LOG_ITEMS);
break;
case Logcat.REMOVE_LOGS:
mRecyclerAdapter.clear();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setStackFromEnd(true);
mRecyclerAdapter = new AdapterLog();
mRecyclerView = (RecyclerView) findViewById(R.id.activity_main_recyclerview);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setAdapter(mRecyclerAdapter);
mRecyclerView.setOnScrollListener(new UIUtils.ScrollManager(toolbarContainer != null ?
toolbarContainer : toolbar){
@Override public void onScrolled(RecyclerView r, int dx, int dy) {
super.onScrolled(r, dx, dy);
mAutoScroll = !r.canScrollVertically(1);
}
});
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch(keyCode){
case KeyEvent.KEYCODE_VOLUME_UP:
// mAutoScroll = false;
// mRecyclerView.scrollToPosition(0);
// if (mRecyclerAdapter.getItemCount() > MAX_LOG_ITEMS)
mRecyclerAdapter.removeFirstItems(mRecyclerAdapter.getItemCount() - 50);
return true;
case KeyEvent.KEYCODE_VOLUME_DOWN:
mAutoScroll = true;
mRecyclerView.scrollToPosition(mRecyclerAdapter.getItemCount() -1);
return true;
}
return false;
}
private void updateLogs(final List<Log> logList) {
final boolean scroll = mAutoScroll;
mRecyclerAdapter.addAll(logList);
if (scroll) mRecyclerView.smoothScrollToPosition(mRecyclerAdapter.getItemCount() - 1);
}
}
RecyclerAdapter:
public class AdapterLog extends RecyclerView.Adapter<AdapterLog.ViewHolder> {
private final List<Log> mLogList;
public AdapterLog() {
this.mLogList = new ArrayList<Log>();
}
@Override
public AdapterLog.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.listitem_log, parent, false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mTextView.setText(getItem(position).getMessage());
holder.mTextView.setTextColor(getItem(position).getLevel().getColor());
}
@Override
public int getItemCount() {
return mLogList.size();
}
public Log getItem(int position) {
return mLogList.get(position);
}
public void addAll(List<Log> logList) {
mLogList.addAll(logList);
notifyDataSetChanged();
}
public void removeFirstItems(int count) {
for (int i=0; i<count; i++) mLogList.remove(0);
notifyDataSetChanged();
}
public void clear() {
mLogList.clear();
notifyDataSetChanged();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView;
public ViewHolder(View v) {
super(v);
mTextView = (TextView) v.findViewById(R.id.listitem_log_textview);
}
}
}
アダプター全体を変更したという見方を示しています。追加、削除、並べ替えについては、次の方法の使用を検討してください。
notifyItemRangeChanged
notifyItemRangeInserted
notifyItemRangeRemoved
notifyItemMoved
notifyItemInserted
notifyItemChanged
notifyItemRemoved
したがって、あなたの場合、上位のcount
アイテムを削除するので、
notifyItemRangeRemoved(0,count)
仕事をする必要があります。
public class viewHolderFav extends RecyclerView.ViewHolder {
private ImageView image;
private TextView name;
public viewHolderFav( View itemView ) {
super( itemView );
image = ( ImageView ) itemView.findViewById( R.id.txt_image_fav );
name = ( TextView ) itemView.findViewById( R.id.txt_name_fav );
edite.setOnClickListener( new View.OnClickListener( ) {
@Override
public void onClick( View v ) {
remove( posts.get( getLayoutPosition() ) );
}
} );
}
public void remove(DataBoj item) {
int position = posts.indexOf(item);
posts.remove(position);
notifyItemRemoved(position);
}