根据手势顶部View自动展示与隐藏

首先来看一下效果:
根据手势顶部View自动展示与隐藏_第1张图片
大体思路如下:
总体布局用了一个自定义的ViewGroup,里面包了两个View(top View,bottomView)
我在bottomView里放了ViewPager,里面又有Fragment,Fragment里放的是ListView
原理:
ViewGroup在分发touchEvent的时候先通过手势GestureDetector判断手势方向,当向上滑动的时候让topView和bottomView同时向上移动,反之亦然。

整体思路不是很难如下是干货:

布局文件

    <com.lin.gesturedetector.MyViewGroup
        android:id="@+id/view_group"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        "@+id/group_top"
            layout="@layout/view_top" />

        "@+id/group_bottom"
            layout="@layout/view_bottom" />

    com.lin.gesturedetector.MyViewGroup>

手势监听重要的是打log看一下上下滑动是数值的变化,找到其规律:

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                Log.i(tag, "onScroll -> distanceY" + distanceY);
                if (distanceY < 0) {// 手势向下滑动是负值
                    animatorLayoutOffset(1);
                }

                if (distanceY > 0) {
                    animatorLayoutOffset(0f);
                }
                return true;
            }

一定记得在ViewGroup内查找控件需要在onFinishInflate后才能找到:

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        viewTop = findViewById(R.id.group_top);
        viewBottom = findViewById(R.id.group_bottom);
    }

在ViewGroup布局的逻辑中需要处理的有一下几点:
1、onMeasure的时候要把子控件测量出来
2、onLayout时需要手动将子控件布局
接下来就是监听手势设置动画,不停的onLayout以达到topView和bottomView的布局效果

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        viewTop.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST));
        viewBottom.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

        int topHeight = viewTop.getMeasuredHeight();

        float offset = layoutOffset * topHeight;
        int width = r - l;

        float topViewYTop = offset - topHeight;
        float topViewYBottom = topViewYTop + topHeight;
        viewTop.layout(0, (int) topViewYTop, width, (int) topViewYBottom);

        viewBottom.layout(0, (int) topViewYBottom, width, (int) topViewYBottom + viewBottom.getMeasuredHeight());
    }

    private void animatorLayoutOffset(float offset) {
        if (animator != null && animator.isRunning()) {
            return;
        }

        animator = ObjectAnimator.ofFloat(this, "layoutOffset", layoutOffset, offset);
        animator.setDuration(500);
        animator.start();
    }

项目地址在这:
GitHub

你可能感兴趣的:(Android分享,布局)