这个效果现在很多软件都实现了,其实说穿了很简单的。就是一个动画,做的地道点的加一个手势拖拉效果。
我写的代码(未参考任何代码,不知道别人怎么实现的。):
import java.util.ArrayList; import android.content.Context; import android.os.Bundle; import android.util.Log; import android.view.GestureDetector; import android.view.GestureDetector.OnGestureListener; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.LinearInterpolator; import android.view.animation.TranslateAnimation; import android.widget.AbsoluteLayout; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; public class SlideRightActivity extends BaseActivity implements OnTouchListener,OnGestureListener{ private Context context; private Button btn; private LinearLayout left_panel,right_panel; private boolean isShowing=false; private final int duration=200; // private GestureDetector mGestureDetector; // private ViewGroup container; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_slide_right); context=this; initViews(); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); initValues(); } @Override protected void updateViews(Object o) { // TODO Auto-generated method stub } @Override protected void initViews() { // TODO Auto-generated method stub // container=(ViewGroup)findViewById(R.id.container); left_panel=(LinearLayout)findViewById(R.id.left_panel); left_panel.setLayoutParams(new AbsoluteLayout.LayoutParams((int)(getResources().getDisplayMetrics().widthPixels*0.8), AbsoluteLayout.LayoutParams.MATCH_PARENT, 0, 0)); right_panel=(LinearLayout)findViewById(R.id.right_panel); right_panel.setOnTouchListener(this); //定义手势识别 mGestureDetector = new GestureDetector(this,this); mGestureDetector.setIsLongpressEnabled(false); ArrayList<String> list=new ArrayList<String>(); list.add("1"); list.add("2"); list.add("3"); list.add("4"); list.add("5"); list.add("6"); ListView listView=(ListView)findViewById(R.id.listView); ListViewAdapter adapter=new ListViewAdapter(list); listView.setAdapter(adapter); btn=(Button)findViewById(R.id.btn); btn.setOnClickListener(onClickListener); ArrayList<String> texts=new ArrayList<String>(); texts.add("111"); texts.add("222"); texts.add("333"); texts.add("444"); texts.add("555"); texts.add("666"); texts.add("777"); ListView listViewBeside=(ListView)findViewById(R.id.listViewBeside); ListViewAdapter adapterBeside=new ListViewAdapter(texts); listViewBeside.setAdapter(adapterBeside); /**让ListView不拦截手势滑动*/ listViewBeside.setOnTouchListener(new View.OnTouchListener(){ @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub doSlideWhenTouchUp(event); mGestureDetector.onTouchEvent(event); return false; } }); listViewBeside.setOnItemClickListener(new ListView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // TODO Auto-generated method stub Log.i("tag", "position=="+position); } }); } View.OnClickListener onClickListener=new View.OnClickListener(){ @Override public void onClick(View v) { // TODO Auto-generated method stub int width=left_panel.getMeasuredWidth(); if(isShowing){ doSlideCloseAnimation(right_panel,width); }else{ doSlideOpenAnimation(right_panel,width); } } }; @Override protected void initValues() { // TODO Auto-generated method stub } @Override protected void initHandler() { // TODO Auto-generated method stub } private void doSlideOpenAnimation(View v,int width) { TranslateAnimation animation = new TranslateAnimation(0, width, 0, 0); animation.setInterpolator(new LinearInterpolator()); animation.setDuration(duration); animation.setFillAfter(true); v.startAnimation(animation); animation.setAnimationListener(new AnimationListener(){ @Override public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { // TODO Auto-generated method stub resetLayout(left_panel.getMeasuredWidth(),0); isShowing=true; } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } }); } private void resetLayout(int width,int height){ AbsoluteLayout.LayoutParams params = (AbsoluteLayout.LayoutParams)right_panel.getLayoutParams(); params.x=width; params.y=height; right_panel.setLayoutParams(params); right_panel.clearAnimation(); } private void doSlideCloseAnimation(View v,final int width) { TranslateAnimation animation = new TranslateAnimation(0, -width, 0, 0); animation.setInterpolator(new LinearInterpolator()); animation.setDuration(duration); animation.setFillAfter(true); v.startAnimation(animation); animation.setAnimationListener(new AnimationListener(){ @Override public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { // TODO Auto-generated method stub resetLayout(0,0); isShowing=false; } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } }); } class ListViewAdapter extends BaseAdapter{ private ArrayList<String> list; public ListViewAdapter(ArrayList<String> list){ this.list=list; } @Override public int getCount() { // TODO Auto-generated method stub return list.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return list.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub if (convertView == null) { convertView = LayoutInflater.from(context).inflate( R.layout.simple_item_1_for_listview, null); } TextView tv0=(TextView)convertView.findViewById(R.id.simple_item_0); tv0.setText(list.get(position)); return convertView; } } @Override public boolean onDown(MotionEvent e) { // TODO Auto-generated method stub return true; } @Override public void onShowPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onSingleTapUp(MotionEvent e) { // TODO Auto-generated method stub return false; } private int mScrollx; @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // TODO Auto-generated method stub mScrollx -= distanceX;//distanceX:向左为正,右为负 AbsoluteLayout.LayoutParams params = (AbsoluteLayout.LayoutParams)right_panel.getLayoutParams(); params.x+=mScrollx;//distanceX:向左为正,右为负 if(params.x>left_panel.getMeasuredWidth()){ params.x=left_panel.getMeasuredWidth(); } if(params.x<0){ params.x=0; } right_panel.setLayoutParams(params); return false; } @Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // TODO Auto-generated method stub /** 手势快速滑动,打开/关闭panel。现已被onScroll()完成同样的功能 */ /*int width=left_panel.getMeasuredWidth(); if(velocityX>500){ if(!isShowing) if(right_panel.getLeft()==0) doSlideOpenAnimation(right_panel, width); }else if(velocityX<-500){ if(isShowing) if(right_panel.getLeft()==width) doSlideCloseAnimation(right_panel, width); }*/ return false; } @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub doSlideWhenTouchUp(event); return mGestureDetector.onTouchEvent(event); } private void doSlideWhenTouchUp(MotionEvent event){ switch (event.getAction()) { case MotionEvent.ACTION_UP: /** 手势拖动到一 半松手时,根据拖动的距离判断打开/关闭 */ AbsoluteLayout.LayoutParams params = (AbsoluteLayout.LayoutParams)right_panel.getLayoutParams(); int width=left_panel.getMeasuredWidth(); int slideDistance=width>>1; if (params.x >= slideDistance) { doSlideOpenAnimation(right_panel, width-params.x); }else{ doSlideCloseAnimation(right_panel, params.x); } default: break; } } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { return super.onKeyDown(keyCode, event); } }
布局:
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/container" android:layout_width="fill_parent" android:layout_height="fill_parent" > <LinearLayout android:id="@+id/left_panel" android:layout_width="250dp" android:layout_height="fill_parent" android:orientation="vertical" android:layout_x="0dp" android:layout_y="0dp" > <ListView android:id="@+id/listView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:cacheColorHint="@android:color/transparent" /> </LinearLayout> <LinearLayout android:id="@+id/right_panel" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:background="@color/green" android:layout_x="0dp" android:layout_y="0dp" > <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="open/close" /> <ListView android:id="@+id/listViewBeside" android:layout_width="fill_parent" android:layout_height="fill_parent" android:cacheColorHint="@android:color/transparent" /> </LinearLayout> </AbsoluteLayout>
如果不加手势的话,其实也可以的:
import java.util.ArrayList; import android.content.Context; import android.os.Bundle; import android.util.Log; import android.view.GestureDetector; import android.view.GestureDetector.OnGestureListener; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.View.OnTouchListener; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.LinearInterpolator; import android.view.animation.TranslateAnimation; import android.widget.AbsoluteLayout; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; public class SlideRightActivity extends BaseActivity implements OnTouchListener/*,OnGestureListener*/{ private Context context; private Button btn; private LinearLayout left_panel,right_panel; private boolean isShowing=false; private final int duration=200; // private GestureDetector mGestureDetector; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_slide_right); context=this; initViews(); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); initValues(); } @Override protected void updateViews(Object o) { // TODO Auto-generated method stub } @Override protected void initViews() { // TODO Auto-generated method stub left_panel=(LinearLayout)findViewById(R.id.left_panel); left_panel.setLayoutParams(new AbsoluteLayout.LayoutParams((int)(getResources().getDisplayMetrics().widthPixels*0.8), AbsoluteLayout.LayoutParams.MATCH_PARENT, 0, 0)); right_panel=(LinearLayout)findViewById(R.id.right_panel); right_panel.setOnTouchListener(this); //定义手势识别 // mGestureDetector = new GestureDetector(this,this); // mGestureDetector.setIsLongpressEnabled(false); ArrayList<String> list=new ArrayList<String>(); list.add("1"); list.add("2"); list.add("3"); list.add("4"); list.add("5"); list.add("6"); ListView listView=(ListView)findViewById(R.id.listView); ListViewAdapter adapter=new ListViewAdapter(list); listView.setAdapter(adapter); btn=(Button)findViewById(R.id.btn); btn.setOnClickListener(onClickListener); ArrayList<String> texts=new ArrayList<String>(); texts.add("111"); texts.add("222"); texts.add("333"); texts.add("444"); texts.add("555"); texts.add("666"); texts.add("777"); ListView listViewBeside=(ListView)findViewById(R.id.listViewBeside); ListViewAdapter adapterBeside=new ListViewAdapter(texts); listViewBeside.setAdapter(adapterBeside); /**让ListView不拦截手势滑动*/ listViewBeside.setOnTouchListener(new View.OnTouchListener(){ @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub doSlideWhenTouchUp(event); // mGestureDetector.onTouchEvent(event); return false; } }); listViewBeside.setOnItemClickListener(new ListView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // TODO Auto-generated method stub Log.i("tag", "position=="+position); } }); } View.OnClickListener onClickListener=new View.OnClickListener(){ @Override public void onClick(View v) { // TODO Auto-generated method stub int width=left_panel.getMeasuredWidth(); if(isShowing){ doSlideCloseAnimation(right_panel,width); }else{ doSlideOpenAnimation(right_panel,width); } } }; @Override protected void initValues() { // TODO Auto-generated method stub } @Override protected void initHandler() { // TODO Auto-generated method stub } private void doSlideOpenAnimation(View v,int width) { TranslateAnimation animation = new TranslateAnimation(0, width, 0, 0); animation.setInterpolator(new LinearInterpolator()); animation.setDuration(duration); animation.setFillAfter(true); v.startAnimation(animation); animation.setAnimationListener(new AnimationListener(){ @Override public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { // TODO Auto-generated method stub resetLayout(left_panel.getMeasuredWidth(),0); isShowing=true; } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } }); } private void resetLayout(int width,int height){ AbsoluteLayout.LayoutParams params = (AbsoluteLayout.LayoutParams)right_panel.getLayoutParams(); params.x=width; params.y=height; right_panel.setLayoutParams(params); right_panel.clearAnimation(); } private void doSlideCloseAnimation(View v,final int width) { TranslateAnimation animation = new TranslateAnimation(0, -width, 0, 0); animation.setInterpolator(new LinearInterpolator()); animation.setDuration(duration); animation.setFillAfter(true); v.startAnimation(animation); animation.setAnimationListener(new AnimationListener(){ @Override public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { // TODO Auto-generated method stub resetLayout(0,0); isShowing=false; } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } }); } class ListViewAdapter extends BaseAdapter{ private ArrayList<String> list; public ListViewAdapter(ArrayList<String> list){ this.list=list; } @Override public int getCount() { // TODO Auto-generated method stub return list.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return list.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub if (convertView == null) { convertView = LayoutInflater.from(context).inflate( R.layout.simple_item_1_for_listview, null); } TextView tv0=(TextView)convertView.findViewById(R.id.simple_item_0); tv0.setText(list.get(position)); return convertView; } } /*@Override public boolean onDown(MotionEvent e) { // TODO Auto-generated method stub return true; } @Override public void onShowPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onSingleTapUp(MotionEvent e) { // TODO Auto-generated method stub return false; } private int mScrollx; @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // TODO Auto-generated method stub mScrollx -= distanceX;//distanceX:向左为正,右为负 AbsoluteLayout.LayoutParams params = (AbsoluteLayout.LayoutParams)right_panel.getLayoutParams(); params.x+=mScrollx;//distanceX:向左为正,右为负 if(params.x>left_panel.getMeasuredWidth()){ params.x=left_panel.getMeasuredWidth(); } if(params.x<0){ params.x=0; } right_panel.setLayoutParams(params); return false; } @Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // TODO Auto-generated method stub return false; }*/ @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub // doSlideWhenTouchUp(event); // return mGestureDetector.onTouchEvent(event); Log.i("tag", "Action="+event.getAction()); doSlideWhenTouchUp(event); return true; } private VelocityTracker tracker = null;//速度跟踪器,用于判断偏左还是偏右 private boolean direction=true;//向左or向右拉 private void doSlideWhenTouchUp(MotionEvent event){ switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if(tracker == null){ tracker = VelocityTracker.obtain(); }else{ tracker.clear(); } tracker.addMovement(event); break; case MotionEvent.ACTION_UP: tracker.recycle(); /** 手势拖动到一 半松手时,根据拖动的距离判断打开/关闭 */ AbsoluteLayout.LayoutParams params = (AbsoluteLayout.LayoutParams)right_panel.getLayoutParams(); int width=left_panel.getMeasuredWidth(); int slideDistance=width/3; if(direction){ if (params.x >= slideDistance) { doSlideOpenAnimation(right_panel, width-params.x); }else{ doSlideCloseAnimation(right_panel, params.x); } }else{ if (params.x >= width-slideDistance) { doSlideOpenAnimation(right_panel, width-params.x); }else{ doSlideCloseAnimation(right_panel, params.x); } } case MotionEvent.ACTION_MOVE: tracker.addMovement(event); tracker.computeCurrentVelocity(1000); float XVelocity=tracker.getXVelocity()*0.02f;//0.02是速度系数,这个根据手机世纪表现调出来的 if(XVelocity<0){//向左划 direction=false; }else{//向右划 direction=true; } // Log.i("tag", "XVelocity="+XVelocity); params = (AbsoluteLayout.LayoutParams)right_panel.getLayoutParams(); params.x+=XVelocity;//distanceX:向左为正,右为负 if(params.x>left_panel.getMeasuredWidth()){ params.x=left_panel.getMeasuredWidth(); } if(params.x<0){ params.x=0; } right_panel.setLayoutParams(params); break; default: break; } } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { return super.onKeyDown(keyCode, event); } }