热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

AndroidListView中子控件的状态保存以及点击子控件改变子控件状态

这两天用到了ListView,写下遇到的一些问题。首先是ListView本身与子控件的焦点问题,比如我这里子控件用到了Button,在需要ListView中的根布局属性上加上下面的这一个属性:and

这两天用到了ListView,写下遇到的一些问题。首先是ListView本身与子控件的焦点问题,比如我这里子控件用到了Button,在需要ListView中的根布局属性上加上下面的这一个属性:

 android:descendantFocusability="blocksDescendants"
用于屏蔽子控件抢夺ListView的焦点,也可在Button本身设置焦点属性为false。其它的一些控件的点击问题就不说了,网上有很多。

然后是需要点击Button进行网络操作,返回正确结果后设置Button的test为"XXX",我这里不需要设置其它控件状态改变了,处理方法除了下面我的方法外,也可以用selector。此外还需要保存每个item的position位置用来保存Button的状态(应该这么说:记录此Item(position)上Button的状态,因为是在getView方法里去判断Button状态来设置的,所以叫记录比较好吧),这个问题需要细心的处理,不然就会出现只点击第一个Button后,后面position的Button也被设置成了“XXX”,还有Button的设置的setClickable也会有问题。


好吧,不说了,下面是写的代码, 代码里我应该写的挺清楚的了。这里只是ListView的布局,还有Adapter的代码。要用的话自己在一个Activity的布局里加上个ListView控件,再在代码里设置listview的adapter就可以用了。



ListView的布局



android:layout_
android:layout_
android:descendantFocusability="blocksDescendants"
android:orientation="horizontal" >

android:layout_
android:layout_
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical" >

android:id="@+id/txt_pre_entry_class"
android:layout_
android:layout_
android:singleLine="true"
android:text="test" />


android:layout_
android:layout_
android:layout_weight="2"
android:gravity="center"
android:orientation="vertical" >

android:id="@+id/txt_pre_entry_teacher"
android:layout_
android:layout_
android:singleLine="true"
android:text="Txt1" />

android:id="@+id/txt_pre_entry_course"
android:layout_
android:layout_
android:singleLine="true"
android:text="Txt2" />

android:id="@+id/txt_pre_entry_class_name"
android:layout_
android:layout_
android:singleLine="true"
android:text="Txt3" />


android:layout_
android:layout_
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical" >

android:id="@+id/btn_pre_entry_order"
android:layout_
android:layout_
android:singleLine="true"
android:background="@drawable/button_rounded"
android:text="未预约"
/>





ListView的Adapter

public class PreEntryAdapter extends BaseAdapter
{
    private LayoutInflater inflater;
    private Context context;
    private Dialog orderDialog;
    private String summitUrl;
    private Handler orderHandler;
    private viewHolder holder;
    OrderAsyncTask orderAsyncTask;
    List listSize, listList;
    TextView txtClass, teacherName, className, courseName;
    //当前的位置,这个很重要,Button的状态记录就靠它了
    private int currentPosition = 0;
    //这个Button用于在重网络返回数据后设置其显示的内容,如成功、失败等。
    private Button currentBtn;
    //这个数组参数是记录每个position上的Button的请求是否成功
    private boolean[] ORDER_SUCCESS;
    //这是我用来填充假数据的
    private String[] classes;


    /**
     * 这里后面两个参数是我要填充的数据,子控件的显示内容就由listList得到
     */
    public PreEntryAdapter(Context context, List listSize, List listList)
    {
        this.cOntext= context;
        this.listSize = listSize;
        this.listList = listList;
        ORDER_SUCCESS = new boolean[30];// int[listSize.get(0).get(0)];
        classes = new String[30];
        for (int i = 0; i <30; i++)
        {
            classes[i] = "教2-" + i;
        }
        initView();
    }


    private void initView()
    {
        inflater = LayoutInflater.from(context);
        orderDialog = new Dialog(context);
        View view = inflater.inflate(R.layout.dialog_evaluate_order_preentry, null);
        orderDialog.setContentView(view);
        orderDialog.setCancelable(false);
        orderDialog.setTitle("提交");
    }


    @Override
    public int getCount()
    {
        //这里先设有30条Item数据
        return 30;// listSize.get(0).get(0);
    }


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


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


    @Override
    public View getView(final int position, View convertView, ViewGroup parent)
    {
        Log.v("log", "--->getView()-" + position);
        if (cOnvertView== null)
        {
            holder = new viewHolder();
            cOnvertView= inflater.inflate(R.layout.adapter_preentry, null);


            holder.btn_order = (Button) convertView.findViewById(R.id.btn_pre_entry_order);
            holder.txt_class = (TextView) convertView.findViewById(R.id.txt_pre_entry_class);
            holder.txt_class_name = (TextView) convertView.findViewById(R.id.txt_pre_entry_class_name);
            holder.txt_course = (TextView) convertView.findViewById(R.id.txt_pre_entry_course);
            holder.txt_teacher = (TextView) convertView.findViewById(R.id.txt_pre_entry_teacher);


            convertView.setTag(holder);
        }
        else
        {
            holder = (viewHolder) convertView.getTag();
        }
        Log.v("log", "-->getView()--ORDER_SUCCESS[" + position + "]-" + ORDER_SUCCESS[position]);
        // 判断保存的position位置上的Butoon是否已预约成功
        if (ORDER_SUCCESS[position])
        {
            holder.btn_order.setText("已预约");
            // 这里不设的话返回来时还会可点击,因为向下拉时,Holder里的btn被设置成可点击了
            // holder.btn_order.setEnabled(false);
            holder.btn_order.setClickable(false);
        }
        else
        {
            // 这里要写上默认的显示内容,要不然后面的子控件会出现显示已预订的情况。因为不设置的话btn还是Holder中的btn,而此时holder中的btn是已经设置了已预约的
            holder.btn_order.setText("未预约");
            // 要设置为可点击,不然是Holder里的状态
            // holder.btn_order.setEnabled(true);
            holder.btn_order.setClickable(true);
            // 这个也要放这里判断
            holder.btn_order.setOnClickListener(new btnListener(position, holder.btn_order));
        }
        // 课室假数据
        holder.txt_class.setText(classes[position]);
        /*
         * holder.txt_class.setText((CharSequence)
         * listList.get(position).get(4)); //
         * holder.txt_class_name.setText(listList.get(position).get()); //
         * holder.txt_course.setText((CharSequence)
         * listList.get(position).get(2)); //
         * holder.txt_teacher.setText((CharSequence)
         * listList.get(position).get(3));
         */


        return convertView;
    }


    /**
     * 要传入当前点击的Button,用于设置currentBtn为当前点击的Button,这样点击后的setText就不会错位了。
     */
    class btnListener implements OnClickListener
    {
        private int position;
        private Button Btn;


        public btnListener(int position, Button currentBtn)
        {
            this.position = position;
            this.Btn = currentBtn;
        }


        @Override
        public void onClick(View v)
        {
            currentPosition = position;
            currentBtn = Btn;
            Toast.makeText(context, "点击第 " + (position + 1) + "个Button", 0).show();
            orderAsyncTask = new OrderAsyncTask();
            orderAsyncTask.execute("");
            orderDialog.show();
        }


    }


    private static class viewHolder
    {
        private Button btn_order;
        private Button btn_temp;
        private TextView txt_class, txt_teacher, txt_course, txt_class_name;


    }


    /**
     * 异步AsyncTask
     */
    private class OrderAsyncTask extends AsyncTask
    {


        @Override
        protected void onPreExecute()
        {
            super.onPreExecute();
        }


        // 异步处理
        @Override
        protected Integer doInBackground(String... nullNow)
        {
            Log.v("log", "-->doInBackground()--params-" + nullNow[0]);
            try
            {
                Thread.sleep(2500);
                return SubmitHandler.submitOrder((String) listList.get(currentPosition).get(0), (String) listList
                                                 .get(currentPosition).get(1), (String) listList.get(currentPosition).get(5),
                                                 Edu_Survey_OrderInfo.ORDER_WEEK);


            }
            catch (Exception e)
            {
                e.printStackTrace();
                Log.v("log", "-->doInBackground() ERROR!");
            }
            return 0;
        }


        @Override
        protected void onProgressUpdate(Integer... values)
        {
            super.onProgressUpdate(values);
        }


        @Override
        protected void onPostExecute(Integer responseCode)
        {
            Log.v("log", "-->responseCode-" + responseCode);
            //先假设已经请求成功了
            respOnseCode= 200;
            switch (responseCode)
            {
            case 200:
                ORDER_SUCCESS[currentPosition] = true;
                currentBtn.setText("已预约");
                // 这里不设的话在当前页面下currentBtn一直可点击,因为getView里设的话是要调用getView时才能起作用的。
                // currentBtn.setEnabled(false);
                currentBtn.setClickable(false);
                break;
            case 404:
                break;
            default:
                break;
            }


            Log.v("log", "-->onPostExecute()--currentPosition-" + currentPosition);
            Log.v("log", "-->onPostExecute()--ORDER_SUCCESS[" + currentPosition + "]-"
                  + ORDER_SUCCESS[currentPosition]);
            orderDialog.dismiss();
            super.onPostExecute(responseCode);
        }


    }


}



效果图:




补充:

Button可以设置tag来唯一标记它,之后就可以通过listview.findViewWithTag(tag)找到了。不需要上面这么麻烦。




推荐阅读
author-avatar
骑猪猪-逛恋空
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有