栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 移动开发 > Android

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

Android 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

先看看QQ的侧滑效果

分析一下

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

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

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

具体实现

布局代码


    
    
      
      
    
    
    
    
    
    
    
    
    
    
    
  

自定义的侧滑视图

最核心的部分

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 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;
    
    float scaleLeft = 0.4f - 0.4f * scale;
    
    ViewHelper.setTranslationX(bluetooth, -(mBluetoothWidth * scaleLeft));
    Log.e("TAG", "mBluetoothWidth+" + mBluetoothWidth);
    Log.e("TAG", "=============" + mBluetoothWidth * scale + "scale" + scale);


  }
}

扩展

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


  
    
    
  

在布局里设置边距

 

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

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

总结

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/157945.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号