已经好久没写过Android开发的技术博客,只因最近项目比较急。耽误了。今天带来的QQ5.0侧滑效果。我们都对QQ5.0侧滑效果很熟悉了,就不多做介绍,就一个字“炫”。正好这次在项目就需要用这个效果,所以就拿出来给大家分享一下。也许大家认为都看了很多了,确实但是相同的效果用在不同的环境,也许你会遇到一些不一样的问题,那样你将收获到不同的东西。就比如我这次使用的时候就出现了一个HorizontalScrollView与Viewpager冲突的问题。就是我的菜单界面就是侧滑界面,然后主界面是使用了Vewpager+Fragment滑动的,然后主界面和侧滑界面就是放在同一个HorizontalScrollView中的。侧滑是实现了,后来发现ViewPager中的Fragment划不动了。所以等下我会具体讲解一下解决办法。

实现QQ5.0侧滑效果可以很多办法实现,比如可以使用一些开源框架,自定义组件。当然使用别人写好的框架固然没什么错,但是你就不想自己掌握其真正的原理吗?相信大家都是渴望对技术热爱与追求吧。如果你是一个Geek那就和我一起来了解一下华丽侧滑效果的原理吧。欢迎大家提出宝贵意见。废话不多说,开始吧

我这次主要是通过自定义控件来实现高仿QQ5.0侧滑效果的。

实现该效果的大概思想是这样的:就是将侧滑菜单的界面和主界面同时放在一个继承于HorizontalScrollView的一个自定义组件中,然后通过实时获得系统设备屏幕的宽度(主要通过重写onMeasure()方法),当我们在滑动的时候onMeasure方法会实时测量此时屏幕的宽度,也就是说屏幕的宽度会随着滑动变化而变化,为什么要获取设备的宽度呢??因为只有获取到设备宽度后,然后分别设置菜单界面宽度占屏幕宽度多少比例,主界面宽度占屏幕宽度多少比例。高度就不需要了因为高度都是一样占满屏幕,获取到屏幕的宽度后,然后按一定比例分配宽度给左菜单视图和主视图。然后把这个各自分配宽度设置到两个视图中,设置好宽度后就是定义好两个视图的位置,这个是通过重写onLayout方法来实现,该方法有个非常重要的参数就是个Boolean类型的changed参数,该参数默认是false,该参数表示默认就是初始的位置,初始位置就是左菜单占屏幕80%,而主界面占20%,那这不是我们想要的结果,我想要的结果是一进来是左菜单隐藏,而主界面占屏幕100%,所以需要对changed的值进行修改。然后通过调用smoothScrollTo(left_menu_width, 0)表示显示主界面,smoothScrollTo(0, 0)则表示显示左菜单(显示)和主界面(隐藏),先说下left_menu_width是什么,它表示左菜单的宽度。smoothScrollTo(left_menu_width, 0)表示从0到left_menu_width的位移,此时表示手指向左滑动主界面全部显示左菜单隐藏,那么主界面需要滑到的位置也就是left_menu_width(是从左菜单显示主菜单隐藏的位置滑到主菜单显示左菜单隐藏的位置),那么smoothScrollTo(0, 0)表示一直左菜单正好全部滑到屏幕的左下角(0,0)位置的时候全部显示左菜单。那么如何判别是左滑动还是右滑动呢?主要就是重写了一个onTouchEvent的方法,通过Action等于down的时候,表示手指按下,获得此时的在X轴上的坐标,然后再监听Action等于UP的时候,通过getScrollX()方法获得到从down到up事件转变所发生的位移,做个这样的设置若位移大于了左菜单的一半时候,并且为正数时,表示此时向右滑动,我们就是直接滑到左菜单显示主界面隐藏的位置也就是smoothScrollTo(0, 0),若小于左菜单的一半时候,即表示此时为负的,向左滑动,即此时向左滑动,左菜单隐藏,主界面显示也就是smoothScrollTo(left_menu_width, 0)。这样就基本实现了侧滑的原理,但是并没有做完,因为要华丽的侧滑还远远不够,因为需要在侧滑的过程中加入属性动画,当向左滑动的时候,左菜单透明度变小,字体缩放,位移变小,主界面透明度变大,字体扩大。这里对于属性动画我就直接引用一个第三方的jar包,nineoldandroids-2.4.0.jar。那么如何去控制缩放的比例的呢?别忘我们前面有个屏幕宽度,因为它是在随着滑动宽度在不断变化,从而就形成一个动态变化的比例。巧妙的利用这个比例,可以做出很多意想不到的效果出来。

下面请看代码:Activity_menu.xml总体布局代码:

<com.zhongqihong.slidingmenu.MySlidingMenu xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/left_menu"android:layout_width="wrap_content"android:layout_height="match_parent"android:fadingEdge="none"android:background="@drawable/left_menu_bg"android:scrollbars="none" ><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="match_parent"android:orientation="horizontal" ><!-- 菜单页面 --><include layout="@layout/activity_left" /><!-- 主界面 --><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:background="#FFF"android:orientation="vertical" ><includeandroid:id="@+id/includes"android:layout_width="match_parent"android:layout_height="wrap_content"layout="@layout/header_menu" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="9" ><android.support.v4.view.ViewPagerandroid:id="@+id/viewpager"android:layout_width="match_parent"android:layout_height="match_parent" ></android.support.v4.view.ViewPager></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="55dp"android:background="#eee"android:orientation="horizontal" ><LinearLayoutandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:orientation="vertical" ><ImageViewandroid:id="@+id/iv_icon_first"android:layout_width="match_parent"android:layout_height="0dp"android:layout_marginTop="2dp"android:layout_weight="2"android:scaleType="centerInside"android:src="@drawable/first2" /><TextViewandroid:id="@+id/tv_text_first"android:layout_width="match_parent"android:layout_height="0dp"android:layout_marginBottom="5dp"android:layout_weight="1"android:gravity="center"android:text="首页"android:textColor="#FF6600"android:textSize="14sp" /></LinearLayout><LinearLayoutandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:orientation="vertical" ><ImageViewandroid:id="@+id/iv_icon_second"android:layout_width="match_parent"android:layout_height="0dp"android:layout_marginTop="2dp"android:layout_weight="2"android:scaleType="centerInside"android:src="@drawable/two" /><TextViewandroid:id="@+id/tv_text_second"android:layout_width="match_parent"android:layout_height="0dp"android:layout_marginBottom="5dp"android:layout_weight="1"android:gravity="center"android:text="收入"android:textColor="#fdaf33"android:textSize="14sp" /></LinearLayout><LinearLayoutandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:orientation="vertical" ><ImageViewandroid:id="@+id/iv_icon_three"android:layout_width="match_parent"android:layout_height="0dp"android:layout_marginTop="2dp"android:layout_weight="2"android:scaleType="centerInside"android:src="@drawable/three" /><TextViewandroid:id="@+id/tv_text_three"android:layout_width="match_parent"android:layout_height="0dp"android:layout_marginBottom="5dp"android:layout_weight="1"android:gravity="center"android:text="支出"android:textColor="#fdaf33"android:textSize="14sp" /></LinearLayout><LinearLayoutandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:orientation="vertical" ><ImageViewandroid:id="@+id/iv_icon_four"android:layout_width="match_parent"android:layout_height="0dp"android:layout_marginTop="2dp"android:layout_weight="2"android:scaleType="centerInside"android:src="@drawable/four" /><TextViewandroid:id="@+id/tv_text_four"android:layout_width="match_parent"android:layout_height="0dp"android:layout_marginBottom="5dp"android:layout_weight="1"android:gravity="center"android:text="便签"android:textColor="#fdaf33" /></LinearLayout></LinearLayout></LinearLayout></LinearLayout>
自定义框架MySlidingMenu.java
<pre name="code" class="java">package com.zhongqihong.slidingmenu;import com.nineoldandroids.view.ViewHelper;
import com.zhongqihong.loadpager.R;import android.R.bool;
import android.R.integer;
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
/*** @author zhongqihong* 自定义侧滑框架* 集成HorizontalScrollView高级控件并且重写两个参数的构造方法* */
public class MySlidingMenu extends HorizontalScrollView {private int widthPixel;//屏幕的宽度private ViewGroup left_menu;private ViewGroup main_menu,main_menu_ll;private int left_menu_width;private int downX;private int main_menu_width;private float LEFT_MENU_PERCENT=0.7f;private boolean isOpen;private ViewPager vp;private ImageView Bariv;public MySlidingMenu(Context context, AttributeSet attrs) {super(context, attrs);//获取屏幕的宽度//先获取到窗体的管理器,然后通过窗口管理器去测量屏幕的宽度WindowManager manager=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);//获取窗体管理器//拿到屏幕的显示器DisplayMetrics metrics=new DisplayMetrics();manager.getDefaultDisplay().getMetrics(metrics);widthPixel=metrics.widthPixels;}/*** @author zhongqihong* 当我们滑动HorizontalScrollView时,会发现Viewpager不能再滑动了,这就是所谓HorizontalScrollView与Viewpager产生了冲突* 解决办法:* 在HorizontalScrollView类或者子类中重写dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent方法,并且加上* 在重写的每个方法中加入     vp.requestDisallowInterceptTouchEvent(true);代码,vp就是一个ViewPager滑动的时候的对象* */@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {// TODO Auto-generated method stubvp.requestDisallowInterceptTouchEvent(true);return super.dispatchTouchEvent(ev);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {// TODO Auto-generated method stubvp.requestDisallowInterceptTouchEvent(true);return super.onInterceptTouchEvent(ev);}//测量视图高度和宽度@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {LinearLayout ll=(LinearLayout) this.getChildAt(0);//拿到当前视图中的整个布局的第一个子视图,最外层的线性布局left_menu= (ViewGroup) ll.getChildAt(0);//线性布局中的第一个子视图就是左边菜单布局main_menu=(ViewGroup) ll.getChildAt(1);//线性布局中的第二个子视图就是主菜单布局//接着就是给他们设置宽度main_menu_ll=(ViewGroup)main_menu.getChildAt(1);//获得主菜单中的线性布局vp=(ViewPager)main_menu_ll.getChildAt(0);//在主菜单的线性布局中再获取Viewpager对象Bariv=(ImageView) main_menu.getChildAt(0).findViewById(R.id.includes).findViewById(R.id.iv_to_slidmenu);//获取到header_menu.xml中的iv_slidingMenu控件对象left_menu.getLayoutParams().width=(int) (widthPixel*LEFT_MENU_PERCENT);//左菜单占整个屏幕的80%left_menu_width=(int) (widthPixel*LEFT_MENU_PERCENT);main_menu.getLayoutParams().width=widthPixel;//主菜单占整个屏幕//main_menu_width=widthPixel;super.onMeasure(widthMeasureSpec, heightMeasureSpec);}//设置子视图的位置,重写onlayout方法@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {//默认change为false,默认两个子视图的位置,就是初始时给属性宽度赋值的状态,是一个左菜单视图占屏幕的80%,而主菜单则占//20%,故此这并不是我们想要的结果,我们想先看到的是主菜单,然而changed这个boolean类型的变量控制的,所以首先赋值为true使得//首先看到的是主界面changed=true;//if (changed) {this.smoothScrollTo(left_menu_width, 0);}super.onLayout(changed, l, t, r, b);}//手滑动的时候,重写滑动时候方法@Overrideprotected void onScrollChanged(int l, int t, int oldl, int oldt) {//l表示:滑动时候左边滑动的位移,top上面的位置,oldl表示之前没右滑动的时候的位置//加入属性动画、l左边位移的范围是0~left_menu_widthfloat scale=(float)l/left_menu_width;//这就是缩放的比例,是根据位移的变化而变化的(缩放范围:先是从1再变到0,以为初始位置是左菜单隐藏,left_menu_width为左菜单的宽度,左边的位移也是左菜单的宽度)//左边菜单缩放float leftScale=1.0f-scale*0.3f;//缩放比例的范围:1-0.7ViewHelper.setScaleX(left_menu, leftScale);ViewHelper.setScaleY(left_menu, leftScale);//透明度变化float leftAlpha= 0.6f + 0.4f * (1 - scale);ViewHelper.setAlpha(left_menu, leftAlpha);//位移变化ViewHelper.setTranslationX(left_menu, left_menu_width * scale * 0.8f);//主菜单的缩放功能 缩放比例0.8~1float rightScale=0.7f + 0.3f * scale;// 设置content的缩放的中心点ViewHelper.setPivotX(main_menu, 0);ViewHelper.setPivotY(main_menu, main_menu.getHeight() / 2);ViewHelper.setScaleX(main_menu, rightScale);ViewHelper.setScaleY(main_menu, rightScale);/*使得当滑动的时候,利用缩放比例scale这个动态变量,左上角的图标会随着滑动旋转的角度而变化 */float rotateDegree=(1-scale)*45.0f;//Bariv.setRotation(rotateDegree);super.onScrollChanged(l, t, oldl, oldt);}@Overridepublic boolean onTouchEvent(MotionEvent ev) {vp.requestDisallowInterceptTouchEvent(true);switch (ev.getAction()) {case MotionEvent.ACTION_DOWN://按下事件,取得按下时候X的坐标,通过按下的和抬起的时候的位移大小来判断downX=(int) ev.getX();case MotionEvent.ACTION_UP://抬起事件,获取抬起的事件int d=getScrollX();//拿到了在X轴上滑动的位移if(d<left_menu_width/2){//若滑动的位移大于左菜单的一半时表示此时向右滑动,并且就直接滑到左菜单占屏幕的70%this.smoothScrollTo(0, 0);isOpen=true;}else{this.smoothScrollTo(left_menu_width, 0);isOpen=false;}return true;}return super.onTouchEvent(ev);}//打开菜单public void openMenu(){if (isOpen) {//isOpen为true,则表明此时的左菜单已经打开的状态就直接结束函数return ;}else{//ipOpen为false,则表明此时的左菜单处于关闭状态,就需要打开this.smoothScrollTo(0, 0);//左菜单出来isOpen=true;//并把状态修改为打开状态}}//关闭菜单public void closeMenu(){if (!isOpen) {//isOpen为false,则表明此时的左菜单已经关闭的状态就直接结束函数return;}else{//ipOpen为true,则表明此时的左菜单处于打开状态,就需要关闭this.smoothScrollTo(left_menu_width, 0);//左菜单关闭isOpen=false;//并把状态修改为关闭状态}}//切换菜单的按钮public void toggle() {// TODO Auto-generated method stubif (isOpen) {//打开状态,就要关闭,调用closeMenu()closeMenu();}else{//关闭状态,就要打开,调用openMenu()openMenu();}}
}
最后就来解决一下HorizontalScrollView和Viewpager滑动的冲突问题:
解决办法如下:再重写两个方法dispatchTouchEvent,onInterceptTouchEvent在它们两个和已经重写的onTouchEvent方法中加入:
vp.requestDisallowInterceptTouchEvent(true);代码,vp也就是一个ViewPager滑动对象。就能解决此问题。
运行效果为:

打造华丽QQ5.0侧滑效果相关推荐

  1. Android 高仿 QQ5.0 侧滑菜单效果 自定义控件来袭

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/39257409,本文出自[张鸿洋的博客] 上一篇博客带大家实现了:Android ...

  2. 仿QQ5.0侧滑菜单

    一.概述 侧滑菜单现在已经非常流行了,目前大概有这么几种:最普通的侧滑,抽屉侧滑,QQ侧滑 注:本文来自慕课网 二.最普通的侧滑 先上图 代码如下: 1 public class MainActivi ...

  3. Android之高仿QQ6.6.0侧滑效果(背景动画、透明+沉浸式状态栏、渐变效果)

    根据需求实现类似QQ侧滑效果,之前看到过很多实现方式通过SlidingMenu,但是既然官方推出了自己的专属控件,那么使用DrawerLayout就是不二选择.且看下文. 一.先来看看官方文档解释 D ...

  4. android 缩放透明动画,Android之高仿QQ6.6.0侧滑效果(背景动画、透明+沉浸式状态栏、渐变效果)...

    根据需求实现类似QQ侧滑效果,之前看到过很多实现方式通过SlidingMenu,但是既然官方推出了自己的专属控件,那么使用DrawerLayout就是不二选择.且看下文. 一.先来看看官方文档解释 D ...

  5. Android仿QQ5.0侧滑菜单ResideMenu的使用和源码分析

    本文出自Cym的博客(http://blog.csdn.net/cym492224103) ResideMenu github:https://github.com/SpecialCyCi/Andro ...

  6. android中仿qq最新版抽屉,Android实现3种侧滑效果(仿qq侧滑、抽屉侧滑、普通侧滑)...

    自己实现了一下侧滑的三种方式(注释都写代码里了) 本文Demo下载地址:Andriod侧滑 本文实现所需框架:nineoldandroids下载地址:nineoldandroids 1.普通侧滑: 主 ...

  7. Android自定义控件----继承ViewGroup侧滑菜单5,抽屉式侧滑,QQ5.0效果(完结)

    效果图: 项目结构: QQ5.0的侧滑 和抽屉菜单的区别 简单的说就是在onScrollChanged方法中加入了缩放,偏移,渐变属性动画效果 区别1:内容1:内容区域 1.0到0.7 缩放效果 sc ...

  8. 使用DrawerLayout实现QQ5.0侧拉菜单效果

    在上一篇文章中,我们介绍了怎么使用DrawerLayout来实现一个简单的侧拉菜单(使用DrawerLayout实现侧拉菜单),也就是我们常说的抽屉效果,GitHub上类似效果的实现方式非常多,实现出 ...

  9. Android 沉浸式状态栏(QQ5.0透明状态栏的效果)

    大家注意一个问题: 魅族4.4系统,如果增加沉浸式状态栏,页面底部如果有按钮可能会被魅族的smbar遮挡,导致按钮不能被点击到的现象 看上面的这张图就是,魅族smatbar被隐藏后,挡住底部按钮,并且 ...

最新文章

  1. 转:delphi用URLDownloadToFile下载文件,用进度条跟踪下载进度
  2. 【算法】我面了N+算法岗候选人,这样的给了SSP
  3. selective gaussian blur /adaptive-blur
  4. mpi tcp连接报错_关于WinCC与真实PLC之间的TCP/IP连接问题-工业支持中心-西门子中国...
  5. matlab 维纳滤波恢复运动模糊,运动模糊恢复专题
  6. 用HTTP的PUT方式发送请求
  7. 奉献给你:《Visual C# 2005程序开发与界面设计秘诀》
  8. java互换_两个变量交换的四种方法(Java)
  9. 论文浅尝 - TACL2020 | TYDI QA:Google 发表一个多语言的问答语料库
  10. 2345王牌浏览器九宫格个性化设置
  11. 【leetcode刷题笔记】Merge k Sorted Lists
  12. Netty工作笔记0011---Channel应用案例2
  13. 转:完全卸载Oracle方法
  14. postman使用之二:数据同步和创建测试集
  15. c#的装箱和拆箱及值类型和引用类型
  16. mysql驱动5.1_mysql jdbc 驱动 5.1.26 官方最新版
  17. ubuntu 卸载anaconda
  18. 借用传感器用计算机测速度题,传感器原理及应用试题库(已做)
  19. 我的gitbub的学习目录
  20. 小米笔试题(句子反转)

热门文章

  1. C# 简单判断枚举值是否被定义
  2. 【办公应用软件】万彩办公大师教程丨屏幕OCR工具的应用
  3. 路由-策略Policy(路由重分发、路由过滤、路由策略)
  4. iOS 15 导航栏(Navigation)变白(导航栏不见)
  5. 伦敦国王学院EEM专业介绍
  6. kcl计算机科学与技术研究生,KCL的Data Science「伦敦大学国王学院数据科学理学硕士」...
  7. vhd虚拟硬盘作用_如何从VHD(虚拟硬盘)引导和安装Windows 8 Consumer Preview的指南
  8. 用C语言来实现扫雷小游戏
  9. 【算法打卡(二分查找)---7.12】
  10. 在python中、int表示的数据类型是_python--002--数据类型(int、str)