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