package reco.frame.tv.view;
import reco.frame.tv.R;
import reco.frame.tv.view.component.RecycleBin;
import reco.frame.tv.view.component.TvBaseAdapter;
import reco.frame.tv.view.component.TvUtil;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.database.DataSetObservable;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Scroller;
public class TvListView extends RelativeLayout {
/**
* 光标
*/
private ImageView cursor;
private int cursorId;
/**
* 光标资源
*/
private int cursorRes;
/**
* item可否缩放
*/
private boolean scalable;
/**
* 放大比率
*/
private float scale;
/**
* 光标飘移动画 默认无效果(尚未实现)
*/
private int animationType;
public final static int ANIM_DEFAULT = 0;// 无效果
public final static int ANIM_TRASLATE = 1;// 平移
/**
* 放大用时
*/
private int durationLarge = 100;
/**
* 缩小用时
*/
private int durationSmall = 100;
/**
* 放大延迟
*/
private int delay = 0;
/**
* 滚动速度
*/
private int scrollDelay = 0;
/**
* 滚动速度
*/
private int scrollDuration = 0;
/**
* 光标边框宽度 包括阴影
*/
private int boarder;
/**
* 光标左边框宽度 含阴影
*/
private int boarderLeft;
/**
* 光标顶边框宽度 含阴影
*/
private int boarderTop;
/**
* 光标右边框宽度 含阴影
*/
private int boarderRight;
/**
* 光标底边框宽度 含阴影
*/
private int boarderBottom;
/**
* 外层容器布局是否改变
*/
private boolean parentLayout = true;
/**
* 除光标外 当前子类数
*/
private int currentChildCount = 0;
/**
* 可否滚动
*/
private final int ACTION_START_SCROLL = 0, ACTION_INIT_ITEMS = 1,
ACTION_ADD_ITEMS = 2;
private boolean scrollable;
/**
* 刷新延迟
*/
private final int DELAY = 231;
/**
* 屏幕可显示最大行数
*/
private int screenMaxRow;
/**
* 当前选中子项下示
*/
private int selectIndex;
private int paddingLeft, paddingTop;
private int spaceHori;
private int spaceVert;
/**
* item宽高 不包括纵横间距
*/
private int itemWidth, itemHeight;
/**
* item真实宽高 包括纵横间距
*/
private int rowWidth, rowHeight;
private SparseArray<Integer> itemIds, focusIds;
private OnItemSelectListener onItemSelectListener;
private OnItemClickListener onItemClickListener;
public AdapterDataSetObservable mDataSetObservable;
private TvBaseAdapter adapter;
private AnimatorSet animatorSet;
private ObjectAnimator largeX;
private WindowManager wm;
private Scroller mScroller;
private RecycleBin mRecycleBin;
private boolean isInit = true;
private boolean canAdd = true;
/**
* 以1280为准,其余分辨率放大比率 用于适配
*/
private float screenScale = 1;
/**
* 焦点优先级
*/
private int focusOption = 0;
/**
*
*/
private final static int PARENT_ONLY = 0;
private final static int CHILD_ONLY = 1;
private final static int PARENT_FIRST = 2;
private final static int CHILD_FIRST = 3;
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case ACTION_START_SCROLL:
int direction = (Integer) msg.obj;
if (scrollable) {
scrollable = false;
scrollByRow(direction);
}
break;
case ACTION_INIT_ITEMS:
initItems();
break;
case ACTION_ADD_ITEMS:
addNewItems();
break;
}
};
};
public TvListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public TvListView(Context context) {
super(context);
}
public TvListView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray custom = getContext().obtainStyledAttributes(attrs,
R.styleable.TvListView);
this.cursorRes = custom.getResourceId(R.styleable.TvListView_cursorRes,
0);
this.scalable = custom
.getBoolean(R.styleable.TvListView_scalable, true);
this.scale = custom.getFloat(R.styleable.TvListView_scale, 1.1f);
this.animationType = custom.getInt(
R.styleable.TvListView_animationType, 0);
this.focusOption = custom.getInt(R.styleable.TvListView_focusOption, 0);
this.delay = custom.getInteger(R.styleable.TvListView_delay, 110);
this.scrollDelay = custom.getInteger(
R.styleable.TvGridView_scrollDelay, 171);
this.scrollDuration = custom.getInteger(
R.styleable.TvGridView_scrollDuration, 371);
this.durationLarge = custom.getInteger(
R.styleable.TvListView_durationLarge, 100);
this.durationSmall = custom.getInteger(
R.styleable.TvListView_durationSmall, 100);
this.spaceVert = (int) custom.getDimension(
R.styleable.TvListView_spaceVert, 10);
itemWidth = (int) custom.getDimension(R.styleable.TvListView_itemWidth,
10);
itemHeight = (int) custom.getDimension(
R.styleable.TvListView_itemHeight, 10);
rowHeight = itemHeight + spaceVert;
rowWidth = itemWidth + spaceHori;
paddingLeft = (int) custom.getDimension(
R.styleable.TvListView_paddingLeft, 0);
paddingTop = (int) custom.getDimension(
R.styleable.TvListView_paddingTop, 2);
this.boarder = (int) custom.getDimension(
R.styleable.TvListView_boarder, 0)
+ custom.getInteger(R.styleable.TvListView_boarderInt, 0);
if (boarder == 0) {
this.boarderLeft = (int) custom.getDimension(
R.styleable.TvListView_boarderLeft, 0)
+ custom.getInteger(R.styleable.TvListView_boarderLeftInt,
0);
this.boarderTop = (int) custom.getDimension(
R.styleable.TvListView_boarderTop, 0)
+ custom.getInteger(R.styleable.TvListView_boarderTopInt, 0);
this.boarderRight = (int) custom.getDimension(
R.styleable.TvListView_boarderRight, 0)
+ custom.getInteger(R.styleable.TvListView_boarderRightInt,
0);
this.boarderBottom = (int) custom.getDimension(
R.styleable.TvListView_boarderBottom, 0)
+ custom.getInteger(
R.styleable.TvListView_boarderBottomInt, 0);
} else {
this.boarderLeft = boarder;
this.boarderTop = boarder;
this.boarderRight = boarder;
this.boarderBottom = boarder;
}
if (cursorRes == 0) {
switch (getResources().getDisplayMetrics().widthPixels) {
case TvUtil.SCREEN_1280:
cursorRes = custom.getResourceId(
R.styleable.TvListView_cursorRes_1280, 0);
break;
case TvUtil.SCREEN_1920:
cursorRes = custom.getResourceId(
R.styleable.TvListView_cursorRes_1920, 0);
break;
case TvUtil.SCREEN_2560:
cursorRes = custom.getResourceId(
R.styleable.TvListView_cursorRes_2560, 0);
break;
case TvUtil.SCREEN_3840:
cursorRes = custom.getResourceId(
R.styleable.TvListView_cursorRes_3840, 0);
break;
}
}
custom.recycle();
// 关闭子控件动画缓存 使嵌套动画更流畅
// setAnimationCacheEnabled(false);
init();
}
private void init() {
itemIds = new SparseArray<Integer>();
focusIds = new SparseArray<Integer>();
mScroller = new Scroller(getContext());
wm = (WindowManager) getContext().getSystemService(
Context.WINDOW_SERVICE);
mDataSetObservable = new AdapterDataSetObservable();
mRecycleBin = new RecycleBin(getContext().getCacheDir()
.getAbsolutePath());
}
/**
* 设置适配器
*
* @param adapter
*/
public void setAdapter(TvBaseAdapter adapter) {
this.adapter = adapter;
if (adapter != null) {
adapter.registerDataSetObservable(mDataSetObservable);
}
// 清理原先数据
clear();
if (isInit) {
initBuild();
isInit = false;
}
Message msg = handler.obtainMessage();
msg.what = ACTION_INIT_ITEMS;
handler.sendMessageDelayed(msg, DELAY);
}
private void clear() {
itemIds.clear();
focusIds.clear();
this.removeAllViews();
this.clearDisappearingChildren();
this.destroyDrawingCache();
mScroller.setFinalY(0);
parentLayout = false;
currentChildCount = 0;
}
/**
* 首次加载屏幕可见行数*2
*/
public void initBuild() {
// 重设参数
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) getLayoutParams();
RelativeLayout.LayoutParams newParams = new RelativeLayout.LayoutParams(
params.width, params.height);
this.setPadding((int) (boarderLeft * scale),
(int) (boarderTop * scale), boarderRight, boarderBottom);
newParams.setMargins(params.leftMargin, params.topMargin,
params.rightMargin, params.bottomMargin);
this.setLayoutParams(newParams);
}
private void initItems() {
// 避免冲突
if (getChildCount() > 0) {
return;
}
int screenHeight = wm.getDefaultDisplay().getHeight();
int initRows = screenHeight % rowHeight == 0 ? screenHeight / rowHeight
: screenHeight / rowHeight + 1;
int initLength = Math.min(adapter.getCount(), initRows * 2);
for (int i = 0; i < initLength; i++) {
int left = 0;
int top = i * (spaceVert + itemHeight);
RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(
itemWidth, itemHeight);
if (initLength == 1) {
rlp.setMargins(left, top, paddingLeft, 0);
} else {
rlp.setMargins(left, top, 0, 0);
}
View child = adapter.getView(i, null, this);
bindEvent(child, i);
this.addView(child, rlp);
}
cursor = new ImageView(getContext());
cursorId = TvUtil.buildId();
cursor.setId(cursorId);
cursor.setBackgroundResource(cursorRes);
this.addView(cursor);
cursor.setVisibility(View.INVISIBLE);
View focus = ((ViewGroup) getParent()).findFocus();
if (focus == null) {
View item = getChildAt(0);
if (item != null) {
item.requestFocus();
}
}
}
private void addNewItems() {
currentChildCount = getChildCount();
parentLayout = false;
int start = itemIds.size();
int end = Math.min(start + screenMaxRow * 2, adapter.getCount());
for (int i = start; i < end; i++) {
int left = 0;
int top = i * (spaceVert + itemHeight);
RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(
itemWidth, itemHeight);
rlp.setMargins(left, top, 0, 0);
View child = adapter.getView(i, null, this);
int viewId = child.getId();
if (viewId == -1) {
viewId = TvUtil.buildId();
// 此处硬设置id同时建议开发者不用此范围id
}
child.setId(viewId);
this.addView(child, rlp);
itemIds.put(viewId, i);
bindEvent(child, i);
}
canAdd = true;
}
/**
* 绑定事件
*
* @param child
*/
private void bindEvent(final View item, final int index) {
int viewId = item.getId();
if (viewId == -1) {
viewId = TvUtil.buildId();
// 此处硬设置id同时建议开发者不用此范围id
}
item.setId(viewId);
itemIds.put(viewId, index);
// 根据焦点优先级设定选中效果
switch (focusOption) {
case PARENT_ONLY:
focusIds.put(viewId, index);
item.setFocusable(true);
item.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(final View child, boolean focus) {
if (focus) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
moveCover(item, child);
}
}, delay);
// 选中事件
if (onItemSelectListener != null) {
onItemSelectListener
.onItemSelect(item, index);
}
} else {
returnCover(child);
// 失去焦点
if (onItemSelectListener != null) {
onItemSelectListener
.onItemDisSelect(item, index);
}
}
}
});
if (onItemClickListener != null) {
item.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View item) {
onItemClickListener.onItemClick(item, index);
}
});
}
break;
case CHILD_ONLY:
item.setFocusable(false);
ViewGroup itemGroup = ((ViewGroup) item);
for (int i = 0; i < itemGroup.getChildCount(); i++) {
focusIds.put(viewId, index);
View itemChild = itemGroup.getChildAt(i);
if (!itemChild.isFocusable()) {
continue;
}
itemChild.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(final View child, boolean focus) {
if (focus) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
moveCover(item, child);
}
}, delay);
// 选中事件
if (onItemSelectListener != null) {
onItemSelectListener.onItemSelect(item,
index);
}
} else {
returnCover(child);
// 失去焦点
if (onItemSelectListener != null) {
onItemSelectListener.onItemDisSelect(item,
selectIndex);
}
}
}
});
if (onItemClickListener != null) {
itemChild.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View item) {
onItemClickListener.onItemClick(item, index);
}
});
}
}
itemGroup = null;
break;
case PARENT_FIRST:
break;
case CHILD_FIRST:
break;
}
}
@Override
protected void 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);
// 计算出所有的childView的宽和高
measureChildren(widthMeasureSpec, heightMeasureSpec);
/**
* 记录如果是wrap_content是设置的宽和高
*/
int width = 0;
int height = 0;
int cCount = getChildCount();
int cWidth = 0;
int cHeight = 0;
MarginLayoutParams cParams = null;
/**
* 根据childView计算的出的宽和高,以及设置的margin计算容器的宽和高,主要用于容器是warp_content时
*/
// Log.e(VIEW_LOG_TAG, "onMeasure=" + currentChildCount + "---cCount="
// + cCount + "---" + parentLayout);
for (int i = currentChildCount; i < cCount; i++) {
View childView = getChildAt(i);
cWidth = childView.getMeasuredWidth();
cHeight = childView.getMeasuredHeight();
cParams = (MarginLayoutParams) childView.getLayoutParams();
// 上面两个childView
width += cWidth + cParams.leftMargin + cParams.rightMargin;
height += cHeight + cParams.topMargin + cParams.bottomMargin;
}
/**
* 如果是wrap_content设置为我们计算的值 否则:直接设置为父容器计算的值
*/
setMeasuredDimension(
(widthMode == MeasureSpec.EXACTLY || width == 0) ? sizeWidth
: width,
(heightMode == MeasureSpec.EXACTLY || height == 0) ? sizeHeight
: height);
// Log.e(VIEW_LOG_TAG, "onMeasure----" + width + "----" + height + "---"
// + getHeight());
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (parentLayout) {
parentLayout = false;
return;
}
if (changed) {
int cCount = getChildCount();
int cWidth = 0;
int cHeight = 0;
// boolean cursorFlag=false;
/**
* 遍历所有childView根据其宽和高,以及margin进行布局
*/
int start = currentChildCount;
// Log.e(VIEW_LOG_TAG, "onLayout=" + currentChildCount + "----"
// + itemIds.size());
for (int i = start; i < cCount; i++) {
// 跳过光标子项
int index = i;
if (currentChildCount != 0) {
index = i - 1;
}
if (index < itemIds.size()) {
View childView = findViewById(itemIds.keyAt(index));
if (childView != null) {
// Log.e(VIEW_LOG_TAG, "index" + index);
// Log.e(VIEW_LOG_TAG, cursorId + "---" + childView.getId()
// + "---" + itemIds.keyAt(index));
cWidth = childView.getMeasuredWidth();
cHeight = childView.getMeasuredHeight();
int cl = 0, ct = 0, cr = 0, cb = 0;
cl = 0;
ct = index * (spaceVert + itemHeight);
cr = cl + cWidth;
cb = cHeight + ct;
childView.layout(cl + paddingLeft, ct + paddingTop, cr
+ paddingLeft, cb + paddingTop);
}
}
}
screenMaxRow = getHeight() % rowHeight == 0 ? getHeight()
/ rowHeight : getHeight() / rowHeight + 1;
}
}
@Override
public boolean dispatchKeyEventPreIme(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
boolean flag = false;
View focused = this.findFocus();
View next = null;
int focusIndex = 0;
switch (focusOption) {
case PARENT_ONLY:
focusIndex = itemIds.get(focused.getId());
break;
case CHILD_ONLY:
focusIndex = itemIds.get(((View) focused.getParent()).getId());
break;
case PARENT_FIRST:
focusIndex = itemIds.get(focused.getId());
break;
case CHILD_FIRST:
focusIndex = itemIds.get(((View) focused.getParent()).getId());
break;
}
int direction = 0;
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_DPAD_DOWN:
direction = View.FOCUS_DOWN;
// 获得目标焦点控件
if (focusIndex < itemIds.size() - 1) {
next = findViewById(itemIds.keyAt(focusIndex + 1));
}
if (!canAdd) {
return true;
}
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
direction = View.FOCUS_RIGHT;
break;
case KeyEvent.KEYCODE_DPAD_UP:
if (focusIndex > 0) {
next = findViewById(itemIds.keyAt(focusIndex - 1));
}
direction = View.FOCUS_UP;
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
direction = View.FOCUS_LEFT;
break;
}
if (direction != 0) {
if (next != null) {
Integer temp = itemIds.get(next.getId());
// 焦点切出容器时
if (temp != null) {
selectIndex = temp;
} else {
parentLayout = true;
return super.dispatchKeyEventPreIme(event);
}
int nextIndex = temp;
// 向下到达最后一完整行时,可滚动; 向上到达最上一行完整行时,可滚动
if (nextIndex > focusIndex) {
if ((next.getTop() - mScroller.getFinalY()) >= (rowHeight * (screenMaxRow - 1))
+ paddingTop) {
flag = true;
}
} else if (nextIndex < focusIndex && nextIndex != 0) {
if ((next.getTop() - mScroller.getFinalY()) < rowHeight
+ paddingTop
&& focusIndex != 0) {
flag = true;
}
}
// 建缓冲区允许快速翻动
selectIndex = nextIndex;
if (flag) {
if (nextIndex > -1 && !scrollable
&& mScroller.isFinished()) {
// 先清除按钮动画
scrollable = true;
Message msg = handler.obtainMessage();
msg.obj = direction;
msg.what = ACTION_START_SCROLL;
handler.sendMessageDelayed(msg, scrollDelay);
} else {
return true;
}
}
}
}
}
return super.dispatchKeyEventPreIme(event);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
if (t == mScroller.getFinalY()) {
if (t > oldt) {
// 下翻加载 当剩余行数小于一屏时
if ((itemIds.size() - selectIndex) < screenMaxRow) {
canAdd = false;
Message msg = handler.obtainMessage();
msg.what = ACTION_ADD_ITEMS;
handler.sendMessageDelayed(msg, DELAY);
}
}
}
super.onScrollChanged(l, t, oldl, oldt);
}
/**
* 翻页
*
* @param page
*/
private void scrollByRow(final int direction) {
if (selectIndex < 0 || selectIndex > itemIds.size() - 1) {
return;
}
if (direction == View.FOCUS_UP) {
mScroller.startScroll(0, mScroller.getFinalY(), 0, -rowHeight,
scrollDuration);
} else if (direction == View.FOCUS_DOWN) {
mScroller.startScroll(0, mScroller.getFinalY(), 0, rowHeight,
scrollDuration);
}
invalidate();
// 滚动同时进行回收操作 避免卡顿
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//recycle(direction);
}
}, scrollDuration);
}
@Override
public void computeScroll() {
super.computeScroll();
// 先判断mScroller滚动是否完成
if (mScroller.computeScrollOffset()) {
// 这里调用View的scrollTo()完成实际的滚动
scrollTo(0, mScroller.getCurrY());
// 必须调用该方法,否则不一定能看到滚动效果
postInvalidate();
}
super.computeScroll();
}
/**
* 回收
*
* @param page
*/
private void recycle(int direction) {
if (selectIndex < 0 || selectIndex > itemIds.size() - 1) {
return;
}
if (direction == View.FOCUS_UP) {
int reloadIndex = selectIndex - screenMaxRow + 1;
// 上翻刷新 并重新选中行前一屏的行
if (reloadIndex > -1) {
// 4Log.e(VIEW_LOG_TAG, "reloadRow="+reloadRow);
mRecycleBin.reloadView(findViewById(itemIds
.keyAt(reloadIndex)));
}
// 回收行数大于selectIndex 2倍屏数的子项
int recyleIndex = selectIndex + screenMaxRow * 2;
if (recyleIndex < itemIds.size() - 1) {
// Log.e(VIEW_LOG_TAG, "recyleRow="+recyleRow);
mRecycleBin
.recycleView(findViewById(itemIds.keyAt(recyleIndex)));
}
} else if (direction == View.FOCUS_DOWN) {
// 重新加载选中行以下一屏行数
int reloadIndex = selectIndex + screenMaxRow - 1;
// 上翻刷新 并重新选中行前一屏的行
if (reloadIndex > -1) {
// 4Log.e(VIEW_LOG_TAG, "reloadRow="+reloadRow);
mRecycleBin.reloadView(findViewById(itemIds
.keyAt(reloadIndex)));
}
// 回收行数小于selectIndex 2倍屏数的子项
int recyleIndex = selectIndex - screenMaxRow * 2;
if (recyleIndex>-1&&recyleIndex < itemIds.size() - 1) {
// Log.e(VIEW_LOG_TAG, "recyleRow="+recyleRow);
mRecycleBin
.recycleView(findViewById(itemIds.keyAt(recyleIndex)));
}
}
}
/**
* 光标移动 到达后 与控件同时放大
*/
private void moveCover(View item, View focus) {
if (cursor == null) {
return;
}
setBorderParams(item, focus);
focus.bringToFront();
cursor.bringToFront();
if (scalable) {
scaleToLarge(focus);
}
}
/**
* 还原控件状态
*/
private void returnCover(View item) {
if (cursor == null) {
return;
}
cursor.setVisibility(View.INVISIBLE);
if (scalable) {
scaleToNormal(item);
}
}
private void scaleToLarge(View item) {
if (!item.isFocused()) {
return;
}
animatorSet = new AnimatorSet();
largeX = ObjectAnimator.ofFloat(item, "ScaleX", 1f, scale);
ObjectAnimator largeY = ObjectAnimator.ofFloat(item, "ScaleY", 1f,
scale);
ObjectAnimator cursorX = ObjectAnimator.ofFloat(cursor, "ScaleX", 1f,
scale);
ObjectAnimator cursorY = ObjectAnimator.ofFloat(cursor, "ScaleY", 1f,
scale);
animatorSet.setDuration(durationLarge);
animatorSet.play(largeX).with(largeY).with(cursorX).with(cursorY);
animatorSet.start();
}
private void scaleToNormal(View item) {
if (animatorSet == null) {
return;
}
if (animatorSet.isRunning()) {
animatorSet.cancel();
}
ObjectAnimator oa = ObjectAnimator.ofFloat(item, "ScaleX", 1f);
oa.setDuration(durationSmall);
oa.start();
ObjectAnimator oa2 = ObjectAnimator.ofFloat(item, "ScaleY", 1f);
oa2.setDuration(durationSmall);
oa2.start();
}
/**
* 指定光标相对位置
*/
private void setBorderParams(View item, View focus) {
cursor.clearAnimation();
cursor.setVisibility(View.VISIBLE);
// 判断类型
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) item
.getLayoutParams();
RelativeLayout.LayoutParams focusParams = (RelativeLayout.LayoutParams) focus
.getLayoutParams();
int l = 0, t = 0, r = 0, b = 0;
if (item == focus) {
l = params.leftMargin + paddingLeft - boarderLeft;
t = params.topMargin + paddingTop - boarderTop;
r = l + itemWidth + boarderRight + boarderLeft;
b = t + itemHeight + boarderBottom + boarderTop;
} else {
l = params.leftMargin + focus.getLeft() + paddingLeft - boarderLeft;
t = params.topMargin + focus.getTop() + paddingTop - boarderTop;
r = l + focusParams.width + boarderRight + boarderLeft;
b = t + focusParams.height + boarderBottom + boarderTop;
}
cursor.layout(l, t, r, b);
}
public void setOnItemSelectListener(OnItemSelectListener myListener) {
this.onItemSelectListener = myListener;
}
public void setOnItemClickListener(OnItemClickListener myListener) {
this.onItemClickListener = myListener;
}
public interface OnItemSelectListener {
/**
* 子项获得焦点
*
* @param item
* @param position
*/
public void onItemSelect(View item, int position);
/**
* 子项失去焦点
*
* @param item
* @param position
*/
public void onItemDisSelect(View item, int position);
}
public interface OnItemClickListener {
public void onItemClick(View item, int position);
}
public class AdapterDataSetObservable extends DataSetObservable {
@Override
public void notifyChanged() {
// 数据改变 若已翻至末端 则立即调用addNewItems
Log.i(VIEW_LOG_TAG, "收到数据改变通知");
if (adapter.getCount()<=itemIds.size()) {
//删减刷新
clear();
clear();
Message msg = handler.obtainMessage();
msg.what = ACTION_INIT_ITEMS;
handler.sendMessageDelayed(msg, DELAY);
}else{
//添加刷新
if ((itemIds.size() - selectIndex) < screenMaxRow) {
canAdd = false;
Message msg = handler.obtainMessage();
msg.what = ACTION_ADD_ITEMS;
handler.sendMessageDelayed(msg, DELAY);
}
}
super.notifyChanged();
}
@Override
public void notifyInvalidated() {
super.notifyInvalidated();
}
}
}