您的位置:首页 > 移动开发 > Android开发

Android 分享机顶盒项目的封装类《GridView》 推荐

2011-01-18 21:09 260 查看
由于使用系统自带的GridView 不够灵活,不能允许拖拉控件,故自己结合LinearLayout 封装的一个GridView ,通过本篇文章的阅读你可以学会如何自定义控件,如何使用组合控件,如何为自己的组合控件添加数据源和如何为自定义控件添加属性。

  首先,我们要实现的效果是这样的:



  上面1 2也是一个封装控件,用来为应用程序分页,具体如何实现下篇文章会提到,本篇先讲GridView。如图,这是一个标准的800*480大小的屏幕,所以设置了一页GridView 显示的应用程序数据为 三行五列,不足五列则按需显示。

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



  思路如下:

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

  实现这一效果我们需要两个类,一个类用来表示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 的操作,等下文再讲述。效果是这样的:



该 类的全部源码为:




GridViewExt

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

下篇将讲述如何实现手势切屏,如何实现分页显示数据,如何实现封装分页控件。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息