虽然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控件自定义吧。
标签:控件,layout,自定义,int,cell,new,Android,public,android From: https://blog.51cto.com/jdsjlzx/5733507