• Android -- 仿小米锁屏画报


    1,首先看一下我们今天实现的效果,效果图如下:

    2,首先说一下大体的实现思路,首先这个视图一共分为三层,最外层是一个RecyclerView,第二层是一个被虚化的ImageView,第三层是一个正常的ImageView。当用户滑动RecyclerView,监听滑动的高度而动态的改变第二层ImageView的透明度,当RecyclerView滑动高度超过某个特定的高度的时候,透明度达到最大值即第二层虚化的ImageView完全展现。当RecyclerView滑动到起始位置的时候,透明度达到最小值即第二层虚化的ImageView完全隐藏从而展示的是第一层的ImageView。,下面看一下具体的实现步骤:

      第一步:了解Renderscript

      这是它的官方文档,我们只需要了解它的使用就行了,大致分为一下几个步骤:

    ① 首先需要通过 Context 创建一个 Renderscript ;
    ② 其次通过创建的 Renderscript 来创建一个自己需要的脚本( ScriptIntrinsic ),比如这里③ 需要模糊,那就是 ScriptIntrinsicBlur ;
    ④ 然后至少创建一个 Allocation 类来创建、分配内存空间;
    ⑤ 接着就是对图像进行一些处理,比如说模糊处理;
    ⑥ 处理完成后,需要刚才的 Allocation 类来填充分配好的内存空间;
    ⑦ 最后可以选择性的对一些资源进行回收。
    

      这里我们创建一个BlurBitmapUtil来简单的封装一下,注释很详细,就不废话了,代码如下:

      BlurBitmapUtil.java

    package com.qianmo.xiaomiblue.utils;
    
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.os.Build;
    import android.renderscript.Allocation;
    import android.renderscript.Element;
    import android.renderscript.RenderScript;
    import android.renderscript.ScriptIntrinsicBlur;
    
    /**
     * Created by wangjitao on 2017/3/6 0006.
     * E-Mail:543441727@qq.com
     * <p>
     * 模糊图片工具类
     */
    
    public class BlurBitmapUtil {
    
        /**
         * Renderscript 的简单的使用步骤
         * 下面简单说一下使用的步骤,这也是官方文档中的说明:
         * 首先需要通过 Context 创建一个 Renderscript ;
         * 其次通过创建的 Renderscript 来创建一个自己需要的脚本( ScriptIntrinsic ),比如这里需要模糊,那就是 ScriptIntrinsicBlur ;
         * 然后至少创建一个 Allocation 类来创建、分配内存空间;
         * 接着就是对图像进行一些处理,比如说模糊处理;
         * 处理完成后,需要刚才的 Allocation 类来填充分配好的内存空间;
         * 最后可以选择性的对一些资源进行回收。
         */
    
        //图片等比缩放
        private static final float BITMAP_SCALE = 0.4f;
    
        /**
         * 模糊图片工具类
         *
         * @param context
         * @param image
         * @param blurRadius
         * @return
         */
        public static Bitmap blurBitmap(Context context, Bitmap image, float blurRadius) {
            //设置渲染模糊程度,25f是最大的模糊化度
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                //计算等比缩小的长宽度
                int width = Math.round(image.getWidth() * BITMAP_SCALE);
                int height = Math.round(image.getHeight() * BITMAP_SCALE);
    
                //将缩小后的图片作为预渲染的图片
                Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
                //创建一张渲染后的输出图片
                Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);
    
                //创建RenderScript内核对象
                RenderScript rs = RenderScript.create(context);
                //创建模糊效果的RenderScript工具对象
                ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
    
                //由于RenderScript并没有使用VM分配内存,所以需要使用Allocation来创建和分配内存空间
                //创建Allocation对象的时候其实内存使用的,需要使用copyto将数据填充
                Allocation allocationInput = Allocation.createFromBitmap(rs, inputBitmap);
                Allocation allocationOutput = Allocation.createFromBitmap(rs, outputBitmap);
    
    
                blurScript.setRadius(blurRadius);
    
                //设置blurscript对象的输入内存
                blurScript.setInput(allocationInput);
                //将输出数据保存到输入内存中
                blurScript.forEach(allocationOutput);
    
                //将数据填充到allocation中
                allocationOutput.copyTo(outputBitmap);
                return outputBitmap;
            } else {
                return null;
            }
    
        }
    }
    

      第二步:自定义BlurredView,具体实现是实现原ImageView和虚化ImageView的组合,继承自Relativelayout,注释很详细,就直接贴代码了,只要是由setBlurredLevel()方法来控制透明度的改变

      自定义的属性:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="BlurredView">
            <attr name="src" format="reference"/>
            <attr name="disableBlurred" format="boolean"/>
        </declare-styleable>
    </resources>
    

      对应的布局文件blurredview.xml

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
                 android:orientation="vertical"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent">
    
        <ImageView
            android:id="@+id/blurredview_blurred_img"
            android:scaleType="fitXY"
            android:visibility="gone"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    
        <ImageView
            android:id="@+id/blurredview_origin_img"
            android:scaleType="fitXY"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    
    </FrameLayout>
    

      BlurredView.java

    package com.qianmo.xiaomiblue.view;
    
    import android.annotation.TargetApi;
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Bitmap;
    import android.graphics.drawable.Drawable;
    import android.os.Build;
    import android.util.AttributeSet;
    import android.view.LayoutInflater;
    import android.widget.ImageView;
    import android.widget.RelativeLayout;
    
    import com.qianmo.xiaomiblue.R;
    import com.qianmo.xiaomiblue.utils.BitmapUtil;
    import com.qianmo.xiaomiblue.utils.BlurBitmapUtil;
    
    import static android.R.attr.level;
    
    /**
     * Created by wangjitao on 2017/3/6 0006.
     * E-Mail:543441727@qq.com
     */
    
    public class BlurredView extends RelativeLayout {
        private Context mContext;
    
        //最大透明值
        private static final int ALPHA_MAX_VALUE = 255;
        //最大模糊度
        private static final float BLUR_RADIUS = 25f;
    
        //原图片
        private ImageView mOriginalImg;
        //模糊化后
        private ImageView mBlurredImg;
    
        private Bitmap mOriginalBitmap;
        private Bitmap mBlurredBitmap;
    
        //是否禁止使用高斯模糊
        private boolean isDisableBlurred;
    
        public BlurredView(Context context) {
            super(context);
            initView(context);
        }
    
        public BlurredView(Context context, AttributeSet attrs) {
            super(context, attrs);
            initView(context);
            initAttr(context, attrs);
        }
    
        public BlurredView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            initView(context);
            initAttr(context, attrs);
        }
    
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        public BlurredView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
            initView(context);
            initAttr(context, attrs);
        }
    
        /**
         * 当所有子View出现后 设置相关内容
         */
        @Override
        protected void onFinishInflate() {
            super.onFinishInflate();
            setImageView();
        }
    
        /**
         * 初始化View
         *
         * @param context
         */
        private void initView(Context context) {
            mContext = context;
            LayoutInflater.from(mContext).inflate(R.layout.blurredview, this);
            mOriginalImg = (ImageView) findViewById(R.id.blurredview_origin_img);
            mBlurredImg = (ImageView) findViewById(R.id.blurredview_blurred_img);
        }
    
        /**
         * 初始化属性
         *
         * @param context
         * @param attrs
         */
        private void initAttr(Context context, AttributeSet attrs) {
    
            TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BlurredView);
            Drawable drawable = typedArray.getDrawable(R.styleable.BlurredView_src);
            isDisableBlurred = typedArray.getBoolean(R.styleable.BlurredView_disableBlurred, false);
            typedArray.recycle();
    
            //虚化照片
            if (null != drawable) {
                mOriginalBitmap = BitmapUtil.drawableToBitmap(drawable);
                mBlurredBitmap = BlurBitmapUtil.blurBitmap(context, mOriginalBitmap, BLUR_RADIUS);
            }
    
            //是否可见
            if (!isDisableBlurred) {
                mBlurredImg.setVisibility(VISIBLE);
            }
        }
    
    
        /**
         * 以代码的方式添加待模糊的图片
         *
         * @param blurredBitmap 待模糊的图片
         */
        public void setBlurredImg(Bitmap blurredBitmap) {
            if (null != blurredBitmap) {
                mOriginalBitmap = blurredBitmap;
                mBlurredBitmap = BlurBitmapUtil.blurBitmap(mContext, blurredBitmap, BLUR_RADIUS);
                setImageView();
            }
        }
    
        /**
         * 以代码的方式添加待模糊的图片
         *
         * @param blurDrawable 待模糊的图片
         */
        public void setBlurredImg(Drawable blurDrawable) {
            if (null != blurDrawable) {
                mOriginalBitmap = BitmapUtil.drawableToBitmap(blurDrawable);
                mBlurredBitmap = BlurBitmapUtil.blurBitmap(mContext, mOriginalBitmap, BLUR_RADIUS);
                setImageView();
            }
        }
    
        /**
         * 填充ImageView
         */
        private void setImageView() {
            mBlurredImg.setImageBitmap(mBlurredBitmap);
            mOriginalImg.setImageBitmap(mOriginalBitmap);
        }
    
        /**
         * 设置模糊程度
         *
         * @param level 模糊程度, 数值在 0~100 之间.
         */
        @SuppressWarnings("deprecation")
        public void setBlurredLevel(int level) {
            //超过模糊级别范围 直接抛异常
            if (level < 0 || level > 100) {
                throw new IllegalStateException("No validate level, the value must be 0~100");
            }
    
            //禁用模糊直接返回
            if (isDisableBlurred) {
                return;
            }
    
            //设置透明度
            mOriginalImg.setAlpha((int) (ALPHA_MAX_VALUE - level * 2.55));
        }
    
        /**
         * 显示模糊图片
         */
        public void showBlurredView() {
            mBlurredImg.setVisibility(VISIBLE);
        }
    
        /**
         * 选择是否启动/禁止模糊效果
         *
         * @param isDisableBlurred 是否禁用模糊效果
         */
        @SuppressWarnings("deprecation")
        public void setBlurredable(boolean isDisableBlurred) {
            if (isDisableBlurred) {
                mOriginalImg.setAlpha(ALPHA_MAX_VALUE);
                mBlurredImg.setVisibility(INVISIBLE);
            } else {
                mBlurredImg.setVisibility(VISIBLE);
            }
        }
    
        /**
         * 禁用模糊效果
         */
        @SuppressWarnings("deprecation")
        public void disableBlurredView() {
            isDisableBlurred = true;
            mOriginalImg.setAlpha(ALPHA_MAX_VALUE);
            mBlurredImg.setVisibility(INVISIBLE);
        }
    
        /**
         * 启用模糊效果
         */
        public void enableBlurredView() {
            isDisableBlurred = false;
            mBlurredImg.setVisibility(VISIBLE);
        }
    }
    

      第三步:设置RecyclerView,并监听滑动,改变虚化图片的透明度

      MyAdapter

    package com.qianmo.xiaomiblue.adapter;
    
    import android.content.Context;
    import android.support.v7.widget.RecyclerView;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    
    import com.qianmo.xiaomiblue.R;
    
    /**
     * Created by Administrator on 2017/3/6 0006.
     * E-Mail:543441727@qq.com
     */
    
    public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    
        private Context context;
        private static final int ITEM_COUNT = 10;
        private static final int TYPE_HEAD = 0;
        private static final int TYPE_ITEM = 1;
    
        public MyAdapter(Context context) {
            this.context = context;
        }
    
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            if (viewType == TYPE_HEAD) {
                return new HeadViewHolder(LayoutInflater.from(context).inflate(R.layout.recyclerview_head, parent, false));
            }
            return new ItemViewHolder(LayoutInflater.from(context).inflate(R.layout.recyclerview_item, parent, false));
        }
    
        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    
        }
    
        @Override
        public int getItemViewType(int position) {
            if (position == 0) {
                return TYPE_HEAD;
            } else {
                return TYPE_ITEM;
            }
        }
    
        @Override
        public int getItemCount() {
            return ITEM_COUNT;
        }
    
        public class ItemViewHolder extends RecyclerView.ViewHolder {
            public ItemViewHolder(View itemView) {
                super(itemView);
            }
        }
    
        public class HeadViewHolder extends RecyclerView.ViewHolder {
            public HeadViewHolder(View itemView) {
                super(itemView);
            }
        }
    }
    

      在MainActivity中设置

     recyclerView.setLayoutManager(new LinearLayoutManager(this));
            recyclerView.setAdapter(new MyAdapter(this));
    
            recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                }
    
                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                    mScrollerY += dy;
                    //根据滚动距离控制模糊程度 滚动距离是模糊程度的十倍
                    if (Math.abs(mScrollerY) > 1000) {
                        mAlpha = 100;
                    } else {
                        mAlpha = Math.abs(mScrollerY) / 10;
                    }
                    //设置透明度等级
                    blurredView.setBlurredLevel(mAlpha);
                }
            });
    

      ok,这样我们的功能就实现了  ,很简单有没有,主要是Rederscript的掌握

      github项目地址

  • 相关阅读:
    简易仿ios菊花加载loading图
    android 仿微信表情雨下落!
    android view 转Bitmap 生成截图
    设计模式——享元模式
    虚拟内存技术原理解析
    读史——回望勾吴
    android日志搜集原理及方案比较
    java四种引用及在LeakCanery中应用
    读史——秦历史概况
    git使用总结
  • 原文地址:https://www.cnblogs.com/wjtaigwh/p/6510693.html
Copyright © 2020-2023  润新知