Android个人学习笔记之ListView知识应用-仿IOS百度云条目点击显示菜单模块实现

前言:因为业务的需要,需要实现IOS百度云里面的列表条目点击下部出现菜单的功能,这一次就来记录一下这个实现的具体过程吧,同时也将详细的讲一下ListView的使用方法,如果你正在需要这种Demo或者是初学者,那好好的看看这篇文章,你一定会有系统的认识的(不百分之百保证会—_—)。

1、前期准备

和之前一样,在开始之前我们需要先了解一下大概的思路,毕竟知己知彼百战不殆。
废话少说先看一下百度云里面的具体效果是什么,不过这个功能大部分的软件也都有,所以这也是为什么要自己动手做一下的原因。

                             图1

                            图2
在Android的百度云中菜单打开方式与IOS不同,此次实现的是仿照IOS版本的百度云。在开始之前先介绍一个图标网站,之前我也在其他文章中介绍过了,本次的操作图标全部来自于该网站- 点击进入

2、开发思路

本次实现是在listview的基础上进行的,listview是有不同的条目也即是item,通过点击出现菜单,可见每一个item都应该有一个菜单,初始状态时,菜单处于隐藏状态,当点击按钮图标时显示点击按钮图标的item,实现对应item显示菜单的效果。

思路比较简单,主要还是看listview的使用是否熟练,同时还要自定义adapter来满足我们的需求,该模块的实现也算是对listview的一次加深认识,初学者也可以通过该部分实现认识listview的实现方法和实现的思路。

对于其他的跟listview类似的列如:PullToRefresh ListView(下拉刷新),实现方法类似。

3、ListView实现

第一步:每个人的习惯都不同,我们首先来建立xml布局文件,如下:
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main"
    android:layout_width="match_parent" android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.listviewmenuontouch.MainActivity">
    <TextView
        android:id="@+id/tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="仿IOS百度云条目点击显示菜单"
        android:gravity="center"
        />
    <ListView
        android:id="@+id/listView"
        android:paddingTop="10dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</RelativeLayout>



该部分只写了布局显示效果如下(由于没有绑定adapter数据,listview没有显示):


第二步:编写MainActivity.java,给listview加入数据
public class MainActivity extends AppCompatActivity {

    //布局文件中存在的textview和listview声明
    private TextView tv;
    private ListView listView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //调用布局初始化
        initUI();
    }

    //布局赋值初始化
    public void initUI(){
        //从布局文件中获得控件
        tv = (TextView) findViewById(R.id.tv);
        listView = (ListView) findViewById(R.id.listView);
        //设置显示在listview上的字符集合
        String[] array = {"第一个item","第二个item","第三个item","第四个item",
                "第五个item","第六个item"};
        //采用简单的adapter进行数据写入,android.R.layout.simple_list_item_1为Android提供的单一项布局文件
        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1,array);
        //为listview设置adapter
        listView.setAdapter(arrayAdapter);
    }
}
如下图显示效果,此时为简单的条目显示效果:



4、自定义adapter的ListView实现

上一节主要使用ArrayAdapter来实现ListView的数据绑定,实际在百度云里的界面可以看出,并没有像我们展示的那样简单,要想做出像百度云这样的条目,简单的使用Android给我们提供的布局文件是达不到的,所以我们就需要自定义布局文件来实现该效果。

在使用自定义adapter之前先介绍一下Simpleadaper的使用,使用Simpleadapter和自定义的布局文件我们就可以做出百度云类似的条目了,下面先看一下我们的自定义ListView的布局文件list_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    >
    <ImageView
        android:id="@+id/item_image"
        android:layout_width="46dp"
        android:layout_height="46dp"
        android:layout_marginLeft="10dp"
        android:src="@drawable/file"
        />
    <TextView
        android:id="@+id/item_tv_main"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="项目文件"
        android:textSize="20sp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="2dp"
        android:layout_toRightOf="@id/item_image"
        />
    <TextView
        android:id="@+id/item_tv_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="2016-12-07 15:00"
        android:textSize="15sp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="2dp"
        android:layout_toRightOf="@id/item_image"
        android:layout_below="@id/item_tv_main"
        />
    <ImageView
        android:id="@+id/item_open"
        android:layout_width="25dp"
        android:layout_height="25dp"
        android:layout_marginRight="20dp"
        android:layout_centerVertical="true"
        android:src="@drawable/zhankai"
        android:layout_alignParentRight="true"
        />

</RelativeLayout>

item的具体xml布局,由文件可以看到有两个image和两个文本文件,我大致按照图片进行调整,在Androidstudio中的显示效果如下图:


item的布局文件写好后就需要进行MainActivity的编写了,如下采用了simpleadapter适配器,使用自定义布局:

public class MainActivity extends AppCompatActivity {

    //布局文件中存在的textview和listview声明
    private TextView tv;
    private ListView listView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //调用布局初始化
        initUI();
    }

    //布局赋值初始化
    public void initUI(){
        //从布局文件中获得控件
        tv = (TextView) findViewById(R.id.tv);
        listView = (ListView) findViewById(R.id.listView);
       //注意该适配器的构造函数的参数,第一个为context,第二个为一个list<Map<String,Object>>,第三个为自定义的item布局文件,第四个为一个String数组        //声明每一个item的控件名称,与map中的对应,第五个为控件布局id,也即是一个int的数组,是对应的自定义布局中的控件的id,与第四个参数要一一对应
        SimpleAdapter adapter = new SimpleAdapter(this,getData(),
                R.layout.list_item,
                new String[]{"item_image","item_tv_main","item_tv_time"},
                new int[]{R.id.item_image,R.id.item_tv_main,R.id.item_tv_time}
                );
        listView.setAdapter(adapter);
    }

    private List<Map<String,Object>> getData(){

        List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("item_image",R.drawable.file);
        map.put("item_tv_main","文件一");
        map.put("item_tv_time","2016-12-07 15:00");
        list.add(map);

        map = new HashMap<String,Object>();
        map.put("item_image",R.drawable.file);
        map.put("item_tv_main","文件二");
        map.put("item_tv_time","2016-12-07 15:10");
        list.add(map);

        map = new HashMap<String,Object>();
        map.put("item_image",R.drawable.file);
        map.put("item_tv_main","文件三");
        map.put("item_tv_time","2016-12-07 15:20");
        list.add(map);

        map = new HashMap<String,Object>();
        map.put("item_image",R.drawable.file);
        map.put("item_tv_main","文件四");
        map.put("item_tv_time","2016-12-07 15:30");
        list.add(map);

        map = new HashMap<String,Object>();
        map.put("item_image",R.drawable.file);
        map.put("item_tv_main","文件五");
        map.put("item_tv_time","2016-12-07 15:40");
        list.add(map);

        map = new HashMap<String,Object>();
        map.put("item_image",R.drawable.file);
        map.put("item_tv_main","文件六");
        map.put("item_tv_time","2016-12-07 15:50");
        list.add(map);

        return list;
    }
}


自定义布局文件做了微调,下面是实际的效果图:


接下来就要开始自定义的adapter进行实现,最终的实现效果是点击右侧的ImageView图标,然后在该列显示出一列菜单出来,之前思路也显示我们需要对布局文件做一下改动,将菜单文件添加进来,然后设置为不可见,之后再在自定义的adapter编写点击的响应事件,完成最终功能的实现。

首先看一下改过的布局和实际显示效果(为了直观显示,此时没有把菜单设置为不可见):

list_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:paddingBottom="5dp"
    android:paddingTop="5dp"
    android:gravity="center"
    >
    <RelativeLayout
        android:id="@+id/item_show"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <ImageView
            android:id="@+id/item_image"
            android:layout_width="46dp"
            android:layout_height="46dp"
            android:layout_marginLeft="10dp"
            android:src="@drawable/file"
            />
        <TextView
            android:id="@+id/item_tv_main"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="项目文件"
            android:textSize="20sp"
            android:textColor="#000"
            android:layout_marginLeft="16dp"
            android:layout_marginTop="2dp"
            android:layout_toRightOf="@id/item_image"
            />
        <TextView
            android:id="@+id/item_tv_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="2016-12-07 15:00"
            android:textSize="15sp"
            android:layout_marginLeft="16dp"
            android:layout_marginTop="2dp"
            android:layout_toRightOf="@id/item_image"
            android:layout_below="@id/item_tv_main"
            />
        <ImageView
            android:id="@+id/item_open"
            android:layout_width="25dp"
            android:layout_height="25dp"
            android:layout_marginRight="20dp"
            android:layout_centerVertical="true"
            android:src="@drawable/zhankai"
            android:layout_alignParentRight="true"
            />
    </RelativeLayout>

    <LinearLayout
        android:id="@+id/item_hide"
        android:layout_below="@id/item_show"
        android:layout_width="match_parent"
        android:background="#D6D6D6"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        >
    <TextView
        android:id="@+id/item_hide_1"
        android:layout_width="26dp"
        android:layout_height="wrap_content"
        android:text="下载"
        android:gravity="center"
        android:layout_weight="1"
        android:drawableTop="@drawable/xz"
        />
    <TextView
        android:id="@+id/item_hide_2"
        android:layout_width="26dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="分享"
        android:gravity="center"
        android:drawableTop="@drawable/fx"
        />
    <TextView
        android:id="@+id/item_hide_3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="删除"
        android:gravity="center"
        android:drawableTop="@drawable/sc"
        />
    </LinearLayout>

</RelativeLayout>


这个时候看确实有点丑,,,,,,

接下来编写自定义的adapter:

public class MyAdapter extends SimpleAdapter implements View.OnClickListener{

    private Context context;
    private Map<String, Object> map;
    private int resource;
    private String[] from;
    private int[] to;
    private ViewHolder viewHolder;

    private int currentItem = -1; //用于记录点击的 Item 的 position,是控制 item 展开的核心

    public MyAdapter(Context context, List<? extends Map<String, ?>> data,
                     int resource, String[] from, int[] to) {
        super(context, data, resource, from, to);
        this.resource = resource;
        this.from = from;
        this.to = to;
        this.context = context;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        //获得单个item的map
        map = (Map<String, Object>)getItem(position);
        View view = convertView;
        //获取到每个控件对应的布局中的控件
        if(view == null){
            view = LayoutInflater.from(context).inflate(resource, null);
            viewHolder = new ViewHolder();
            viewHolder.item_image = (ImageView)view.findViewById(R.id.item_image);
            viewHolder.item_tv_main = (TextView)view.findViewById(R.id.item_tv_main);
            viewHolder.item_tv_time = (TextView)view.findViewById(R.id.item_tv_time);
            viewHolder.item_open = (ImageView)view.findViewById(R.id.item_open);
            viewHolder.item_hide = (LinearLayout)view.findViewById(R.id.item_hide);
            //设置点击监听
            viewHolder.item_open.setOnClickListener(this);
            //将隐藏的部分隐藏起来
            viewHolder.item_hide.setVisibility(View.GONE);
            view.setTag(viewHolder);
        }else
            viewHolder = (ViewHolder) view.getTag();
        //根据设置的数据设置数据
        viewHolder.item_image.setImageResource((int)map.get(from[0]));
        viewHolder.item_tv_main.setText((String)map.get(from[1]));
        viewHolder.item_tv_time.setText((String)map.get(from[2]));
        //设置点击展开菜单控件为未选择状态,选择状态图标会改变,编写背景xml文件即可实现
        viewHolder.item_open.setSelected(false);

        //根据 currentItem 记录的点击位置来设置"对应Item"的可见性(在list依次加载列表数据时,每加载一个时都看一下是不是需改变可见性的那一条)
        if (currentItem == position) {
            viewHolder.item_open.setSelected(true);
            viewHolder.item_hide.setVisibility(View.VISIBLE);
        } else {
            viewHolder.item_open.setSelected(false);
            viewHolder.item_hide.setVisibility(View.GONE);
        }
        viewHolder.item_open.setTag(position);
        viewHolder.item_open.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //用 currentItem 记录点击位置
                int tag = (Integer) view.getTag();
                if (tag == currentItem) { //再次点击
                    currentItem = -1; //给 currentItem 一个无效值
                } else {
                    currentItem = tag;
                }
                //通知adapter数据改变需要重新加载
                notifyDataSetChanged(); //必须有的一步
            }
        });

        return view;
    }

    @Override
    public void onClick(View view) {
        //此处可将隐藏部分的控件设置监听,来响应不同的操作,通过setTag设置的position可以得到哪一个item点击
    }

    /**
     * item控件列表
     */
    static class ViewHolder{
        ImageView item_image;
        TextView item_tv_main;
        TextView item_tv_time;
        ImageView item_open;
        LinearLayout item_hide;

    }

}
整个调用过程与simpleadapter一样,因为自定义的adapter是继承了它的,所以MainActivity调用adapter如下:

MyAdapter adapter = new MyAdapter(this,getData(),
                R.layout.list_item,
                new String[]{"item_image","item_tv_main","item_tv_time"},
                new int[]{R.id.item_image,R.id.item_tv_main,R.id.item_tv_time}
                );
        listView.setAdapter(adapter);
只需将该部分修改即可,这也就完成整个demo,看图:



5、一些注意事项

按钮的点击通过setselected的值得改变来改变图片的显示,将点击图片的src改为xml文件,文件如下:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/bihe"
        android:state_selected="true"
        />
    <!--暂时背景图片没有变化-->
    <item android:drawable="@drawable/zhankai"/>
</selector>

6、下载


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值