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

一、概述

  在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();
 }
 });

四、源码下载

下载:侧滑菜单

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

(0)

相关推荐

  • Android控件之菜单的创建方式

    显示效果图: 第一种创建方式 ------- package com.example.androidthismenus; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; public class MainActivity extends Activity { @Override protected void onCreate

  • Android 中 SwipeLayout一个展示条目底层菜单的侧滑控件源码解析

    由于项目上的需要侧滑条目展示收藏按钮,记得之前代码家有写过一个厉害的开源控件 AndroidSwipeLayout 本来准备直接拿来使用,但是看过 issue 发现现在有不少使用者反应有不少的 bug ,而且代码家现在貌似也不进行维护了.故自己实现了一个所要效果的一个控件.因为只是实现我需要的效果,所以大家也能看到,代码里有不少地方我是写死的.希望对大家有些帮助.而且暂时也不需要 AndroidSwipeLayout 大而全的功能,算是变相给自己做的项目精简代码了. 完整示例代码请看:GitHu

  • Android自定义控件简单实现侧滑菜单效果

    侧滑菜单在很多应用中都会见到,最近QQ5.0侧滑还玩了点花样~~对于侧滑菜单,一般大家都会自定义ViewGroup,然后隐藏菜单栏,当手指滑动时,通过Scroller或者不断的改变leftMargin等实现:多少都有点复杂,完成以后还需要对滑动冲突等进行处理~~今天给大家带来一个简单的实现,史上最简单有点夸张,但是的确是我目前遇到过的最简单的一种实现~~~ 1.原理分析 既然是侧滑,无非就是在巴掌大的屏幕,塞入大概两巴掌大的布局,需要滑动可以出现另一个,既然这样,大家为啥不考虑使用Android

  • Android自定义控件之仿优酷菜单

    去年的优酷HD版有过这样一种菜单,如下图: 应用打开之后,先是三个弧形的三级菜单,点击实体键menu之后,这三个菜单依次旋转退出,再点击实体键menu之后,一级菜单会旋转进入,点击一级菜单,二级菜单旋转进入,点击二级菜单的menu键,三级菜单旋转进入,再次点击二级菜单的旋转键,三级菜单又会旋转退出,这时再点击一级菜单,二级菜单退出,最后点击实体menu键,一级菜单退出. 总体来说实现这样的功能: (1)点击实体menu键时,如果界面上有菜单显示,不管有几个,全部依次退出,如果界面上没有菜单显示,

  • Android自定义控件实现底部菜单(下)

    在app中经常会用到底部菜单的控件,每次都需要写好多代码,今天我们用到了前几篇博客里的控件来进一步封装底部菜单.先看效果图: 主要包括以下功能: 1 设置icon以及点击之后的icon 2 设置文字 3 设置文字颜色以及点击之后的文字颜色 4 设置未读数量.更多以及new 我们先看如何使用,然后再看如何实现的 1 在布局文件中引用MenuM <com.landptf.view.MenuM android:id="@+id/mm_bottom" android:layout_wid

  • Android编程之下拉菜单Spinner控件用法示例

    本文实例讲述了Android下拉菜单Spinner控件用法.分享给大家供大家参考,具体如下: activity_main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent

  • Android使用自定义控件HorizontalScrollView打造史上最简单的侧滑菜单

    侧滑菜单在很多应用中都会见到,最近QQ5.0侧滑还玩了点花样~~对于侧滑菜单,一般大家都会自定义ViewGroup,然后隐藏菜单栏,当手指滑动时,通过Scroller或者不断的改变leftMargin等实现:多少都有点复杂,完成以后还需要对滑动冲突等进行处理~~今天给大家带来一个简单的实现,史上最简单有点夸张,但是的确是我目前遇到过的最简单的一种实现~~~ 1.原理分析 既然是侧滑,无非就是在巴掌大的屏幕,塞入大概两巴掌大的布局,需要滑动可以出现另一个,既然这样,大家为啥不考虑使用Android

  • Android自定义控件案例汇总1(菜单、popupwindow、viewpager)

    自定义控件是根据自己的需要自己来编写控件.安卓自带的控件有时候无法满足你的需求,这种时候,我们只能去自己去实现适合项目的控件.同时,安卓也允许你去继承已经存在的控件或者实现你自己的控件以便优化界面和创造更加丰富的用户体验.在平常的项目中,我们 人为的把自定义控件分为两种:一种是组合方式实现.一种是通过继承view或viewgroup及其子类实现.两者都可以实现我们想要的效果,因此,我们可以根据自己的需求,选择合适的方案.本文以案例的形式来显示几种较为常见的自定义控件. 案例一 优酷菜单: 功能介

  • Android自定义控件实现底部菜单(上)

    今天我们封装一个底部的菜单栏,这个大多数的应用都会用到,因此我们来自定义,方便以后项目的使用. 该控件的实现将分上下篇来介绍,先来看一个菜单栏的子控件–MenuItemM,这个控件有什么用呢?我们来看下一些主流app上的一些控件,如: 以上三张图片分别来自微信,今日头条和去哪儿,接下来我们将看到如何通过一个控件来实现不同的效果. 首先看下我写的一个deme 可以看到标题栏的消息控件,以及底部三个菜单项都是通过MenuItemM来实现的 这里面只是演示菜单栏的子控件,我们将在下一篇博客中完成底部菜

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

    一.概述 在App中,经常会出现侧滑菜单,侧滑滑出View等效果,虽然说Android有很多第三方开源库,但是实际上咱们可以自己也写一个自定义的侧滑View控件,其实不难,主要涉及到以下几个要点: 1.对Android中Window类中的DecorView有所了解 2.对Scroller类实现平滑移动效果 3.自定义ViewGroup的实现 首先来看看效果图吧:     下面现在就来说说这里咱们实现侧滑View的基本思路吧,这里我采用的是自定义一个继承于RelativeLayout的控件叫做XC

  • 使用PlatformView将 Android 控件view制作成Flutter插件

    目录 引言 1. FlutterPlugin 创建 2. 创建 Android 控件 3. 注册 Android 控件 4. 封装 Android 层通信交互 ‘CustomViewController’ 代码说明 5. 在 flutter 中如何使用已注册的 Android 控件(view) 代码说明 如何使用这个View 6. 附上 example 完整代码 引言 小编最近在项目中实现相机识别人脸的功能,将 Android 封装的控件 view 进行中转,制作成 FlutterPlugin

  • Android控件View的文字周围添加图标

    在Android控件View的文字周围添加图标,供大家参考,具体内容如下 在控件TextView文字周围放置图片(基于TextView的Button也能实现),减少多布局组合嵌套. 优点:使用LinearLayout对ImageView和TextView组合布局固然可行, 但是布局文件会冗长许多. 以TextView为例: 在XML布局文件中设置以下5个属性: drawableTop: 指定文本上方的图形. drawableBottom: 指定文本下方的图形. drawableLeft: 指定文

  • Android控件之RatingBar自定义星级评分样式

    一.RatingBar简单介绍 RatingBar是基于SeekBar(拖动条)和ProgressBar(状态条)的扩展,用星形来显示等级评定,在使用默认RatingBar时,用户可以通过触摸/拖动/按键(比如遥控器)来设置评分, RatingBar自带有两种模式 ,一个小风格 ratingBarStyleSmall,大风格为ratingBarStyleIndicator,大的只适合做指示,不适用与用户交互. 效果图展示: 二.实例 1.布局文件 <?xml version="1.0&qu

  • Android布局控件View ViewRootImpl WindowManagerService关系

    目录 1. View,ViewRoot和WindowManager简单介绍 1.1 View和ViewGroup 1.2 ViewRootImpl 1.3 WindowManager 2. ViewRootImpl的起源 2.1 ViewRootImpl创建时机 2.2 ViewRootImpl通知注册Window 3.ViewRootImpl与WindowManagerService的通信 3.1 WindowSession 3.2 IWindow 4. ViewRootImpl与View 1

  • android 控件同时监听单击和双击实例

    不适用click而用touch 自定义监听: class myOnGestureListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onDoubleTap(MotionEvent e) { //点赞 mLoadingListener.onFinishedLoading("0");//取消点赞 是一个接口 //已经点赞 更换图片 1:已经点赞 0 :没有点赞 if (lik

  • Android控件ListView使用方法详解

    Android控件ListView使用方法介绍,具体如下 一.ListView的简单用法 首先新建一个ListViewTest项目,并让Android Studio自动创建好活动.然后修改activity_main.xml中的代码,如下: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/re

  • Android控件之ListView用法实例详解

    本文实例讲述了Android控件之ListView用法.分享给大家供大家参考.具体如下: 示例一: 在android开发中ListView是比较常用的组件,它以列表的形式展示具体内容,并且能够根据数据的长度自适应显示. main.xml布局文件: <?xml version="1.0" encoding="utf-8"?> <LinearLayout android:id="@+id/LinearLayout01" androi

  • Android控件之Gallery用法实例分析

    本文实例讲述了Android控件之Gallery用法.分享给大家供大家参考.具体如下: Gallery组件主要用于横向显示图像列表,不过按常规做法.Gallery组件只能有限地显示指定的图像.也就是说,如果为Gallery组件指定了10张图像,那么当Gallery组件显示到第10张时,就不会再继续显示了.这虽然在大多数时候没有什么关系,但在某些情况下,我们希望图像显示到最后一张时再重第1张开始显示,也就是循环显示.要实现这种风格的Gallery组件,就需要对Gallery的Adapter对象进行

  • Android控件系列之Button以及Android监听器使用介绍

    学习目的: 1.掌握在Android中如何建立Button 2.掌握Button的常用属性 3.掌握Button按钮的点击事件(监听器) Button是各种UI中最常用的控件之一,它同样也是Android开发中最受欢迎的控件之一,用户可以通过触摸它来触发一系列事件,要知道一个没有点击事件的Button是没有任何意义的,因为使用者的固定思维是见到它就想去点! 先看下Android中普通Button的样子: 以及点中Button后的样子: 我在Android控件系列之XML静态资源中已经强调了布局和

随机推荐