AndroidTVWidget框架
在此框架上封裝了幾個類用于快速實現(xiàn)焦點動畫。
使用AndroidTVWidget完成運動焦點框效果。
- 盡可能減少布局層級。
- 需獲取焦點的view最好在同一層級上。
- 焦點框要處于最上層,避免遮蓋。
- 注意view的邊距,防止view放大時顯示不全。
以下展示幾種不同布局環(huán)境下對焦點框的處理:重點是獲取到view的焦點并對焦點得失兩種狀態(tài)分別處理。
Demo地址
在布局中添加MainUpView,使MainUpView處于布局的上層。
設(shè)置焦點框:
private void initMoveBridge() {
float density = getResources().getDisplayMetrics().density;
mEffectNoDrawBridge = new EffectNoDrawBridge();
mainUpView.setEffectBridge(mEffectNoDrawBridge);
mEffectNoDrawBridge.setUpRectResource(R.drawable.white_light); // 設(shè)置移動邊框圖片.
RectF rectF = new RectF(15 * density, 15 * density, 14 * density, 15 * density);
mEffectNoDrawBridge.setDrawUpRectPadding(rectF);
}
對view添加監(jiān)聽:
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);
}
}
});
}
不同應(yīng)用場景中的封裝類:
MainUpViewActivity
- 適合含有View,不包含ViewGroup的布局。
- 使用簡單方便。
- 創(chuàng)建Activity繼承MainUpViewActivity
- 在onCreate方法中調(diào)用init方法初始化
- 不需要在布局中添加MainUpView控件
如下:
public class Example1Activity extends MainUpViewActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//參數(shù)分別為邊框圖片,左上右下的邊距,根據(jù)需求自行調(diào)整
init(R.drawable.white_light,12,12,12,12);
}
}
若要使一些view不能獲取焦點或者展示不同的樣式??芍貙慽nitFocusTree();
詳情見Demo中的Example1Activity。
BaseActivity
用于處理activity中RecyclerViewTV的焦點框,RecyclerViewTV是AndroidTVWidget中為Android TV開發(fā)自定義的控件,使用RecyclerViewTV代替RecyclerView。 BaseActivity是一個抽象類,只需實現(xiàn)幾個固定的方法即可。
public class Example2Activity extends BaseActivity {
@Override
public int getLayout() {
//布局xml
return 0;
}
@Override
public void initView() {
init(...);//初始化焦點框
//初始化布局
}
@Override
public void loadData() {
//數(shù)據(jù)加載
}
@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);//設(shè)置焦點放大的倍數(shù),默認為1.2倍。
當前BaseActivity實現(xiàn)類中的其他view,可以通過setOnFocusListener()來監(jiān)聽焦點并實現(xiàn)動畫。詳情請見,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;
}
}