這幾天在學習開源項目SwipeMenuListView的簡單使用,之因此說是「幾天」,是由於在導入項目到Android-studio的過程當中出現了各類各樣的問題,我是直接打開的它裏面的Demo,可是會出現各類錯誤,彷佛並非一個完整的Project,發現沒有app目錄。在網上看各類教程,也大都是要你把它的類庫直接複製一份到本身的項目中去,可是既然Android-studio支持直接使用依賴,爲何那麼多人仍是那麼麻煩的去複製文件到本身的項目中呢?java
答案就是:做者並無把最新的依賴添加進去,可是網上卻幾乎沒有幾我的指出來,這才致使本身反覆在這裏折騰(畢竟這是個下載量很大的開源項目啊,爲何都沒幾我的指出來呢?)做者提供的Demo裏使用了一個BaseSwipListAdapter,代碼以下:android
class AppAdapter extends BaseSwipListAdapter {...}
若是咱們直接也這樣寫的話,會報錯,告訴咱們該類找不到,那些添加了依賴的同窗能夠在jar包中打開看下,看看裏面是否是真的缺乏了BaseSwipListAdapter 這個類(使用依賴的話裏面有不少bug,刪除一條項目只有在咱們將Menu拉回來的時候纔會真正刪除掉)
下面來說下具體怎麼導入而且使用SwipeMenuListView:git
咱們能夠從github上下載開源項目SwipeMenuListView的源碼
https://github.com/baoyongzha...github
在此也附上它的依賴,不過在此處並不會用到:app
dependencies { compile 'com.baoyz.swipemenulistview:library:1.3.0' }
這裏咱們在項目中新建一個包,名字爲:ide
com.baoyz.swipemenulistview
(這裏咱們包的名字最好不要改變,不然裏面一些導入的類也要改變路徑),而後將目錄佈局
SwipeMenuListView-master\library\src\main\java\com\baoyz\swipemenulistview\
下面的文件複製到咱們新建的包裏面:學習
(這裏爲了方便直接運行,咱們直接將Demo裏的文件、資源等也逐一的複製到了咱們的目錄項目中,可是記得要在清單文件中爲activity進行配置)this
這裏咱們先粘貼下Demo中的示例(部分地方有修改),SimpleActivity.javaspa
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); } }
具體步驟:
在咱們須要使用該效果的佈局文件中添加以下代碼:
<com.baoyz.swipemenulistview.SwipeMenuListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="match_parent" />
生成一個菜單建立器,在其中生成菜單項,而且將其添加進菜單中,此處的菜單爲咱們側滑具體的列表項以後顯示出來的視圖,以下圖:
代碼:
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);
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) {//具體實現}
設置側滑監聽器,監聽側滑開始和側滑結束。
注意:當咱們將一個已經側滑出來的菜單從新收回去的時候並不會調用onSwipeStart方法,可是結束的時候依然會調用onSwipeEnd方法
mListView.setOnSwipeListener(new SwipeMenuListView.OnSwipeListener() { @Override public void onSwipeStart(int position) { // swipe start } @Override public void onSwipeEnd(int position) { // swipe end } });
mListView.setOnMenuStateChangeListener(new SwipeMenuListView.OnMenuStateChangeListener() { @Override public void onMenuOpen(int position) { } @Override public void onMenuClose(int position) { } });
咱們的適配器能夠繼承自BasseAdapter,也能夠繼承自該開源項目提供的一個適配器類BaseSwipListAdapter,並重寫其中的方法
@Override public boolean getSwipEnableByPosition(int position) { if(position % 2 == 0){ return false; } return true; }
這裏做者設置的是當爲偶數項的時候不容許側滑(返回值爲false)
// 將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);
其實咱們可讓列表項顯示不一樣的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()); } }