AndroidTVWidget框架之运动焦点框(五)

AndroidTVWidget框架
在此框架上封装了几个类用于快速实现焦点动画。

使用AndroidTVWidget完成运动焦点框效果。
* 尽可能减少布局层级。
* 需获取焦点的view最好在同一层级上。
* 焦点框要处于最上层,避免遮盖。
* 注意view的边距,防止view放大时显示不全。

以下展示几种不同布局环境下对焦点框的处理:重点是获取到view的焦点并对焦点得失两种状态分别处理。

Demo地址
在布局中添加MainUpView,使MainUpView处于布局的上层。

设置焦点框:

private void initMoveBridge() {
    float density = getResources().getDisplayMetrics().density;
    mEffectNoDrawBridge = new EffectNoDrawBridge();
    mainUpView.setEffectBridge(mEffectNoDrawBridge);
    mEffectNoDrawBridge.setUpRectResource(R.drawable.white_light); // 设置移动边框图片.
    RectF rectF = new RectF(15 * density, 15 * density, 14 * density, 15 * density);
    mEffectNoDrawBridge.setDrawUpRectPadding(rectF);
}

对view添加监听:

  private void initListener(){
    cardView1.setOnFocusChangeListener(this);
    cardView2.setOnFocusChangeListener(this);
    cardView3.setOnFocusChangeListener(this);
    cardView4.setOnFocusChangeListener(this);
    cardView5.setOnFocusChangeListener(this);
    cardView6.setOnFocusChangeListener(this);
    cardView7.setOnFocusChangeListener(this);
    cardView8.setOnFocusChangeListener(this);
    cardView9.setOnFocusChangeListener(this);
}

处理:

    @Override
public void onFocusChange(View v, boolean hasFocus) {
    if (hasFocus) {
        mOldView = v;
        mEffectNoDrawBridge.setVisibleWidget(false);
        //可以对某个view进行特殊处理
//            if (v.getId()==R.id.card_img) {
//                mEffectNoDrawBridge.setFocusView(v, 1.05f);
//            } else {
//                mEffectNoDrawBridge.setFocusView(v, 1.15f);
//            }
        mEffectNoDrawBridge.setFocusView(v, 1.15f);
        v.bringToFront();
    } else {
        mEffectNoDrawBridge.setUnFocusView(mOldView);
        mEffectNoDrawBridge.setVisibleWidget(true);
    }
}

详情见Demo中的MainActivity

另一种方式:

  private void initFocusTree(){
    rootView.getViewTreeObserver().addOnGlobalFocusChangeListener(new ViewTreeObserver.OnGlobalFocusChangeListener() {
        @Override
        public void onGlobalFocusChanged(View oldFocus, View newFocus) {

            if (newFocus != null ) {
                //可以在此对newFocus进行过滤,可以使一些view不能获取焦点或者展示不同的样式。
                mEffectNoDrawBridge.setVisibleWidget(false);
                mNewFocus = newFocus;
                mOldView = oldFocus;
                mainUpView.setFocusView(newFocus, oldFocus, 1.2f);
                newFocus.bringToFront();
            } else { // 标题栏处理.
                mNewFocus = null;
                mOldView = null;
                mainUpView.setUnFocusView(oldFocus);
                mEffectNoDrawBridge.setVisibleWidget(true);
            }
        }
    });
}

不同应用场景中的封装类:

MainUpViewActivity

  • 适合含有View,不包含ViewGroup的布局。
  • 使用简单方便。
  • 创建Activity继承MainUpViewActivity
  • 在onCreate方法中调用init方法初始化
  • 不需要在布局中添加MainUpView控件

如下:

public class Example1Activity extends MainUpViewActivity {
    @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
        //参数分别为边框图片,左上右下的边距,根据需求自行调整
         init(R.drawable.white_light,12,12,12,12);
     }
}

若要使一些view不能获取焦点或者展示不同的样式。可重写initFocusTree();
详情见Demo中的Example1Activity。

BaseActivity
用于处理activity中RecyclerViewTV的焦点框,RecyclerViewTV是AndroidTVWidget中为Android TV开发自定义的控件,使用RecyclerViewTV代替RecyclerView。 BaseActivity是一个抽象类,只需实现几个固定的方法即可。

public class Example2Activity extends BaseActivity {

@Override
public int getLayout() {
    //布局xml
    return 0;
}

@Override
public void initView() {
    init(...);//初始化焦点框
    //初始化布局
}

@Override
public void loadData() {
    //数据加载
}

@Override
public RecyclerView.LayoutManager getLayoutManager() {
    //RecyclerView的LayoutManager类型
    return null;
}

@Override
public RecyclerView.Adapter getAdapter() {
    //适配器
    return null;
}

@Override
public void onItemClick(View itemView, int position) {
    //item的点击事件
}

@Override
public void onItemSelected(View itemView, int position) {
    //选中item
}

@Override
public void onItemUnSelected(View itemView, int position) {
    //失去选中item
}
}

setAutoFocus(false);//默认为true,第一项获取焦点;为false,不自动获取焦点。
setAnimScale(1.2f);//设置焦点放大的倍数,默认为1.2倍。

当前BaseActivity实现类中的其他view,可以通过setOnFocusListener()来监听焦点并实现动画。详情请见,Demo中的Example2Activity。

BaseFragment
RecyclerViewTV在Fragment中,与BaseActivity类似。
见Demo中Example3Fragment。

public class Example3Fragment extends BaseFragment {

private RecyclerViewTV recyclerViewTV;
private MainUpView mainUpView;
private List<String> list=new ArrayList<>();
private ExamAdapter examAdapter;

@Override
public int getLayout() {
    return 0;
}

@Override
public void initView(View view) {

}

@Override
public void loadData() {

}

@Override
public void onItemClick(View itemView, int position) {

}

@Override
public void onItemSelected(View itemView, int position) {

}

@Override
public void unItemSelected(View itemView, int position) {

}

@Override
public RecyclerView.Adapter getAdapter() {
    return null;
}

@Override
public RecyclerView.LayoutManager getLayoutManager() {

    return null;
}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值