当前位置: 代码迷 >> Android >> 可上下两侧挤压傍边布局的Android抽屉
  详细解决方案

可上下两侧挤压傍边布局的Android抽屉

热度:73   发布时间:2016-05-01 19:02:57.0
可左右两侧挤压傍边布局的Android抽屉
我参考了这篇文章,我将它改了一下:
可动态布局的Android抽屉之基础

工程中需要这样的效果,左边和右边的Panel可以打开关闭:



我把左边和右边的Panel封装成2个类了。这里要特别注意,抽屉是需要“handler”的,我这里可以把任何View都看成“handler”,使用setBindView(View bindView)方法进行绑定“handler”。这样做的好处是“把手”可以独立于抽屉,可以任意控制把手的位置,而不需要把手跟着抽屉移动!

先看左边的Panel:
import android.content.Context;import android.os.AsyncTask;import android.view.View;import android.widget.LinearLayout;public class LeftPanel extends LinearLayout{		/**每次自动展开/收缩的范围*/	private final static int SPEED=20;	private int MAX_WIDTH=0;	private Context mContext;	public LeftPanel(Context context,int width,int height) {		super(context);		this.mContext=context;		//设置Panel本身的属性		LayoutParams lp=new LayoutParams(width, height);		lp.leftMargin=-lp.width;		MAX_WIDTH=Math.abs(lp.leftMargin);		this.setLayoutParams(lp);	}	/**	 * 	 * @param context	 * @param width	 * @param height	 * @param bindView	 * @param contentView	 */	public LeftPanel(Context context,int width,int height,View bindView,View contentView) {		this(context,width,height);		setBindView(bindView);		setContentView(contentView);	}	/**	 * 把View放在Panel中	 * @param v	 */	public void setContentView(View v){		this.addView(v);	}		/**	 * 绑定触发动画的View	 * @param bindView	 */	public void setBindView(View bindView){		bindView.setOnClickListener(new OnClickListener(){			@Override			public void onClick(View v) {				LayoutParams lp = (LayoutParams) getLayoutParams();				if (lp.leftMargin < 0)// CLOSE的状态					new AsynMove().execute(new Integer[] { SPEED });// 正数展开				else if (lp.leftMargin >= 0)// OPEN的状态					new AsynMove().execute(new Integer[] { -SPEED });// 负数收缩			}					});	}		class AsynMove extends AsyncTask<Integer, Integer, Void> {		@Override		protected Void doInBackground(Integer... params) {			int times;			if (MAX_WIDTH % Math.abs(params[0]) == 0)// 整除				times = MAX_WIDTH / Math.abs(params[0]);			else				times = MAX_WIDTH / Math.abs(params[0]) + 1;// 有余数			for (int i = 0; i < times; i++) {				publishProgress(params);				try {					Thread.sleep(Math.abs(params[0]));				} catch (InterruptedException e) {					// TODO Auto-generated catch block					e.printStackTrace();				}			}			return null;		}		@Override		protected void onProgressUpdate(Integer... params) {			LayoutParams lp = (LayoutParams)getLayoutParams();			if (params[0] < 0){//关闭				lp.leftMargin = Math.max(lp.leftMargin + params[0],-MAX_WIDTH);			}			else{//打开				lp.leftMargin = Math.min(lp.leftMargin + params[0],MAX_WIDTH);			}			if(lp.leftMargin==0 && onPanelStatusChangedListener!=null){//展开之后				onPanelStatusChangedListener.onPanelOpened(LeftPanel.this);//调用OPEN回调函数			}			else if(lp.leftMargin==-MAX_WIDTH && onPanelStatusChangedListener!=null){//收缩之后				onPanelStatusChangedListener.onPanelClosed(LeftPanel.this);//调用CLOSE回调函数			}			setLayoutParams(lp);		}	}		public interface OnPanelStatusChangedListener{		void onPanelOpened(LeftPanel panel);		void onPanelClosed(LeftPanel panel);	}	private OnPanelStatusChangedListener onPanelStatusChangedListener;	public void setOnPanelStatusChangedListener(OnPanelStatusChangedListener onPanelStatusChangedListener){		this.onPanelStatusChangedListener=onPanelStatusChangedListener;	}}

右边的Panel,需要注意构造函数多了viewBeside参数:
import android.content.Context;import android.os.AsyncTask;import android.view.View;import android.widget.LinearLayout;public class RightPanel extends LinearLayout{		/**每次自动展开/收缩的范围*/	private final static int SPEED=20;	private int MAX_WIDTH=0;	private Context mContext;	/**	 * viewBeside自动布局以适应Panel展开/收缩的空间变化	 *	 */		public RightPanel(Context context,View viewBeside,int width,int height) {		super(context);		this.mContext=context;			//必须改变Panel左侧组件的weight属性		LayoutParams p=(LayoutParams) viewBeside.getLayoutParams();		p.weight=1;//支持挤压		viewBeside.setLayoutParams(p);				//设置Panel本身的属性		LayoutParams lp=new LayoutParams(width, height);		lp.rightMargin=-lp.width;		MAX_WIDTH=Math.abs(lp.rightMargin);		this.setLayoutParams(lp);			}	/**	 * 	 * @param context	 * @param otherView	 * @param width	 * @param height	 * @param bindView	 * @param contentView	 */	public RightPanel(Context context,View viewBeside,int width,int height,View bindView,View contentView) {		this(context,viewBeside,width,height);		setBindView(bindView);		setContentView(contentView);	}		/**	 * 把View放在Panel中	 * @param v	 */	public void setContentView(View v){		this.addView(v);	}		/**	 * 绑定触发动画的View	 * @param bindView	 */	public void setBindView(View bindView){		bindView.setOnClickListener(new OnClickListener(){			@Override			public void onClick(View v) {				LayoutParams lp = (LayoutParams) getLayoutParams();				if (lp.rightMargin < 0)// CLOSE的状态					new AsynMove().execute(new Integer[] { SPEED });// 正数展开				else if (lp.rightMargin >= 0)// OPEN的状态					new AsynMove().execute(new Integer[] { -SPEED });// 负数收缩			}					});	}		class AsynMove extends AsyncTask<Integer, Integer, Void> {		@Override		protected Void doInBackground(Integer... params) {			int times;			if (MAX_WIDTH % Math.abs(params[0]) == 0)// 整除				times = MAX_WIDTH / Math.abs(params[0]);			else				times = MAX_WIDTH / Math.abs(params[0]) + 1;// 有余数			for (int i = 0; i < times; i++) {				publishProgress(params);				try {					Thread.sleep(Math.abs(params[0]));				} catch (InterruptedException e) {					// TODO Auto-generated catch block					e.printStackTrace();				}			}			return null;		}		@Override		protected void onProgressUpdate(Integer... params) {			LayoutParams lp = (LayoutParams)getLayoutParams();			if (params[0] < 0)				lp.rightMargin = Math.max(lp.rightMargin + params[0], -MAX_WIDTH);			else				lp.rightMargin = Math.min(lp.rightMargin + params[0], 0);			if(lp.rightMargin==0 && onPanelStatusChangedListener!=null){//展开之后				onPanelStatusChangedListener.onPanelOpened(RightPanel.this);//调用OPEN回调函数			}			else if(lp.rightMargin==-MAX_WIDTH && onPanelStatusChangedListener!=null){//收缩之后				onPanelStatusChangedListener.onPanelClosed(RightPanel.this);//调用CLOSE回调函数			}			setLayoutParams(lp);		}	}		public interface OnPanelStatusChangedListener{		void onPanelOpened(RightPanel panel);		void onPanelClosed(RightPanel panel);	}	private OnPanelStatusChangedListener onPanelStatusChangedListener;	public void setOnPanelStatusChangedListener(OnPanelStatusChangedListener onPanelStatusChangedListener){		this.onPanelStatusChangedListener=onPanelStatusChangedListener;	}}


使用方法:
import android.app.Activity;import android.graphics.Color;import android.os.Bundle;import android.util.Log;import android.view.Gravity;import android.view.View;import android.widget.Button;import android.widget.LinearLayout;import android.widget.TextView;import android.widget.LinearLayout.LayoutParams;public class App extends Activity {	public LeftPanel leftPanel;	public RightPanel rightPanel;	public LinearLayout container;	public Button btn_0,btn_1;	private View tv;	public void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		setContentView(R.layout.main);		container=(LinearLayout)findViewById(R.id.container);		btn_0 = (Button) findViewById(R.id.btn_0);		btn_1 = (Button) findViewById(R.id.btn_1);		tv = findViewById(R.id.tv);				//新建测试组件		TextView content0=new TextView(this);		content0.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));		content0.setText("左边的panel");		content0.setGravity(Gravity.CENTER);		content0.setTextColor(Color.RED);		content0.setBackgroundColor(Color.WHITE);				//新建测试组件		TextView content1=new TextView(this);		content1.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));		content1.setText("右边的panel");		content1.setGravity(Gravity.CENTER);		content1.setTextColor(Color.RED);		content1.setBackgroundColor(Color.WHITE);				leftPanel=new LeftPanel(this,120,LayoutParams.FILL_PARENT);		leftPanel.setBindView(btn_0);		leftPanel.setContentView(content0);		leftPanel.setOnPanelStatusChangedListener(new LeftPanel.OnPanelStatusChangedListener() {						@Override			public void onPanelOpened(LeftPanel panel) {				// TODO Auto-generated method stub				Log.i("tag", "======onPanelOpened=======");			}						@Override			public void onPanelClosed(LeftPanel panel) {				// TODO Auto-generated method stub				Log.i("tag", "======onPanelClosed=======");			}		});				container.addView(leftPanel,0);//加入Panel控件		//		rightPanel=new RightPanel(this,tv,120,LayoutParams.FILL_PARENT);		rightPanel.setBindView(btn_1);		rightPanel.setContentView(content1);		rightPanel.setOnPanelStatusChangedListener(new RightPanel.OnPanelStatusChangedListener() {						@Override			public void onPanelOpened(RightPanel panel) {				// TODO Auto-generated method stub				Log.i("tag", "======onPanelOpened=======");			}						@Override			public void onPanelClosed(RightPanel panel) {				// TODO Auto-generated method stub				Log.i("tag", "======onPanelClosed=======");			}		});		container.addView(rightPanel);//加入Panel控件	}}

main.xml:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"	android:layout_width="fill_parent" 	android:layout_height="fill_parent"	android:orientation="vertical"	>	<LinearLayout		android:id="@+id/container"		android:layout_width="fill_parent" 		android:layout_height="fill_parent"		android:orientation="horizontal"		android:layout_weight="1"		>		<TextView  android:id="@+id/tv" 			android:layout_width="fill_parent"			android:layout_height="fill_parent" 			android:gravity="center"			android:text="hello,squeeze me."			/>	</LinearLayout>	<LinearLayout		android:layout_width="fill_parent" 		android:layout_height="wrap_content"		android:orientation="horizontal"		android:gravity="center"		>		<Button android:id="@+id/btn_0" 				android:layout_width="wrap_content"				android:layout_height="wrap_content" 				android:text="left"				/>		<Button android:id="@+id/btn_1" 				android:layout_width="wrap_content"				android:layout_height="wrap_content" 				android:text="right"				/>	</LinearLayout></LinearLayout>
1 楼 nidehengji 2012-02-08  
灰常灰常感谢楼主
2 楼 蜗牛/ 2012-05-31  
感谢你提供这篇文章!
  相关解决方案