点击listview的item中的button让文字变化

1. 概述

在开发过程中,有时候会遇到这种需求,如下图所示:


图片.png

这个列表是一个listview,领券购买是这个item中的一个 button,要实现的需求是这样的:
点击领券购买,让文字变为已领券;
点击已领券,让文字恢复为领券购买;

2. 做法如下

错误做法:

自己刚开始做的时候,采用的方法是:点击领券购买的button时直接修改文字为已领券,当再次点击时让文字为恢复为领券购买时。这样做是有问题的,问题就是:如果数据较少,只有一屏的话是可以的,如果数据大于一屏,上下滑动时刚才点击的文字就又会变为领券购买,而且可能在第二屏幕或者其他屏幕数据也会变成已领券,造成数据错乱;

原因就是:由于listview的 convertView的复用机制造成的;

正确做法:

我们可以判断item中的 TextView被点击了、Button被点击了、还是item被点击了,但是却不能判断我们点击的是哪个 item中的 TextView或者Button,这里可以采用一种方式:就是在 MyAdapter中的 getView()方法中,通过 View 的setTag(int key , Object tag)方法给每个被点击的控件设置一个 tag标记,第一个参数必须是 该控件的id,这个可以在 res -> values 下边创建 ids.xml文件,然后把 点击 该控件的id 写到里边就可以;

3. 具体步骤

1>:让 MyAdapter 实现View.OnClickListener接口,然后重写 onClick方法;
2>:在 MyAdapter 中定义接口Callback,用于在MainActivity中回调 点击item中的 textView 和 button;
3>:在 res -> values 下边创建 ids.xml文件,然后把 点击 该控件的id 写到里边就可以;
4>:然后在 MyAdapter中的 getView()方法中:
    用 viewHolder.textView.setTag(R.id.tv,position)给 textView 设置tag标记;
    用 viewHolder.button.setTag(R.id.btn,position)给 Button 设置tag标记;
    然后给 textView和button设置点击事件;
5>:然后在 ListViewActivity中实现 MyAdapter 中定义接口Callback,然后重写click方法,在 这个方法中:
    调用view.getTag(R.id.tv) 获取textView,返回tv;
    调用view.getTag(R.id.btn) 获取button,返回 btn;
6>:然后 从data数据中 根据判断返回的 btn判断:
    如果当前文字是 领券购买,则修改文字为 已领券;
    如果当前文字是 已领券,则修改文字为 领券购买;
4. 代码如下

1>:ListViewActivity如下:
/**
 * Email: 2185134304@qq.com
 * Created by Novate 2018/8/13 15:25
 * Version 1.0
 * Params:
 * Description:
*/

public class ListViewActivity extends AppCompatActivity implements MyAdapter.Callback,AdapterView.OnItemClickListener{

    //ListView控件
    private ListView mList;
    //ListView数据源
    private List<AppBean> data;
    private MyAdapter adapter ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.listview_main);
        data = new ArrayList<AppBean>();
        mList = (ListView)findViewById(R.id.mList);

        for(int i = 0; i < 20; i ++){
            AppBean appBean = new AppBean();
            appBean.setAppName("斗鱼APP"+i);
            appBean.setDownloadStatus("安装");
            data.add(appBean);
        }
        adapter = new MyAdapter(data,this);
        mList.setAdapter(adapter);
        mList.setOnItemClickListener(this);
    }


    /**
     * MyAdapter中 点击item中的 TextView或者Button 接口定义的方法
     */
    @Override
    public void click(View view) {
        switch (view.getId()){
            case R.id.mTv:
                int tv = (int) view.getTag(R.id.tv);
                Toast.makeText(ListViewActivity.this,"我是文本"+tv,Toast.LENGTH_SHORT).show();
                break;
            case R.id.mBtn:
                int btn = (int) view.getTag(R.id.btn);
                Toast.makeText(ListViewActivity.this,"我是按钮"+btn,Toast.LENGTH_SHORT).show();
                if (data.get(btn).getDownloadStatus().equals("已安装")){
                    data.get(btn).setDownloadStatus("安装");
                }else if(data.get(btn).getDownloadStatus().equals("安装")){
                    data.get(btn).setDownloadStatus("已安装");
                }
                updateItem(btn);
                //adapter.notifyDataSetChanged();  //更新全部
                break;
        }
    }

    //listView局部更新
    private void updateItem(int position) {
        //屏幕中第一个可见的条目位置
        int firstVisiblePosition = mList.getFirstVisiblePosition();
        //屏幕中最后一个可见的条目位置
        int lastVisiblePosition = mList.getLastVisiblePosition();
        //在看见范围内才更新,不可见的滑动后自动会调用getView方法更新
        if (position >= firstVisiblePosition && position <= lastVisiblePosition) {
            //获取指定位置view对象
            View view = mList.getChildAt(position - firstVisiblePosition);
            adapter.getView(position, view, mList);
        }

    }

    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
        Toast.makeText(ListViewActivity.this,"我是条目"+i,Toast.LENGTH_SHORT).show();
    }
}
2>:MyAdapter如下:
/**
 * Created by Administrator on 2018/8/13.
 */

public class MyAdapter extends BaseAdapter implements View.OnClickListener {

    //上下文
    private Context context;
    //数据项
    private List<AppBean> data;
    private Callback mCallback;
    public MyAdapter(List<AppBean> data,Callback callback){
        this.data = data;
        mCallback = callback;
    }

    @Override
    public int getCount() {
        return data == null ? 0 : data.size();
    }

    @Override
    public Object getItem(int position) {
        return data.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }


    @Override
    public View getView(int position, View convertView, ViewGroup viewGroup) {
        System.out.println("position:"+position+"convertView:"+convertView);
        ViewHolder viewHolder = null;
        if(context == null) {
            context = viewGroup.getContext();
        }
        if(convertView == null){
            convertView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item_button,null);
            viewHolder = new ViewHolder();
            viewHolder.textView = (TextView)convertView.findViewById(R.id.mTv);
            viewHolder.button = (Button)convertView.findViewById(R.id.mBtn);
            //为convertView设置tag标志
            convertView.setTag(viewHolder);
        }

        //获取viewHolder实例
        viewHolder = (ViewHolder)convertView.getTag();

        //设置数据
        viewHolder.textView.setText(data.get(position).getAppName());
        viewHolder.button.setText(data.get(position).getDownloadStatus());

        //为viewHolder.mTv和viewHolder.mBtn设置tag标记
        viewHolder.textView.setTag(R.id.tv,position);
        viewHolder.button.setTag(R.id.btn,position);

        //设置监听事件
        viewHolder.textView.setOnClickListener(this);
        viewHolder.button.setOnClickListener(this);
        return convertView;
    }

    @Override
    public void onClick(View view) {
        mCallback.click(view);
    }

    static class ViewHolder{
        TextView textView;
        Button button;
    }

    public interface Callback {
        void click(View view);
    }
}
3>:AppBean如下:
/**
 * Created by Administrator on 2018/8/13.
 */

public class AppBean implements Serializable {

    private String appName ;
    private String downloadStatus ;

    public String getAppName() {
        return appName;
    }

    public void setAppName(String appName) {
        this.appName = appName;
    }

    public String getDownloadStatus() {
        return downloadStatus;
    }

    public void setDownloadStatus(String downloadStatus) {
        this.downloadStatus = downloadStatus;
    }
}
4>:res -> values下边创建 ids.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--
    我们如何判断我们点击的是哪个item中的TextView和Button呢,因为目前的点击事件
    只能判断是TextView点击了,还是Button,或者item被点击了,除了item能知道是哪
    一项被点击了,其他两个却不知道是在哪个item中被点击了,所以我们需要将代码进
    行在此修改。只需要在MyAdapter中修改代码即可。基本思路是,我们可以在每个被点
    击的控件中设置一个标记,通过View中的setTag(int key, Object tag)方法设置即可,
    第一个key必须是一个资源id
-->
    <item
        name="btn" type="id" >
    </item>

    <item
        name="tv" type="id">
    </item>
</resources>
5. 注意事项

在实际开发过程中上边的 领劵购买变为已领劵、立即抢购变为已抢购,这两个状态是由服务器控制的,不管上边的列表使用 lv还是rv 写的列表,自己需要做的就是:区分开点击的是领劵购买还是立即抢购,然后直接调用接口,接口调用成功后,服务器会给你判断好,比如:
点击领劵购买,服务器会把领劵购买状态变为已领劵状态;
点击立即抢购,服务器会把立即抢购状态变为已抢购状态;

然后自己还需要重新调用列表接口,用于刷新下状态就可以;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容