标签:
在tv上开发gridview有焦点放大这个效果还是很普遍的做法,今天就讲下这个实现方案,当然要实现这个效果有很多种,我这里只是讲其中的一种实现方案,也是比较简单而且容易看懂的一个,首先看下效果图是怎么样的?
这个肯定也许会这么想我选中了那个item就设置一张焦点框图片就可以实现,告诉你没这么简单,这个框是根据你选中了那个item而动态画上去的,而画的位置是要获取item view的坐标的,我准备把这个用到的知识点分开一点点讲,然后再合拼起来,首先说下怎么把一个背景图画上去,我们知道自定义一个view在onDraw()方法中画
public class CutomView extends View { private Paint mPaint; private Bitmap bitmap; public CutomView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public CutomView(Context context, AttributeSet attrs) { super(context, attrs); mPaint = new Paint(); bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); } public CutomView(Context context) { super(context); // TODO Auto-generated constructor stub } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawBitmap(bitmap, 100, 100, mPaint); } }但是其实还有一个方法也可以实现这个:
@Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); canvas.drawBitmap(bitmap, 400, 400, mPaint); }看下效果:
前面一个是坐标点(100,100)后一个坐标点是(400,400) 说明这二个方法都可以把一个资源通过canvas画上去,而dispatchDraw通常是用在容器view中的,所谓的容器view就是能有addView()方法,比如RelativeLayout,LinearLayout,ListView,GridView等,但是像上面的焦点框是咋么画上去的呢?是一个view还是一个其他的东西呢?如果是view的画就要再自定义一个view,当然也可以不用view,用Drawable也行,看下view的继承或者实现关系:
从图可以看出来view实现了Drawable.Callback还有KeyEvent.Callback,前者是关于Drawable一些方法比如如何把一张图片绘制到view上,后者是一些关于一些遥控器事件,关于Drawable一些方法大概如下:
这些方法我我们不可能全部搞懂或者用到,在这里就讲2到3个方法,
draw(Canvas canvas)是用于把drawable绘制到view上的
setBounds(Rect bounds)和setBounds(int left, int top, int right, int bottom)这二个方法其实是一个意思,当你要把一个drawable绘制到屏幕上.你肯定要知道要绘制在那个位置,而我们知道其实每个view都是一个Rect也就是一个矩形,我们知道这个矩形也就意味着把这个view的2个点确定下来,那么现在就自定义一个RelativeLayout,然后通过上面讲的方法如何把一个图片绘制到view上,代码如下:
public class CutomView extends RelativeLayout { private Paint mPaint; private Bitmap bitmap; private Drawable drawable; public CutomView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public CutomView(Context context, AttributeSet attrs) { super(context, attrs); mPaint = new Paint(); drawable = getResources().getDrawable(R.drawable.topic_focus);//这是焦点框 } public CutomView(Context context) { super(context); // TODO Auto-generated constructor stub } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); drawable.setBounds(100, 100, 500, 500); drawable.draw(canvas); } }效果图:
如果要达到gridview焦点放大的效果是不是要知道每个item view的坐标点,知道了这个如何动态绘制这个焦点框是不是就可以了,通常获取一个view的坐标有如下四种做法
1:getLocationInWindow
这个获取坐标是相当于当前的activity,我现在做一个实验,如何获取这个坐标点,
button = (Button) findViewById(R.id.button); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { int[] position = new int[2]; button.getLocationInWindow(position); Log.e(TAG,"getLocationInWindow:" + position[0] + "," + position[1]); } });
结果是:
x=0y=228但是我button的位置是这样的:
我这button离父view左边是0上边也是0也就是y轴的高度也是0,而这打印出来是228,就说明这个是相对于屏幕的,屏幕就有状态栏和标题栏,获取状态栏高度
Rect frame = new Rect(); getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); int statusBarHeight = frame.top;
获取标题栏高度
//statusBarHeight是上面所求的状态栏的高度 int titleBarHeight = contentTop - statusBarHeight ; 结果是statusBarHeight 是60 titleBarHeight是168 加起来就是228了,这就验证了getLocationInWindow()是相对屏幕而已不是相对父view而言, int[] position = new int[2]; button.getLocationOnScreen(position); System.out.println("getLocationOnScreen:" + position[0] + "," + position[1]);
这个获取x,y轴坐标是一样的,
getGlobalVisibleRec
这个是通过view围城的矩形来获取它的坐标:
<pre name="code" class="java">Rect viewRect = new Rect(); button.getGlobalVisibleRect(viewRect); Log.e(TAG,"left="+viewRect.left+"top="+viewRect.top+"right="+viewRect.right+"bottom"+viewRect.bottom)
结果:<span style="font-family: Arial, Helvetica, sans-serif;">left=0top=228right=353bottom372</span>
这个也是相对它屏幕而言的,
getLocalVisibleRect
Rect globeRect = new Rect(); button.getLocalVisibleRect(globeRect); Log.e(TAG,"left="+globeRect.left+"top="+globeRect.top+"right="+globeRect.right+"bottom"+globeRect.bottom);结果:
这个结果说明这个是相对于父view而言的 子view的坐标<span style="line-height: 25.2px;">好了分析就到这里了,现在把好的效果代码贴上来</span>
<span style="line-height: 25.2px;">example.demo;</span>
import java.util.ArrayList; import java.util.List; import com.commons.CustomImageView; import com.commons.ZoneGridView; import android.app.Activity; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; public class MainActivity extends Activity { private ZoneGridView gridview; private List<String> datas; private MyAdapter adapter; private CustomImageView iv; private int[] ids={R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w,R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e,R.drawable.f,R.drawable.g,R.drawable.h ,R.drawable.i,R.drawable.j,R.drawable.x,R.drawable.y,R.drawable.r,R.drawable.w}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); gridview = (ZoneGridView) findViewById(R.id.gridview); iv = (CustomImageView) findViewById(R.id.iv); initData(); adapter = new MyAdapter(); gridview.setAdapter(adapter); gridview.setClipToPadding(false); gridview.setSelected(true); gridview.setSelection(0); gridview.setSelector(android.R.color.transparent); gridview.setMySelector(R.drawable.topic_focus); gridview.setMyScaleValues(1.2f, 1.2f); } private void initData() { datas = new ArrayList<String>(); for(int i=0;i<ids.length;i++){ datas.add("专辑列表---"+i); } } class MyAdapter extends BaseAdapter{ @Override public int getCount() { // TODO Auto-generated method stub return datas.size(); } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder = null; if(convertView==null){ viewHolder = new ViewHolder(); convertView = LayoutInflater.from(getApplicationContext()).inflate(R.layout.item, null); convertView.setTag(viewHolder); }else{ viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.iv = (ImageView) convertView.findViewById(R.id.iv); viewHolder.tv_name = (TextView) convertView.findViewById(R.id.tv_name); viewHolder.tv_name.setText(datas.get(position)); viewHolder.iv.setImageResource(ids[position]); return convertView; } } class ViewHolder{ ImageView iv; TextView tv_name; } }
xml文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <com.commons.ZoneGridView android:id="@+id/gridview" android:layout_width="match_parent" android:layout_height="match_parent" android:numColumns="6" android:horizontalSpacing="8dp" android:verticalSpacing="30dp" android:layout_marginTop="20dp" android:gravity="center_horizontal" android:drawSelectorOnTop="true" android:scrollbars="none" android:padding="30dp" android:background="#ff0000" > </com.commons.ZoneGridView> </RelativeLayout>
package com.commons; import android.content.Context; 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.widget.GridView; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; public class ZoneGridView extends GridView { float mMyScaleX = 1.0f; float mMyScaleY = 1.0f; protected Rect mMySelectedPaddingRect = new Rect(); int mPlayIconMargin; private int position = 0; public ZoneGridView(Context contxt) { super(contxt); setChildrenDrawingOrderEnabled(true); setClipChildren(false); setClipToPadding(false); } public ZoneGridView(Context contxt, AttributeSet attrs) { super(contxt, attrs); setChildrenDrawingOrderEnabled(true); setClipChildren(false); setClipToPadding(false); } public ZoneGridView(Context contxt, AttributeSet attrs, int defStyle) { super(contxt, attrs, defStyle); setChildrenDrawingOrderEnabled(true); setClipChildren(false); setClipToPadding(false); } @Override public void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); if (mMySelectedDrawable == null) return; drawSelector(canvas); } /** * 设置焦点框的图片 * @param resId */ public void setMySelector(int resId) { mMySelectedDrawable = getResources().getDrawable(resId); mMySelectedPaddingRect = new Rect(); mMySelectedDrawable.getPadding(mMySelectedPaddingRect);//获取drawable所画区域的内边框 } protected Drawable mMySelectedDrawable = null; protected View mMySelectedView = null; protected Rect mTmpSelectedRect = new Rect(); protected Rect mTmpGridViewRect = new Rect(); /** * 这是关键点 * @param canvas */ protected void drawSelector(Canvas canvas) { View v = getSelectedView(); bringChildToFront(v); if (isFocused() && v != null) { scaleCurrentView(); if(v instanceof RelativeLayout){ RelativeLayout rl = (RelativeLayout) v; ImageView tmepView = (ImageView) rl.getChildAt(0); TextView tv = (TextView) rl.getChildAt(1); tv.setTextColor(Color.WHITE); Rect r = mTmpSelectedRect; tmepView.getGlobalVisibleRect(r);//Rect(62, 152 - 398, 512) 计算出imageview在屏幕的坐标点 getGlobalVisibleRect(mTmpGridViewRect);//计算出屏幕的坐标点 Rect(45, 141 - 1875, 1035) r.offset(-mTmpGridViewRect.left, -mTmpGridViewRect.top);//向左移动--mTmpGridViewRect.left就是向右滑动-mTmpGridViewRect.left r.top -= mMySelectedPaddingRect.top+DensityUtil.dip2px(getContext(), 6); r.left -= mMySelectedPaddingRect.left+DensityUtil.dip2px(getContext(), 6); r.right += mMySelectedPaddingRect.right+DensityUtil.dip2px(getContext(), 6); r.bottom += mMySelectedPaddingRect.bottom+DensityUtil.dip2px(getContext(), 6); mMySelectedDrawable.setBounds(r); mMySelectedDrawable.draw(canvas); } } } public void setMyScaleValues(float scaleX, float scaleY) { mMyScaleX = scaleX; mMyScaleY = scaleY; } void scaleCurrentView(){ View v = getSelectedView(); unScalePrevView(); if(v != null){ mMySelectedView = v; mMySelectedView.setScaleX(mMyScaleX); mMySelectedView.setScaleY(mMyScaleY); } } /** * 把上一次获取焦点 还原 */ void unScalePrevView(){ if(mMySelectedView != null){ if(mMySelectedView instanceof RelativeLayout){ RelativeLayout rl = (RelativeLayout) mMySelectedView; TextView tv = (TextView) rl.getChildAt(1); tv.setTextColor(Color.RED); } mMySelectedView.setScaleX(1); mMySelectedView.setScaleY(1); mMySelectedView = null; } } protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) { if(!gainFocus){ unScalePrevView(); requestLayout(); } super.onFocusChanged(gainFocus, direction, previouslyFocusedRect); } protected int mMyVerticalSpacing = 0; public void setMyVerticalSpacing(int verticalSpacing) { mMyVerticalSpacing = verticalSpacing; } public int getMyVerticalSpacing() { return mMyVerticalSpacing; } @Override protected int getChildDrawingOrder(int childCount, int i) { if (position != -1) { if (i == childCount - 1) return position; if (i == position) return childCount - 1; } return i; } @Override public void bringChildToFront(View child) { position = indexOfChild(child); postInvalidate(); } }
item布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ImageView android:id="@+id/iv" android:layout_width="200dp" android:layout_height="200dp" android:src="@drawable/w" android:scaleType="fitXY" /> <TextView android:id="@+id/tv_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:textColor="#ff0000" android:text="江湖论剑" android:layout_below="@id/iv" android:layout_marginTop="5dp" /> </RelativeLayout>
<pre code_snippet_id="1675432" snippet_file_name="blog_20160508_28_338885" name="code" class="java">@Override protected int getChildDrawingOrder(int childCount, int i) { if (position != -1) { if (i == childCount - 1) return position; if (i == position) return childCount - 1; } return i; } @Override public void bringChildToFront(View child) { position = indexOfChild(child); postInvalidate(); }这个是为了解决焦点框被上层item挡住
getChildDrawingOrder 是改变子view的绘制顺序,如果要重写这个必须先 setChildrenDrawingOrderEnabled(true);来允许子类排序
标签:
原文地址:http://blog.csdn.net/coderinchina/article/details/51344970