Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android tv gridview焦點放大效果

android tv gridview焦點放大效果

編輯:關於Android編程

在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圍城的矩形來獲取它的坐標:

Rect viewRect = new Rect(); button.getGlobalVisibleRect(viewRect); Log.e(TAG,"left="+viewRect.left+"top="+viewRect.top+"right="+viewRect.right+"bottom"+viewRect.bottom)

結果:left=0top=228right=353bottom372

這個也是相對它屏幕而言的,

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的坐標好了分析就到這裡了,現在把好的效果代碼貼上來
example.demo;
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 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();
    	for(int i=0;i

xml文件

    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    
        


自定義的GridView

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布局:

<relativelayout android:layout_height="match_parent" android:layout_width="match_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android">
    <imageview android:id="@+id/iv" android:layout_height="200dp" android:layout_width="200dp" android:scaletype="fitXY" android:src="@drawable/w">
	<textview android:gravity="center" android:id="@+id/tv_name" android:layout_below="@id/iv" android:layout_height="wrap_content" android:layout_margintop="5dp" android:layout_width="match_parent" android:text="江湖論劍" android:textcolor="#ff0000">
</textview></imageview></relativelayout>

其中自定義gridview有一段關鍵的代碼:


@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);來允許子類排序
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved