Android GridView控件自定义

虽然Android已自带了GridView,但是,却不够灵活,同时也不能自由添加控件,因此,本人通过需要进一步封装,来实现Android自定义GridView控件,达到自己需要的效果。

我们看一下最终所需要的效果图:

说明:

上图:这里先省去分页,只讲:Android GridView 控件实现自定义。

按照上面的图例需求,大致上可以把Android GridView 画成如下的方式:

思路如下:

   默认将我们的组合控件设置为Orientation 是VERTICAL。 首先一行五个,那么一行以一个Orientation 为HORIZONTAL 的线性布局包起来。然后在一行结束后,将Orientation 的线性布局添加进组合控件里面来,不足五个则按需添加进来。

  实现这一效果我们需要两个类,一个类用来表示Android GridView 的行,这里我们起名为TableRow,代码如下:

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() {

return cell.length;

}

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() {

@Override
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) {
lastRowCount = j;
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, 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();
}

当然,你必须在res 创建属性xml ,这里不多讲,可以去我博客看看如何为 View 添加属性

还有,还必须实现它的支持键盘的上下左右的焦点,下面的代码将会提供该功能,但还必须配合Activity 的操作,等下文再讲述。效果是这样的:

全部源码为:

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 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();
}

public void setOnItemClickListener(onItemClickListener click) {
this.onItemClickEvent = click;
}

public void setOnLongPressListener(onLongPressExt longPress) {
this.onLongPress = longPress;
}

public void NotifyDataChange() {
removeAllViews();
}

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() {

@Override
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) {
lastRowCount = j;
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, j, tr);
}

}

}

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 setAdapter(AppsAdapter appsAdapter) {
this.adapter = appsAdapter;
this.setOrientation(LinearLayout.VERTICAL);
bindView();
}

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);
}
if (name[1].toString().equals(
"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);
HashMap<String, Object> map = new HashMap<String, Object>();
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);

}
}

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() {

return cell.length;

}

public int getLastCellCount() {
return lastRowCount;
}
}

static public
class TableCell {
private Object value;

public TableCell(Object value) {
this.value = value;
}

public Object getValue() {
return value;
}
}

}

每行显示的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 出来,但注意要设置它每列显示的个数。

如何,看到这里,是不是觉得自定义的GridView很强大呢?大也自己DIY一下Android GridView控件自定义吧。

时间: 2024-11-19 01:31:17

Android GridView控件自定义的相关文章

net-使用gridview控件自定义列之后怎么删除默认的?

问题描述 使用gridview控件自定义列之后怎么删除默认的? 怎么把图中右边的那几个默认的列给删了,在线等,多谢多谢 解决方案 自定义GridView控件GridVieW控件自定义删除按钮-解决多级相关中删除问题Gridview全解之自定义删除控件

ASP.NET技巧:GridView控件自定义分页详解

asp.net|分页|技巧|控件|详解   前些天我写了关于 <<在存储过程中实现分页>>和<<GridView控件事件详解 >> ,后来又有一些人问我怎样在GridView中应用这个东东!其实很简单,主要是怎么保存当前页面的页码PageIndex问题,不过把这个解决了什么都好办了.因为在分页过程中:PageSize是一定的,我们可以用一个属性来表示.保存PageIndex好多中方法,而且数据不是很庞大,基本不会好太多的资源.还是一句老话,话再多都没有例子直

Android实用控件自定义逼真相机光圈View_Android

最近手机界开始流行双摄像头,大光圈功能也应用而生.所谓大光圈功能就是能够对照片进行后期重新对焦,其实现的原理主要是对拍照期间获取的深度图片与对焦无穷远的图像通过算法来实现重新对焦的效果.  在某双摄手机的大光圈操作界面有个光圈的操作图标,能够模拟光圈调节时的真实效果,感觉还不错,于是想着实现该效果.现在把我的实现方法贡献给大家,万一你们公司也要做双摄手机呢?( ̄┰ ̄*)  首先,百度一下光圈图片,观察观察,就可以发现其关键在于计算不同的光圈值时各个光圈叶片的位置.为了计算简便,我以六个直边叶片的

Android实用控件自定义逼真相机光圈View

最近手机界开始流行双摄像头,大光圈功能也应用而生.所谓大光圈功能就是能够对照片进行后期重新对焦,其实现的原理主要是对拍照期间获取的深度图片与对焦无穷远的图像通过算法来实现重新对焦的效果. 在某双摄手机的大光圈操作界面有个光圈的操作图标,能够模拟光圈调节时的真实效果,感觉还不错,于是想着实现该效果.现在把我的实现方法贡献给大家,万一你们公司也要做双摄手机呢?( ̄┰ ̄*) 首先,百度一下光圈图片,观察观察,就可以发现其关键在于计算不同的光圈值时各个光圈叶片的位置.为了计算简便,我以六个直边叶片的光圈

GridView控件自定义分页的实现

前人栽树,后人乘凉,话不多说,代码如下:     实现方式一: .aspx: [c-sharp] view plain copy <form id="form1" runat="server">       <table style="width: 605px">         <tr>           <td style="width: 921px">          

小弟请教个自定义gridView控件遇到的问题?

问题描述 我现在打算自己写个GridView控件,但是排序的问题让我有点不好实现,我在调用的时候怎么将当前的排序字段传给控件呢也就是说排序功能怎么可以实现自定义,使得这个控件更通用?各位有什么好的建议...我用的是vs2005 解决方案 解决方案二:在表头加上单击事件然后在后台:usingSystem;usingSystem.Data;usingSystem.Configuration;usingSystem.Collections;usingSystem.Web;usingSystem.Web

Android学习教程之动态GridView控件使用(6)

本文实例为大家分享了Android动态GridView控件使用的具体代码,供大家参考,具体内容如下 MainActivity.java代码: package siso.haha; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button

Android编程实现GridView控件点击图片变暗效果的方法

本文实例讲述了Android编程实现GridView控件点击图片变暗效果的方法.分享给大家供大家参考,具体如下: @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); grid = (GridView) findViewById(R.id.grid); grid.setAdapte

扩展ASP.NET内置GridView控件之一

asp.net|控件 本文Bilal Haidar详细解释如何扩展ASP.NET2.0内置的GridView控件,同样还将解释了扩展后的GridView控件所具有的新的重要特征:基于行的上下文菜单和GridViews行的过滤功能. 引言 本文将聚焦对ASP.NET2.0内置的GridView进行扩展的一系列新功能.其中本文介绍两个主要特征:基于行的上下文菜单(Row_base ContextMenu)和基于过滤功能的GridView的行,在上周我曾经介绍了GridView控件. 在我们自定义的G