1

这几天在学习开源项目SwipeMenuListView的简单使用,之所以说是“几天”,是因为在导入项目到Android-studio的过程中出现了各种各样的问题,我是直接打开的它里面的Demo,但是会出现各种错误,似乎并不是一个完整的Project,发现没有app目录。在网上看各种教程,也大都是要你把它的类库直接复制一份到自己的项目中去,但是既然Android-studio支持直接使用依赖,为什么那么多人还是那么麻烦的去复制文件到自己的项目中呢?

答案就是:作者并没有把最新的依赖添加进去,但是网上却几乎没有几个人指出来,这才导致自己反复在这里折腾(毕竟这是个下载量很大的开源项目啊,为什么都没几个人指出来呢?)作者提供的Demo里使用了一个BaseSwipListAdapter,代码如下:

class AppAdapter extends BaseSwipListAdapter {...}

如果我们直接也这样写的话,会报错,告诉我们该类找不到,那些添加了依赖的同学可以在jar包中打开看下,看看里面是不是真的缺少了BaseSwipListAdapter 这个类(使用依赖的话里面有很多bug,删除一条项目只有在我们将Menu拉回来的时候才会真正删除掉)
下面来讲下具体怎么导入并且使用SwipeMenuListView:

1.导入SwipeMenuListView

我们可以从github上下载开源项目SwipeMenuListView的源码
https://github.com/baoyongzha...

在此也附上它的依赖,不过在此处并不会用到:

dependencies {
    compile 'com.baoyz.swipemenulistview:library:1.3.0'
}

这里我们在项目中新建一个包,名字为:

com.baoyz.swipemenulistview

(这里我们包的名字最好不要改变,否则里面一些导入的类也要改变路径),然后将目录

SwipeMenuListView-master\library\src\main\java\com\baoyz\swipemenulistview\

下面的文件复制到我们新建的包里面:

clipboard.png

clipboard.png

(这里为了方便直接运行,我们直接将Demo里的文件、资源等也逐一的复制到了我们的目录项目中,但是记得要在清单文件中为activity进行配置)

2.SwipeMenuListView的具体使用

这里我们先粘贴下Demo中的示例(部分地方有修改),SimpleActivity.java

package com.qc.administrator.myswipedemo;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.baoyz.swipemenulistview.BaseSwipListAdapter;
import com.baoyz.swipemenulistview.SwipeMenu;
import com.baoyz.swipemenulistview.SwipeMenuCreator;
import com.baoyz.swipemenulistview.SwipeMenuItem;
import com.baoyz.swipemenulistview.SwipeMenuListView;

import java.util.List;

/**
 * SwipeMenuListView
 * Created by baoyz on 15/6/29.
 */
public class SimpleActivity extends Activity {

    private List<ApplicationInfo> mAppList;
    private AppAdapter mAdapter;
    private SwipeMenuListView mListView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list);

        mAppList = getPackageManager().getInstalledApplications(0);

        mListView = (SwipeMenuListView) findViewById(R.id.listView);

        mAdapter = new AppAdapter();
        mListView.setAdapter(mAdapter);

        // 第1步:设置创建器,并且在其中生成我们需要的菜单项,将其添加进菜单中
        SwipeMenuCreator creator = new SwipeMenuCreator() {

            @Override
            public void create(SwipeMenu menu) {
                // 创建“打开”项
                SwipeMenuItem openItem = new SwipeMenuItem(
                        getApplicationContext());
                openItem.setBackground(new ColorDrawable(Color.rgb(0xC9, 0xC9,
                        0xCE)));
                openItem.setWidth(dp2px(90));
                openItem.setTitle("Open");
                openItem.setTitleSize(18);
                openItem.setTitleColor(Color.WHITE);
                // 将创建的菜单项添加进菜单中
                menu.addMenuItem(openItem);

                // 创建“删除”项
                SwipeMenuItem deleteItem = new SwipeMenuItem(
                        getApplicationContext());
                deleteItem.setBackground(new ColorDrawable(Color.rgb(0xF9,
                        0x3F, 0x25)));
                deleteItem.setWidth(dp2px(90));
                deleteItem.setIcon(R.drawable.ic_delete);
                // 将创建的菜单项添加进菜单中
                menu.addMenuItem(deleteItem);
            }
        };
        // 为ListView设置创建器
        mListView.setMenuCreator(creator);

        // 第2步:为ListView设置菜单项点击监听器,来监听菜单项的点击事件
        mListView.setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(int position, SwipeMenu menu, int index) {
                //position:列表项的下标。如:0,1,2,3,4,...
                //index:菜单项的下标。如:0,1,2,3,4,...
                ApplicationInfo item = mAppList.get(position);
                switch (index) {
                    case 0:
                        // open
                        open(item);
                        break;
                    case 1:
                        // delete
//                    delete(item);
                        mAppList.remove(position);
                        //通知监听者数据集发生改变,更新ListView界面
                        mAdapter.notifyDataSetChanged();
                        break;
                }
                // true:其他已打开的列表项的菜单状态将保持原样,不会受到其他列表项的影响而自动收回
                // false:已打开的列表项的菜单将自动收回
                return false;
            }
        });

        // 设置侧滑监听器,监听侧滑开始和侧滑结束
        // 注意:当我们将一个已经侧滑出来的菜单重新收回去的时候并不会调用onSwipeStart方法,
        // 但是结束的时候依然会调用onSwipeEnd方法
        mListView.setOnSwipeListener(new SwipeMenuListView.OnSwipeListener() {

            @Override
            public void onSwipeStart(int position) {
                // swipe start
            }

            @Override
            public void onSwipeEnd(int position) {
                // swipe end
            }
        });

        // 设置监听Menu状态改变的监听器(Menu的打开和关闭)
        mListView.setOnMenuStateChangeListener(new SwipeMenuListView.OnMenuStateChangeListener() {
            @Override
            public void onMenuOpen(int position) {
            }

            @Override
            public void onMenuClose(int position) {
            }
        });

        // other setting
//        listView.setCloseInterpolator(new BounceInterpolator());

        // 设置列表项长点击的监听器
        mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {

            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view,
                                           int position, long id) {
                Toast.makeText(getApplicationContext(), position + " long click", Toast.LENGTH_SHORT).show();
                return false;
            }
        });

    }

    //删除一个应用,在这里并没有被调用,因为这会卸载相应的app
    private void delete(ApplicationInfo item) {
        try {
            Intent intent = new Intent(Intent.ACTION_DELETE);
            intent.setData(Uri.fromParts("package", item.packageName, null));
            startActivity(intent);
        } catch (Exception e) {
        }
    }

    // 打开app
    private void open(ApplicationInfo item) {
        // Intent.ACTION_MAIN:作为主进入点启动,并不期望获得数据
        Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
        resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        //根据传进来的ApplicationInfo item设置要解析的应用的包名
        resolveIntent.setPackage(item.packageName);
        //根据指定的Intent解析出对应的应用中所有的activity的信息
        List<ResolveInfo> resolveInfoList = getPackageManager()
                .queryIntentActivities(resolveIntent, 0);
        if (resolveInfoList != null && resolveInfoList.size() > 0) {
            //ResolveInfo:返回依据IntentFilter解析出来的Intent所返回的信息。
            //此部分对应于从AndroidManifest.xml中<意图>标签收集信息。
            //解析出来的第一个为主activity的信息
            ResolveInfo resolveInfo = resolveInfoList.get(0);
            String activityPackageName = resolveInfo.activityInfo.packageName;
            String className = resolveInfo.activityInfo.name;

            Intent intent = new Intent(Intent.ACTION_MAIN);
            intent.addCategory(Intent.CATEGORY_LAUNCHER);
            ComponentName componentName = new ComponentName(
                    activityPackageName, className);

            intent.setComponent(componentName);
            startActivity(intent);
        }
    }

    class AppAdapter extends BaseSwipListAdapter {

        @Override
        public int getCount() {
            return mAppList.size();
        }

        @Override
        public ApplicationInfo getItem(int position) {
            return mAppList.get(position);
        }

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                //夹在金列表项的布局item_list_app.xml
                convertView = View.inflate(getApplicationContext(),
                        R.layout.item_list_app, null);
                new ViewHolder(convertView);
            }
            ViewHolder holder = (ViewHolder) convertView.getTag();
            // 获取手机全部应用的信息
            ApplicationInfo item = getItem(position);
            // 加载应用的图标
            holder.iv_icon.setImageDrawable(item.loadIcon(getPackageManager()));
            // 加载应用的标题
            holder.tv_name.setText(item.loadLabel(getPackageManager()));
            // 为图标设置点击事件监听器(弹出一个toast)
            holder.iv_icon.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(SimpleActivity.this, "iv_icon_click", Toast.LENGTH_SHORT).show();
                }
            });
            // 为应用名字设置点击监听器(弹出一个toast)
            holder.tv_name.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(SimpleActivity.this,"iv_icon_click",Toast.LENGTH_SHORT).show();
                }
            });
            return convertView;
        }

        class ViewHolder {
            ImageView iv_icon;
            TextView tv_name;

            //根据传进来的convertView创建ViewHolder,并且将其设置为convertView的Tag
            public ViewHolder(View view) {
                iv_icon = (ImageView) view.findViewById(R.id.iv_icon);
                tv_name = (TextView) view.findViewById(R.id.tv_name);
                view.setTag(this);
            }
        }

        //这里我们可以根据列表项的位置来设置某项是否允许侧滑
        //(此处我们设置的是当下标为偶数项的时候不允许侧滑)
        @Override
        public boolean getSwipEnableByPosition(int position) {
            if(position % 2 == 0){
                return false;
            }
            return true;
        }
    }

    // 将dp转换为px
    private int dp2px(int value) {
        // 第一个参数为我们待转的数据的单位,此处为 dp(dip)
        // 第二个参数为我们待转的数据的值的大小
        // 第三个参数为此次转换使用的显示量度(Metrics),它提供屏幕显示密度(density)和缩放信息
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value,
                getResources().getDisplayMetrics());
    }
    //另一种将dp转换为px的方法
    private int dp2px(float value){
        final float scale = getResources().getDisplayMetrics().density;
        return (int)(value*scale + 0.5f);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        if (id == R.id.action_left) {
            //这里我们可以通过mListView的setSwipeDirection方法来设置SwipeMenuListView的滑动方向
            mListView.setSwipeDirection(SwipeMenuListView.DIRECTION_LEFT);
            return true;
        }
        if (id == R.id.action_right) {
            mListView.setSwipeDirection(SwipeMenuListView.DIRECTION_RIGHT);
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

具体步骤:

1.添加布局代码

在我们需要使用该效果的布局文件中添加如下代码:

<com.baoyz.swipemenulistview.SwipeMenuListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

2.生成一个菜单创建器

生成一个菜单创建器,在其中生成菜单项,并且将其添加进菜单中,此处的菜单为我们侧滑具体的列表项之后显示出来的视图,如下图:

clipboard.png

代码:

SwipeMenuCreator creator = new SwipeMenuCreator() {

            @Override
            public void create(SwipeMenu menu) {
                // 创建“打开”项
                SwipeMenuItem openItem = new SwipeMenuItem(
                        getApplicationContext());
                openItem.setBackground(new ColorDrawable(Color.rgb(0xC9, 0xC9,
                        0xCE)));
                openItem.setWidth(dp2px(90));
                openItem.setTitle("Open");
                openItem.setTitleSize(18);
                openItem.setTitleColor(Color.WHITE);
                // 将创建的菜单项添加进菜单中
                menu.addMenuItem(openItem);

                // 创建“删除”项
                SwipeMenuItem deleteItem = new SwipeMenuItem(
                        getApplicationContext());
                deleteItem.setBackground(new ColorDrawable(Color.rgb(0xF9,
                        0x3F, 0x25)));
                deleteItem.setWidth(dp2px(90));
                deleteItem.setIcon(R.drawable.ic_delete);
                // 将创建的菜单项添加进菜单中
                menu.addMenuItem(deleteItem);
            }
        };

然后为列表设置创建器:

mListView.setMenuCreator(creator);

3.为ListView设置菜单项点击监听器,监听菜单项的点击事件

mListView.setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() {
            //position:列表项的下标。如:0,1,2,3,4,...
            //index:菜单项的下标。如:0,1,2,3,4,...
            @Override
            public boolean onMenuItemClick(int position, SwipeMenu menu, int index) {//具体实现}

4.设置侧滑监听器(如果有需要的话)

设置侧滑监听器,监听侧滑开始和侧滑结束。
注意:当我们将一个已经侧滑出来的菜单重新收回去的时候并不会调用onSwipeStart方法,但是结束的时候依然会调用onSwipeEnd方法

 mListView.setOnSwipeListener(new SwipeMenuListView.OnSwipeListener() {

            @Override
            public void onSwipeStart(int position) {
                // swipe start
            }

            @Override
            public void onSwipeEnd(int position) {
                // swipe end
            }
        });

5.设置监听Menu状态改变的监听器(Menu的打开和关闭)

  mListView.setOnMenuStateChangeListener(new SwipeMenuListView.OnMenuStateChangeListener() {
            @Override
            public void onMenuOpen(int position) {
            }

            @Override
            public void onMenuClose(int position) {
            }
        });

6.为我们的ListView设置适配器

我们的适配器可以继承自BasseAdapter,也可以继承自该开源项目提供的一个适配器类BaseSwipListAdapter,并重写其中的方法

7.设置具体的某个列表项是否允许侧滑

 

   @Override
    public boolean getSwipEnableByPosition(int position) {
        if(position % 2 == 0){
            return false;
        }
        return true;
    }

这里作者设置的是当为偶数项的时候不允许侧滑(返回值为false)

8.dp转px方法

  // 将dp转换为px
    private int dp2px(int value) {
        // 第一个参数为我们待转的数据的单位,此处为 dp(dip)
        // 第二个参数为我们待转的数据的值的大小
        // 第三个参数为此次转换使用的显示量度(Metrics),它提供屏幕显示密度(density)和缩放信息
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value,
                getResources().getDisplayMetrics());
    }
    //另一种将dp转换为px的方法
    private int dp2px(float value){
        final float scale = getResources().getDisplayMetrics().density;
        return (int)(value*scale + 0.5f);
    }

9.设置侧滑的方向(也决定了Menu的出现位置)

//设置向左滑动出现Menu
mListView.setSwipeDirection(SwipeMenuListView.DIRECTION_LEFT);
//设置向右滑动出现Menu
mListView.setSwipeDirection(SwipeMenuListView.DIRECTION_RIGHT);

10.设置列表项显示不同的Menu

其实我们可以让列表项显示不同的Menu,我们可以通过重写BaseAdapter的getItemViewType(int position)和 getViewTypeCount()方法,然后在菜单创建器SwipeMenuCreator中根据传进去的SwipeMenu的getViewType()的值来决定生成怎样的Menu

文章最后附上原作者Demo中DifferentMenuActivity.java的代码供参考:

/**
 * SwipeMenuListView
 * Created by baoyz on 15/6/29.
 */
public class DifferentMenuActivity  extends Activity {

    private List<ApplicationInfo> mAppList;
    private AppAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list);

        mAppList = getPackageManager().getInstalledApplications(0);

        SwipeMenuListView listView = (SwipeMenuListView) findViewById(R.id.listView);
        mAdapter = new AppAdapter();
        listView.setAdapter(mAdapter);

        // step 1. create a MenuCreator
        SwipeMenuCreator creator = new SwipeMenuCreator() {

            @Override
            public void create(SwipeMenu menu) {
                // Create different menus depending on the view type
                switch (menu.getViewType()) {
                    case 0:
                        createMenu1(menu);
                        break;
                    case 1:
                        createMenu2(menu);
                        break;
                    case 2:
                        createMenu3(menu);
                        break;
                }
            }

            private void createMenu1(SwipeMenu menu) {
                SwipeMenuItem item1 = new SwipeMenuItem(
                        getApplicationContext());
                item1.setBackground(new ColorDrawable(Color.rgb(0xE5, 0x18,
                        0x5E)));
                item1.setWidth(dp2px(90));
                item1.setIcon(R.drawable.ic_action_favorite);
                menu.addMenuItem(item1);
                SwipeMenuItem item2 = new SwipeMenuItem(
                        getApplicationContext());
                item2.setBackground(new ColorDrawable(Color.rgb(0xC9, 0xC9,
                        0xCE)));
                item2.setWidth(dp2px(90));
                item2.setIcon(R.drawable.ic_action_good);
                menu.addMenuItem(item2);
            }

            private void createMenu2(SwipeMenu menu) {
                SwipeMenuItem item1 = new SwipeMenuItem(
                        getApplicationContext());
                item1.setBackground(new ColorDrawable(Color.rgb(0xE5, 0xE0,
                        0x3F)));
                item1.setWidth(dp2px(90));
                item1.setIcon(R.drawable.ic_action_important);
                menu.addMenuItem(item1);
                SwipeMenuItem item2 = new SwipeMenuItem(
                        getApplicationContext());
                item2.setBackground(new ColorDrawable(Color.rgb(0xF9,
                        0x3F, 0x25)));
                item2.setWidth(dp2px(90));
                item2.setIcon(R.drawable.ic_action_discard);
                menu.addMenuItem(item2);
            }

            private void createMenu3(SwipeMenu menu) {
                SwipeMenuItem item1 = new SwipeMenuItem(
                        getApplicationContext());
                item1.setBackground(new ColorDrawable(Color.rgb(0x30, 0xB1,
                        0xF5)));
                item1.setWidth(dp2px(90));
                item1.setIcon(R.drawable.ic_action_about);
                menu.addMenuItem(item1);
                SwipeMenuItem item2 = new SwipeMenuItem(
                        getApplicationContext());
                item2.setBackground(new ColorDrawable(Color.rgb(0xC9, 0xC9,
                        0xCE)));
                item2.setWidth(dp2px(90));
                item2.setIcon(R.drawable.ic_action_share);
                menu.addMenuItem(item2);
            }
        };
        // set creator
        listView.setMenuCreator(creator);

        // step 2. listener item click event
        listView.setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(int position, SwipeMenu menu, int index) {
                ApplicationInfo item = mAppList.get(position);
                switch (index) {
                    case 0:
                        // open
                        break;
                    case 1:
                        // delete
//                    delete(item);
                        mAppList.remove(position);
                        mAdapter.notifyDataSetChanged();
                        break;
                }
                return false;
            }
        });

    }

    class AppAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            return mAppList.size();
        }

        @Override
        public ApplicationInfo getItem(int position) {
            return mAppList.get(position);
        }

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

        @Override
        public int getViewTypeCount() {
            // menu type count
            return 3;
        }

        @Override
        public int getItemViewType(int position) {
            // current menu type
            return position % 3;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = View.inflate(getApplicationContext(),
                        R.layout.item_list_app, null);
                new ViewHolder(convertView);
            }
            ViewHolder holder = (ViewHolder) convertView.getTag();
            ApplicationInfo item = getItem(position);
            holder.iv_icon.setImageDrawable(item.loadIcon(getPackageManager()));
            holder.tv_name.setText(item.loadLabel(getPackageManager()));
            return convertView;
        }

        class ViewHolder {
            ImageView iv_icon;
            TextView tv_name;

            public ViewHolder(View view) {
                iv_icon = (ImageView) view.findViewById(R.id.iv_icon);
                tv_name = (TextView) view.findViewById(R.id.tv_name);
                view.setTag(this);
            }
        }
    }

    private int dp2px(int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                getResources().getDisplayMetrics());
    }
}

warmcheng
153 声望14 粉丝