Android recyclerView findViewHolderForAdapterPosition возвращает ноль
Я хочу, чтобы программно щелкнуть по элементу в recyclerView, я нашел способ сделать это:
recyclerView.findViewHolderForAdapterPosition(0).itemView.performClick();
но это не работает для меня, findViewHolderForAdapterPosition просто возвращает ноль.
Я что-то пропустил в своем коде?
HistoryListAdapter:
public class HistoryListAdapter extends RecyclerView.Adapter<HistoryListAdapter.ViewHolder> {
private static ArrayList<RecordItem> recordItems;
private static FragmentActivity activity;
private static RecordList recordList;
public HistoryListAdapter(ArrayList<RecordItem> recordItems, FragmentActivity FA, RecordList FRL) {
this.recordItems = recordItems;
this.activity = FA;
this.recordList = FRL;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.recorditem, parent, false);
return new ViewHolder(itemLayoutView);
}
@Override
public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
// TextView setText ...
}
// Return the size of the itemsData (invoked by the layout manager)
@Override
public int getItemCount() {
return recordItems.size();
}
// inner class to hold a reference to each item of RecyclerView
public static class ViewHolder extends RecyclerView.ViewHolder{
public TextView result, datetime;
public ViewHolder(View itemLayoutView) {
super(itemLayoutView);
itemLayoutView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (activity != null) {
// do something...
}
}
});
result = (TextView) itemLayoutView.findViewById(R.id.result);
heartrate = (TextView) itemLayoutView.findViewById(R.id.heartrate);
datetime = (TextView) itemLayoutView.findViewById(R.id.datetime);
}
}
}
RecordList:
RecyclerView listView = (RecyclerView) layoutView.findViewById(R.id.listView);
HistoryListAdapter listadapter = new HistoryListAdapter(itemsToShow, getActivity(), RecordList.this);
listView.swapAdapter(listadapter, false);
listView.findViewHolderForAdapterPosition(0).itemView.performClick();
Я пропустил некоторый код, но он не должен влиять на общую структуру моего кода.
7 ответов
Согласно официальной документации:
если notifyDataSetChanged() был вызван, но новый макет еще не был рассчитан, этот метод вернет значение null, поскольку новые позиции представлений неизвестны до тех пор, пока макет не будет вычислен.
Это не безопасно использовать findViewHolderForAdapterPosition()
,
Пока вы вызываете этот метод после listView.swapAdapter(listadapter, false);
вы всегда получите null
как результат, потому что notifyDataSetChanged()
будет называться.
Вы можете сделать это:
listView.postDelayed(new Runnable()
{
@Override
public void run()
{
if(listView.findViewHolderForAdapterPosition(0)!=null )
{
listView.findViewHolderForAdapterPosition(0).itemView.performClick();
}
}
},50);
Я знаю, что это очень поздно, но, возможно, это поможет другим людям в эпоху Котлина:
binding.recycler.post {
val view = binding.recycler.findViewHolderForAdapterPosition(position)?.itemView?.performClick()
}
Вы можете сделать это:
postAndNotifyAdapter(new Handler(),mRecyclerView);
protected void postAndNotifyAdapter(final Handler handler, final RecyclerView recyclerView) {
handler.post(new Runnable() {
@Override
public void run() {
if ( recyclerView.findViewHolderForLayoutPosition(0)!=null) {
// This will call first item by calling "performClick()" of view.
recyclerView.findViewHolderForLayoutPosition(0).itemView.performClick();
} else {
//
postAndNotifyAdapter(handler, recyclerView);
}
}
});
}
Эй, я решил проблему следующим образом:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private TextView mTotalSum;
protected int mSum;
protected ArrayList<BasketRVAdapter.ViewHolder> mViewHolders;
public BasketRVAdapter(JSONArray recyclerItems, Context context, TextView totalSum) {
super(recyclerItems, context);
mTotalSum = totalSum;
mViewHolders = new ArrayList<>();
}
@Override
public RecyclerView.ViewHolder onCreateSwipeViewHolder(ViewGroup parent, int i) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.view_basket_rv_item, parent, true);
return new ViewHolder(view);
}
@Override
public void onBindSwipeViewHolder(final RecyclerView.ViewHolder viewHolder, int position) {
final BasketRVAdapter.ViewHolder holder = (BasketRVAdapter.ViewHolder) viewHolder;
JSONObject object;
try {
object = mRecyclerItems.getJSONObject(position);
final int priceValue = object.getInt("price");
final int quantityValue = object.getInt("quantity");
holder.setId(object.getInt("id"));
holder.title.setText(object.getString("title"));
holder.price.setText(String.format(mContext.getString(R.string.price), priceValue));
holder.quantity.setText(String.valueOf(quantityValue));
holder.sum.setText(String.valueOf(priceValue * quantityValue));
holder.quantity.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
String value = holder.quantity.getText().toString();
if (value.equals("")) {
return;
}
if (value.equals("0")) {
Toast.makeText(mContext, R.string.null_value_error, Toast.LENGTH_SHORT).show();
return;
}
holder.sum.setText(String.valueOf(priceValue * Integer.valueOf(value)));
setTotalSum();
}
});
mViewHolders.add(holder);
mSum += priceValue * quantityValue;
if (position == getItemCount() - 1) {
mTotalSum.setText(String.format(mContext.getString(R.string.total_sum), mSum));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public SwipeConfiguration onCreateSwipeConfiguration(Context context, int i) {
return new SwipeConfiguration.Builder(context)
.setLeftSwipeBehaviour(SwipeConfiguration.SwipeBehaviour.NORMAL_SWIPE)
.setRightSwipeBehaviour(SwipeConfiguration.SwipeBehaviour.NO_SWIPE)
.setLeftBackgroundColorResource(R.color.dt_basket_deleted)
.setLeftUndoDescription(R.string.deleted)
.setDescriptionTextColorResource(R.color.dt_white)
.setLeftUndoable(true)
.build();
}
@Override
public void onSwipe(int i, int i1, RecyclerView.ViewHolder holder) {
try {
if (i1 == SWIPE_LEFT) {
remove(i);
notifyItemRemoved(i);
mViewHolders.remove(i);
setTotalSum();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
public int getSum() {
return mSum;
}
public void setTotalSum() {
int totalSum = 0;
for (BasketRVAdapter.ViewHolder holder : mViewHolders) {
totalSum += Integer.valueOf(holder.sum.getText().toString());
}
mSum = totalSum;
mTotalSum.setText(String.format(mContext.getString(R.string.total_sum), totalSum));
}
public static class ViewHolder extends RecyclerView.ViewHolder {
@Bind(R.id.trade_title)
public TextView title;
@Bind(R.id.trade_price)
public TextView price;
@Bind(R.id.trade_quantity)
public EditText quantity;
@Bind(R.id.sum)
public TextView sum;
private int mId;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
public int getId() {
return mId;
}
public void setId(int id) {
mId = id;
}
}}
- Добавлено поле ArrayList mViewholder внутри класса
- добавили каждый экземпляр виджета в массив списков mViewHolders внутри метода onBindSwipeViewHolder
- использовал метод mViewholder arraylist вместо метода findViewHolderForadapterposition внутри метода setTotalSum
ты должен использовать
recyclerview.findViewHolderForLayoutPosition(position)
Я не рекомендовал бы использовать почтовую задержку. Хотя это работает, время произвольно.
Используя OnPreDrawListener в представлении реселлера, время будет выровнено со следующим циклом отрисовки, и видимые элементы будут доступны.