这几天在学习开源项目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\
下面的文件复制到我们新建的包里面:
(这里为了方便直接运行,我们直接将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.生成一个菜单创建器
生成一个菜单创建器,在其中生成菜单项,并且将其添加进菜单中,此处的菜单为我们侧滑具体的列表项之后显示出来的视图,如下图:
代码:
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());
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。