首页 > 其他分享 >可左右两侧挤压傍边布局的Android抽屉

可左右两侧挤压傍边布局的Android抽屉

时间:2023-04-06 20:35:14浏览次数:50  
标签:LayoutParams 傍边 params lp new Android 抽屉 public View


我参考了这篇文章,我将它改了一下:


可动态布局的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>


  • 可左右两侧挤压傍边布局的Android抽屉_ide

  • 大小: 28.7 KB
  • StretchDemo.zip (2.2 MB)
  • 描述: 相互挤压的Button
  • 下载次数: 127
  • 查看图片附件

标签:LayoutParams,傍边,params,lp,new,Android,抽屉,public,View
From: https://blog.51cto.com/u_5454003/6174094

相关文章

  • Android自定义捕获Application全局异常
    参考:http://bigcat.easymorse.com/?p=1152packageqianlong.qlmobile.ui;importjava.io.File;importjava.io.FileOutputStream;importjava.io.FilenameFilter;importjava.io.PrintWriter;importjava.io.StringWriter;importjava.io.Writer......
  • Android播放GIF动画
    Android支持GIF动画,但是如果利用ImageView标签直接写在布局文件中:<ImageViewandroid:id="@+id/gifpicture"android:layout_width="fill_parent"android:layout_height="wrap_content"android:src="@drawable/animation"......
  • 安卓项目源码 校园跑腿帮APP android stu dio项目 附源码
    全新安卓项目源码校园跑腿帮APPandroidstudio项目附源码,安装包,说明,录屏,截屏。Materialdesign风格设计,支持登录注册,任务发布,修改,上拉加载,下拉刷新,一键换肤等。YID:7598641395930165......
  • Android 11全屏显示
    @OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);//去掉标题栏this.requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(ActivityLoginBinding.inflate(getLayoutInflater()......
  • Android - Activity
     1.活动 Activity  是一种可以包含用户界面的组件,主要用于和用户进行交互,一个应用程序可以包含0个或多个活动;项目中的任何Activity都要重写onCreate()方法app/java/.activitytest/FirstActivity(AS自动完成)  2.基本用法(1)创建activity(2)布局文件app/res/layout/fir......
  • Android(安卓)IOS(苹果)判断是否开启通知权限
    在首页onLoad调用permissions()方法;this.permissions();permissions()方法具体代码://判断是否有通知权限permissions(){//#ifdefAPP-PLUSif(plus.os.name=='Android'){//判断是Androidva......
  • Android Api版本对照表
     Android版本ApiAPIAndroid13.0(T)32Android12.0(S)31Android11.0(R)30Android10.0(Q)29Android9.0(Pie)28Android8.1(Oreo)27Android8.0(Oreo)26Android7.1(Nougat)25Android7.0(Nougat)24Android6.0(Marshmallow)23......
  • 在Android编程中,下拉刷新Webview
    1.添加支持库依赖项:在build.gradle文件中添加以下行以添加SwipeRefreshLayout支持库:implementation'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'2.在布局文件中添加SwipeRefreshLayout和WebView:<?xmlversion="1.0"encoding="utf-8"?><an......
  • 从Android手机中取出已安装的app包,导出apk
    从Android手机中取出已安装的app包,导出apkTAG:Android,提取,apk,adb,pm,root,导出apk假设有这样一个场景,A君看到你手机上一个实用APP,想要安装到自己手机上,限于下载浪费流量,那么最简单的就是从你的手机中拷贝一个,不过你安装过的apk包已经删除了,不能直接复制出来进行安装。办法来了,就是......
  • 解决"No toolchains found in the NDK toolchains folder for ABI with prefix: mips6
    版权声明:本文为博主原创文章,遵循 CC4.0BY-SA 版权协议,转载请附上原文出处链接和本声明。今天安装了AndroidStudio3.2,打开一个旧工程,编译提示"NotoolchainsfoundintheNDKtoolchainsfolderforABIwithprefix:mips64el-linux-android"网上也有解决办法,就是下载旧版......