編輯:關於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;ixml文件
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);來允許子類排序
Android開發學習之路--圖表實現(achartengine/MPAndroidChart)之初體驗
??已經有一段時間沒有更新博客了,在上周離開工作了4年的公司,從此不再安安穩穩地工作了,更多的是接受挑戰和實現自身價值的提高。離開了嵌入式linux,從此擁抱移動互聯網,
AndroidHttpClient詳解及調用示例
下面給大家展示了AndroidHttpClient結構:public final classAndroidHttpClientextends Objectimplemen
Android開發學習路線圖
行業背景: 今天,涉及通信產業鏈中的每個環節,都有Android的身影,Android是第一款完全
android自定義控件之中間是斜線的占比條
最近一直在看各路大神的自定義控件,自己受益非淺,可是一直也沒有自己動手寫一個,這幾天有一個項目中要求有如下圖這樣一個功能:兩個動態值,根據其占比,在這個橫柱上顯示出來,中