標籤:android
老規矩先看:
這個代碼很常見,網上大牛已經做過好幾遍了,但是本著學習的態度,去研究了下別人寫的代碼。發現有好幾種實現方法。最為流行的一種是使用Scroller實現滑動,然後按鈕的實現有三種方法。
1. 一種是全部用java類繼承一個viewgroup來動態產生listviewitem.這樣靈活性很高,但是技巧性也高。
2. 一種是整個listviewitem用xml編寫,然後inflate進去。這樣寫的好處是可以複用,而且只需要adapter重寫view, 但是按鈕和內容是固定的,不能輕鬆的實現QQ好友那種,有時候是刪除,有時候是置頂,有時候是標記什麼的、多種按鈕結合
3. 為此我試著把基本listviewitem和按鈕xml分開寫,寫成2個布局,然後用一個linerlayout動態合成起來。這樣在擴充的時候可以寫多組按鈕布局,然後動態判斷合成,更容易實現多種類按鈕的方法。
4.完成工程在我的github裡面:
戳戳戳:https://github.com/younfor/DragListView
下面是核心源碼:
package com.draglistview;import android.content.Context;import android.util.AttributeSet;import android.util.TypedValue;import android.view.MotionEvent;import android.widget.ListView;/** * * @author https://github.com/younfor * */public class DragDelListView extends ListView { //是否可以拖動 private boolean moveable=false; //是否全部關閉 private boolean closed=true; private float mDownX,mDownY; private int mTouchPosition,oldPosition=-1; private DragDelItem mTouchView,oldView; private Context context; public DragDelListView(Context context) { super(context); init(context); } public DragDelListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } public DragDelListView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } private void init(Context context) { this.context=context; } @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: //擷取點擊的position mTouchPosition = pointToPosition((int) ev.getX(), (int) ev.getY()); //擷取點擊的view (是可見範圍裡面的) mTouchView=(DragDelItem)getChildAt(mTouchPosition - getFirstVisiblePosition()); //擷取點擊的地方 mDownX = ev.getX(); mDownY=ev.getY(); //點擊的是同一個或者全部初始 if(oldPosition==mTouchPosition ||closed) { //可以移動 moveable=true; mTouchView.mDownX =(int)mDownX; }else { moveable=false; if(oldView!=null) { //舊的歸位 oldView.smoothCloseMenu(); } } oldPosition=mTouchPosition; oldView=mTouchView; break; case MotionEvent.ACTION_MOVE: //判斷是否側滑 if (Math.abs(mDownX-ev.getX()) < Math.abs(mDownY-ev.getY()) * dp2px(2)) { break; } if (moveable) { int dis = (int) (mTouchView.mDownX -ev.getX()); //此時方向會變 if(mTouchView.state==mTouchView.STATE_OPEN) dis+=mTouchView.mMenuView.getWidth(); mTouchView.swipe(dis); ev.setAction(MotionEvent.ACTION_CANCEL); } break; case MotionEvent.ACTION_UP: if (moveable) { if ((mTouchView.mDownX -ev.getX()) > (mTouchView.mMenuView.getWidth()/2)) { // open mTouchView.smoothOpenMenu(); closed=false; } else { // close mTouchView.smoothCloseMenu(); closed=true; } ev.setAction(MotionEvent.ACTION_CANCEL); } break; } return super.onTouchEvent(ev); } //將dp轉換為px private int dp2px(int dp) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getContext().getResources().getDisplayMetrics()); }}
package com.draglistview;
import android.content.Context;
import android.support.v4.view.GestureDetectorCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.GestureDetector.OnGestureListener;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.widget.AbsListView;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.Scroller;
/**
*
* @author https://github.com/younfor
*
*/
public class DragDelItem extends LinearLayout {
public static final int STATE_CLOSE = 0;public static final int STATE_OPEN = 1;private View mContentView;public View mMenuView;public int mDownX;public int state = STATE_CLOSE;public boolean isFling;private int mBaseX;private Scroller scroll;public DragDelItem(View contentView, View menuView) { super(contentView.getContext()); scroll=new Scroller(getContext()); mContentView = contentView; mMenuView = menuView; init();}private DragDelItem(Context context, AttributeSet attrs) { super(context, attrs);}private DragDelItem(Context context) { super(context);}private void init() { setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); LayoutParams contentParams = new LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); mContentView.setLayoutParams(contentParams); mMenuView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); addView(mContentView); addView(mMenuView);}public void swipe(int dis) { if (dis > mMenuView.getWidth()) { dis = mMenuView.getWidth(); } if (dis < 0) { dis = 0; } mContentView.layout(-dis, mContentView.getTop(), mContentView.getWidth() - dis, getMeasuredHeight()); mMenuView.layout(mContentView.getWidth() - dis, mMenuView.getTop(), mContentView.getWidth() + mMenuView.getWidth() - dis, mMenuView.getBottom());}@Overridepublic void computeScroll() { if (state == STATE_OPEN) { if (scroll.computeScrollOffset()) { swipe(scroll.getCurrX()); postInvalidate(); } } else { if (scroll.computeScrollOffset()) { swipe(mBaseX - scroll.getCurrX()); postInvalidate(); } }}public void smoothCloseMenu() { state = STATE_CLOSE; mBaseX = -mContentView.getLeft(); scroll.startScroll(0, 0, mBaseX, 0, 350); postInvalidate();}public void smoothOpenMenu() { state = STATE_OPEN; scroll.startScroll(-mContentView.getLeft(), 0, mMenuView.getWidth()/2, 0, 350); postInvalidate();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mMenuView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec( getMeasuredHeight(), MeasureSpec.EXACTLY)); mContentView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec( getMeasuredHeight(), MeasureSpec.EXACTLY));}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) { mContentView.layout(0, 0, getMeasuredWidth(), mContentView.getMeasuredHeight()); mMenuView.layout(getMeasuredWidth(), 0, getMeasuredWidth() + mMenuView.getMeasuredWidth(), mContentView.getMeasuredHeight());}
}
package com.draglistview;import java.util.List;import com.draglistview.*;import android.app.Activity;import android.content.pm.ApplicationInfo;import android.os.Bundle;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;import android.widget.Toast;/** * * @author https://github.com/younfor * */public class MainActivity extends Activity { private List<ApplicationInfo> mAppList; private DragDelListView mListView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_list); mAppList = getPackageManager().getInstalledApplications(0); mListView = (DragDelListView) findViewById(R.id.listView); mListView.setAdapter(new AppAdapter(mAppList)); } class AppAdapter extends BaseAdapter { private List<ApplicationInfo> mAppList; public AppAdapter(List<ApplicationInfo> appList) { mAppList=appList; } @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) { final int loc=position; ViewHolder holder=null; View menuView=null; if (convertView == null) { convertView = View.inflate(getApplicationContext(), R.layout.swipecontent, null); menuView = View.inflate(getApplicationContext(), R.layout.swipemenu, null); //合成內容與菜單 convertView = new DragDelItem(convertView,menuView);; holder=new ViewHolder(convertView); } else { holder = (ViewHolder) convertView.getTag(); } ApplicationInfo item = getItem(position); holder.iv_icon.setImageDrawable(item.loadIcon(getPackageManager())); holder.tv_name.setText(item.loadLabel(getPackageManager())); holder.tv_open.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { Toast.makeText(MainActivity.this, "open:"+loc, Toast.LENGTH_SHORT).show(); } }); holder.tv_del.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { } }); return convertView; } class ViewHolder { ImageView iv_icon; TextView tv_name; TextView tv_open,tv_del; public ViewHolder(View view) { iv_icon = (ImageView) view.findViewById(R.id.iv_icon); tv_name = (TextView) view.findViewById(R.id.tv_name); tv_open=(TextView)view.findViewById(R.id.tv_open); tv_del=(TextView)view.findViewById(R.id.tv_del); view.setTag(this); } } }}
Android UI設計: 仿ios,仿qq實現Listview側滑出現按鈕