Android控件View打造完美的自定义侧滑菜单

发布时间 - 2026-01-10 23:10:50    点击率:

一、概述

  在App中,经常会出现侧滑菜单,侧滑滑出View等效果,虽然说Android有很多第三方开源库,但是实际上咱们可以自己也写一个自定义的侧滑View控件,其实不难,主要涉及到以下几个要点:

1.对Android中Window类中的DecorView有所了解

2.对Scroller类实现平滑移动效果

3.自定义ViewGroup的实现

首先来看看效果图吧:

     

  下面现在就来说说这里咱们实现侧滑View的基本思路吧,这里我采用的是自定义一个继承于RelativeLayout的控件叫做XCSlideView类吧。

首先从布局文件中inflater出来一个menuView,然后通过addView的方法,将该侧滑View添加到自定义的控件View中怎么让XCSlideView 这个侧滑View 隐藏到屏幕之外呢?很简单通过ScrollTo方法,移动一个屏幕宽度的距离即可,这里以左侧滑出为例吧,只需要这样 XCSlideView.this.scrollTo(mScreenWidth, 0);mScreenWidth是屏幕宽度。下面还要处理的就是底下的半透明黑色的蒙层效果,这个其实就是一个View,然后设置半透明效果。这个当然简单了,关键是咱们让他显示在咱们的自定义侧滑View的下面呢,这里咱们先给出DecorView的简单分析,方便下面介绍添加半透明View蒙层下:

下面是对上面这张图的解释:

1、DecorView为整个Window界面的最顶层View。

2、DecorView只有一个子元素为LinearLayout。代表整个Window界面,包含通知栏,标题栏,内容显示栏三块区域。

3、LinearLayout里有两个FrameLayout子元素。

  (20)为标题栏显示界面。只有一个TextView显示应用的名称。也可以自定义标题栏,载入后的自定义标题栏View将加入FrameLayout中。

  (21)为内容栏显示界面。就是setContentView()方法载入的布局界面,加入其中。 

有了上面的DecorVIew知识背景,现在就来说说 怎么添加蒙层View和将自定义侧滑View添加到Activity的DecorView中,首先把蒙层View添加到

(31)customView中去,然后将自定义侧滑View添加到 (21)FrameLayout中去,至于为什么要这样,是因为考虑到自定义侧滑View不一定是宽度为屏幕宽度,所以才这么做,而且也方面处理有无标题栏,有无采用沉浸式状态栏设计等情况。

二、自定义侧滑View的实现

根据上面的概述,大家应该知道大概的思路了,下面我就给出自定义侧滑View类的核心代码:

1、自定义侧滑View用到的变量:

//侧滑方向-从哪侧滑出
 public static enum Positon {
 LEFT, RIGHT
 }
 private Context mContext;
 private Activity mActivity;
 private Scroller mScroller = null;
 //侧滑菜单布局View
 private View mMenuView;
 //底部蒙层View
 private View mMaskView;
 private int mMenuWidth = 0;
 //屏幕宽度
 private int mScreenWidth = 0;
 //是否在滑动中
 private boolean mIsMoving = false;
 //显示登录界面与否
 private boolean mShow = false;
 //滑动动画时间
 private int mDuration = 600;
 //缺省侧滑方向为左
 private Positon mPositon = Positon.LEFT;

2、初始化创建自定义侧滑View:

**
 * 创建侧滑菜单View
 */
 public static XCSlideView create(Activity activity) {
 XCSlideView view = new XCSlideView(activity);
 return view;
 }
 /**
 * 创建侧滑菜单View
 */
 public static XCSlideView create(Activity activity, Positon positon) {
 XCSlideView view = new XCSlideView(activity);
 view.mPositon = positon;
 return view;
 }

3、创建半透明蒙层View,并添加到contentView中去

/**
 * 创建 蒙层View并添加到contentView中
 */
 private void attachToContentView(Activity activity, Positon positon) {
 mPositon = positon;
 ViewGroup contentFrameLayout = (ViewGroup) activity.findViewById(android.R.id.content);
 ViewGroup contentView = ((ViewGroup) contentFrameLayout.getChildAt(0));
 mMaskView = new View(activity);
 mMaskView.setBackgroundColor(mContext.getResources().getColor(R.color.mask_color));
 contentView.addView(mMaskView, contentView.getLayoutParams());
 mMaskView.setVisibility(View.GONE);
 mMaskView.setClickable(true);
 mMaskView.setOnClickListener(new OnClickListener() {
 @Override
 public void onClick(View view) {
 if (isShow()) {
  dismiss();
 }
 }
 });
 }

4、设置侧滑菜单View,并添加到DectorView->LinearLayout->内容显示区域View(FrameLayout)中

/**
 * 设置侧滑菜单View,并添加到DectorView->LinearLayout->内容显示区域View中
 */
 public void setMenuView(Activity activity, View view) {
 mActivity = activity;
 mMenuView = view;
 LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
 addView(mMenuView, params);
 mMenuView.post(new Runnable() {
 @Override
 public void run() {
 // TODO Auto-generated method stub
 mMenuWidth = mMenuView.getWidth();
 switch (mPositon) {
  case LEFT:
  XCSlideView.this.scrollTo(mScreenWidth, 0);
  break;
  case RIGHT:
  XCSlideView.this.scrollTo(-mScreenWidth, 0);
  break;
 }

 }
 });
 ViewGroup contentFrameLayout = (ViewGroup) activity.findViewById(android.R.id.content);
 ViewGroup contentView = contentFrameLayout;
 contentView.addView(this);
 FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) this.getLayoutParams();
 switch (mPositon) {
 case LEFT:
 layoutParams.gravity = Gravity.LEFT;
 layoutParams.leftMargin = 0;
 break;
 case RIGHT:
 layoutParams.gravity = Gravity.RIGHT;
 layoutParams.rightMargin = 0;
 break;
 }
 TextView titleFrameLayout = (TextView) activity.findViewById(android.R.id.title);
 if( titleFrameLayout != null){
 layoutParams.topMargin = DensityUtil.getStatusBarHeight(mContext);
 }
 int flags = mActivity.getWindow().getAttributes().flags;
 int flag = (flags & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
 if(flag == WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS){
 //说明状态栏使用沉浸式
 layoutParams.topMargin = DensityUtil.getStatusBarHeight(mContext);
 }
 this.setLayoutParams(layoutParams);
 }

5、处理自定义侧滑View的侧滑滑动和隐藏效果:

/**
 * 显示侧滑菜单View
 */
 public void show(){
 if(isShow() && !mIsMoving)
 return;
 switch (mPositon) {
 case LEFT:
 startScroll(mMenuWidth, -mMenuWidth, mDuration);
 break;
 case RIGHT:
 startScroll(-mMenuWidth, mMenuWidth, mDuration);
 break;
 }
 switchMaskView(true);
 mShow = true;
 }
 /**
 * 蒙层显示开关
 */
 private void switchMaskView(boolean bShow){
 if(bShow){
 mMaskView.setVisibility(View.VISIBLE);
 Animation animation = new AlphaAnimation(0.0f, 1.0f);
 animation.setDuration(mDuration);
 mMaskView.startAnimation(animation);
 }else{
 mMaskView.setVisibility(View.GONE);
 }
 }
 /**
 * 关闭侧滑菜单View
 */
 public void dismiss() {
 // TODO Auto-generated method stub
 if(!isShow() && !mIsMoving)
 return;
 switch (mPositon) {
 case LEFT:
 startScroll(XCSlideView.this.getScrollX(), mMenuWidth, mDuration);
 break;
 case RIGHT:
 startScroll(XCSlideView.this.getScrollX(), -mMenuWidth, mDuration);
 break;
 }
 switchMaskView(false);
 mShow = false;
 }
 public boolean isShow(){
 return mShow;
 }
 @Override
 public void computeScroll() {
 // TODO Auto-generated method stub
 if (mScroller.computeScrollOffset()) {
 scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
 // 更新界面
 postInvalidate();
 mIsMoving = true; 
 } else {
 mIsMoving = false;
 }
 super.computeScroll();
 }
 /**
 * 拖动移动
 */
 public void startScroll(int startX, int dx,int duration){
 mIsMoving = true;
 mScroller.startScroll(startX,0,dx,0,duration);
 invalidate();
 }


三、如何使用该自定义侧滑View控件

使用起来,比较简单,通过create方法创建一个侧滑VIew,然后通过setMenuView方法设置一个侧滑View进去,有需要设置宽度的话, 通过setMenuWidth方法来设置即可,最后用show()方法滑出来就可以啦,使用起来是不是很方便?

private XCSlideView mSlideViewLeft;
//屏幕宽度
private int mScreenWidth = 0;
View menuViewLeft = LayoutInflater.from(mContext).inflate(R.layout.layout_slideview,null);
mSlideViewLeft = XCSlideView.create(this, XCSlideView.Positon.LEFT);
mSlideViewLeft.setMenuView(MainActivity.this, menuViewLeft);
mSlideViewLeft.setMenuWidth(mScreenWidth * 7 / 9);
Button left = (Button)findViewById(R.id.btn_left);
 left.setOnClickListener(new View.OnClickListener() {

 @Override
 public void onClick(View v) {
 // TODO Auto-generated method stub
 if (!mSlideViewLeft.isShow())
  mSlideViewLeft.show();
 }
 });

四、源码下载

下载:侧滑菜单

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# Android  # View  # 侧滑菜单  # Android编程之下拉菜单Spinner控件用法示例  # Android自定义控件实现底部菜单(下)  # Android自定义控件实现底部菜单(上)  # Android 中 SwipeLayout一个展示条目底层菜单的侧滑控件源码解析  # Android自定义控件案例汇总1(菜单、popupwindow、viewpager)  # Android自定义控件简单实现侧滑菜单效果  # Android自定义控件之仿优酷菜单  # Android使用自定义控件HorizontalScrollView打造史上最简单的侧滑菜单  # Android控件之菜单的创建方式  # 自定义  # 标题栏  # 中去  # 滑出  # 只有一个  # 就来  # 有无  # 的是  # 状态栏  # 几个  # 我就  # 是因为  # 让他  # 有很多  # 很简单  # 来看看  # 考虑到  # 只需要  # 为例  # 拖动 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 浅谈redis在项目中的应用  在线ppt制作网站有哪些软件,如何把网页的内容做成ppt?  Laravel事件监听器怎么写_Laravel Event和Listener使用教程  制作ppt免费网站有哪些,有哪些比较好的ppt模板下载网站?  Laravel如何监控和管理失败的队列任务_Laravel失败任务处理与监控  详解Android——蓝牙技术 带你实现终端间数据传输  Laravel怎么实现搜索功能_Laravel使用Eloquent实现模糊查询与多条件搜索【实例】  Laravel Eloquent:优雅地将关联模型字段扁平化到主模型中  文字头像制作网站推荐软件,醒图能自动配文字吗?  教你用AI润色文章,让你的文字表达更专业  昵图网官网入口 昵图网素材平台官方入口  Thinkphp 中 distinct 的用法解析  购物网站制作费用多少,开办网上购物网站,需要办理哪些手续?  Win11摄像头无法使用怎么办_Win11相机隐私权限开启教程【详解】  Laravel如何将应用部署到生产服务器_Laravel生产环境部署流程  湖南网站制作公司,湖南上善若水科技有限公司做什么的?  Laravel Docker环境搭建教程_Laravel Sail使用指南  公司网站制作价格怎么算,公司办个官网需要多少钱?  晋江文学城电脑版官网 晋江文学城网页版直接进入  如何在万网自助建站中设置域名及备案?  zabbix利用python脚本发送报警邮件的方法  如何用手机制作网站和网页,手机移动端的网站能制作成中英双语的吗?  Python企业级消息系统教程_KafkaRabbitMQ高并发应用  如何快速搭建高效可靠的建站解决方案?  利用vue写todolist单页应用  Laravel distinct去重查询_Laravel Eloquent去重方法  Laravel观察者模式如何使用_Laravel Model Observer配置  电商网站制作价格怎么算,网上拍卖流程以及规则?  深圳网站制作的公司有哪些,dido官方网站?  东莞市网站制作公司有哪些,东莞找工作用什么网站好?  如何选择PHP开源工具快速搭建网站?  Linux网络带宽限制_tc配置实践解析【教程】  详解阿里云nginx服务器多站点的配置  Python制作简易注册登录系统  Laravel如何使用Gate和Policy进行权限控制_Laravel权限判定与策略规则配置  laravel怎么用DB facade执行原生SQL查询_laravel DB facade原生SQL执行方法  Laravel如何实现邮件验证激活账户_Laravel内置MustVerifyEmail接口配置【步骤】  如何在HTML表单中获取用户输入并用JavaScript动态控制复利计算循环  音响网站制作视频教程,隆霸音响官方网站?  Linux后台任务运行方法_nohup与&使用技巧【技巧】  详解Huffman编码算法之Java实现  Edge浏览器提示“由你的组织管理”怎么解决_去除浏览器托管提示【修复】  Laravel如何使用Blade组件和插槽?(Component代码示例)  Laravel怎么创建自己的包(Package)_Laravel扩展包开发入门到发布  高配服务器限时抢购:企业级配置与回收服务一站式优惠方案  Laravel如何实现多表关联模型定义_Laravel多对多关系及中间表数据存取【方法】  Laravel如何处理跨站请求伪造(CSRF)保护_Laravel表单安全机制与令牌校验  深圳网站制作培训,深圳哪些招聘网站比较好?  Android Socket接口实现即时通讯实例代码  制作旅游网站html,怎样注册旅游网站?