SwipeListView实现QQ消息侧滑删除功能

看到别人实现SwipeListView,说的不清楚,好多细节要注意,作为菜鸟的我,也是拿来主义。

在 github有这个开源项目https://github.com/47deg/android-swipelistview

好了,我整理好了这些,也不必大家去github下载。点击此处下载必要源码。

空说无意,先看一下效果图。


one,先建立一个工程demo,

two,另外再建立一个包,取名为com.fortysevendeg.swipelistview

为什么取这个名,下面再讲

three,把我上传的文件中的四个Java文件复制到名为com.fortysevendeg.swipelistview的包中

会发现四个Java的顶部是package com.fortysevendeg.swipelistview;为了不必要的麻烦这样去步奏2的包名。

four,把我上传的文件中的swipelistview__attrs.xml复制到res/values文件夹在


其中要添加

xmlns:swipe="http://schemas.android.com/apk/res-auto" 

必需要添加,自定义的SwipeListView因为添加了,可定义属性要添加这一句

<com.fortysevendeg.swipelistview.SwipeListView
            xmlns:swipe="http://schemas.android.com/apk/res-auto"
            android:id="@+id/example_lv_list"
            android:listSelector="#00000000"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            swipe:swipeFrontView="@+id/front"
            swipe:swipeBackView="@+id/back"
            swipe:swipeActionLeft="[reveal | dismiss]"
            swipe:swipeActionRight="[reveal | dismiss]"
            swipe:swipeMode="[none | both | right | left]"
            swipe:swipeCloseAllItemsWhenMoveList="[true | false]"
            swipe:swipeOpenOnLongPress="[true | false]"
            swipe:swipeAnimationTime="[miliseconds]"
            swipe:swipeOffsetLeft="[dimension]"
            swipe:swipeOffsetRight="[dimension]"
            />
基本属性如下:

  • swipeFrontView - Required - front view id. 即ListView Item正常显示的控件Id,且必须与Item的布局文件中的控件id一样
  • swipeBackView - Required - back view id.  手指滑动时显示的,隐藏在FrontView后面,且必须与item的布局文件中控件Id一样
  • swipeActionLeft - Optional - left swipe action Default: 'reveal'  左滑的动作,默认reveal,即显示BackView,还有dismiss,choice会触发响应的方法。
  • swipeActionRight - Optional - right swipe action Default: 'reveal' 同上
  • swipeMode - Gestures to enable or 'none'. Default: 'both' 设置左滑、右滑、都支持
  • swipeCloseAllItemsWhenMoveList - Close revealed items on list motion. Default: 'true' 当滚动listview时,关闭所有展开的Item,最好不要设置为false,由于item的复用,false存在一些问题。
  • swipeOpenOnLongPress - Reveal on long press Default: 'true' 长按时触发显示
  • swipeAnimationTime - item drop animation time. Default: android configuration 动画时间长度
  • swipeOffsetLeft - left offset 左偏移量
  • swipeOffsetRight - right offset 右偏移量
下面是我的demo

activity_main.xml

记得加上这句:xmlns:swipe="http://schemas.android.com/apk/res-auto" 


<span style="font-size:14px;"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:swipe="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    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.demo.swipelistviewdemo.MainActivity" >

    <com.fortysevendeg.swipelistview.SwipeListView
        android:id="@+id/example_lv_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:listSelector="#00000000"
        swipeActionLeft="reveal"
        swipe:swipeAnimationTime="0"
        swipe:swipeBackView="@+id/back"
        swipe:swipeCloseAllItemsWhenMoveList="true"
        swipe:swipeFrontView="@+id/front"
        swipe:swipeMode="left"
        swipe:swipeOffsetLeft="0dp"
        swipe:swipeOffsetRight="0dp"
        swipe:swipeOpenOnLongPress="false"/>

</RelativeLayout></span>
要注意两个属性

swipe:swipeFrontView="@+id/front" 

 swipe:swipeBackView="@+id/back"

必须与Item的布局文件中的控件id一样

swipeActionLeft要最好swipeMode=“left”,属性要一致,否则,很容易有bug;


list_item.xml布局

注意前台布局,和隐藏布局的id要与swipe:swipeFrontView="@+id/front"swipe:swipeBackView="@+id/back"

一致。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    

    <!-- linearlayout中的布局是每一项后面隐藏的布局 -->

    <LinearLayout
        android:id="@+id/back"
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:background="#eee"
        android:tag="back" >

        <Button
            android:id="@+id/example_row_b_action_2"
            android:layout_width="0dp"
            android:layout_height="60dp"
            android:layout_gravity="center"
            android:layout_marginLeft="10dp"
            android:layout_weight="1"
            android:background="@android:color/holo_purple"
            android:text="删除" />

        <Button
            android:id="@+id/example_row_b_action_3"
            android:layout_width="0dp"
            android:layout_height="60dp"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:background="@android:color/holo_red_dark"
            android:text="编辑" />
    </LinearLayout>

    <!-- 这里是前台显示的布局 -->

    <RelativeLayout
        android:id="@+id/front"
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:background="#ffffff"
        android:orientation="vertical"
        android:tag="front" >

        <TextView
            android:id="@+id/example_row_tv_title"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:textSize="18sp" />
    </RelativeLayout>


</FrameLayout>

下面是Mainactivity.Java源码


package com.demo.swipelistviewdemo;

import java.util.ArrayList;
import java.util.List;

import com.fortysevendeg.swipelistview.BaseSwipeListViewListener;
import com.fortysevendeg.swipelistview.SwipeListView;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
	private SwipeListView mSwipeListView;
	private SwipeAdapter adapter;
	public static int deviceWidth ;
	private List<String> testData ;
	private int closeItem=0;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mSwipeListView=(SwipeListView)findViewById(R.id.example_lv_list);
		testData=getTestData();
		adapter=new SwipeAdapter();
		//拿到设备宽度
        deviceWidth = getResources().getDisplayMetrics().widthPixels;
        //数据适配
		mSwipeListView.setAdapter(adapter);
		reload();
		//设置监听事件
		mSwipeListView.setSwipeListViewListener(new testBaseSwipeListViewListener());
		
		
	}
	//设置SwipeListView的属性
	  private void reload() {
	        //滑动时向左偏移量,根据设备的大小来决定偏移量的大小
	        mSwipeListView.setOffsetLeft(deviceWidth * 1 / 3);
	        mSwipeListView.setOffsetRight(0);
	        //设置动画时间
	        mSwipeListView.setAnimationTime(30);
	        mSwipeListView.setSwipeOpenOnLongPress(false);
	    }
	//虚拟数据
	 private List<String> getTestData() {
	        String [] obj = new String[]{"红楼梦","西游记","水浒传","管锥编","宋诗选注","三国演义","android开发高级编程","红楼梦","西游记","水浒传","管锥编","宋诗选注","三国演义","android开发高级编程"};
	        List<String> list = new ArrayList<String>();
	        for (String string : obj) {
				list.add(string);
			}
	        return list;
	    }
	
	public class SwipeAdapter extends BaseAdapter{
		private LayoutInflater mInflater ;
		
		public SwipeAdapter(){
			mInflater=LayoutInflater.from(MainActivity.this);
		}
		
		@Override
		public int getCount() {
			// TODO Auto-generated method stub
			return testData.size();
		}

		@Override
		public Object getItem(int position) {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public long getItemId(int position) {
			// TODO Auto-generated method stub
			return 0;
		}

		@Override
		public View getView(final int position, View convertView, ViewGroup parent) {
			  ViewHolder holder = null ;
		        if(convertView == null){
		            convertView = mInflater.inflate(R.layout.list_item, parent, false);
		            holder = new ViewHolder();
		            holder.mFrontText = (TextView) convertView.findViewById(R.id.example_row_tv_title);
		            holder.mBackEdit = (Button) convertView.findViewById(R.id.example_row_b_action_3);
		            holder.mBackDelete = (Button) convertView.findViewById(R.id.example_row_b_action_2);
		            convertView.setTag(holder);
		        }else{
		            holder = (ViewHolder) convertView.getTag();
		        }
		        closeItem=position;
		        holder.mFrontText.setText(testData.get(position));
		        holder.mBackDelete.setOnClickListener(new OnClickListener() {
					
					@Override
					public void onClick(View v) {
						//关闭动画
						mSwipeListView.closeAnimate(position);
						//调用dismiss方法删除该项(这个方法在MainActivity中)
						mSwipeListView.dismiss(position);
						//可以在此删除testData
					}
				});
		        
		        
			return convertView;
		}
		
		private class ViewHolder{
			TextView mFrontText ;
			Button mBackEdit;
			Button mBackDelete ;
		}
	}
	//ListView的监听事件
	public class testBaseSwipeListViewListener extends BaseSwipeListViewListener{
		 //点击每一项的响应事件
		@Override
		public void onClickFrontView(int position) {
			// TODO Auto-generated method stub
			super.onClickFrontView(position);
			 Toast.makeText(getApplicationContext(), testData.get(position), 
					 Toast.LENGTH_SHORT).show();
			 mSwipeListView.closeOpenedItems();
			
		}
		//关闭事件
		@Override
		public void onDismiss(int[] reverseSortedPositions) {
			// TODO Auto-generated method stub
			super.onDismiss(reverseSortedPositions);
			  for (int position : reverseSortedPositions) {
	                Log.i("lenve", "position--:"+position);
	                testData.remove(position);
	            }
	            adapter.notifyDataSetChanged();
		}
		
		 @Override  
         public void onChoiceChanged(int position, boolean selected)  
         {  
             Log.d("msg", "onChoiceChanged:" + position + ", " + selected); 
				mSwipeListView.closeOpenedItems();
         }  

         @Override  
         public void onChoiceEnded()  
         {  
             Log.d("msg", "onChoiceEnded");  
         }  

         @Override  
         public void onChoiceStarted()  
         {  
             Log.d("msg", "onChoiceStarted"); 
             
         }  

         @Override  
         public void onClickBackView(int position)  
         {  
             Log.d("msg", "onClickBackView:" + position);  
         }  

       //滑动时调用已关闭
         @Override  
         public void onClosed(int position, boolean fromRight)  
         {  
             Log.d("msg", "onClosed:" + position + "," + fromRight);  
         }  


         @Override  
         public void onFirstListItem()  
         {  
             Log.d("msg", "onFirstListItem");  
         }  

         @Override  
         public void onLastListItem()  
         {  
             Log.d("msg", "onLastListItem");  
         }  
         //删除一个item会list会changed调用
         @Override  
         public void onListChanged()  
         {  
             Log.d("msg", "onListChanged");  

             mSwipeListView.closeOpenedItems();  

         }  
         //滑动时调用正在滑动
         @Override  
         public void onMove(int position, float x)  
         {  
             Log.d("msg", "onMove:" + position + "," + x);  
         }  
       //滑动时调用已展开
         @Override  
         public void onOpened(int position, boolean toRight)  
         {  
             Log.d("msg", "onOpened:" + position + "," + toRight);  
         }  
       //滑动时调用开始关闭
         @Override  
         public void onStartClose(int position, boolean right)  
         {  
             Log.d("msg", "onStartClose:" + position + "," + right);  
         }  
         //滑动时调用开始打开
         @Override  
         public void onStartOpen(int position, int action, boolean right)  
         {  
             Log.d("msg", "onStartOpen:" + position + "," + action + ","  
                     + right);  
             if (closeItem!=position) {
 				mSwipeListView.closeOpenedItems();
 				mSwipeListView.openAnimate(position);
 			}
             
         }  
	}
}

在监听事件中的这几个方法中关闭 mSwipeListView.closeOpenedItems();就可以实现QQ侧滑效果

  @Override  
         public void onStartOpen(int position, int action, boolean right)  
         {  
             Log.d("msg", "onStartOpen:" + position + "," + action + ","  
                     + right);  
             if (closeItem!=position) {
 				mSwipeListView.closeOpenedItems();
 				mSwipeListView.openAnimate(position);
 			}
             
         } 
@Override  
         public void onListChanged()  
         {  
             Log.d("msg", "onListChanged");  
             mSwipeListView.closeOpenedItems();  
         }  
@Override  
         public void onChoiceChanged(int position, boolean selected)  
         {  
             Log.d("msg", "onChoiceChanged:" + position + ", " + selected); 
<span style="white-space:pre">				</span>mSwipeListView.closeOpenedItems();
         }   

经过一些调试,勉强达到我的效果,demo源码下载


先来看activity_main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:swipe="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <com.fortysevendeg.swipelistview.SwipeListView android:id="@+id/example_lv_list" android:layout_width="match_parent" android:layout_height="match_parent" android:listSelector="#00000000" swipe:swipeActionLeft="dismiss" swipe:swipeActionRight="reveal" swipe:swipeAnimationTime="0" swipe:swipeBackView="@+id/back" swipe:swipeCloseAllItemsWhenMoveList="true" swipe:swipeFrontView="@+id/front" swipe:swipeMode="both" swipe:swipeOffsetLeft="0dp" swipe:swipeOffsetRight="0dp" swipe:swipeOpenOnLongPress="false" /> </RelativeLayout> 这里就一个swipelistview控件,我说几个不易理解的属性 表示滑动时的操作,dismiss表示滑动时删除,如果设置为reveal表示滑动时会显示出item后面的选项 swipe:swipeActionLeft=”dismiss” swipe:swipeActionRight=”reveal” 这个是背面布局的id(我们把直接看到的布局叫做前面的,滑动之后才能看到的布局叫做背面的),必须与背面布局id对应 swipe:swipeBackView=”@+id/back” 这个是滚动时候是否关闭背面的布局,true表示关闭,false表示不关闭,一般设置为true swipe:swipeCloseAllItemsWhenMoveList=”true” 这个是前面布局的id,要与布局的id对应 swipe:swipeFrontView=”@+id/front” both表示可以向左滑也可以向右滑,right和left分别表示只能向有或者向左滑动。 swipe:swipeMode=”both” 下面两个表示向左或者向右滑动时的偏移量,一般不在xml文件中设置,而是在代码中根据设置的大小来设置偏移量。 swipe:swipeOffsetLeft=”0dp” swipe:swipeOffsetRight=”0dp” 再来看看Item布局文件,这里包括前面的和后面的,两个重叠在一起: <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <!-- linearlayout中的布局是每一项后面隐藏的布局 --> <LinearLayout android:id="@+id/back" android:layout_width="match_parent" android:layout_height="80dp" android:background="#eee" android:tag="back" > <Button android:id="@+id/example_row_b_action_1" android:layout_width="0dp" android:layout_height="60dp" android:layout_gravity="center" android:layout_marginRight="10dp" android:layout_weight="1" android:text="测试" /> <Button android:id="@+id/example_row_b_action_2" android:layout_width="0dp" android:layout_height="60dp" android:layout_gravity="center" android:layout_marginLeft="10dp" android:layout_weight="1" android:text="删除" /> <Button android:id="@+id/example_row_b_action_3" android:layout_width="0dp" android:layout_height="60dp" android:layout_gravity="center" android:layout_weight="1" android:text="编辑" /> </LinearLayout> <!-- 这里是前台显示的布局 --> <RelativeLayout android:id="@+id/front" android:layout_width="match_parent" android:layout_height="80dp" android:background="#ffffff" android:orientation="vertical" android:tag="front" > <TextView android:id="@+id/example_row_tv_title" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textSize="18sp" /> </RelativeLayout> </FrameLayout> 这个布局是一个常规布局,我就不解释了。 MainActivity.Java,关键地方都有注释 public class MainActivity extends Activity { private SwipeListView mSwipeListView ; private SwipeAdapter mAdapter ; public static int deviceWidth ; private List<String> testData ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mSwipeListView = (SwipeListView) findViewById(R.id.example_lv_list); testData = getTestData(); //数据适配 mAdapter = new SwipeAdapter(this, R.layout.package_row, testData,mSwipeListView); //拿到设备宽度 deviceWidth = getDeviceWidth(); mSwipeListView.setAdapter(mAdapter); //设置事件监听 mSwipeListView.setSwipeListViewListener( new TestBaseSwipeListViewListener()); reload(); } private List<String> getTestData() { String [] obj = new String[]{"红楼梦","西游记","水浒传","管锥编","宋诗选注","三国演义","android开发高级编程","红楼梦","西游记","水浒传","管锥编","宋诗选注","三国演义","android开发高级编程"}; List<String> list = new ArrayList<String>(Arrays.asList(obj)); return list; } private int getDeviceWidth() { return getResources().getDisplayMetrics().widthPixels; } private void reload() { // mSwipeListView.setSwipeMode(SwipeListView.SWIPE_MODE_LEFT); // mSwipeListView.setSwipeActionLeft(SwipeListView.SWIPE_ACTION_REVEAL); // mSwipeListView.setSwipeActionRight(settings.getSwipeActionRight()); //滑动时向左偏移量,根据设备的大小来决定偏移量的大小 mSwipeListView.setOffsetLeft(deviceWidth * 1 / 3); mSwipeListView.setOffsetRight(deviceWidth * 1 / 3); // mSwipeListView.setOffsetRight(convertDpToPixel(settings.getSwipeOffsetRight())); //设置动画时间 mSwipeListView.setAnimationTime(30); mSwipeListView.setSwipeOpenOnLongPress(false); } class TestBaseSwipeListViewListener extends BaseSwipeListViewListener{ //点击每一项的响应事件 @Override public void onClickFrontView(int position) { super.onClickFrontView(position); Toast.makeText(getApplicationContext(), testData.get(position), Toast.LENGTH_SHORT).show(); } //关闭事件 @Override public void onDismiss(int[] reverseSortedPositions) { for (int position : reverseSortedPositions) { Log.i("lenve", "position--:"+position); testData.remove(position); } mAdapter.notifyDataSetChanged(); } } } 数据适配器: public class SwipeAdapter extends ArrayAdapter<String> { private LayoutInflater mInflater ; private List<String> objects ; private SwipeListView mSwipeListView ; public SwipeAdapter(Context context, int textViewResourceId,List<String> objects, SwipeListView mSwipeListView) { super(context, textViewResourceId, objects); this.objects = objects ; this.mSwipeListView = mSwipeListView ; mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public View getView(final int position, View convertView, ViewGroup parent) { ViewHolder holder = null ; if(convertView == null){ convertView = mInflater.inflate(R.layout.package_row, parent, false); holder = new ViewHolder(); holder.mFrontText = (TextView) convertView.findViewById(R.id.example_row_tv_title); holder.mBackEdit = (Button) convertView.findViewById(R.id.example_row_b_action_3); holder.mBackDelete = (Button) convertView.findViewById(R.id.example_row_b_action_2); convertView.setTag(holder); }else{ holder = (ViewHolder) convertView.getTag(); } holder.mBackDelete.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //关闭动画 mSwipeListView.closeAnimate(position); //调用dismiss方法删除该项(这个方法在MainActivity中) mSwipeListView.dismiss(position); } }); String item = getItem(position); holder.mFrontText.setText(item); return convertView; } class ViewHolder{ TextView mFrontText ; Button mBackEdit,mBackDelete ; } } 以上就是SwipeListViewTest的用法,希望对你有帮助
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值