Android Tv 背景动态改变,带过渡效果

在Android TV 中,当选中某一个item时,背景切换成模糊处理后的该资源图片,切换时不能很突兀,要有过渡效果.


实现步骤

  • 获取当前选中item中的图片:首先获取当前焦点所在的View,通过ViewTreeObserver.OnGlobalFocusChangeListener监听全局焦点,当焦点移动时,获取焦点所在View,如果按键间隔时间低于350ms,则不执行。
public class LauncherActivity extends BaseActivity implements ViewTreeObserver.OnGlobalFocusChangeListener{
    private final static int MSG_BLUR_BG = 0x2003;
    private final static int MSG_UPDATE_BG = 0x2004;
    private final static int MSG_REFRESH_BG_DELAY = 350;
    private ViewTreeObserver mViewTreeObserver;
    private TransitionDrawable mTransitionDrawable;
    private View focusView;
.......

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_launcher);
        .......
        mViewTreeObserver = this.getWindow().getDecorView().getViewTreeObserver();
        mViewTreeObserver.addOnGlobalFocusChangeListener(this);
        .......
    }

  @Override
    public void onGlobalFocusChanged(View oldFocus, View newFocus) {
        mHandler.removeMessages(MSG_BLUR_BG);
        Message msg = mHandler.obtainMessage();
        msg.what = MSG_BLUR_BG;
        msg.obj = newFocus;
        mHandler.sendMessageDelayed(msg, MSG_REFRESH_BG_DELAY);
    }
}
  • 获取到焦点所在的View后,通过View.getDrawingCache()获取View上的Bitmap对象,此方法比较耗时,故放在线程中执行,然后进行压缩模糊处理。CustomFrameLayout 为每个item的布局。使用View.getDrawingCache()前必须调用View.setDrawingCacheEnabled(true);使用完Bitmap对象之后,要 调用View.destroyDrawingCache();
    View.setDrawingCacheEnabled(false);释放资源。
    高斯模糊算法使用android系统提供的ScriptIntrinsicBlur,直接调用底层C/C++,效率很快,在执行模糊之前,最好是将图片进行缩放出来,这样效率会更快。
private void blurCurFocusImage(View curFocusView) {
        if (curFocusView == null) {
            return;
        }
        focusView = curFocusView;
        if (focusView instanceof CustomFrameLayout) {//如果焦点在顶部导航栏时,不做处理
            focusView.setDrawingCacheEnabled(true);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Bitmap newBitmap = focusView.getDrawingCache();//此方法耗时,放在线程中执行
                    Drawable newDrawable = new    BitmapDrawable(DisplayUtil.rsBlur(LauncherActivity.this, newBitmap));
                    Message msg = mHandler.obtainMessage();
                    msg.what = MSG_UPDATE_BG;
                    msg.obj = newDrawable;
                    mHandler.sendMessage(msg);
                    newBitmap.recycle();
                }
            }).start();
        }
 public static Bitmap rsBlur(Context context, Bitmap source) {
        int radius = BLUR_RADIUS;//模糊程度
        float scale = BLUR_SCALE;//缩放比例
        int width = Math.round(source.getWidth() * scale);
        int height = Math.round(source.getHeight() * scale);
        Bitmap inputBmp = Bitmap.createScaledBitmap(source, width, height, false);
        RenderScript renderScript = RenderScript.create(context);
        // Allocate memory for Renderscript to work with
        final Allocation input = Allocation.createFromBitmap(renderScript, inputBmp);
        final Allocation output = Allocation.createTyped(renderScript, input.getType());
        // Load up an instance of the specific script that we want to use.
        ScriptIntrinsicBlur scriptIntrinsicBlur = ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript));
        scriptIntrinsicBlur.setInput(input);
        // Set the blur radius
        scriptIntrinsicBlur.setRadius(radius);
        // Start the ScriptIntrinisicBlur
        scriptIntrinsicBlur.forEach(output);
        // Copy the output to the blurred bitmap
        output.copyTo(inputBmp);
        renderScript.destroy();
        return inputBmp;
    }
  • 至此我们已经完成一半了,如果将处理后的图片直接设置为背景,在一瞬间由原先的背景切换到新的背景,会造成视觉上的突兀感,所以我们要在两者之间添加过渡动画。Android提供了TransitionDrawable可以实现此功能。当获取到最新的背景图时,执行下面方法,实现背景过渡。mBgView为背景View。TransitionDrawable 可以设置一个Drawable数组,数组中保存我们要转换的图片,TransitionDrawable startTransition 时会从数组中图片依次渐变。
    获取上次焦点所在View的背景的结束背景 作为当前焦点所在View 的起始背景,模糊处理后的图片为结束背景。
private void updateMainBg(Drawable drawable) {
        if (drawable == null) {
            return;
        }
        Drawable oldDrawable;
        //第一次未设置背景时,currentBgDrawable=null
        Drawable currentBgDrawable = mBgView.getDrawable();
        if (currentBgDrawable instanceof TransitionDrawable) {
            oldDrawable = ((TransitionDrawable) currentBgDrawable).getDrawable(1);
            mTransitionDrawable.setDrawable(0, oldDrawable);
            mTransitionDrawable.setDrawable(1, drawable);
        } else {
            //第一次设置背景
            oldDrawable = getDrawable(R.drawable.launcher_bg_new);
            mTransitionDrawable = new TransitionDrawable(new Drawable[]{oldDrawable, drawable});
            mTransitionDrawable.setCrossFadeEnabled(true);
            mBgView.setImageDrawable(mTransitionDrawable);
        }
        mTransitionDrawable.startTransition(500);//转换时间
        focusView.destroyDrawingCache();
        focusView.setDrawingCacheEnabled(false);
    }

handler 代码部分

private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case MSG_BLUR_BG:
                    blurCurFocusImage((View) msg.obj);
                    break;
                case MSG_UPDATE_BG:
                    updateMainBg((Drawable) msg.obj);
                    break;
            }

        }
    };

你可能感兴趣的:(Android,Android,TV,高斯模糊,背景动态切换,Android,Tv,效果)