Android 自定义View修炼-打造完美的自定义侧滑菜单/侧滑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(); } });
四、源码下载:
源码下载:http://download.csdn.net/detail/jczmdeveloper/9119423
http://www.cnblogs.com/JczmDeveloper/p/4821148.html
转载于:https://www.cnblogs.com/softidea/p/4822148.html
Android 自定义View修炼-打造完美的自定义侧滑菜单/侧滑View控件(转)相关推荐
- Android绘制竖直虚线完美解决方案—自定义View
Android绘制竖直虚线完美解决方案-自定义View 开发中我们经常会遇到绘制虚线的需求,一般我们使用一个drawable文件即可实现,下面我会先列举常规drawable文件的实现方式. 使用dra ...
- Android 打造完美的侧滑菜单/侧滑View控件
概述 Android 打造完美的侧滑菜单/侧滑View控件,完全自定义实现,支持左右两个方向弹出,代码高度简洁流畅,兼容性高,控件实用方便. 详细 代码下载:http://www.demodashi. ...
- 在vb中实现真正锁定的带自定义菜单的文本控件
在vb中实现真正锁定的带自定义菜单的文本控件 /// ///这个东西的出台,是由于一个网友的帖子,太气人,我才写的,很匆忙,又什么问题,请指出!谢谢 //QQ:9181729/mail:shawfil ...
- android自定义控件(6)-详解在onMeasure()方法中如何测量一个控件尺寸
今天的任务就是详细研究一下protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)方法.如果只是说要重写什么方法有什么 ...
- Android仿抖音加载框之两颗小球转动控件
Android仿抖音加载框之两颗小球转动控件 本篇文章已授权微信公众号 hongyangAndroid(鸿洋)独家发布. 效果图 安卓版抖音v2.5加载框: 本控件效果图: 使用方法 源码地址:And ...
- 自定义view学习-手把手教你制作一个可扩展日历控件
来看看效果图先,手把手教你实现一个简易,但高扩展度的日历控件,可自由扩展成签到,单选,多选日期. 首先我们来分析实现思路.对于上图的效果,很明显是一个6x7的表格. 我们可以两个for循环控制绘制每个 ...
- 代码android点击效果,GitHub - likaiyuan559/TouchEffects: Android View点击特效TouchEffects,几行代码为所有控件添加点击效果...
Android 点击特效TouchEffects TouchEffects能够帮助你更快速方便的增加点击时候的效果,TouchEffects的目标是打造一个稳定.全面.且能更方便的自定义及个性化的一款 ...
- Android仿苹果版QQ下拉刷新实现(一) ——打造简单平滑的通用下拉刷新控件
前言: 因为公司人员变动原因,导致了博主四个月没有动安卓,一直在做IOS开发,如今接近年前,终于可以花一定的时间放在安卓上了.好了,废话不多说,今天我们要带来的效果是苹果版本的QQ下拉刷新.首先看一下 ...
- view类不响应自定义消息_安卓平台如何给控件添加自定义操作?
在安卓应用设计和开发过程中,设计人员为了界面简洁.有独特的交互方式,可能会为控件设计特殊的操作手势,例如消息列表中单指按住消息向左滑删除消息:系统顶部的通知单指向左滑可以关闭通知等. 这些操作对于普通 ...
最新文章
- 抽样方法,采样方法 shuffle
- 图像色彩空间与应用转换
- C++ 流体效果的实现
- 读书精要《从一到无穷大》
- vue element-ui-tree样式总结
- web页面制作-环游记(一)
- ASP.NET Web API 2框架揭秘
- 上采样卷积转置的deconvolution方法实现双线性插值,代码实现,结果不一样
- 5天玩转C#并行和多线程编程 —— 第三天 认识和使用Task
- 框架的配置文件的映射机制
- 【JAVASCRIPT】使用ztree树,实现右键增加,修改,删除节点。带有复选框。
- 爬取汽车之家所有汽车参数配置
- python就业方向
- python 钉钉导出Excel考勤统计
- 正确的姿势很重要:该如何执笔
- 论文Re-ranking Person Re-identification with k-reciprocal Encoding(person re-id的re-ranking)
- 俞一帆:5G边缘计算助力工业现场智能
- 抖音常见的违规封号行为;怎么避免抖音违规;丨国仁网络资讯
- 常用图形渲染API简介
- iOS 使用 SceneKit 实现全景图