前端时间在做安卓盒子的界面开发,网上搜索就看到了一个框架,很全面,但用DEMO看了下效果,只支持键盘的上下左右操作,不支持鼠标等的操作,但感觉做的还是可以的,就基于此类进行了优化,主要优化了以下几点:
1.加入支持鼠标的操作
2.加入滑动的效果
3.优化了界面的焦点效果及切换的过渡动画。
详细如下:
1.加入支持鼠标的操作
这个主要是在找到每个子view时,对每个子view增加一个设置即可,如下:
private void bindEventOnChild(View child, final int index) { //绑定事件
child.setFocusable(true);
child.setFocusableInTouchMode(true); //加入鼠标触摸的支持
。。。
2.加入滑动的效果
这部分主要是在TVGridView的外围,增加一个Scrollview控件,使其支持鼠标的拖动与滑动,但此时需修改onMeasure()方法,否则会出现bug
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.d(TAG, “onMeasure(int widthMeasureSpec, int heightMeasureSpec)”);
/**
* 获得此ViewGroup父容器为其推荐的宽和高,以及计算模式
*/
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
// Log.d(TAG, "sizeWidth="+sizeWidth+"sizeHeight="+sizeHeight);
// 计算出所有的childView的宽和高
measureChildren(widthMeasureSpec, heightMeasureSpec);
int cCount = getChildCount(); //40
Log.d(TAG, "cCount="+cCount);
/**
* 根据childView计算的出的宽和高,以及设置的margin计算容器的宽和高,主要用于容器是warp_content时
*/
//wrap_content
setMeasuredDimension(sizeWidth, rowHeight*rowCount+70 );
}
3.优化了界面的焦点效果及切换的过渡动画。
这部分主要是对焦点的效果及过渡进行了重新处理,对于焦点更换了另外一种效果图,对于过渡的动画这部分,主要是增加焦点切换时,当前focus与下一个direction的焦点进行处理,
主要思路是,判断当前按下的是哪个方向健,根据此 得出focus与next的子view,如果next不为null,说明有下一个子view,则根据direction进行判断,对next子view进行做动画处理,如果next为null,说明已到边界,则也可以根据direction判断 分别作出靠边的动画效果,
部分代码如下:
public boolean dispatchKeyEventPreIme(KeyEvent event) {
Log.d(TAG, “dispatchKeyEventPreIme(KeyEvent event)”);
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (!mScroller.isFinished()) {
return true;
}
int direction = 0;
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_DPAD_DOWN:
direction = View.FOCUS_DOWN;
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
direction = View.FOCUS_RIGHT;
break;
case KeyEvent.KEYCODE_DPAD_UP:
direction = View.FOCUS_UP;
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
direction = View.FOCUS_LEFT;
break;
}
View focused = this.findFocus(); //当前有焦点的item
if (focused != null && direction != 0) {
View next = focused.focusSearch(direction);//根据方向确定的下一个view
// 根据下标算出所在行
if (next != null) {
int focusIndex = itemIds.get(focused.getId());
Integer temp = itemIds.get(next.getId());
int nextRow = 0;
// 焦点切出容器时
if (temp != null) { //next不为null 对direction的view做动画
focusIsOut=false;
selectIndex = temp;
if(direction == View.FOCUS_DOWN) {
enScrollDown=true;
AnimationViewDown(next);
}else if(direction == View.FOCUS_LEFT) {
onetimes=false; //去除按左键时 scrollview向上移动的bug
AnimationViewLeft(next);
}else if(direction == View.FOCUS_RIGHT) {
onetimes=false;//去除按右键时 scrollview向上移动的bug
AnimationViewRight(next);
}else if(direction == View.FOCUS_UP) {
enScrollUp=true;
AnimationViewUp(next);
}
selectRow = focusIndex / columns;
nextRow = selectIndex / columns;
Log.d(TAG, "selectRow="+selectRow+"nextRow="+nextRow);
if(nextRow==1) { //第2行
// onetimes=true;
}
} else {
Log.d(TAG, "焦点切出容器");
parentLayout = true;
focusIsOut=true;
firstFocus=true; //保证每次再切入焦点时 第一行的app 有动画
return super.dispatchKeyEventPreIme(event);
}
}else { //已到边源,next会为null,对当前的view动画
if(direction == View.FOCUS_DOWN) {
AnimationViewDown(focused);
}else if(direction == View.FOCUS_LEFT) {
AnimationViewLeft(focused);
}else if(direction == View.FOCUS_RIGHT) {
AnimationViewRight(focused);
}else if(direction == View.FOCUS_UP) {
AnimationViewUp(focused);
}
}
}
}
return super.dispatchKeyEventPreIme(event);
}
动画实例:
private void AnimationViewDown(View item) { //向下
ObjectAnimator mAnimatorTranslateY = ObjectAnimator.ofFloat(item, “translationY”, 0.0f,10f,0f);
mAnimatorTranslateY.setRepeatMode(Animation.REVERSE);
// mAnimatorTranslateY.setRepeatCount(3);
mAnimatorTranslateY.setInterpolator(new DecelerateInterpolator());
mAnimatorTranslateY.setDuration(1000);
mAnimatorTranslateY.start();
}
焦点效果如下: