仿QQ打开“我”界面的滑动效果

这个效果其实就是QQ主界面弹出“我”的滑动效果,类似于一个slideMenu的变种版。第一次看的时候老板觉得这个效果很不错,于是就让我们实现一下了。文章的主体结构就是:
讲述一下本效果的主要功能;
实现的思路;
代码展示;
代码下载;


主要功能

大概的实现效果请见下图:
效果图

通过上面的图,我们来说下这个效果的主要功能:
1.横向滑动时(有滑动边界,比如距左边20dp滑动有效,多了就不算是有效滑动),可以将菜单滑出来。
2.在菜单关闭状态下,点击”点击打开”文字,直接弹出菜单。
3.在菜单打开状态下,点击右边的布局,菜单收回。
4.在菜单打开状态下,向右滑动,菜单收回。
5.在菜单打开状态下,点击返回键,菜单收回。

实现思路

通过观察QQ的设置动画,发现其实这个动画只是主界面和”我“的界面在同时”播放“一段动画。只不过两个动画的行为不同,而这个动画通过左上角的按钮触发,而滑动的时候,是这段动画的分解动作。而图形的绘制方面,可以采用一个ViewGroup里放置两个子ViewGroup分别用来当作”主界面”和“我”的界面来使用。
本demo采用的方法是自定义一个ViewGroup,让他继承FrameLayout(与效果最契合的layout),然后给这个ViewGroup定义两个子View,leftView和rightView。然后左右两边分别定义一套动画逻辑,让他们在事件处理的时候可以“播放”这些动画。
给这个View定义两个可以让用户自己定义的属性,1个是leftView的宽度,这样等于定义了用户可以滑动的距离(因为左边的视图完全显示了,滑动也就结束了)。另一个是滑动的边界值,用来控制滑动事件的范围。

代码展示

下面来说说代码的具体实现。首先自定义了一个视图,起名为SlideView,它继承于FrameLayout,定义一些必要的成员变量

public class SlideView extends FrameLayout {
   
    private View leftView;// 左边视图的内容
    private View rightView;// 右边视图的内容
    private int width_left;// 自界面的宽度,也代表最大可滑动的距离
    private float offsetX = 0.0f;// 当前视图的偏移量(X)
    private final int OPEN = 1;// 当前状态,打开
    private final int CLOSE = 0;// 当前状态,关闭
    private int state = CLOSE;// 当前视图的状态
    private int boundary;// 可以滑动的边缘
    ...
}

我们需要把这两个视图添加进去并且进行初始化,可以使用xml的方式也可以在代码里添加,这里选择了在使用时在代码里添加,,并且对两个子视图分别进行了设置:

public void initView(final View vLeft, final View vRight) {
        if (isInit) {
  // 已经初始化,没有必要再次进行
            return;
        }
        leftView = vLeft;
        rightView = vRight;
        setupLeftView();
        setupRightView();
        SlideView.this.removeAllViews();
        SlideView.this.addView(leftView);
        SlideView.this.addView(rightView);
    }
private void setupLeftView() {
        FrameLayout.LayoutParams lps = new FrameLayout.LayoutParams(width_left,
                FrameLayout.LayoutParams.MATCH_PARENT);
        lps.gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL;
        leftView.setLayoutParams(lps);
    }

    private void setupRightView() {
        FrameLayout.LayoutParams lps = new FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.MATCH_PARENT,
                FrameLayout.LayoutParams.MATCH_PARENT);
        lps.gravity = Gravity.CENTER;
        rightView.setLayoutParams(lps);
    }

对于左边和右边的动画,定义了两个方法,这两个方法都是通过当前的进度(0-1)来决定播放到哪里,当传进0的时候,菜单完全关闭,传1,菜单完全打开

/** 进行左边的动画(参数为0.0-1.0),代表当前动画进行的进度 */
    private void doLeftAnimation(float avg) {
        leftView.setTranslationX(-width_left / 10 + avg *
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值