Android沉浸式状态栏 + actionBar渐变 + scrollView顶部伸缩

来源:互联网 发布:c 语言入门经典下载 编辑:程序博客网 时间:2024/04/30 19:05

闲话不多说,直接上图。




给大家讲讲我的编程思想吧。

第一部分:沉浸式状态栏(API-Level 19, Android4.4 KitKat 之后加入的东西),而且在Api-Level 21版本中新增了一个属性(下面会说到)。所以,style文件应该声明三份。




values

<style name="TranslucentTheme" parent="@style/AppTheme"></style>

values-19

<style name="TranslucentTheme" parent="@style/AppTheme">    <item name="android:windowTranslucentStatus">true</item>    <item name="android:windowTranslucentNavigation">false</item></style>

values-V21

<style name="TranslucentTheme" parent="@style/AppTheme">    <item name="android:windowTranslucentStatus">true</item>    <item name="android:windowTranslucentNavigation">false</item>    <!-- v-21 中新增的属性 -->    <item name="android:statusBarColor">@android:color/transparent</item></style>


至于以上属性的含义及使用方式,就不多做解释了。详细可参见 http://blog.csdn.net/fan7983377/article/details/51604657


第二部分:actionBar渐变


因为要实现actionBar渐变,所以我没有使用系统的actionBar。而是自定义了一个继承自LinearLayout的ViewGroup。

直接给各位看代码

package test.com.widget;import android.content.Context;import android.text.TextUtils;import android.util.AttributeSet;import android.view.View;import android.view.ViewGroup;import android.widget.LinearLayout;import android.widget.TextView;import test.com.R;import test.com.impl.ActionBarClickListener;/** * 支持渐变的 actionBar * Created by 晖仔(Milo) on 2016/12/28. * email:303767416@qq.com */public final class TranslucentActionBar extends LinearLayout {    private View layRoot;    private View vStatusBar;    private View layLeft;    private View layRight;    public TextView tvTitle;    private TextView tvLeft;    private TextView tvRight;    private View iconLeft;    private View iconRight;    public TranslucentActionBar(Context context) {        this(context, null);    }    public TranslucentActionBar(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    public TranslucentActionBar(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    private void init() {        setOrientation(HORIZONTAL);        View contentView = inflate(getContext(), R.layout.actionbar_trans, this);        layRoot = contentView.findViewById(R.id.lay_transroot);        vStatusBar = contentView.findViewById(R.id.v_statusbar);        tvTitle = (TextView) contentView.findViewById(R.id.tv_actionbar_title);        tvLeft = (TextView) contentView.findViewById(R.id.tv_actionbar_left);        tvRight = (TextView) contentView.findViewById(R.id.tv_actionbar_right);        iconLeft = contentView.findViewById(R.id.iv_actionbar_left);        iconRight = contentView.findViewById(R.id.v_actionbar_right);    }    /**     * 设置状态栏高度     *     * @param statusBarHeight     */    public void setStatusBarHeight(int statusBarHeight) {        ViewGroup.LayoutParams params = vStatusBar.getLayoutParams();        params.height = statusBarHeight;        vStatusBar.setLayoutParams(params);    }    /**     * 设置是否需要渐变     */    public void setNeedTranslucent() {        setNeedTranslucent(true, false);    }    /**     * 设置是否需要渐变,并且隐藏标题     *     * @param translucent     */    public void setNeedTranslucent(boolean translucent, boolean titleInitVisibile) {        if (translucent) {            layRoot.setBackgroundDrawable(null);        }        if (!titleInitVisibile) {            tvTitle.setVisibility(View.GONE);        }    }    /**     * 设置标题     *     * @param strTitle     */    public void setTitle(String strTitle) {        if (!TextUtils.isEmpty(strTitle)) {            tvTitle.setText(strTitle);        } else {            tvTitle.setVisibility(View.GONE);        }    }    /**     * 设置数据     *     * @param strTitle     * @param resIdLeft     * @param strLeft     * @param resIdRight     * @param strRight     * @param listener     */    public void setData(String strTitle, int resIdLeft, String strLeft, int resIdRight, String strRight, final ActionBarClickListener listener) {        if (!TextUtils.isEmpty(strTitle)) {            tvTitle.setText(strTitle);        } else {            tvTitle.setVisibility(View.GONE);        }        if (!TextUtils.isEmpty(strLeft)) {            tvLeft.setText(strLeft);            tvLeft.setVisibility(View.VISIBLE);        } else {            tvLeft.setVisibility(View.GONE);        }        if (!TextUtils.isEmpty(strRight)) {            tvRight.setText(strRight);            tvRight.setVisibility(View.VISIBLE);        } else {            tvRight.setVisibility(View.GONE);        }        if (resIdLeft == 0) {            iconLeft.setVisibility(View.GONE);        } else {            iconLeft.setBackgroundResource(resIdLeft);            iconLeft.setVisibility(View.VISIBLE);        }        if (resIdRight == 0) {            iconRight.setVisibility(View.GONE);        } else {            iconRight.setBackgroundResource(resIdRight);            iconRight.setVisibility(View.VISIBLE);        }        if (listener != null) {            layLeft = findViewById(R.id.lay_actionbar_left);            layRight = findViewById(R.id.lay_actionbar_right);            layLeft.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                    listener.onLeftClick();                }            });            layRight.setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View v) {                    listener.onRightClick();                }            });        }    }}


下面是actionbar_trans.xml的代码

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/lay_transroot"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:background="@color/colorPrimary"    android:orientation="vertical">    <View        android:id="@+id/v_statusbar"        android:layout_width="match_parent"        android:layout_height="1.0dp" />    <RelativeLayout        android:layout_width="match_parent"        android:layout_height="45dp"        android:orientation="vertical">        <RelativeLayout            android:id="@+id/lay_actionbar_left"            android:layout_width="100dp"            android:layout_height="match_parent"            android:orientation="horizontal">            <ImageView                android:id="@+id/iv_actionbar_left"                android:layout_width="20dp"                android:layout_height="20dp"                android:layout_centerVertical="true"                android:layout_marginLeft="10dp"                android:background="@mipmap/ic_left_light"                android:visibility="gone" />            <TextView                android:id="@+id/tv_actionbar_left"                style="@style/text_white"                android:layout_height="match_parent"                android:layout_marginLeft="10dp"                android:layout_toRightOf="@+id/iv_actionbar_left"                android:gravity="center_vertical"                android:maxLength="2"                android:singleLine="true"                android:text="返回"                android:visibility="gone" />        </RelativeLayout>        <TextView            android:id="@+id/tv_actionbar_title"            style="@style/text_white"            android:layout_centerInParent="true"            android:text="标题"            android:textSize="16sp" />        <RelativeLayout            android:id="@+id/lay_actionbar_right"            android:layout_width="100dp"            android:layout_height="match_parent"            android:layout_alignParentRight="true"            android:gravity="right"            android:orientation="horizontal">            <View                android:id="@+id/v_actionbar_right"                android:layout_width="20dp"                android:layout_height="20dp"                android:layout_alignParentRight="true"                android:layout_centerVertical="true"                android:layout_marginRight="10dp"                android:visibility="gone" />            <TextView                android:id="@+id/tv_actionbar_right"                style="@style/text_white"                android:layout_height="match_parent"                android:layout_marginRight="10dp"                android:layout_toLeftOf="@+id/v_actionbar_right"                android:gravity="center_vertical|right"                android:singleLine="true"                android:visibility="gone" />        </RelativeLayout>    </RelativeLayout></LinearLayout>

这里我即没有用到 android:fitsSystemWindows="true" 属性,也没有用到 StatusBarUtils ,因为我发现使用的时候很容易造成兼容问题。

所以,我的做法是声明了一个高度为0.0dp的 statusbar,背景为透明,然后获取状态栏高度并赋值到它上,来实现兼容。事实证明,这样做的兼容效果最好。


获取状态栏高度代码:

    /**     * 获取状态栏高度     *     * @return     */    public int getStatusBarHeight() {        //获取status_bar_height资源的ID        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");        if (resourceId > 0) {            //根据资源ID获取响应的尺寸值            return getResources().getDimensionPixelSize(resourceId);        }        return 0;    }

设置 statusbar高度:

    /**     * 设置状态栏高度     *     * @param statusBarHeight     */    public void setStatusBarHeight(int statusBarHeight) {        ViewGroup.LayoutParams params = vStatusBar.getLayoutParams();        params.height = statusBarHeight;        vStatusBar.setLayoutParams(params);    }

开启渐变:

  /**     * 设置是否需要渐变     */    public void setNeedTranslucent() {        setNeedTranslucent(true, false);    }    /**     * 设置是否需要渐变,并且隐藏标题     *     * @param translucent     */    public void setNeedTranslucent(boolean translucent, boolean titleInitVisibile) {        if (translucent) {            layRoot.setBackgroundDrawable(null);        }        if (!titleInitVisibile) {            tvTitle.setVisibility(View.GONE);        }    }


第三步:实现ScrollView顶部伸缩

到了这里,必须得说一下,因为是个人项目中用到,所以并没有把功能做的很强大,本人都是以最简单、有效的方式实现的。所以,代码并不像gitHub上那些被下载很多次的开源项目一样,有很高的扩展性。

时间关系,我直接贴代码吧,代码里我都写了注释的。

package test.com.widget;import android.animation.ObjectAnimator;import android.animation.ValueAnimator;import android.content.Context;import android.graphics.Color;import android.support.annotation.ColorInt;import android.support.v4.graphics.ColorUtils;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.view.WindowManager;import android.widget.ScrollView;import test.com.R;import test.com.utils.SizeUtils;/** * Created by 晖仔(Milo) on 2017/2/13. * email:303767416@qq.com */public class TranslucentScrollView extends ScrollView {    static final String TAG = "TranslucentScrollView";    //伸缩视图    private View zoomView;    //伸缩视图初始高度    private int zoomViewInitHeight = 0;    // 记录首次按下位置    private float mFirstPosition = 0;    // 是否正在放大    private Boolean mScaling = false;    //渐变的视图    private View transView;    //渐变颜色    private int transColor = Color.WHITE;    //渐变开始位置    private int transStartY = 50;    //渐变结束位置    private int transEndY = 300;    //渐变开始默认位置,Y轴,50dp    private final int DFT_TRANSSTARTY = 50;    //渐变结束默认位置,Y轴,300dp    private final int DFT_TRANSENDY = 300;    private TranslucentScrollView.TranslucentChangedListener translucentChangedListener;    public interface TranslucentChangedListener {        /**         * 透明度变化,取值范围0-255         *         * @param transAlpha         */        void onTranslucentChanged(int transAlpha);    }    public TranslucentScrollView(Context context) {        super(context);    }    public TranslucentScrollView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public TranslucentScrollView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    public void setTranslucentChangedListener(TranslucentScrollView.TranslucentChangedListener translucentChangedListener) {        this.translucentChangedListener = translucentChangedListener;    }    /**     * 设置伸缩视图     *     * @param zoomView     */    public void setPullZoomView(View zoomView) {        this.zoomView = zoomView;        zoomViewInitHeight = zoomView.getLayoutParams().height;        if (zoomViewInitHeight == LayoutParams.MATCH_PARENT || zoomViewInitHeight == WindowManager.LayoutParams.WRAP_CONTENT) {            zoomView.post(new Runnable() {                @Override                public void run() {                    zoomViewInitHeight = TranslucentScrollView.this.zoomView.getHeight();                }            });        }    }    /**     * 设置渐变视图     *     * @param transView 渐变的视图     */    public void setTransView(View transView) {        setTransView(transView, getResources().getColor(R.color.colorPrimary), SizeUtils.dip2px(getContext(), DFT_TRANSSTARTY), SizeUtils.dip2px(getContext(), DFT_TRANSENDY));    }    /**     * 设置渐变视图     *     * @param transView  渐变的视图     * @param transColor 渐变颜色     * @param transEndY  渐变结束位置     */    public void setTransView(View transView, @ColorInt int transColor, int transStartY, int transEndY) {        this.transView = transView;        //初始视图-透明        this.transView.setBackgroundColor(ColorUtils.setAlphaComponent(transColor, 0));        this.transStartY = transStartY;        this.transEndY = transEndY;        this.transColor = transColor;        if (transStartY > transEndY) {            throw new IllegalArgumentException("transStartY 不得大于 transEndY .. ");        }    }    /**     * 获取透明度     *     * @return     */    private int getTransAlpha() {        float scrollY = getScrollY();        if (transStartY != 0) {            if (scrollY <= transStartY) {                return 0;            } else if (scrollY >= transEndY) {                return 255;            } else {                return (int) ((scrollY - transStartY) / (transEndY - transStartY) * 255);            }        } else {            if (scrollY >= transEndY) {                return 255;            }            return (int) ((transEndY - scrollY) / transEndY * 255);        }    }    /**     * 重置ZoomView     */    private void resetZoomView() {        final ViewGroup.LayoutParams lp = zoomView.getLayoutParams();        final float h = zoomView.getLayoutParams().height;// ZoomView当前高度        // 设置动画        ValueAnimator anim = ObjectAnimator.ofFloat(0.0F, 1.0F).setDuration(200);        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                float cVal = (Float) animation.getAnimatedValue();                lp.height = (int) (h - (h - zoomViewInitHeight) * cVal);                zoomView.setLayoutParams(lp);            }        });        anim.start();    }    @Override    protected void onScrollChanged(int l, int t, int oldl, int oldt) {        super.onScrollChanged(l, t, oldl, oldt);        int transAlpha = getTransAlpha();        if (transView != null) {            Log.d(TAG, "[onScrollChanged .. in ], 透明度 == " + transAlpha);            transView.setBackgroundColor(ColorUtils.setAlphaComponent(transColor, transAlpha));        }        if (translucentChangedListener != null) {            translucentChangedListener.onTranslucentChanged(transAlpha);        }    }    @Override    public boolean onTouchEvent(MotionEvent event) {        if (zoomView != null) {            ViewGroup.LayoutParams params = zoomView.getLayoutParams();            switch (event.getAction()) {                case MotionEvent.ACTION_UP:                    //手指离开后恢复图片                    mScaling = false;                    resetZoomView();                    break;                case MotionEvent.ACTION_MOVE:                    if (!mScaling) {                        if (getScrollY() == 0) {                            mFirstPosition = event.getY();                        } else {                            break;                        }                    }                    int distance = (int) ((event.getY() - mFirstPosition) * 0.6);                    if (distance < 0) {                        break;                    }                    mScaling = true;                    params.height = zoomViewInitHeight + distance;                    Log.d(TAG, "params.height == " + params.height + ", zoomViewInitHeight == " + zoomViewInitHeight + ", distance == " + distance);                    zoomView.setLayoutParams(params);                    return true;            }        }        return super.onTouchEvent(event);    }}


如有问题,欢迎留言。

 

资源CSDN下载地址:还没上传,要等一下。

资源GitHub下载地址:https://github.com/yanjunhui2014/TranslucentScrollView


原创不易,转载请附上本文地址:




0 0
原创粉丝点击