可左右两侧挤压傍边布局的Android抽屉
16lz
2021-01-26
我参考了这篇文章,我将它改了一下:
可动态布局的Android抽屉之基础
工程中需要这样的效果,左边和右边的Panel可以打开关闭:
我把左边和右边的Panel封装成2个类了。这里要特别注意,抽屉是需要“handler”的,我这里可以把任何View都看成“handler”,使用setBindView(View bindView)方法进行绑定“handler”。这样做的好处是“把手”可以独立于抽屉,可以任意控制把手的位置,而不需要把手跟着抽屉移动!
先看左边的Panel:
右边的Panel,需要注意构造函数多了viewBeside参数:
使用方法:
main.xml:
可动态布局的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>
更多相关文章
- Dalvik虚拟机JNI方法的注册过程分析
- Android单元测试研究与实践
- 如何用Android(安卓)webview播放HTML5 video标签
- Android情景分析之属性服务
- Android中贝塞尔曲线的绘制方法示例代码
- 【Android】 Tablayout、XTablayout、SlidingTablayout的比较
- 对新浪微博android客户端中ListView的实现
- 最全面的Android(安卓)Intent机制讲解
- AndroidLinker与SO加壳技术之上篇