天天看點

自定義gradview

http://blog.csdn.net/jdsjlzx/article/details/7525724

我們看一下最終所需要的效果圖:

自定義gradview

說明:

自定義gradview

思路如下:

   預設将我們的組合控件設定為orientation 是vertical。 首先一行五個,那麼一行以一個orientation 為horizontal 的線性布局包起來。然後在一行結束後,将orientation 的線性布局添加進組合控件裡面來,不足五個則按需添加進來。

public class tablerow {

private tablecell[] cell;

public tablerow(tablecell[] cell) {

this.cell = cell;

}

public int getsize() {

return cell.length;

public tablecell getcellvalue(int index) {

if (index >= getsize()) {

return null;

return cell[index];

public int getcellcount() {

public int getlastcellcount() {

return lastrowcount;

  另外一個類用來表示gridview 每行的列個,這裡我們取名為tablecell,代碼如下:

static public class tablecell {

private object value;

public tablecell(object value) {

this.value = value;

public object getvalue() {

return value;

  并且我們還需要為gridview 設定一個外部可添加資料的方法,代碼如下:

public void setadapter(appsadapter appsadapter) {

this.adapter = appsadapter;

this.setorientation(linearlayout.vertical);

bindview();

其中,appsadapter 是一個自定義的baseadapter ,代碼很簡單,這裡就不列出來了。關鍵的還是要看bindview ,這個方法是本篇gridview 顯示資料的核心方法,代碼如下:

void bindview() {

removeallviews();

int count = adapter.getcount();

tablecell[] cell = null;

int j = 0;

linearlayout layout;

tablerowslist = new arraylist<hashmap<string, object>>();

for (int i = 0; i < count; i++) {

j++;

final int position = i;

if (j > getcolumncount() || i == 0) {

cell = new tablecell[getcolumncount()];

final view view = adapter.getview(i, null, null);

view.setontouchlistener(new ontouchlistener() {

@override

public boolean ontouch(view v, motionevent event) {

// todo auto-generated method stub

uncheckpressed();

checkrowid = -1;

checkcolumnid = -1;

if (onitemclickevent != null) {

onitemclickevent.onitemclick(position, event, view);

return false;

});

view.setonlongclicklistener(new onlongclicklistener() {

public boolean onlongclick(view v) {

if (onlongpress != null) {

onlongpress.onlongpress(v);

return true;

cell[j - 1] = new tablecell(view);

if (j == getcolumncount()) {

lastrowcount = j;

j = 0;

hashmap<string, object> map = new hashmap<string, object>();

tablerow tr = new tablerow(cell);

map.put("tablerow", tr);

tablerowslist.add(map);

layout = new linearlayout(getcontext());

addlayout(layout, cell, tr.getsize(), tr);

} else if (i >= count - 1 && j > 0) {

addlayout(layout, cell, j, tr);

getcolumncount()是一個屬性,表示可以從xml或者從代碼動态改變gridview 每列顯示的個數,屬性點的代碼為如下:

public gridviewext(context context, attributeset attrs) {

super(context, attrs);

int resouceid = -1;

typedarray typedarray = context.obtainstyledattributes(attrs,

r.styleable.gridviewext);

int n = typedarray.getindexcount();

for (int i = 0; i < n; i++) {

int attr = typedarray.getindex(i);

switch (attr) {

case r.styleable.gridviewext_columncount:

resouceid = typedarray.getint(

r.styleable.gridviewext_columncount, 0);

setcolumncount(resouceid);

break;

typedarray.recycle();

還有,還必須實作它的支援鍵盤的上下左右的焦點,下面的代碼将會提供該功能,但還必須配合activity 的操作,等下文再講述。效果是這樣的:

自定義gradview

全部源碼為:

package com.yaomei.widget;

import java.util.arraylist;

import java.util.hashmap;

import java.util.list;

import android.content.context;

import android.content.intent;

import android.content.res.typedarray;

import android.util.attributeset;

import android.view.gravity;

import android.view.motionevent;

import android.view.view;

import android.view.viewgroup;

import android.widget.linearlayout;

import android.widget.textview;

import com.yaomei.activity.adapter.appsadapter;

import com.yaomei.activity.info.r;

public class gridviewext extends linearlayout {

public list<hashmap<string, object>> tablerowslist;

private list<hashmap<string, object>> app = new arraylist<hashmap<string, object>>();

private appsadapter adapter;

onitemclicklistener onitemclickevent;

onlongpressext onlongpress;

int checkrowid = -1; // 選中行的下标

int checkcolumnid = -1; // 選中列的下标

int lastrowcount = -1; // 最後一行的總數

private int columncount; // 每列的總數

public void setcolumncount(int count) {

this.columncount = count;

public int getcolumncount() {

return columncount;

public interface onitemclicklistener {

public boolean onitemclick(int position, motionevent event, view view);

public interface onlongpressext {

public boolean onlongpress(view view);

public gridviewext(context context) {

this(context, null);

// todo auto-generated constructor stub

public void setonitemclicklistener(onitemclicklistener click) {

this.onitemclickevent = click;

public void setonlongpresslistener(onlongpressext longpress) {

this.onlongpress = longpress;

public void notifydatachange() {

private void addlayout(linearlayout layout, tablecell[] cell, int size,

tablerow tr) {

linearlayout.layoutparams params = new linearlayout.layoutparams(130,

110);

layout.setgravity(gravity.left);

layout.setorientation(linearlayout.horizontal);

for (int k = 0; k < size; k++) {

view remoteview = (view) tr.getcellvalue(k).getvalue();

layout.addview(remoteview, k, params);

linearlayout.layoutparams firstparams = new linearlayout.layoutparams(

layoutparams.wrap_content, layoutparams.wrap_content);

firstparams.leftmargin = 60;

addview(layout, firstparams);

public void checkpressed(int tablerowid, int tablerowcolumnid) {

viewgroup view = (viewgroup) this.getchildat(tablerowid);

checkcolumnid = tablerowcolumnid;

checkrowid = tablerowid;

changeimagestate(view.getchildat(tablerowcolumnid), app);

public void onclick(int tablerowid, int tablerowcolumnid, context context) {

linearlayout view = (linearlayout) ((viewgroup) this

.getchildat(tablerowid)).getchildat(tablerowcolumnid);

textview tv = (textview) view.findviewbyid(r.id.folder);

final string[] name = tv.gettext().tostring().split("-");

intent intent = null;

if (name[0].tostring().equals("com.android.contacts"))

{

if (name[1].tostring().equals(

"com.android.contacts.dialtactsactivity")) {

intent = new intent(intent.action_dial);

"com.android.contacts.dialtactscontactsentryactivity")) {

intent = new intent(intent.action_call_button);

} else {

intent = getcontext().getpackagemanager()

.getlaunchintentforpackage(name[0].tostring());

context.startactivity(intent);

/**

* 改變圖檔狀态

* @param v

* @param list

*/

private void changeimagestate(view v, list<hashmap<string, object>> list) {

int size = list.size();

for (int i = 0; i < size; i++) {

view view = (view) list.get(i).get("touch");

view.setpressed(false);

list.remove(i);

v.setpressed(true);

map.put("touch", v);

list.add(map);

public void uncheckpressed() {

if (checkcolumnid != -1 && checkrowid != -1) {

viewgroup view = (viewgroup) this.getchildat(checkrowid);

view.getchildat(checkcolumnid).setpressed(false);

每行顯示的layout檔案:

<linearlayout android:orientation="vertical"

android:background="@drawable/lessbtn" android:gravity="center"

android:layout_width="fill_parent" android:id="@+id/grid_layout"

android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android">

<imageview android:id="@+id/btn_appicon"

android:layout_width="55dip" android:layout_height="55dip"></imageview>

<textview android:id="@+id/tv_name" android:layout_width="wrap_content"

android:textcolor="#030303" android:layout_height="wrap_content"></textview>

<textview android:id="@+id/folder" android:layout_width="wrap_content"

android:visibility="invisible" android:layout_height="wrap_content"></textview>

</linearlayout>

完成這一系列的編寫後,你就可以在xml直接寫或者在java檔案裡面new 出來,但注意要設定它每列顯示的個數。

繼續閱讀