基于Android实现仿QQ5.0侧滑

本课程将带领大家通过自定义控件实现QQ5.0侧滑菜单,课程将循序渐进,首先实现最普通的侧滑菜单,然后引入属性动画与拖动菜单效果相结合,最终实现QQ5.0侧滑菜单效果。通过本课程大家会对侧滑菜单有更深层次的了解,通过自定义控件和属性动画打造千变万化的侧滑菜单效果

效果图如下所示:

package com.example;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
public class MainActivity extends ActionBarActivity {
  private SlidingMenu mMenu;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mMenu = (SlidingMenu) findViewById(R.id.id_menu);
  }
  public void toggleMenu(View view)
  {
    mMenu.toggle();
  }
}
package com.example;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.WindowManager;
/**
 * Created by tuhao-pc on 2015/12/28.
 * 获取屏幕相关的辅助类
 */
public class ScreenUtils {
  private ScreenUtils() {
  }
  /**
   *获取屏幕的高度
   * @param context
   * @return
   */
  public static int getScreenWidth(Context context){
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    DisplayMetrics outMetrics = new DisplayMetrics();
    wm.getDefaultDisplay().getMetrics(outMetrics);
    return outMetrics.widthPixels;
  }
  /**
   * 获取屏幕的高度
   * @param context
   * @return
   */
  public static int getScreenHeight(Context context){
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    DisplayMetrics outMetrics = new DisplayMetrics();
    wm.getDefaultDisplay().getMetrics(outMetrics);
    return outMetrics.heightPixels;
  }
  /**
   * 获取手机状态栏的状态
   * @param context
   * @return
   */
  public static int getStatusHeight(Context context){
    int statusHeight = -1;
    Class<?> clazz = null;
    try {
      clazz = Class.forName("com.android.internal.R$dimen");
      Object object = clazz.newInstance();
      int height = Integer.parseInt(clazz.getField("status_bar_height").get(object).toString());
      statusHeight = context.getResources().getDimensionPixelSize(height);
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    } catch (NoSuchFieldException e) {
      e.printStackTrace();
    } catch (InstantiationException e) {
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    }
    return statusHeight;
  }
  /**
   * 获取当前屏幕截图,包含状态栏
   *
   * @param activity
   * @return
   */
  public static Bitmap snapShotWithStatusBar(Activity activity)
  {
    View view = activity.getWindow().getDecorView();
    view.setDrawingCacheEnabled(true);
    view.buildDrawingCache();
    Bitmap bmp = view.getDrawingCache();
    int width = getScreenWidth(activity);
    int height = getScreenHeight(activity);
    Bitmap bp = null;
    bp = Bitmap.createBitmap(bmp, 0, 0, width, height);
    view.destroyDrawingCache();
    return bp;
  }
  /**
   * 获取当前屏幕截图,不包含状态栏
   *
   * @param activity
   * @return
   */
  public static Bitmap snapShotWithoutStatusBar(Activity activity)
  {
    View view = activity.getWindow().getDecorView();
    view.setDrawingCacheEnabled(true);
    view.buildDrawingCache();
    Bitmap bmp = view.getDrawingCache();
    Rect frame = new Rect();
    activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
    int statusBarHeight = frame.top;
    int width = getScreenWidth(activity);
    int height = getScreenHeight(activity);
    Bitmap bp = null;
    bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height
        - statusBarHeight);
    view.destroyDrawingCache();
    return bp;
  }
}
package com.example;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import com.nineoldandroids.view.ViewHelper;
/**
 * Created by tuhao-pc on 2015/12/28.
 */
public class SlidingMenu extends HorizontalScrollView{
  private int mScreenWidth;
  private int mMenuRightPadding;
  private int mMenuWidth;
  private int mHalfMenuWidth;
  private boolean isOpen;
  private boolean once;
  private ViewGroup mMenu;
  private ViewGroup mContent;
  public SlidingMenu(Context context) {
    this(context,null);
  }
  public SlidingMenu(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }
  public SlidingMenu(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    mScreenWidth = ScreenUtils.getScreenWidth(context);
    TypedArray a = context.getTheme().obtainStyledAttributes(attrs,R.styleable.SlidingMenu,defStyleAttr,0);
    int count = a.getIndexCount();
    for(int i = 0;i < count;i++){
      int attr = a.getIndex(i);
      switch (attr){
        case R.styleable.SlidingMenu_rightPadding:{
//          默认是50
          mMenuRightPadding = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,50f,getResources().getDisplayMetrics()));
          break;
        }
      }
    }
    a.recycle();
  }
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    /**
     * 显示设置一个宽度
     */
    if(!once){
      LinearLayout wrapper = (LinearLayout) getChildAt(0);
      mMenu = (ViewGroup) wrapper.getChildAt(0);
      mContent = (ViewGroup) wrapper.getChildAt(1);
      mMenuWidth = mScreenWidth - mMenuRightPadding;
      mHalfMenuWidth = mMenuWidth/2;
      mMenu.getLayoutParams().width = mMenuWidth;
      mContent.getLayoutParams().width = mScreenWidth;
    }
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  }
  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    super.onLayout(changed, l, t, r, b);
    if(changed) {
//      将菜单隐藏
      this.scrollTo(mMenuWidth, 0);
      once = true;
    }
  }
  @Override
  public boolean onTouchEvent(MotionEvent ev) {
    int action = ev.getAction();
    switch (action){
      // Up时,进行判断,如果显示区域大于菜单宽度一半则完全显示,否则隐藏
      case MotionEvent.ACTION_UP:{
        int scrollX = getScrollX();
        if(scrollX > mHalfMenuWidth){
          this.smoothScrollTo(mMenuWidth,0);
          isOpen = false;
        }
        else{
          this.smoothScrollTo(0,0);
          isOpen = true;
        }
        return true;
      }
    }
    return super.onTouchEvent(ev);
  }
  /**
   * 打开菜单
   */
  public void openMenu()
  {
    if (isOpen)
      return;
    this.smoothScrollTo(0, 0);
    isOpen = true;
  }
  /**
   * 关闭菜单
   */
  public void closeMenu()
  {
    if (isOpen)
    {
      this.smoothScrollTo(mMenuWidth, 0);
      isOpen = false;
    }
  }
  /**
   * 切换菜单状态
   */
  public void toggle()
  {
    if (isOpen)
    {
      closeMenu();
    } else
    {
      openMenu();
    }
  }
  @Override
  protected void onScrollChanged(int l, int t, int oldl, int oldt)
  {
    super.onScrollChanged(l, t, oldl, oldt);
    float scale = l * 1.0f / mMenuWidth;
    float leftScale = 1 - 0.3f * scale;
    float rightScale = 0.8f + scale * 0.2f;
    ViewHelper.setScaleX(mMenu, leftScale);
    ViewHelper.setScaleY(mMenu, leftScale);
    ViewHelper.setAlpha(mMenu, 0.6f + 0.4f * (1 - scale));
    ViewHelper.setTranslationX(mMenu, mMenuWidth * scale * 0.7f);
    ViewHelper.setPivotX(mContent, 0);
    ViewHelper.setPivotY(mContent, mContent.getHeight() / 2);
    ViewHelper.setScaleX(mContent, rightScale);
    ViewHelper.setScaleY(mContent, rightScale);
  }
}

布局文件和资源文件(xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tu = "http://schemas.android.com/apk/res-auto"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <com.example.SlidingMenu
    android:id="@+id/id_menu"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@mipmap/img_frame_background"
    tu:rightPadding="20dp">
    <LinearLayout
      android:layout_width="wrap_content"
      android:layout_height="fill_parent"
      android:orientation="horizontal" >
      <include layout="@layout/layout_menu" />
      <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="@mipmap/qq" >
        <Button
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:onClick="toggleMenu"
          android:text="切换菜单" />
      </LinearLayout>
    </LinearLayout>
  </com.example.SlidingMenu>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="#0000" >
  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:orientation="vertical" >
    <RelativeLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content" >
      <ImageView
        android:id="@+id/one"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="20dp"
        android:src="@mipmap/img_1" />
      <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginLeft="20dp"
        android:layout_toRightOf="@id/one"
        android:text="第1个Item"
        android:textColor="#f0f0f0"
        android:textSize="20sp" />
    </RelativeLayout>
    <RelativeLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content" >
      <ImageView
        android:id="@+id/two"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="20dp"
        android:src="@mipmap/img_2" />
      <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginLeft="20dp"
        android:layout_toRightOf="@id/two"
        android:text="第2个Item"
        android:textColor="#f0f0f0"
        android:textSize="20sp" />
    </RelativeLayout>
    <RelativeLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content" >
      <ImageView
        android:id="@+id/three"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="20dp"
        android:src="@mipmap/img_3" />
      <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginLeft="20dp"
        android:layout_toRightOf="@id/three"
        android:text="第3个Item"
        android:textColor="#f0f0f0"
        android:textSize="20sp" />
    </RelativeLayout>
    <RelativeLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content" >
      <ImageView
        android:id="@+id/four"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="20dp"
        android:src="@mipmap/img_4" />
      <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginLeft="20dp"
        android:layout_toRightOf="@id/four"
        android:text="第一个Item"
        android:textColor="#f0f0f0"
        android:textSize="20sp" />
    </RelativeLayout>
    <RelativeLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content" >
      <ImageView
        android:id="@+id/five"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_centerVertical="true"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="20dp"
        android:src="@mipmap/img_5" />
      <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginLeft="20dp"
        android:layout_toRightOf="@id/five"
        android:text="第5个Item"
        android:textColor="#f0f0f0"
        android:textSize="20sp" />
    </RelativeLayout>
  </LinearLayout>
</RelativeLayout> 
(0)

相关推荐

  • Android仿QQ6.0主页面侧滑效果

    1.概述 最近一直都在带实习生做项目,发现自己好久没有写博客了,这几天更新会比较频繁,今天玩QQ的时候发现QQ主页菜单滑动效果早就变了,实在忍不住晚上就来实现一下了! 2.实现 2.1. 实现的方式多种多样 2.1.1 自定义ViewGroup ,处理其onTouch事件 2.1.2 FrameLayout + 手势处理类GestureDetector 2.2.3 使用Google自带的DrawerLayout 对其进行修改 2.2.4 继承自水平滚动HorizontalScrollView 大

  • Android基于ViewDragHelper仿QQ5.0侧滑界面效果

    QQ5.0侧滑效果实现方案有很多方式,今天我们使用ViewDragHelper来实现一下. 先上效果图: ①自定义控件SlidingMenu继承FrameLayout,放在FrameLayout上面的布局一层叠着者一层,通过getChildAt()可以很方便的获取到任意一层,进而控制此布局的变化. public class SlidingMenu extends FrameLayout { private ViewDragHelper mViewDragHelper; private int m

  • Android使用ViewDragHelper实现仿QQ6.0侧滑界面(一)

    QQ是大家离不开的聊天工具,方便既实用,自从qq更新至6.0之后,侧滑由原来的划出后主面板缩小变成了左右平滑,在外观上有了很大的提升,于是我就是尝试理解下里面的各种逻辑,结合相关资料,研究研究. 知道这里面的一个主要类是ViewDragHelper,那么首先我们要先来了解一下这个ViewDragHelper类,正所谓打蛇打七寸,我们就先来看看官方文档怎么介绍的,有什么奇特的功能. 首先继承: java.lang.Object android.support.v4.widget.ViewDragH

  • Android使用ViewDragHelper实现QQ6.X最新版本侧滑界面效果实例代码

    (一).前言: 这两天QQ进行了重大更新(6.X)尤其在UI风格上面由之前的蓝色换成了白色居多了,侧滑效果也发生了一些变化,那我们今天来模仿实现一个QQ6.X版本的侧滑界面效果.今天我们还是采用神器ViewDragHelper来实现. 本次实例具体代码已经上传到下面的项目中,欢迎各位去star和fork一下. https://github.com/jiangqqlmj/DragHelper4QQ FastDev4Android框架项目地址:https://github.com/jiangqqlm

  • Android滑动优化高仿QQ6.0侧滑菜单(滑动优化)

     推荐阅读:Android使用ViewDragHelper实现仿QQ6.0侧滑界面(一) 但是之前的实现,只是简单的可以显示和隐藏左侧的菜单,但是特别生硬,而且没有任何平滑的趋势,那么今天就来优化一下吧,加上平滑效果,而且可以根据手势滑动的方向来判断是否是显示和隐藏. 首先先来实现手势判断是否隐藏和显示 这里就要用到了一个方法了,如下: 这个是ViewDradHelper里面的方法: /** * 当view被释放的时候处理的事情(松手) * * @param releasedChild 被释放的

  • Android自定义布局实现仿qq侧滑部分代码

    自定义布局实现仿qq侧滑部分Android代码,供大家参考,具体内容如下 源码DEMO地址:https://github.com/applelili/ImitationQQ 实现说明: 通过自定义布局实现: SlidingLayout继承于 HorizontalScrollView /** * Created by Administrator on 2017/3/29. */ public class SlidingLayout extends HorizontalScrollView{ /**

  • Android使用DrawerLayout实现仿QQ双向侧滑菜单

    1.概述 之前写了一个Android 高仿 QQ5.0 侧滑菜单效果 自定义控件来袭 ,恰逢QQ5.2又加了一个右侧菜单,刚好看了下DrawerLayout,一方面官方的东西,我都比较感兴趣:另一方面,这玩意用起来的确方便,于是简单写了个demo,高仿QQ5.2双向侧滑,分享给大家. 首先看看效果图: DrawerLayout用起来真的很方便,下面一起看看用法~ 2.DrawerLayout的使用 直接将DrawerLayout作为根布局,然后其内部第一个View为内容区域,第二个View为左侧

  • Android自定义view系列之99.99%实现QQ侧滑删除效果实例代码详解

    首先声明本文是基于GitHub上"baoyongzhang"的SwipeMenuListView修改而来,该项目地址: https://github.com/baoyongzhang/SwipeMenuListView 可以说这个侧滑删除效果是我见过效果最好且比较灵活的项目,没有之一!!! 但是在使用它之前需要给大家提两点注意事项: 1,该项目支持Gradle dependence,但是目前作者提供的依赖地址对应的项目不是最新的项目,依赖过后的代码与demo中使用的不一致,会提示没有B

  • Android程序开发之使用Design包实现QQ动画侧滑效果和滑动菜单导航

    Google在2015的IO大会上,给我们带来了更加详细的Material Design设计规范,同时,也给我们带来了全新的Android Design Support Library,在这个support库里面,Google给我们提供了更加规范的MD设计风格的控件.最重要的是,Android Design Support Library的兼容性更广,直接可以向下兼容到Android 2.2.这不得不说是一个良心之作. 使用方法很简单,只需要添加一句依赖 compile 'com.android

  • Android高仿QQ6.0侧滑删除实例代码

    推荐阅读: 先给大家分享一下,侧滑删除,布局也就是前面一个item,然后有两个隐藏的按钮(TextView也可以),然后我们可以向左侧滑动,然后显示出来,然后对delete(删除键)实现监听,就可以了哈.好了那就来看看代码怎么实现的吧. 首先和之前一样 自定义View,初始化ViewDragHelper: package com.example.removesidepull; import android.content.Context; import android.support.v4.wi

随机推荐