• 开源项目MultiChoiceAdapter详解(六)——GridView和MultiChoiceBaseAdapter配合使用


    这篇其实没啥重要的,主要就算是个总结吧。

    一、布局文件

    这里实现的是类似于上图的多图选择的效果。关键在于item布局文件的写法。这也就是这个框架奇葩的一点,莫名其妙的要在一个自定义控件里面再放一个自定义的控件,如果不这样就出不了选中的效果。分析下原因是这里整个item被图片所覆盖了,仅仅设置一个有选择效果的父控件会被图片所覆盖,所以还得用一个可以选中的imageview进行替换imageview。

    下面就是这个布局文件

    item_gridview.xml

    <?xml version="1.0" encoding="utf-8"?>
    <com.manuelpeinado.multichoiceadapter.view.CheckableLinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" 
        android:background="@drawable/custom_list_item_background">
    
        <com.manuelpeinado.multichoiceadapter.view.CheckableImageView 
            android:id="@+id/item_imageView"
            android:layout_width="match_parent"
            android:layout_height="250dp"
            android:scaleType="centerCrop" />
    
    </com.manuelpeinado.multichoiceadapter.view.CheckableLinearLayout>

    通过查看文档,我们可以知道这里的CheckableImageView 可以设置一个android:foreground属性来显示被选中的状态。类似于:

        <com.manuelpeinado.multichoiceadapter.view.CheckableImageView 
            android:id="@+id/item_imageView"
            android:layout_width="match_parent"
            android:layout_height="250dp"
            android:scaleType="centerCrop" 
            android:foreground="@drawable/custom_list_item_background"/>

    但这样就需要设置下选中状态的透明度,否则会完全遮挡住选中的图片内容了。

    原文:https://github.com/ManuelPeinado/MultiChoiceAdapter/wiki/Gallery-tutorial

    We cannot use an ImageView because the root of the item's layout must implement the Checkable interface. Luckily, the library includes a version of ImageView that does just that. An interesting thing about this class is that it doesn't use the android:background for its selector, since that would be obscured by the image. Instead, it draws the selector over the image, just like a ListView does in the drawSelectorOnTop mode. By default this selector is a semitransparent blue with opaque borders, as you can see in the screenshot above. You can customize it quite easily by defining your own selector in XML (don't forget the checked state) and assigning it to the android:foregroundattribute of your CheckableImageView element.

    另一个布局文件:

    gridview_layout.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    
        <GridView
            android:id="@+id/gridLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#CCC"
            android:horizontalSpacing="2dp"
            android:numColumns="2"
            android:stretchMode="columnWidth"
            android:gravity="center"  
            android:verticalSpacing="2dp" 
            />
    
    </LinearLayout>

    二、改变actionMode标题文字的方法

    在继承MultiChoiceBaseAdapter后可以实现getActionModeTitle()这个方法来设置自定义标题。这个方法名略让人迷茫,总之看源码就是每次item选中状态改变的时候会到这里来要一个String对象,用于设置标题。就和适配器中的getViewImpl()返回view差不多。

    /**
    * 系统在item选中状态被改变的时候会调用getActionModeTitle()来得到要显示的标题字样
    * 这里得到被选中的items数目,可以用来改变actionmode上的标题字样。
    * 下面想返回字符串就是标题了
    */
    @Override
    public String getActionModeTitle(int selected) {
    return String.format("自定义标题:%d / %d", selected, getCount());
    }

    三、继承MultiChoiceBaseAdapter

        private class MultiBaseAdapter extends MultiChoiceBaseAdapter{
    
            private List<Integer> mData;
            
            /**
             * 构造函数
             * @param savedInstanceState
             */
            public MultiBaseAdapter(Bundle savedInstanceState,List<Integer> data) {
                super(savedInstanceState);
                // TODO 自动生成的构造函数存根
                mData = data;
            }
    
            /**
             * 创建ActionMode对象,必须返回true!!!
             */
            @Override
            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                 MenuInflater inflater = mode.getMenuInflater();
                 inflater.inflate(R.menu.my_action_mode, menu);
                return true;
            }
            
            /**
             * item点击时处理的事件,从ActionMode.callback中继承过来的
             */
            @Override
            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                if (item.getItemId() == R.id.menu_share) {
                    Toast.makeText(getContext(), "分享了" + getCheckedItemCount() + "item", Toast.LENGTH_SHORT).show();
                    return true;
                }
                if (item.getItemId() == R.id.menu_discard) {
                    //TODO:删除选中的元素
                    return true;
                }
                return false;
            }
            
            
    
            @Override
            public boolean onPrepareActionMode(ActionMode arg0, Menu arg1) {
                // TODO 自动生成的方法存根
                return false;
            }
            
            /**
             * 系统在item选中状态被改变的时候会调用getActionModeTitle()来得到要显示的标题字样
             * 这里得到被选中的items数目,可以用来改变actionmode上的标题字样。
             * 下面想返回字符串就是标题了
             */
            @Override
            public String getActionModeTitle(int selected) {
                return String.format("自定义标题:%d / %d", selected, getCount());
            }
    
            /**
             * 看适配器中有多少元素需要加载
             */
            @Override
            public int getCount() {
                // TODO 自动生成的方法存根
                return mData.size();
            }
    
            /**
             * 通过position来得到相应的item,这里返回object对象
             */
            @Override
            public Object getItem(int position) {
                // TODO 自动生成的方法存根
                return mData.get(position);
            }
    
            /**
             * 通过position得到id
             */
            @Override
            public long getItemId(int position) {
                // TODO 自动生成的方法存根
                return position;
            }
    
            /**
             * 返回item的view对象
             */
            @Override
            protected View getViewImpl(int position, View convertView, ViewGroup parent) {
                if (convertView == null) {
                    int layout = R.layout.item_gridview;
                    LayoutInflater inflater = LayoutInflater.from(getContext());
                    convertView = inflater.inflate(layout, parent, false);
                }
                ViewGroup group = (ViewGroup)convertView;
                ((ImageView)group.findViewById(R.id.item_imageView)).setImageResource((mData.get(position)));
                return group;
            }
            
        }

    四、配置适配器

    如果不想要显示actionMode,只需要用adapter.showActionMode(false);来屏蔽掉它。这就是我扩展的比较好的一点,既不改变原来的使用方法,又可以自由扩展。

        MultiBaseAdapter adapter;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            // TODO 自动生成的方法存根
            super.onCreate(savedInstanceState);
            setContentView(R.layout.gridview_layout);
            
            Integer[] pics = {R.drawable.aig,R.drawable.bank_of_america,R.drawable.chrysler,
                    R.drawable.empire_state,R.drawable.nyt,R.drawable.one_wtc};
    
            List<Integer> items = new ArrayList<>(Arrays.asList(pics));
            
            GridView gridView = (GridView)findViewById(R.id.gridLayout);
            
            adapter = new MultiBaseAdapter(savedInstanceState, items);
            adapter.setAdapterView(gridView);
            //adapter.showActionMode(false);//开启后变成普通模式,就不需要实现actionmode了
            adapter.setOnSelectedStateChangeListener(new OnSelectedStateChangeListener() {
                
                @Override
                public void onSelectedStateChanged(int checkedItemCount) {
                    // TODO 自动生成的方法存根
                    Toast.makeText(getApplicationContext(), "选中了"+checkedItemCount+"个", 0).show();
                }
            });
            
        }

    全部搞定~~~

    全部代码:

    package com.kale.multichoiceadaptertest;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    import android.os.Bundle;
    import android.support.v7.app.ActionBarActivity;
    import android.support.v7.view.ActionMode;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.MenuInflater;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.GridView;
    import android.widget.ImageView;
    import android.widget.Toast;
    
    import com.manuelpeinado.multichoiceadapter.base.OnSelectedStateChangeListener;
    import com.manuelpeinado.multichoiceadapter.compat.MultiChoiceBaseAdapter;
    
    
    public class GridViewTestActvity extends ActionBarActivity{
    
        MultiBaseAdapter adapter;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            // TODO 自动生成的方法存根
            super.onCreate(savedInstanceState);
            setContentView(R.layout.gridview_layout);
            
            Integer[] pics = {R.drawable.aig,R.drawable.bank_of_america,R.drawable.chrysler,
                    R.drawable.empire_state,R.drawable.nyt,R.drawable.one_wtc};
    
            List<Integer> items = new ArrayList<>(Arrays.asList(pics));
            
            GridView gridView = (GridView)findViewById(R.id.gridLayout);
            
            adapter = new MultiBaseAdapter(savedInstanceState, items);
            adapter.setAdapterView(gridView);
            //adapter.showActionMode(false);//开启后变成普通模式,就不需要实现actionmode了
            adapter.setOnSelectedStateChangeListener(new OnSelectedStateChangeListener() {
                
                @Override
                public void onSelectedStateChanged(int checkedItemCount) {
                    // TODO 自动生成的方法存根
                    Toast.makeText(getApplicationContext(), "选中了"+checkedItemCount+"个", 0).show();
                }
            });
            
        }
        
        @Override
        protected void onSaveInstanceState(Bundle outState) {
            adapter.save(outState);
        }
        
        private class MultiBaseAdapter extends MultiChoiceBaseAdapter{
    
            private List<Integer> mData;
            
            /**
             * 构造函数
             * @param savedInstanceState
             */
            public MultiBaseAdapter(Bundle savedInstanceState,List<Integer> data) {
                super(savedInstanceState);
                // TODO 自动生成的构造函数存根
                mData = data;
            }
    
            /**
             * 创建ActionMode对象,必须返回true!!!
             */
            @Override
            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                 MenuInflater inflater = mode.getMenuInflater();
                 inflater.inflate(R.menu.my_action_mode, menu);
                return true;
            }
            
            /**
             * item点击时处理的事件,从ActionMode.callback中继承过来的
             */
            @Override
            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                if (item.getItemId() == R.id.menu_share) {
                    Toast.makeText(getContext(), "分享了" + getCheckedItemCount() + "item", Toast.LENGTH_SHORT).show();
                    return true;
                }
                if (item.getItemId() == R.id.menu_discard) {
                    //TODO:删除选中的元素
                    return true;
                }
                return false;
            }
            
            
    
            @Override
            public boolean onPrepareActionMode(ActionMode arg0, Menu arg1) {
                // TODO 自动生成的方法存根
                return false;
            }
            
            /**
             * 系统在item选中状态被改变的时候会调用getActionModeTitle()来得到要显示的标题字样
             * 这里得到被选中的items数目,可以用来改变actionmode上的标题字样。
             * 下面想返回字符串就是标题了
             */
            @Override
            public String getActionModeTitle(int selected) {
                return String.format("自定义标题:%d / %d", selected, getCount());
            }
    
            /**
             * 看适配器中有多少元素需要加载
             */
            @Override
            public int getCount() {
                // TODO 自动生成的方法存根
                return mData.size();
            }
    
            /**
             * 通过position来得到相应的item,这里返回object对象
             */
            @Override
            public Object getItem(int position) {
                // TODO 自动生成的方法存根
                return mData.get(position);
            }
    
            /**
             * 通过position得到id
             */
            @Override
            public long getItemId(int position) {
                // TODO 自动生成的方法存根
                return position;
            }
    
            /**
             * 返回item的view对象
             */
            @Override
            protected View getViewImpl(int position, View convertView, ViewGroup parent) {
                if (convertView == null) {
                    int layout = R.layout.item_gridview;
                    LayoutInflater inflater = LayoutInflater.from(getContext());
                    convertView = inflater.inflate(layout, parent, false);
                }
                ViewGroup group = (ViewGroup)convertView;
                ((ImageView)group.findViewById(R.id.item_imageView)).setImageResource((mData.get(position)));
                return group;
            }
            
        }
    }

    源码下载:http://download.csdn.net/detail/shark0017/8065691

    开源项目MultiChoiceAdapter详解(一)——概要介绍

    开源项目MultiChoiceAdapter详解(二)——MultiChoiceArrayAdapter的使用

    开源项目MultiChoiceAdapter详解(三)——MulitChoiceNormalArrayAdapter的使用

    开源项目MultiChoiceAdapter详解(四)——MultiChoiceBaseAdapter的使用

    开源项目MultiChoiceAdapter详解(五)——可扩展的MultiChoiceBaseAdapter

    开源项目MultiChoiceAdapter详解(六)——GridView和MultiChoiceBaseAdapter配合使用

  • 相关阅读:
    js的发布订阅者模式
    js打开PC的应用程序
    用node创建自己的脚手架
    用Navicat生成数据字典的方法
    Windows 11 前端基本配置【20210127】
    【win11右键】关于解决Win11环境下 vscode 重装后,不在鼠标右键的快捷栏里面
    【win11右键】关于在win11环境让鼠标右键直接显示全部功能的设置
    小程序开发 各种Demo的记录博客
    Android开发 Paging3
    adb命令 shell工具类
  • 原文地址:https://www.cnblogs.com/tianzhijiexian/p/4041623.html
Copyright © 2020-2023  润新知