Android自定义控件继承ViewGrop实现一个GridView的显示效果

来源:互联网 发布:爱淘宝现金红包 编辑:程序博客网 时间:2024/04/27 23:22

 View类和ViewGroup类介绍

 android中所有的UI控件(button,textView,checkbox等等)基类都View类,android中的五种布局(LinearLayout ,RelativeLayout ,FrameLayout ,TableLayout ,AbsoluteLayout)都是View的容器,我们平常在XML文件中写的布局,定义的那些View都是需要VIew容器去包装它们,包括View控件之间的排版,控件与控件之间的间距等。例如LinearLayout就是将你定义的那些VIew控件按照线性的布局方式去排版。

      ViewGroup类就是VIew容器的基类,LinearLayout ,RelativeLayout ,FrameLayout ,TableLayout ,AbsoluteLayout都是继承与ViewGroup。所以我们可以写一个自己的类去继承ViewGroup,这样我们的类就是一个View的容器了。我们写的UI控件就可以定义在我们自己的View容器中。

本文的例子就是继承于ViewGroup实现一个GridView排版效果的容器。
继承ViewGroup类主要是要覆写它的  onMeasure(),onLayout()这两个方法,onMeasure()方法用于测量每个子View的大小尺寸,onLayout()方法用于确定子View在布局中的位置。

DEMO:
<pre name="code" class="java">package cn.mmb.view;import static android.view.View.MeasureSpec.EXACTLY;import static android.view.View.MeasureSpec.makeMeasureSpec;import java.util.Iterator;import com.mmb.demo.R;import android.content.Context;import android.content.res.TypedArray;import android.util.AttributeSet;import android.view.View;import android.view.ViewGroup;public class MyGridLayout extends ViewGroup {public final String TAG = "MyGridLayout";public static int DEFAULT_COLUMS = 2;public static int DEFAULT_HORIZONTAL_SPACING = 20;public static int DEFAULT_VERTICAL_SPACING = 20;public static int DEFAULT_ITEM_HEIGHT = 40;private int mHorizontalSpacing = 0;private int mVerticalSpacing = 0;private int colums = DEFAULT_COLUMS;private int mMaxChildWidth = 0;private int mMaxChildHeight = 0;private int count = 0;private int mItemHeight = 0;private GridAdatper adapter;public MyGridLayout(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);if (attrs != null) {TypedArray typedArray = getContext().obtainStyledAttributes(attrs,R.styleable.MyGridLayout);colums = typedArray.getInteger(R.styleable.MyGridLayout_numColumns,DEFAULT_COLUMS);mHorizontalSpacing = (int) typedArray.getInteger(R.styleable.MyGridLayout_horizontal_spacing,DEFAULT_HORIZONTAL_SPACING);mVerticalSpacing = (int) typedArray.getInteger(R.styleable.MyGridLayout_vertical_spacing,DEFAULT_VERTICAL_SPACING);mItemHeight = (int) typedArray.getInteger(R.styleable.MyGridLayout_itemHeight, DEFAULT_ITEM_HEIGHT);}}public MyGridLayout(Context context, AttributeSet attrs) {this(context, attrs, 0);}public MyGridLayout(Context context) {this(context, null);}/** * @return item Horizontal Spacing */public int getHorizontalSpacing() {return mHorizontalSpacing;}/** * set item Horizontal Spacing *  * @param mHorizontalSpacing */public void setHorizontalSpacing(int mHorizontalSpacing) {this.mHorizontalSpacing = mHorizontalSpacing;}/** * @return item Vertical Spacing */public int getVerticalSpacing() {return mVerticalSpacing;}/** * set item Vertical Spacing *  * @param mVerticalSpacing */public void setVerticalSpacing(int mVerticalSpacing) {this.mVerticalSpacing = mVerticalSpacing;}/** * @return item height */public int getItemHeight() {return mItemHeight;}/** * set item height *  * @param mItemHeight */public void setItemHeight(int mItemHeight) {this.mItemHeight = mItemHeight;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {mMaxChildWidth = 0;mMaxChildHeight = 0;int modeW = 0, modeH = 0;if (MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED) {modeW = MeasureSpec.UNSPECIFIED;}if (MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.UNSPECIFIED) {modeH = MeasureSpec.UNSPECIFIED;}final int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), modeW);final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), modeH);count = getChildCount();if (count == 0) {super.onMeasure(childWidthMeasureSpec, childHeightMeasureSpec);return;}for (int i = 0; i < count; i++) {final View child = getChildAt(i);if (child.getVisibility() == GONE) {continue;}child.measure(childWidthMeasureSpec, childHeightMeasureSpec);mMaxChildWidth = Math.max(mMaxChildWidth, child.getMeasuredWidth());mMaxChildHeight = Math.max(mMaxChildHeight,child.getMeasuredHeight());}setMeasuredDimension(resolveSize(mMaxChildWidth, widthMeasureSpec),resolveSize(mMaxChildHeight, heightMeasureSpec));}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {int height = b - t; // The height of the layout areaint width = r - l; // The width of the layout area// Calculate the number  of  rowsint rows = count % colums == 0 ? count / colums : count / colums + 1;if (count == 0) {return;}// Calculate every item  widthint gridW = (width - (colums + 1) * mHorizontalSpacing) / colums;// item heightint gridH = mItemHeight; // int gridH = (height - mVerticalSpacing * rows) / rows;int left = 0;int top = mVerticalSpacing;for (int i = 0; i < rows; i++) {// Iterator the elements of each rowfor (int j = 0; j < colums; j++) {View child = this.getChildAt(i * colums + j);if (child == null) {return;}left = j * gridW + j * mHorizontalSpacing + mHorizontalSpacing;/** * If the current layout is not the same width and width * measurements, the direct use of re-measuring the width of the * current layout */if (gridW != child.getMeasuredWidth()|| gridH != child.getMeasuredHeight()) {child.measure(makeMeasureSpec(gridW, EXACTLY),makeMeasureSpec(gridH, EXACTLY));}/** * set current child view layout */child.layout(left, top, left + gridW, top + gridH); }top += gridH + mVerticalSpacing; // next rows}}public interface GridAdatper {View getView(int index);int getCount();}/** * set adapter *  * @param adapter */public void setGridAdapter(GridAdatper adapter) {this.adapter = adapter;int size = adapter.getCount();for (int i = 0; i < size; i++) {addView(adapter.getView(i)); // addView}}public interface OnItemClickListener {void onItemClick(View v, int index);}/** * set Item Click Listener *  * @param click */public void setOnItemClickListener(final OnItemClickListener click) {if (this.adapter == null)return;for (int i = 0; i < adapter.getCount(); i++) {final int index = i;View view = getChildAt(i);view.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {click.onItemClick(v, index);}});}}}


布局(activity_main.xml)中使用已经写好的View容器
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:background="#303030"    android:orientation="vertical" >    <cn.mmb.view.MyGridLayout        android:id="@+id/list"        android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:background="#1e1d1d"        android:orientation="vertical"        app:horizontal_spacing="30"        app:vertical_spacing="20"         app:itemHeight="60"        app:numColumns="3">    </cn.mmb.view.MyGridLayout></LinearLayout>
最后在Activity中
package com.mmb.demo;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.List;import org.apache.http.HttpResponse;import org.json.JSONArray;import org.json.JSONException;import org.json.JSONObject;import cn.mmb.view.MyGridLayout;import com.mmb.demo.domin.MyColor;import com.mmb.demo.util.HttpUtil;import com.mmb.demo.util.Utils;import android.os.AsyncTask;import android.os.Bundle;import android.app.Activity;import android.view.Menu;import android.view.View;import android.widget.TextView;import android.widget.Toast;public class MainActivity extends Activity {private static final String MREQUESTPATH = "http://192.168.3.105:8080/demo/json.txt";private List<MyColor> mColorList;private MyGridLayout mGridLayout;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mColorList = new ArrayList<MyColor>();Utils.computeScreenDimen(this);mGridLayout = (MyGridLayout) findViewById(R.id.list);mGridLayout.setVerticalSpacing(Utils.uiHeightPxToScreenPx(30));mGridLayout.setHorizontalSpacing(Utils.uiWidthPxToScreenPx(40));mGridLayout.setItemHeight(Utils.uiHeightPxToScreenPx(100));new myWorkAsyncTask().execute();}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {getMenuInflater().inflate(R.menu.main, menu);return true;}class myWorkAsyncTask extends AsyncTask<Void, Void, Void> {private static final String TAG = "myWorkAsyncTask";@Overrideprotected Void doInBackground(Void... params) {String data = getJsonData(MREQUESTPATH);if (data != null) {parseJson(data);}return null;}private void parseJson(String data) {try {JSONObject jsonObject = new JSONObject(data);JSONArray jsonArray = jsonObject.getJSONArray("array");for (int i = 0; i < jsonArray.length(); i++) {JSONObject object = (JSONObject) jsonArray.get(i);int id = object.getInt("subId");String name = object.getString("name");mColorList.add(new MyColor(id, name));// Log.i (TAG, name);}} catch (JSONException e) {e.printStackTrace();}}private String getJsonData(String mRequestPath) {HttpResponse response = null;BufferedReader lineReader = null;try {response = HttpUtil.getHttpResponse(mRequestPath);int rescode = response.getStatusLine().getStatusCode();if (rescode == 200) {String line = null;StringBuilder builder = new StringBuilder();lineReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));while ((line = lineReader.readLine()) != null) {builder.append(line);}return builder.toString();}} catch (Exception e) {} finally {if (lineReader != null) {try {lineReader.close();} catch (IOException e) {e.printStackTrace();}}}return null;}@Overrideprotected void onPostExecute(Void result) {super.onPostExecute(result);mGridLayout.setGridAdapter(new cn.mmb.view.MyGridLayout.GridAdatper() {@Overridepublic View getView(int index) {View view = getLayoutInflater().inflate(R.layout.actions_item, null);TextView tv = (TextView) view.findViewById(R.id.tv);tv.setText(mColorList.get(index).getName());return view;}@Overridepublic int getCount() {return mColorList.size();}});mGridLayout.setOnItemClickListener(new cn.mmb.view.MyGridLayout.OnItemClickListener() {@Overridepublic void onItemClick(View v, int index) {Toast.makeText(getApplicationContext(),"item=" + index, Toast.LENGTH_SHORT).show();}});}}}
运行结果:其子View item的排列效果类似于GridView。



  
0 0