关于缩放,使用了view.setScaleX/Y 方法,api11以上即可。
重写dispatchDraw(),绘制选中项的焦点效果。(注意带阴影的焦点图需要微调偏移量)
要将选中项绘制显示在顶层,所以要改变GridView的子View绘制顺序;
所以要重写bringChildToFront、getChildDrawingOrder,同时要打开setChildrenDrawingOrderEnabled(true)。
在缩放代码中添加了监听器,用于调用端,设置回调。
注意: 如果GridView的最后一行的个数少于列数,在较少的列上向下,会报异常。 还有就是当快速切换时,可能会看到默认的listSelector,可以将其设置为透明的。
package com.stone.tvapplication.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.stone.tvapplication.R;
import com.stone.tvapplication.util.AdaptionAlgo;
/**
* 重写dispatchDraw,在选中项上绘制一个focus-drawable
*
* author : stone
* email : aa86799@163.com
* time : 16/5/11 10 20
*/
public class TvFocusGridView extends GridView {
private Drawable mFocusBackDrawable;
private Rect mFocusBackRect;
private int mSelectedPosition;
private View mSelectedView;
private float mScaleX;
private float mScaleY;
private onItemFocusSelectedListener mOnItemFocusSelectedListener;
public TvFocusGridView(Context context) {
this(context, null);
}
public TvFocusGridView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TvFocusGridView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setClipChildren(false);
setClipToPadding(false);
setChildrenDrawingOrderEnabled(true);//设置绘制顺序可重定义,需要重写getChildDrawingOrder来变化绘制顺序
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.TvFocusGridView);
mFocusBackDrawable = array.getDrawable(R.styleable.TvFocusGridView_focus_background);
array.recycle();
mFocusBackRect = new Rect();
mFocusBackDrawable.getPadding(mFocusBackRect); //Drawable中实际填充图像的Rect
// System.out.println("mFocusBackRect-->" + mFocusBackRect);
}
public interface onItemFocusSelectedListener {
void onFocused(View child, int position);
void unfocused(View child, int position);
}
public void setOnItemFocusSelectedListener(onItemFocusSelectedListener onItemFocusSelectedListener) {
this.mOnItemFocusSelectedListener = onItemFocusSelectedListener;
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (mFocusBackDrawable == null) {
return;
}
drawSelector(canvas);
}
private void drawSelector(Canvas canvas) {
View view = getSelectedView();
if (view == null) return;
bringChildToFront(view);
if (isFocused()) {
scaleSelectedView(view);
Rect gvVisibleRect = new Rect();
this.getGlobalVisibleRect(gvVisibleRect); //GridView可见区 在屏幕中的绝对坐标 rect
Rect selectedViewRect = new Rect();
if (mSelectedView instanceof ViewGroup) {
mSelectedView.getGlobalVisibleRect(selectedViewRect); //选中View可见区 在屏幕中的绝对坐标 rect
selectedViewRect.offset(-gvVisibleRect.left, - gvVisibleRect.top); //偏移
selectedViewRect.left -= mFocusBackRect.left + 40;//+阴影偏移
selectedViewRect.top -= mFocusBackRect.top + 20;
selectedViewRect.right += mFocusBackRect.right + 40;
selectedViewRect.bottom += mFocusBackRect.bottom + 20;
mFocusBackDrawable.setBounds(selectedViewRect);
mFocusBackDrawable.draw(canvas);
}
}
}
/**
* 使子view位置在上层
* @param child
*/
@Override
public void bringChildToFront(View child) { //重写,不调用父类方法;获取child的实际position
// super.bringChildToFront(child);
mSelectedPosition = indexOfChild(child);
invalidate();
}
@Override
protected int getChildDrawingOrder(int childCount, int i) {//交换 选中项与最后一项 绘制的顺序
if (mSelectedPosition != AbsListView.INVALID_POSITION) {
if (i == mSelectedPosition) {
return childCount - 1;
}
if (i == childCount - 1) {
return mSelectedPosition;
}
}
return super.getChildDrawingOrder(childCount, i);
}
private void scaleSelectedView(View view) {//缩放
unScalePreView();
mSelectedView = view;
mSelectedView.setScaleX(mScaleX); //api11
mSelectedView.setScaleY(mScaleY);
if (mOnItemFocusSelectedListener != null) {
mOnItemFocusSelectedListener.onFocused(mSelectedView, indexOfChild(mSelectedView));
}
}
private void unScalePreView() {//还原
if (mSelectedView != null) {
mSelectedView.setScaleX(1);
mSelectedView.setScaleY(1);
if (mOnItemFocusSelectedListener != null) {
mOnItemFocusSelectedListener.unfocused(mSelectedView, indexOfChild(mSelectedView));
}
mSelectedView = null;
}
}
@Override
protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {//整个GridView焦点状态
if (!gainFocus) {
unScalePreView();
requestLayout();
}
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
}
public void setScale(float scaleX, float scaleY) {
this.mScaleX = scaleX;
this.mScaleY = scaleY;
}
}
调用端设置与监听:
mGridView.setAdapter(mAdapter);
mGridView.setScale(1.2f, 1.2f);
mGridView.setHorizontalSpacing(AdaptionAlgo.scaleX(30));
mGridView.setVerticalSpacing(AdaptionAlgo.scaleY(30));
mGridView.setPadding(60, 40, 60, 40);
mGridView.setOnItemFocusSelectedListener(new TvFocusGridView.onItemFocusSelectedListener() {
@Override
public void onFocused(View child, int position) {
TextView tv = getViewById(child, R.id.tv_text);
tv.setTextColor(Color.RED);
}
@Override
public void unfocused(View child, int position) {
TextView tv = getViewById(child, R.id.tv_text);
tv.setTextColor(Color.MAGENTA);
}
});
核心代码出自:http://blog.csdn.net/coderinchina/article/details/51344970
热门评论
这bug解决了没?这有bug完全不能使用啊