Android 向具有RecyclerView模式的卡添加按钮

Android 向具有RecyclerView模式的卡添加按钮,android,android-recyclerview,Android,Android Recyclerview,根据和RecyclerView模式,我实现了一个活动,显示一系列项目的卡片。我希望每张卡片上都有一个按钮,弹出该项目选项对话框: 如你所见,每张卡的右上角都有一个按钮。我是这样实施的: CardViewHolder.java: public class CardViewHolder extends RecyclerView.ViewHolder { protected TextView itemTitle; protected TextView itemCode; pr

根据和RecyclerView模式,我实现了一个活动,显示一系列项目的卡片。我希望每张卡片上都有一个按钮,弹出该项目选项对话框:

如你所见,每张卡的右上角都有一个按钮。我是这样实施的:

CardViewHolder.java:

public class CardViewHolder extends RecyclerView.ViewHolder {
    protected TextView itemTitle;
    protected TextView itemCode;
    protected TextView itemDate;
    protected TextView itemStatus;
    protected Button optionsButton;
    public CardViewHolder(View v) {
        super(v);
        itemTitle = (TextView) v.findViewById(R.id.itemTitle);
        itemCode = (TextView) v.findViewById(R.id.itemCode);
        itemStatus = (TextView) v.findViewById(R.id.itemStatus);
        itemDate = (TextView) v.findViewById(R.id.itemDate);
        optionsButton = (Button) v.findViewById(R.id.options_button);
    }
}
public class DataAdapter extends RecyclerView.Adapter<CardViewHolder>{
    private JSONArray mDataSet;
    private Context mContext;

    //constructor
    public DataAdapter(JSONArray myDataSet, Context c) {
        mContext = c;
        mDataSet = myDataSet;
    }
    //creates new views (invoked by the layout manager)
    @Override
    public CardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //create a new view
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_text_view, parent, false);
        //set the view's size, margins, padding and layout parameters
        CardViewHolder vh = new CardViewHolder(v);
        return vh;
    }

    @Override
    public void onBindViewHolder(CardViewHolder holder, int position) {
        //get element from dataset at position
        //replace the contets of the view with that element
        String title,itemCode,itemStatus, itemDate;
        title = itemCode = itemDate = itemStatus = "";
        try {
            JSONObject item = new JSONObject(mDataSet.get(position).toString());
            title = item.getString("desc");
            itemCode = item.getString("code");
            itemDate = item.getString("date");
            itemStatus = item.getString("status");

        } catch (JSONException e) {
            e.printStackTrace();
        }
        holder.itemTitle.setText(title);
        holder.itemCode.setText(itemCode);
        holder.itemDate.setText(itemDate);
        holder.itemStatus.setText(Html.fromHtml(itemStatus));
        holder.optionsButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(mContext,title,Toast.LENGTH_LONG).show();
            }
        });
    }

    @Override
    public int getItemCount() {
        return mDataSet.length();
    }

    // Provide a reference to the views for each data item
    // Complex data items may need more than one view per item, and
    // you provide access to all the views for a data item in a view holder
    public static class ViewHolder extends RecyclerView.ViewHolder {
        // each data item is just a string in this case
        public TextView mTextView;
        public ViewHolder(TextView v) {
            super(v);
            mTextView = v;
        }
    }
}
然后,实现了在我的活动中为我的RecyclerView设置的我的DataAdapter:

DataAdapter.java:

public class CardViewHolder extends RecyclerView.ViewHolder {
    protected TextView itemTitle;
    protected TextView itemCode;
    protected TextView itemDate;
    protected TextView itemStatus;
    protected Button optionsButton;
    public CardViewHolder(View v) {
        super(v);
        itemTitle = (TextView) v.findViewById(R.id.itemTitle);
        itemCode = (TextView) v.findViewById(R.id.itemCode);
        itemStatus = (TextView) v.findViewById(R.id.itemStatus);
        itemDate = (TextView) v.findViewById(R.id.itemDate);
        optionsButton = (Button) v.findViewById(R.id.options_button);
    }
}
public class DataAdapter extends RecyclerView.Adapter<CardViewHolder>{
    private JSONArray mDataSet;
    private Context mContext;

    //constructor
    public DataAdapter(JSONArray myDataSet, Context c) {
        mContext = c;
        mDataSet = myDataSet;
    }
    //creates new views (invoked by the layout manager)
    @Override
    public CardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //create a new view
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_text_view, parent, false);
        //set the view's size, margins, padding and layout parameters
        CardViewHolder vh = new CardViewHolder(v);
        return vh;
    }

    @Override
    public void onBindViewHolder(CardViewHolder holder, int position) {
        //get element from dataset at position
        //replace the contets of the view with that element
        String title,itemCode,itemStatus, itemDate;
        title = itemCode = itemDate = itemStatus = "";
        try {
            JSONObject item = new JSONObject(mDataSet.get(position).toString());
            title = item.getString("desc");
            itemCode = item.getString("code");
            itemDate = item.getString("date");
            itemStatus = item.getString("status");

        } catch (JSONException e) {
            e.printStackTrace();
        }
        holder.itemTitle.setText(title);
        holder.itemCode.setText(itemCode);
        holder.itemDate.setText(itemDate);
        holder.itemStatus.setText(Html.fromHtml(itemStatus));
        holder.optionsButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(mContext,title,Toast.LENGTH_LONG).show();
            }
        });
    }

    @Override
    public int getItemCount() {
        return mDataSet.length();
    }

    // Provide a reference to the views for each data item
    // Complex data items may need more than one view per item, and
    // you provide access to all the views for a data item in a view holder
    public static class ViewHolder extends RecyclerView.ViewHolder {
        // each data item is just a string in this case
        public TextView mTextView;
        public ViewHolder(TextView v) {
            super(v);
            mTextView = v;
        }
    }
}
公共类DataAdapter扩展了RecyclerView.Adapter{
私有JSONArray mDataSet;
私有上下文;
//建造师
公共数据适配器(JSONArray myDataSet,上下文c){
mContext=c;
mDataSet=myDataSet;
}
//创建新视图(由布局管理器调用)
@凌驾
公共卡ViewHolder onCreateViewHolder(视图组父级,int-viewType){
//创建新视图
视图v=LayoutInflater.from(parent.getContext()).flate(R.layout.item\u text\u视图,parent,false);
//设置视图的大小、边距、填充和布局参数
CardViewHolder vh=新的CardViewHolder(v);
返回vh;
}
@凌驾
BindViewHolder上的公共无效(CardViewHolder,内部位置){
//从位置处的数据集获取元素
//用该元素替换视图的内容
字符串标题、项目代码、项目状态、项目日期;
title=itemCode=itemDate=itemStatus=“”;
试一试{
JSONObject item=newjsonobject(mDataSet.get(position.toString());
title=item.getString(“desc”);
itemCode=item.getString(“代码”);
itemDate=item.getString(“日期”);
itemStatus=item.getString(“状态”);
}捕获(JSONException e){
e、 printStackTrace();
}
holder.itemTitle.setText(标题);
holder.itemCode.setText(itemCode);
holder.itemDate.setText(itemDate);
holder.itemStatus.setText(Html.fromHtml(itemStatus));
holder.optionsButton.setOnClickListener(新视图.OnClickListener(){
@凌驾
公共void onClick(视图){
Toast.makeText(mContext,title,Toast.LENGTH_LONG).show();
}
});
}
@凌驾
public int getItemCount(){
返回mDataSet.length();
}
//提供对每个数据项的视图的引用
//复杂数据项可能需要每个项有多个视图,并且
//您可以访问视图持有者中数据项的所有视图
公共静态类ViewHolder扩展了RecyclerView.ViewHolder{
//在本例中,每个数据项只是一个字符串
公共文本视图mTextView;
公共视图持有者(文本视图v){
超级(五);
mTextView=v;
}
}
}
我的问题和想法如下:

  • 如何在单击listener时传递此按钮以获取此项的值?例如,尝试从onClick处理程序中访问
    title
    是一个错误,因为它不是最终变量,而是从内部类中访问的。另一方面,如果我让DataAdapter类实现View.onClickListener接口,我仍然不确定如何从onClick方法中获取这些特定于项的值。

  • 这被认为是一种好的做法吗?(将应用程序上下文传递给我的DataAdapter)?我应该从另一个角度来攻击它吗


您可以轻松地使适配器实现查看.OnClickListener或实现自己的类,该类实现OnClickListener并具有可设置的文本参数

static class MyClick implements View.OnClickListener{

    String text
    /**
     * Called when a view has been clicked.
     *
     * @param v The view that was clicked.
     */
    @Override
    public void onClick (View v) {

    }
} 

 MyClick click = new MyClick();
 click.text = text;
 holder.button.setOnClickListener(click);
另外,为什么要传递ApplicationContext而不是activity context?适配器已“绑定”到活动

使您能够不向适配器传递上下文的更好的解决方案是使用侦听器,使您的片段/活动实现侦听器并运行onClick方法。例如:

@适配器:

public interface MyAdapterListener {
    public void onCLick(String text);
}
 private MyAdapterListener mListener;
 ...

 void onClick(){
     mListener.onCLick(text)
 }

我不需要对实现接口的活动进行某种引用吗
mListener.onClick(文本)抛出NullPointerException..当实例化适配器时,将侦听器分配给实现者,通常是活动或片段。这是Androides的常规设计模式,但这正是我的问题。如果我使用另一个类来保存文本字符串,则它无权访问活动侦听器。如果我让适配器本身实现View.OnClickListener,我不知道如何传递字符串:/当然有了,只要把电话线传过去就行了别担心,如果你需要更多的帮助,请告诉我,现在我要睡觉了(: