我参考了这篇文章,我将它改了一下:
可动态布局的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(){@Overridepublic 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> {@Overrideprotected Void doInBackground(Integer... params) {int times;if (MAX_WIDTH % Math.abs(params[0]) == 0)// 整除times = MAX_WIDTH / Math.abs(params[0]);elsetimes = 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 blocke.printStackTrace();}}return null;}@Overrideprotected 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(){@Overridepublic 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> {@Overrideprotected Void doInBackground(Integer... params) {int times;if (MAX_WIDTH % Math.abs(params[0]) == 0)// 整除times = MAX_WIDTH / Math.abs(params[0]);elsetimes = 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 blocke.printStackTrace();}}return null;}@Overrideprotected void onProgressUpdate(Integer... params) {LayoutParams lp = (LayoutParams)getLayoutParams();if (params[0] < 0)lp.rightMargin = Math.max(lp.rightMargin + params[0], -MAX_WIDTH);elselp.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() {@Overridepublic void onPanelOpened(LeftPanel panel) {// TODO Auto-generated method stubLog.i("tag", "======onPanelOpened=======");}@Overridepublic void onPanelClosed(LeftPanel panel) {// TODO Auto-generated method stubLog.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() {@Overridepublic void onPanelOpened(RightPanel panel) {// TODO Auto-generated method stubLog.i("tag", "======onPanelOpened=======");}@Overridepublic void onPanelClosed(RightPanel panel) {// TODO Auto-generated method stubLog.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"><LinearLayoutandroid: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><LinearLayoutandroid: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. Dalvik虚拟机JNI方法的注册过程分析
  2. Android单元测试研究与实践
  3. 如何用Android(安卓)webview播放HTML5 video标签
  4. Android情景分析之属性服务
  5. Android中贝塞尔曲线的绘制方法示例代码
  6. 【Android】 Tablayout、XTablayout、SlidingTablayout的比较
  7. 对新浪微博android客户端中ListView的实现
  8. 最全面的Android(安卓)Intent机制讲解
  9. AndroidLinker与SO加壳技术之上篇

随机推荐

  1. android仿网易云音乐、即时通讯、bilibil
  2. [转]android:layout_gravity 和 android:
  3. Android(安卓)-- StateMachine瑙f瀽
  4. Android 多线程之几个基本问题
  5. Android通知栏微技巧,8.0系统中通知栏的适
  6. Andriod应用开发--第二章作业1--习题答案
  7. Android(安卓)由android:process引发LMK
  8. 请收好这一份全面 & 详细的Android学习指
  9. 完整安卓 Android开发视频教程共10季,迅雷
  10. iPhone和Android UI模式比较列表