简单粗暴打造BottomSheet效果

过程分析

当下很多应用实现了这样一个效果,可以从窗口侧边划出隐藏的部分视图,划出过程中背景色逐渐改变,官方的BottomSheet就实现了这样一个效果。但毕竟官方代码出于健壮性和安全性等的考虑,api设计的较为复杂,今天我们就尝试自己实现一下。为了贯彻”熔岩流”精神,我们先上效果图:

image

image

废话不多说了,来看下实现吧。

代码实现

  • SideMenu类中包含了主要的逻辑,其他的代码较为简单:
package com.ajay.sidemenu.view;

import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.res.Resources;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

/**
 * desc: The menu support above and below.
 * author:AjayNiu
 * date:2016/11/12
 */
public class SideMenu {

    public static final int DIRECTION_TOP = 1;
    public static final int DIRECTION_BOTTOM = 2;

    private static final int ALPHA_SPAN = 200;
    private static final int ANIM_DURATION = 250;

    private int screenHeight;

    private int mStartY;
    private int mEndY;

    private View mMenu;
    private int mDirection;
    private View overlapView;
    private boolean isMenuVisible;

    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            alignPosition(mDirection);
        }
    };

    public void init(Activity activity, View menu, int direction) {
        mMenu = menu;
        mDirection = direction;
        screenHeight = Resources.getSystem().getDisplayMetrics().heightPixels;

        overlapView = new View(activity);
        overlapView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT
                , ViewGroup.LayoutParams.MATCH_PARENT));


        FrameLayout rootLayout = (FrameLayout) activity.getWindow().getDecorView();
        if (direction == DIRECTION_TOP) {
            rootLayout = (FrameLayout) activity.getWindow().getDecorView().findViewById(android.R.id.content);
        } else if (direction == DIRECTION_BOTTOM) {
            rootLayout = (FrameLayout) activity.getWindow().getDecorView();
        }

        rootLayout.addView(overlapView);
        rootLayout.addView(menu);

        menu.post(runnable);

        // touch event
        overlapView.setOnTouchListener(new MenuTouchEventListener());
    }

    public void toggle() {
        if (isMenuVisible) {
            hideMenu();
        } else {
            showMenu();
        }
        isMenuVisible = !isMenuVisible;
    }

    public boolean isMenuVisible() {
        return isMenuVisible;
    }

    private void alignPosition(int direction) {
        if (direction == DIRECTION_BOTTOM) {
            mMenu.setTranslationY(screenHeight);
            mStartY = screenHeight;
            mEndY = screenHeight - mMenu.getHeight();
        } else if (direction == DIRECTION_TOP) {
            mMenu.setTranslationY(-mMenu.getHeight());
            mStartY = -mMenu.getHeight();
            mEndY = 0;
        }
    }

    private void showMenu() {
        ObjectAnimator translationY = ObjectAnimator.ofFloat(mMenu, View.TRANSLATION_Y, mStartY, mEndY);
        translationY.setDuration(ANIM_DURATION);
        translationY.setInterpolator(new FastOutSlowInInterpolator());
        translationY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float fraction = animation.getAnimatedFraction();
                int color = (int) ((fraction) * ALPHA_SPAN) * 0x01000000;
                overlapView.setBackgroundColor(color);
            }
        });
        translationY.start();
    }

    private void hideMenu() {
        ObjectAnimator translationY = ObjectAnimator.ofFloat(mMenu, View.TRANSLATION_Y, mEndY, mStartY);
        translationY.setDuration(ANIM_DURATION);
        translationY.setInterpolator(new FastOutSlowInInterpolator());
        translationY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float fraction = animation.getAnimatedFraction();
                int color = (int) ((1 - fraction) * ALPHA_SPAN) * 0x01000000;
                overlapView.setBackgroundColor(color);
            }
        });
        translationY.start();
    }

    private class MenuTouchEventListener implements View.OnTouchListener {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (isMenuVisible) {
                hideMenu();
                isMenuVisible = false;
            }
            return false;
        }
    }
}

- 完整代码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值