• Android 结合实际项目学会ListView局部刷新和相关知识《一》


    转载本专栏博客,请注明出处:道龙的博客

    最近在公司参与的项目中有一个界面需要做局部UI更新处理,把其化烦为简为Demoi形式写在这里。我们还是运行该Demo,知道ListView局部刷新的使用场景:(受时间限制,本篇就介绍这么多功能,下一篇会在这个Demo中加入更多的功能)


    可以看到,点击每个Item的时候,ListView上的CheckBox会选中或取消选中。这里面用到知识点就是ListView的局部刷新,局部的意思就是脱离ListView,在每个Item位置进行更新UI操作。那么就从头一步步的学习如何实现这个功能:

    一、实现基本功能。

    模拟数据源,把最基本的功能先跑起来:

    布局、自定义样式、自定义选择器都很简单,过多的代码就不再写了,文章只贴出业务逻辑重要的代码(文章最后会给出源代码可自行下载;由于实习公司使用的IDE还是Eclipse,本篇是基于eclipse写的)

    主活动中代码也很常规简单:

    public class MainActivity extends Activity {
    
        private ListView mListView;
        List<ItemBean> mDatas = new ArrayList<ItemBean>();
    	private MyAdapter adapter;
    
    
    	@Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mListView = (ListView) findViewById(R.id.listview);
            initData();
            adapter = new MyAdapter();
            mListView.setAdapter(adapter);
        }
    
    	/**模拟数据*/
        private void initData() {
        	ItemBean mItemBean = null;
        	for (int i = 0; i < 40; i++) {
        		//集合添加20个对象
        		mItemBean = new ItemBean();
        		mItemBean.setText("学习ListView局部刷新"+i);
        		mItemBean.setResIcon(R.drawable.directory_icon);
        		mDatas.add(mItemBean);
    		}
    	}
        
        private class MyAdapter extends BaseAdapter{
    
    		@Override
    		public int getCount() {
    			if(mDatas != null){
    				return mDatas.size();
    			}
    			return 0;
    		}
    
    		@Override
    		public Object getItem(int position) {
    			if(mDatas != null){
    				return mDatas.get(position);
    			}
    			return null;
    		}
    
    		@Override
    		public long getItemId(int position) {
    			return position;
    		}
    
    		@Override
    		public View getView(int position, View convertView, ViewGroup parent) {
    			ViewHolder holder = null;
    			if(convertView == null){
    				holder = new ViewHolder();
    				convertView = View.inflate(getApplicationContext(), R.layout.file_item, null);
    				holder.ivIcon = (ImageView) convertView.findViewById(R.id.iv_icon);
    				holder.tvText = (TextView) convertView.findViewById(R.id.tv_name);
    				holder.ivOption = (ImageView) convertView.findViewById(R.id.iv_option);
    				convertView.setTag(holder);
    			}else{
    				holder = (ViewHolder) convertView.getTag();
    			}
    			
    			//拿到数据
    			ItemBean mItem = (ItemBean) getItem(position);
    			//设置数据
    			holder.ivIcon.setImageResource(mItem.getResIcon());
    			holder.tvText.setText(mItem.getText());
    			return convertView;
    		}
    		
    		class ViewHolder{
    			ImageView ivIcon;
    			TextView tvText;
    			ImageView ivOption;
    		}
        	
        }
    }
    
    此时运行程序:


    接下来就对上边的常规代码做一下修饰了:

    二、进入编辑模式

    我们长按item的时候,希望整个布局改变一下进入编辑模式,让复选框图标展示,对应位置上ImageView图标消失,就可以这么写。

    首先写一个方法,来控制布局的改变:

    private boolean isEdit;
        /**开始编辑模式*/
    	private void startEditMode() {
    		isEdit = true;//标志位置为true
    		//进入编辑模式,要改变IListView的界面
    		adapter.notifyDataSetChanged();
    	}
    	
    	/**结束编辑模式*/
    	private void stopEditMode(){
    		isEdit = false;
    	}

    然后加入长按item的点击事件:

            mListView.setOnItemLongClickListener(new OnItemLongClickListener() {
    
    			@Override
    			public boolean onItemLongClick(AdapterView<?> parent, View view,
    					int position, long id) {
    				startEditMode();
    				return true;//返回true后,mListView.setOnItemClickListener就不会再去调用
    			}
    		});

    三、ListView中CheckBox选中取消,实现局部的刷新

    定义一个item局部刷新的方法:

    /**定义一个item局部刷新的方法*/
    		public void updateItemView(View ItemView){
    			CheckBox itemCb = (CheckBox) ItemView.findViewById(R.id.cb_checkbox);
    			if(itemCb.isChecked()){
    				//点击item,从选中状态调到未选中状态
    				itemCb.setChecked(false);
    			}else{
    				itemCb.setChecked(true);
    			}
    		}

    在item的点击事件的时候,调用这个方法,即可完成checkbox的选中与取消:

    mListView.setOnItemClickListener(new OnItemClickListener() {
    
    			@Override
    			public void onItemClick(AdapterView<?> parent, View view,
    					int position, long id) {
    				if(isEdit){
    					//如果是编辑模式
    					adapter.updateItemView(view);
    				}else{
    					//不是编辑模式,点击item做其他逻辑处理
    					Toast.makeText(getApplicationContext(), "当前item"+position, 0).show();
    				}
    			}
    		});
    目前我们仅仅是实现了界面的刷新,但是cb的选中与取消要记录起来,点击了哪个item也要记录起来,这样才能做接下来的操作,选中cb执行什么样的任务,因此我们需要使用javabean,记录每次点击选中cb的操作:

    具体的局部刷新修改后的方法如下:

    /**定义一个item局部刷新的方法*///position,为了拿到当前item的对象,记录状态
    		public void updateItemView(View ItemView,int position){
    			position = position - mListView.getHeaderViewsCount();
    			ItemBean itemBean = mDatas.get(position);
    			CheckBox itemCb = (CheckBox) ItemView.findViewById(R.id.cb_checkbox);
    			if(itemCb.isChecked()){
    				//点击item,从选中状态调到未选中状态
    				itemCb.setChecked(false);
    				//记录当前item未选中状态
    				itemBean.setChecked(false);
    			}else{
    				itemCb.setChecked(true);
    				//记录当前item选中状态
    				itemBean.setChecked(true);
    			}
    			
    			//通过集合把选中的item的对象itemBean记录起来
    			List<ItemBean> selectDatas = new ArrayList<ItemBean>();
    			for (ItemBean info : mDatas) {
    				if(info.isChecked()){//当前的item是选中的
    					selectDatas.add(info);
    				}
    			}
    			
    			/**测试局部刷新*/
    			for (ItemBean itemBean2 : selectDatas) {
    				System.out.println(itemBean2.getText());
    			}
    		}
    然后该方法肯定要被调用咯,在哪里调用?点击item的时候嘛,那就在注册item的点击事件稍作修改就可以了:

    mListView.setOnItemClickListener(new OnItemClickListener() {
    
    			@Override
    			public void onItemClick(AdapterView<?> parent, View view,
    					int position, long id) {
    				if(isEdit){
    					//如果是编辑模式
    					adapter.updateItemView(view,position);
    				}else{
    					//不是编辑模式,点击item做其他逻辑处理
    					Toast.makeText(getApplicationContext(), "当前item"+position, 0).show();
    				}
    			}
    		});

    但是这个时候还是有许多问题的,比如第二页的数据会复用第一页的数据,那就先解决这个bug。

    只需要在getView里面,对item上边的cb重新复制就可以了。

                                  if(isEdit){//是编辑模式
    				// Ui层面进入编辑模式
    				holder.checkBox.setVisibility(View.VISIBLE);
    				holder.ivOption.setVisibility(View.GONE);
    				
    				/**解决复用问题,对每一个item上的cb都重新赋值*/
    				if (mItem.isChecked()) {
    					holder.checkBox.setChecked(true);
    				} else {
    					holder.checkBox.setChecked(false);
    				}
    				
    			}else{
    				holder.checkBox.setVisibility(View.GONE);
    				holder.ivOption.setVisibility(View.VISIBLE);
    			}

    四、根据是否编辑状态,修改顶部标题栏文本信息

    接下来的逻辑稍微复杂,就是通过当前状态,来修改顶端的标题栏状态。

    首先,长按进入编辑模式的时候,要显示当前选中多少个。需要一个标志位mSelectedCount。进入编辑模式,显示标题:

    //修改标题栏
    		mTextView.setText(String.format("已选择了%d个", mSelectedCount));

    那对于标志的增加减少要放到,updateItemView里面

    if(itemCb.isChecked()){
    				//点击item,从选中状态调到未选中状态
    				itemCb.setChecked(false);
    				//记录当前item未选中状态
    				itemBean.setChecked(false);
    				
    				mSelectedCount --;
    			}else{
    				itemCb.setChecked(true);
    				//记录当前item选中状态
    				itemBean.setChecked(true);
    				
    				mSelectedCount ++;
    			}
    由于逻辑稍微复杂,也不是要介绍局部刷新这个技术点的范围了,就不再继续往下写了。我把Demo全部代码,打包上传了。可以直接去下载,学习。看看一下后边的复杂逻辑是如何实现的:

    明天或者后天加入更多功能后,再把资源上传吧,今天就到这里了~

    源码下载地址




  • 相关阅读:
    替换Srun3000解决掉网问题
    了解Equals所发生的事情
    WPF自定义TextBox及ScrollViewer
    自制多类编码转换工具
    .NET4.5之自制多LRC转SRT小工具
    JAVA_list总结
    记一次线程Timer导致的线程安全问题修正
    JAVA_匿名内部类
    JAVA_map总结
    JAVA_闭包
  • 原文地址:https://www.cnblogs.com/wanghang/p/6299492.html
Copyright © 2020-2023  润新知