现在android中有很多产品实现了侧边栏菜单的滑动,比如说百度贴吧、腾讯QQ、Facebook、知乎等,这样做的好处:
一是可以装下更多的内容,二是给用户更好的视觉感受。
下面举一个知乎的例子:
一、实现的思路:
首先定义三个FrameLayout:leftMenu、middleMenu、rightMenu
middleMenu为主面板,大小设置为屏幕的大小;
leftMenu、rightMenu为左右侧边栏,大小设置为屏幕的一定比例,我设置的是80%,位置分别设置在middleMenu的左右两边,一开始打开的时候并不能看见。
实现的滑动的方法是dispatchTouchEvent() :
通过ACTION_DOWN和ACTION_MOVE不断获取滑动中的x、y坐标来进行判断是上下滑动还是左右滑动,通过Scroller来实现滑动的动画效果。
二、代码:
import android.content.Context; import android.graphics.Color; import android.graphics.Point; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.animation.DecelerateInterpolator; import android.widget.FrameLayout; import android.widget.RelativeLayout; import android.widget.Scroller; public class MainUI extends RelativeLayout { private Context context; private FrameLayout leftMenu;//设置左面板 private FrameLayout middleMenu;//设置主面板 private FrameLayout rightMenu;//设置右面板 private Scroller mScroller; private FrameLayout middleMask; public static final int LEFT_ID = 0xaabbcc; public static final int MIDDLE_ID = 0xaaccbb; public static final int RIGHT_ID = 0xccbbaa; public MainUI(Context context) { super(context); initView(context); } public MainUI(Context context, AttributeSet attrs) { super(context, attrs); initView(context); } private void initView(Context context) {//初始化 this.context = context; mScroller = new Scroller(context, new DecelerateInterpolator()); leftMenu = new FrameLayout(context); middleMenu = new FrameLayout(context); rightMenu = new FrameLayout(context); middleMask = new FrameLayout(context); leftMenu.setBackgroundColor(Color.RED); middleMenu.setBackgroundColor(Color.GREEN); rightMenu.setBackgroundColor(Color.RED); leftMenu.setId(LEFT_ID); middleMenu.setId(MIDDLE_ID ); rightMenu.setId(RIGHT_ID ); middleMask.setBackgroundColor(0x88000000); addView(leftMenu); addView(middleMenu); addView(rightMenu); addView(middleMask); middleMask.setAlpha(0);//设置透明度 } public float onMiddleMask(){ System.out.println("透明度:"+middleMask.getAlpha()); return middleMask.getAlpha(); } public void scrollTo(int x,int y){//滑动方法 super.scrollTo(x,y); onMiddleMask(); int curX = Math.abs(getScrollX()); float scale = curX/(float)leftMenu.getMeasuredWidth(); middleMask.setAlpha(scale); } protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//设置面板大小 super.onMeasure(widthMeasureSpec, heightMeasureSpec); middleMenu.measure(widthMeasureSpec, heightMeasureSpec); middleMask.measure(widthMeasureSpec, heightMeasureSpec); int realWidth = MeasureSpec.getSize(widthMeasureSpec); int tempWidthMeasure = MeasureSpec.makeMeasureSpec((int) (realWidth * 0.8f), MeasureSpec.EXACTLY); leftMenu.measure(tempWidthMeasure, heightMeasureSpec); rightMenu.measure(tempWidthMeasure, heightMeasureSpec); } protected void onLayout(boolean changed, int l, int t, int r, int b) {//设置面板位置 super.onLayout(changed, l, t, r, b); middleMenu.layout(l, t, r, b); middleMask.layout(l, t, r, b); leftMenu.layout(l - leftMenu.getMeasuredWidth(), t, l, b); rightMenu.layout(l + middleMenu.getMeasuredWidth(), t, r + rightMenu.getMeasuredWidth(), b); } private boolean isTestCompete; private boolean isleftrightEvent; public boolean dispatchTouchEvent(MotionEvent ev) {//事件分发 if (!isTestCompete) { getEventType(ev); return true; } if (isleftrightEvent) {//如果是左右滑动 switch (ev.getActionMasked()) { case MotionEvent.ACTION_MOVE: int curScrollX = getScrollX();//滚动距离 int dis_x = (int) (ev.getX() - point.x);//手指按下后滑动距离 int expectX = -dis_x + curScrollX; int finalX = 0; //初始化屏幕滑动距离 if (expectX < 0) { //向左滑动 finalX = Math.max(expectX, -leftMenu.getMeasuredWidth()); } else { //向右滑动 finalX = Math.min(expectX, rightMenu.getMeasuredWidth()); } scrollTo(finalX, 0);//屏幕移动 point.x = (int) ev.getX(); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: curScrollX = getScrollX(); if (Math.abs(curScrollX) > leftMenu.getMeasuredWidth() >> 1) {//滑动大于屏幕距离一半时,启动动画 if (curScrollX < 0) {//向左 mScroller.startScroll(curScrollX, 0, -leftMenu.getMeasuredWidth() - curScrollX, 0); } else {//向右 mScroller.startScroll(curScrollX, 0, leftMenu.getMeasuredWidth() - curScrollX, 0); } } else { mScroller.startScroll(curScrollX, 0, -curScrollX, 0);//距离不到返回原点 } invalidate();//View重绘 isleftrightEvent = false; isTestCompete = false; break; } } else {//上下滑动也要初始化 switch (ev.getActionMasked()) { case MotionEvent.ACTION_UP: isleftrightEvent = false; isTestCompete = false; break; } } return super.dispatchTouchEvent(ev); } private Point point = new Point(); private static final int TEST_DIS = 20; public void computeScroll() {//回调方法 super.computeScroll(); if (!mScroller.computeScrollOffset()) { return; } int tempX = mScroller.getCurrX();//总滑动值 scrollTo(tempX, 0); } private void getEventType(MotionEvent e) {//判断事件类型 switch (e.getActionMasked()){ case MotionEvent.ACTION_DOWN: point.x=(int) e.getX(); point.y=(int) e.getY(); super.dispatchTouchEvent(e); break; case MotionEvent.ACTION_MOVE: int dX = Math.abs((int) e.getX()-point.x); int dY = Math.abs((int) e.getY()-point.y); if(dX > TEST_DIS && dX > dY){//左右滑动 isleftrightEvent = true; isTestCompete = true; point.x = (int)e.getX(); point.y = (int)e.getY(); }else if(dY > TEST_DIS && dY>dX){//上下滑动 isleftrightEvent = false; isTestCompete = true; point.x = (int)e.getX(); point.y = (int)e.getY(); } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: super.dispatchTouchEvent(e); isleftrightEvent = false; isTestCompete = false; break; } } }
源码已上传。
相关推荐
本项目是针对网易新闻客户端的侧滑菜单效果进行的仿制,旨在帮助开发者学习如何在Android中实现自定义的侧滑菜单功能。 首先,我们来了解一下侧滑菜单的基本结构。一个典型的侧滑菜单通常由两部分组成:主内容视图...
在Android应用开发中,侧滑菜单(DrawerLayout)是一种常见的设计模式,用于提供导航和功能选项。本实例代码着重讲解如何实现一个支持双向侧滑的自定义控件,即不仅可从左侧滑出,也能从右侧滑出。下面将详细阐述...
总结起来,实现Android自定义侧滑菜单涉及的关键步骤包括使用`DrawerLayout`作为基础容器,创建菜单视图,处理滑动手势,控制菜单的开关,以及实现菜单项的交互。通过这些步骤,我们可以创建出符合用户习惯的侧滑...
总的来说,自定义ViewGroup和实现侧滑功能是Android开发中的重要技能,通过"Android自定义侧滑框架"项目,你可以锻炼到布局设计、手势检测和动画应用等多个方面的技术。对于初学者来说,这是一个很好的实践项目,有...
这个“Android高级应用源码-android自定义控件-侧滑菜单.zip”压缩包中,很可能包含了一个实现这种侧滑效果的自定义控件的源代码。 侧滑菜单通常由两部分组成:主要内容视图和侧滑视图。主要内容视图显示在屏幕中央...
标题提到的"ViewDragHelper自定义侧滑菜单"就是一个典型的例子,它允许开发者创建类似Google Material Design中的抽屉式菜单,通常用于隐藏主界面之外的附加内容,如导航菜单。ViewDragHelper是Android SDK提供的一...
在Android应用开发中,侧滑菜单(也称为抽屉式导航菜单)是一种常见的设计模式,它允许用户通过从屏幕边缘向内滑动来显示或隐藏菜单。这种设计为用户提供了一种方便的方式来浏览应用的主要功能,而不会遮挡主内容...
总的来说,自定义侧滑菜单涉及到了Android视图系统的深度理解,包括自定义视图、事件分发、状态监听以及布局管理。通过以上步骤,我们可以创建一个功能完善的侧滑菜单,提供给用户更加直观和便捷的操作体验。在实际...
这个"安卓SlidingMenu各种菜单侧滑菜单相关-android自定义控件-侧滑菜单.zip"文件包含了一些关于如何在Android应用中实现这一功能的资源和代码示例。以下是一些关键知识点: 1. **SlidingMenu库**:SlidingMenu是一...
在Android应用开发中,侧滑菜单(Slide Menu)是一种常见的设计模式,用于提供导航和功能选项,用户只需从屏幕边缘向内滑动即可显示或隐藏菜单。这种菜单通常被用在许多应用程序中,如Google应用、Facebook应用等,...
在Android开发中, DrawerLayout 是一个非常重要的布局组件,它被广泛用于实现应用程序的侧滑菜单功能。这个组件是Google官方Android SDK的一部分,是Android Studio中的一个标准库,因此被称为"Android Studio官方...
5. **集成到项目中**:将自定义侧滑菜单作为一个单独的组件,可以通过继承`View`或`ViewGroup`来实现,然后在需要的地方通过XML布局文件或代码动态添加到Activity或Fragment中。 6. **兼容性考虑**:确保自定义控件...
总的来说,实现一个自定义的Android侧滑菜单涉及到手势检测、动画实现、布局管理和组件交互等多个方面。尽管有现成的库可以使用,但自定义控件能让我们更好地控制用户体验,实现更加个性化的设计。通过不断实践和...
1. `CustomSideslipMenu.java`:这是自定义侧滑菜单的核心类,实现了上述两种效果的逻辑。 2. `activity_main.xml`:主布局文件,包含了内容视图和菜单视图。 3. `menu_left.xml`:定义了侧滑菜单的布局和内容。 4. ...
在Android应用开发中,侧滑菜单(也称为抽屉式导航菜单)是常见的设计模式,它为用户提供了一种直观的方式来浏览应用的主要功能或导航选项。本篇将详细讲解如何实现一个具有折叠动画效果的酷炫侧滑菜单。 首先,...
在Android应用开发中,侧滑菜单(也称为抽屉式导航)是一种常见的设计模式,它允许用户通过从屏幕边缘向内滑动来显示隐藏的菜单选项。这种效果在许多流行的应用如易信中都可以看到。在本文中,我们将深入探讨如何...
总之,自定义ViewGroup在Android开发中扮演着重要角色,尤其对于实现特定交互效果如侧滑菜单来说,自定义ViewGroup能帮助开发者更好地控制布局和动画,提升应用的可定制性和用户体验。通过理解并实践这些关键步骤,...