Android自定义View 仿QQ侧滑菜单的实现代码

先看看QQ的侧滑效果

分析一下

先上原理图(不知道能否表达的清楚 ==)

-首先这里使用了 Android 的HorizontalScrollView 水平滑动布局作为容器,当然我们需要继承它自定义一个侧滑视图

- 这个容器里面有一个父布局(一般用LinerLayout,本demo用的是),这个父布局里面有且只有两个子控件(布局),初始状态菜单页的位置在Y轴上存在偏移这样可以就可以形成主页叠在菜单页的上方的视觉效果;然后在滑动的过程程中 逐渐修正偏移,最后菜单页和主页并排排列。原理搞清了实现起来就不是事儿了……

具体实现

布局代码

<fierce_luk.com.sideslipviewdemo2.SideslipView
    android:id="@+id/my_veiw"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="none"
    luk:leftPanding="200dp">
    <!--如果菜单在左边直接用 LinearLayout-->
    <FrameLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="horizontal">
      <TextView
        android:id="@+id/image2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@mipmap/homepage"
        android:gravity="center"
        android:tag="0"
        android:text="菜单"
        android:textColor="@color/colorAccent"
        android:textSize="60sp" />
      <TextView
        android:id="@+id/image1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/color1"
        android:gravity="center"
        android:tag="1"
        android:text="主页面"
        android:textColor="@color/colorAccent"
        android:textSize="60sp" />
    </FrameLayout>
    <!--<fragment-->
    <!--android:name="com.luk.bluetoothapp.fragment.MyBluetoothDevice"-->
    <!--android:layout_width="match_parent"-->
    <!--android:layout_height="match_parent"-->
    <!--android:tag="1" />-->
    <!--<fragment-->
    <!--android:name="com.luk.bluetoothapp.fragment.HomeFragment"-->
    <!--android:layout_width="match_parent"-->
    <!--android:layout_height="match_parent"-->
    <!--android:tag="0" />-->
  </fierce_luk.com.sideslipviewdemo2.SideslipView>

自定义的侧滑视图

最核心的部分

public class SideslipView extends HorizontalScrollView {
  private int mScreenWidth;//屏幕宽度
  private int mMenuLeftPadding;
  private int mBluetoothWidth;//菜单的宽度
  private int mHalfMenuWidth;
  View home;
  View bluetooth;
  protected boolean isOpen;
  protected boolean isFirst = true;
  public SideslipView(Context context) {
    // super 改 this
    this(context, null);
  }
  public SideslipView(Context context, AttributeSet attrs) {
    // super 改 this
    this(context, attrs, 0);
  }
  public SideslipView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    //测量屏幕宽度
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    DisplayMetrics metrics = new DisplayMetrics();
    wm.getDefaultDisplay().getMetrics(metrics);
    mScreenWidth = metrics.widthPixels;
    // mScreenWidth = context.getResources().getDisplayMetrics().widthPixels;
    Log.e("TAG", "MyScrollView: mScreenWidth" + mScreenWidth);
    //获取 自定义的属性值
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyScrollView);
    int n = a.length();
    for (int i = 0; i < n; i++) {
      int arrt = a.getIndex(i);
      switch (arrt) {
        case R.styleable.MyScrollView_leftPanding:
          mMenuLeftPadding = (int) a.getDimension(R.styleable.MyScrollView_leftPanding, 0);
          break;
        default:
          break;
      }
    }
    Log.e("TAG", "MyScrollView: mMenuLeftPadding" + mMenuLeftPadding);
    a.recycle();
  }
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    if (isFirst) {
      //获取子布局 并设置宽度
      //如果菜单在左边 用LinearLayout就行
//      LinearLayout layout = (LinearLayout) this.getChildAt(0);
      /**此处因为 把侧边拉出页面设置在了右边 所有用 FrameLayout
       * 不然在设置偏移量时 隐藏的侧边菜单会跑到主页面的上面*/
      FrameLayout layout = (FrameLayout) this.getChildAt(0);
      home = layout.getChildAt(1);
      bluetooth = layout.getChildAt(0);
      LayoutParams params = new LayoutParams(mBluetoothWidth,
          getResources().getDisplayMetrics().heightPixels);
      params.setMargins(mScreenWidth, 0, 0, 0);
      bluetooth.setLayoutParams(params);
      mBluetoothWidth = mScreenWidth - mMenuLeftPadding;
      home.getLayoutParams().width = mScreenWidth;
      bluetooth.getLayoutParams().width = mBluetoothWidth;
      mHalfMenuWidth = mBluetoothWidth / 2;
      isFirst = false;
    }
    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);
    //首先隐藏 Bluetooth
    if (changed)
      this.scrollTo(0, mBluetoothWidth);
  }
  Animation anim;
  @Override
  public boolean onTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
      case MotionEvent.ACTION_UP:
        int scrollX = getScrollX();
        if (scrollX >= mHalfMenuWidth) {
          Log.e("TAG", "====");
          this.smoothScrollTo(mBluetoothWidth, 0);
          isOpen = true;
        } else {
          this.smoothScrollTo(0, 0);
          isOpen = false;
        }
        //必须消耗事件
        return true;
    }
    return super.onTouchEvent(ev);
    //return true;
  }
  /**
   * 打开菜单栏
   */
  protected void openMenu() {
    if (isOpen)
      return;
    this.smoothScrollTo(mBluetoothWidth, 0);
    isOpen = true;
  }
  /**
   * 关闭菜单栏
   */
  protected void closeMenu() {
    if (!isOpen)
      return;
    this.smoothScrollTo(0, 0);
    isOpen = false;
  }
  /**
   * 按钮切换菜单
   */
  public void toggleMenu() {
    if (isOpen)
      closeMenu();
    else
      openMenu();
  }
  @Override
  protected void onScrollChanged(int l, int t, int oldl, int oldt) {
    super.onScrollChanged(l, t, oldl, oldt);
//此处 l 起始值为零(没有偏移)
    Log.e("TAG", "l=" + l + " t=" + t);
    Log.e("TAG", "oldl=" + oldl + " oldt=" + oldt);
    // scale 在 1 到 0 之间
    float scale = l * 1.0f / mBluetoothWidth;
    /**
     * 抽屉式侧滑
     * scaleLeft 从默认偏移量到偏移量 为零
     *实现
     * */
    float scaleLeft = 0.4f - 0.4f * scale;
    /**设置 X 轴方向的偏移量**/
    ViewHelper.setTranslationX(bluetooth, -(mBluetoothWidth * scaleLeft));
    Log.e("TAG", "mBluetoothWidth+" + mBluetoothWidth);
    Log.e("TAG", "=============" + mBluetoothWidth * scale + "scale" + scale);
/*
    *//**设置缩放时的 轴心点**//*
    //此处轴心为右边界的中点
    ViewHelper.setPivotY(home, mScreenWidth);
    ViewHelper.setPivotX(home, home.getHeight() / 2);
    *//**设置 XY轴方向的 缩放动画(从 1 到 0.9)**//*
    float pivoXY = 1 - 0.4f * scale;
    ViewHelper.setScaleX(home, pivoXY);
    ViewHelper.setScaleY(home, pivoXY);*/
/*
    *//**设置透明度**//*
    //从 1 到 0.6;
    float alpha = 1 - 0.4f * scale;
    ViewHelper.setAlpha(home, alpha);*/
  }
}

扩展

添加之定义属性 让用户配置菜单距离右边的边距的值;
首先在values文件夹下新建一个attr.xml,写入以下内容:

<resources>
  <declare-styleable name="MyScrollView">
    <attr name="rightPanding" format="dimension" />
    <attr name="leftPanding" format="dimension" />
  </declare-styleable>
</resources>

在布局里设置边距

 <fierce_luk.com.sideslipviewdemo2.SideslipView
    android:id="@+id/my_veiw"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="none"
    luk:leftPanding="200dp">

其他的就不赘述了,看看效果

- 源码下载Demo源码点击下载

总结

以上所述是小编给大家介绍的Android自定义View 仿QQ侧滑菜单的实现代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • android RecyclerView侧滑菜单,滑动删除,长按拖拽,下拉刷新上拉加载

    本文介绍的库中的侧滑效果借鉴自SwipeMenu,并对SipwMenu的源码做了修改与Bug修复,然后才开发出的SwipeRecyclerView. 需要说明的是,本库没有对RecyclerView做大的修改,只是ItemView的封装.看起来是对RecyclerView的修改,其实仅仅是为RecyclerView添加了使用的方法API而已. 本库已经更新了三个版本了,会一直维护下去,根据小伙伴的要求,以后也会添加一些其它功能. SwipeRecyclerView将完美解决这些问题: 以下功能全

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

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

  • Android解决viewpager嵌套滑动冲突并保留侧滑菜单功能

    重写子pagerview的dispatchTouchEvent方法,在返回前添加一句getParent().requestDisallowInterceptTouchEvent(true)中断掉事件的传递,类如下 public class SupperViewPager extends ViewPager { private int screenWidth;//屏幕宽度 public SupperViewPager(Context context) { super(context); } pub

  • Android自定义ViewGroup(侧滑菜单)详解及简单实例

    自定义侧滑菜单的简单实现 不少APP中都有这种侧滑菜单,例如QQ这类的,比较有名开源库如slidingmenu. 有兴趣的可以去研究研究这个开源库. 这里我们将一种自己的实现方法,把学习的 东西做个记录,O(∩_∩)O! 首先看效果图: 这里我们实现的侧滑菜单,是将左侧隐藏的菜单和主面板看作一个整体来实现的,而左侧隐藏的菜单和主面板相当于是这个自定义View的子View. 首先来构造该自定义View的布局: 自定义的SlideMenuView包含两个子view,一个是menuView,另一个是m

  • Android自定义HorizontalScrollView实现qq侧滑菜单

    今天看了鸿洋_大神在慕课网讲的qq5.0侧滑菜单.学了不少的知识,同时也佩服鸿洋_大神思路的清晰. 看了教程课下也自己实现了一下.代码几乎完全相同  别喷我啊..没办法 o(︶︿︶)o 唉 像素不好 没办法 找不到好的制作gif的软件. 我们暂且称侧滑左边界面的为menu,右边为content 首先是menu的布局 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:androi

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

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

  • Android自定义View 仿QQ侧滑菜单的实现代码

    先看看QQ的侧滑效果 分析一下 先上原理图(不知道能否表达的清楚 ==) -首先这里使用了 Android 的HorizontalScrollView 水平滑动布局作为容器,当然我们需要继承它自定义一个侧滑视图 - 这个容器里面有一个父布局(一般用LinerLayout,本demo用的是),这个父布局里面有且只有两个子控件(布局),初始状态菜单页的位置在Y轴上存在偏移这样可以就可以形成主页叠在菜单页的上方的视觉效果:然后在滑动的过程程中 逐渐修正偏移,最后菜单页和主页并排排列.原理搞清了实现起来

  • Android自定义SwipeLayout仿QQ侧滑条目

    Android自定义SwipeLayout仿QQ侧滑条目,供大家参考,具体内容如下 先看动图 看布局文件 activity_main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent

  • Android自定义view仿QQ的Tab按钮动画效果(示例代码)

    话不多说 先上效果图 实现其实很简单,先用两张图 一张是背景的图,一张是笑脸的图片,笑脸的图片是白色,可能看不出来.实现思路:主要是再触摸view的时候同时移动这两个图片,但是移动的距离不一样,造成的错位感,代码很简单: import android.content.Context import android.graphics.* import android.util.AttributeSet import android.view.MotionEvent import android.vi

  • Android自定义View仿QQ健康界面

    最近一直在学习自定义View相关的知识,今天给大家带来的是QQ健康界面的实现.先看效果图: 可以设置数字颜色,字体颜色,运动步数,运动排名,运动平均步数,虚线下方的蓝色指示条的长度会随着平均步数改变而进行变化.整体效果还是和QQ运动健康界面很像的. 自定义View四部曲,一起来看看怎么实现的. 1.自定义view的属性: <?xml version="1.0" encoding="utf-8"?> <resources> //自定义属性名,定

  • Android自定义View仿QQ运动步数效果

    本文实例为大家分享了Android QQ运动步数的具体代码,供大家参考,具体内容如下 今天我们实现下面这样的效果: 首先自定义属性: <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="MyQQStep"> <attr name="out_color" format="colo

  • Android自定义View仿QQ等级天数进度

    最近一直都在看自定义View这一块.差不多一个星期了吧.这个星期坚持每天更新博客,感觉自己的技术也有点突破,对自定义View的计算也有了更深的认识. 今天看到手机一个成长天数进度的控件,觉得挺有意思的,于是想自己也写一个.效果如下: 由图可以知道,这里面有很多个元素,首先是背景的矩形区域,其次就是两个环形,然后三个Text文本.其实不复杂,我们一点一点的去实现. 首先呢,画矩形背景.这里用到一个RectF的类,这个类包含一个矩形的四个单精度浮点坐标.矩形通过上下左右4个边的坐标来表示一个矩形.这

  • Android自定义View实现QQ消息气泡

    本文实例为大家分享了Android自定义View实现QQ消息气泡的具体代码,供大家参考,具体内容如下 效果图: 原理: 控件源码: public class DragView extends View {     private int defaultZoomSize = 8;     //初始化圆的大小     private int initRadius;     //圆1的圆心位置     private PointF center1;     private PointF center2

  • iOS中仿QQ侧滑菜单功能

    UITabBarController做QQ侧滑菜单效果: 首先要了解UITabBarController的层级结构: UITabBarController加载的其它UIViewController的View都是被添加在UITransitionView上(这是一个私有API),UITransitionView在self.view的0层,UITabBar在的第一层. 所以我的思路是这样的: UITransitionView与UITabBar转移到一个新的View1上去,作为滑动的部分: 在View1

  • Android_UI 仿QQ侧滑菜单效果的实现

    相信大家对QQ侧滑菜单的效果已经不陌生了吧,侧滑进入个人头像一侧,进行对头像的更改,我的收藏,QQ钱包,我的文件等一系列的操作,今天呢,主要是实现进入侧滑菜单的这一效果原理进行分析. 主要思路分析 1.首先写一个SlideMenu 继承一个帧布局FrameLayout ,因为如果继承自ViewGroup的话,需要我们自己来实现onMeasure方法,而该方法的实现一般比较麻烦且没有必要,所以选择继承系统的已有的控件FrameLayout,不用其他控件是因为FrameLayout最轻量级 2.在布

随机推荐