二、TV上RecyclerView移动焦点放大实现
2022-12-09 本文已影响0人
aitality
在电视上主要的交互就是使用遥控器控制焦点进行选择,所以一个醒目的选中效果会带来很好的体验度。目前上面上的焦点框有两种,第一种是飞框,第二种就是
selector
,其中飞框的体验是最好的,看着焦点框在屏幕上划过,像流星一样很美,但是实现成本也很高。这里我还是使用常规selector
方式实现。简单说一下飞框的实现原理:就是全局监听当前获得焦点的view
,getViewTreeObserver().addOnGlobalFocusChangeListener()
,然后将最上层的焦点框以到焦点位置,并添加放大效果。
第一步、编写selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/general_focus" android:state_focused="true" />
<item android:drawable="@drawable/item_grid_state_normal" />
</selector>
第二步、监听RecyclerView.ViewHolder
中itemView
的焦点变化
holder.itemView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus) {
focusedTo(v);
}else{
focusedFrom(v);
}
}
});
第三步、实现选中和非选中动画
public void focusedTo(View view) {
ViewCompat.animate(view).scaleX(1.2f).scaleY(1.2f).translationZ(1.2f).start();
}
public void focusedFrom(View view) {
ViewCompat.animate(view).scaleX(1.0f).scaleY(1.0f).translationZ(0f).start();
}
第四步、优化RecyclerView
显示顺序,放置放大item被遮挡
//继承RecyclerView实现
//防止item放大后被遮挡
protected int getChildDrawingOrder(int childCount, int i) {
int position = getChildAdapterPosition(getFocusedChild());
if(position < 0) {
return i;
}
if(i == childCount-1) {
if(position > i) {
position = i;
}
return position;
}
if(i == position) {
return childCount-1;
}
return i;
}
以下代码可避免边缘的item被裁剪
android:clipChildren="false"
android:clipToPadding="false"