我的ViewHolder
按照this answer中的建议实施View.OnClickListener
。除此之外,我仔细检查了我的适配器类与官方文档中的示例类似。
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private View view;
public ViewHolder(View view) {
super(view);
view.setOnClickListener(this);
this.view = view;
}
public View getView() {
return view;
}
@Override
public void onClick(View view) {
Context context = view.getContext();
Intent intent = new Intent(context, DetailsActivity.class);
context.startActivity(intent);
}
}
但是,如果我正在测试我的应用程序,我会观察到这种奇怪的行为:如果我正在点击启动时可见的行,onClick
方法将按预期执行。现在我向下滚动,使其他行可见。我点击某个地方没有任何反应,第二次点击 - 如果它在同一行或不同 - 再次工作。如果我回滚到顶部同样的事情发生,我必须点击两次才能调用我的onClick
方法。
为什么会发生这种情况?
编辑:完整代码,现在在onBindViewHolder
中设置了监听器:
public class ComposersAdapter extends RecyclerView.Adapter<ComposersAdapter.ViewHolder> {
public static class ViewHolder extends RecyclerView.ViewHolder {
private View view;
public ViewHolder(View view) {
super(view);
this.view = view;
}
public View getView() {
return view;
}
}
private final String EXTRA_COMPOSER_ID = "composerId";
private List<Composer> composers;
public ComposersAdapter(List<Composer> composers) {
this.composers = composers;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.text_layout, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
View view = holder.getView();
TextView textView = view.findViewById(R.id.textView);
textView.setText(composers.get(position).getTitle());
holder.getView().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Context context = view.getContext();
Intent intent = new Intent(context, ComposerActivity.class);
intent.putExtra(EXTRA_COMPOSER_ID, holder.getAdapterPosition());
context.startActivity(intent);
}
});
}
@Override
public int getItemCount() {
return composers.size();
}
}
更新:此问题似乎与RecyclerView所在活动的工具栏相关联。我已设置app:layout_scrollFlags="scroll|enterAlways"
,如果我删除该问题,则不再存在。也许这与捕获触摸事件的工具栏有关?我没有足够的经验来检验自己。
答案 0 :(得分:1)
分配点击监听器
onBindViewHolder(RecyclerView.ViewHolder holder, int position)
。
onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// start some activity
}
});
}
On Bind View Holder是指视图符号正确绑定到适配器,并且此处提供了视图的各个实例。
holder.itemView
将为您提供viewHolder视图实例的参考。
因此,您不必在ViewHolder中getView()
使用CREATE TABLE #data (
[Time] datetime,
[EQID] nvarchar(10),
[Status] bit,
[User] nvarchar(10)
)
INSERT INTO #data VALUES ('2017-12-27 12:12am', 'EQ1', 0, 'SA')
INSERT INTO #data VALUES ('2017-12-27 12:14am', 'EQ1', 1, 'SA')
INSERT INTO #data VALUES ('2017-12-27 02:30am', 'EQ1', 0, 'SA')
INSERT INTO #data VALUES ('2017-12-27 03:30am', 'EQ1', 1, 'SA')
INSERT INTO #data VALUES ('2017-12-27 05:30am', 'EQ1', 0, 'SA')
INSERT INTO #data VALUES ('2017-12-27 06:30am', 'EQ1', 1, 'SA')
-- Get the next time where status is 1
SELECT D1.[Time] as 'In_Time'
, D2.[Time] as 'Out_Time'
, D1.[EQID]
, D1.[User]
FROM #data D1
LEFT JOIN #data D2
ON D2.[Time] = (SELECT TOP 1 [Time]
FROM #data
WHERE [Status] = 1
AND [Time] > D1.[Time]
AND [User] = D1.[User]
AND [EQID] = D1.[EQID]
ORDER BY [Time])
WHERE D1.[Status] = 0
方法。
答案 1 :(得分:0)
ViewHolder 会在 RecyclerView 中描述项目视图和有关其位置的元数据。
RecyclerView.Adapter 实现应该是ViewHolder的子类,并添加字段以缓存潜在的昂贵的 findViewById(int)结果。
我在项目中有类似的问题,我已经做了一些示例,你可以看看这可能有助于解决你的问题。
public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ViewHolder> {
private List<Ad> adsList= new ArrayList<>();
private Context mContext;
static OnItemClickListener mItemClickListener;
//Provide a reference to the views for each data item
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
@BindView(R.id.mainHolder)
public RelativeLayout placeHolder;
@BindView(R.id.tv_ad_name)
public TextView tvAdName;
@BindView(R.id.tv_no_of_rating)
public TextView tvNoOfRating;
@BindView(R.id.tv_minOs)
public TextView tvMinOs;
@BindView(R.id.iv_product_thumbnail)
public ImageView ivPrductThumbnail;
public ViewHolder(View v) {
super(v);
ButterKnife.bind(this, v);
placeHolder.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (mItemClickListener != null) {
mItemClickListener.onItemClick(itemView, getPosition());
}
}
}
public interface OnItemClickListener {
void onItemClick(View view, int position);
}
public void setOnItemClickListener(final OnItemClickListener mItemClickListener) {
this.mItemClickListener = mItemClickListener;
}
//Provide a suitable constructor
public ProductAdapter(Context context){
mContext = context;
}
public void setAd(List<Ad> aList) {
adsList.clear();
adsList.addAll(aList);
notifyDataSetChanged();
}
//Create new views (invoked by the layout manager)
@Override
public ProductAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//Creating a new view
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.product_list_items,parent,false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
//Replace the contents of a view (invoked by the layout manager
@Override
public void onBindViewHolder(ProductAdapter.ViewHolder holder, int position) {
// - replace the contents of the view with that element
Ad ad = adsList.get(position);
holder.tvAdName.setText(ad.getProductName());
holder.tvNoOfRating.setText(ad.getNumberOfRatings());
holder.tvMinOs.setText(ad.getMinOSVersion());
Glide.with(mContext)
.load(ad.getProductThumbnail())
.into(holder.ivPrductThumbnail);
}
@Override
public int getItemCount() {
return adsList.size();
}
}
修改:您可能需要在 ViewHolder 类中声明 textview 。