QQ分组实现原理(无折叠)

MainActivity:

  1 package com.zzw.qqgroup;
  2
  3 import java.util.ArrayList;
  4 import java.util.HashMap;
  5 import java.util.List;
  6
  7 import android.app.ListActivity;
  8 import android.content.Context;
  9 import android.graphics.Color;
 10 import android.os.Bundle;
 11 import android.util.Log;
 12 import android.view.LayoutInflater;
 13 import android.view.View;
 14 import android.view.ViewGroup;
 15 import android.widget.ArrayAdapter;
 16 import android.widget.ListView;
 17 import android.widget.TextView;
 18
 19 public class MainActivity extends ListActivity {
 20     private static final String TAG = "MainActivity";
 21     private final String DATA = "data";
 22     private final String TYPE = "type";
 23
 24     private final int VIEW_TYPE_COUNT = 2;
 25     private final int GROUP = -2;
 26     private final int ITEM = -3;
 27
 28     private int count = 0;
 29
 30     @Override
 31     protected void onCreate(Bundle savedInstanceState) {
 32         super.onCreate(savedInstanceState);
 33
 34         ListView listView = this.getListView();
 35         ArrayList<HashMap<String, Object>> items = init();
 36
 37         listView.setAdapter(new MyAdapter(this, -1, -1, items));
 38     }
 39
 40     private ArrayList<HashMap<String, Object>> init() {
 41         Log.d(TAG, "添加数据开始");
 42         ArrayList<HashMap<String, Object>> arrayList = new ArrayList<HashMap<String, Object>>();
 43
 44         String groups[] = { "我的好友", "同学", "亲人", "朋友", "同事" };
 45         String datas[] = { "张三", "李四", "王二", "麻子" };
 46         for (String group_data : groups) {
 47
 48             HashMap<String, Object> group_map = new HashMap<String, Object>();
 49             group_map.put(DATA, group_data);
 50             group_map.put(TYPE, GROUP);
 51             arrayList.add(group_map);
 52
 53             for (String datas_data : datas) {
 54                 HashMap<String, Object> data_map = new HashMap<String, Object>();
 55                 data_map.put(TYPE, ITEM);
 56                 data_map.put(DATA, "数据:" + datas_data + (count++));
 57                 arrayList.add(data_map);
 58             }
 59         }
 60         Log.d(TAG, "添加数据成功");
 61         return arrayList;
 62     }
 63
 64     private class MyAdapter extends ArrayAdapter {
 65
 66         private Context context;
 67         private ArrayList<HashMap<String, Object>> items;
 68
 69         private LayoutInflater falter;
 70
 71         public MyAdapter(Context context, int resource, int textViewResourceId, List items) {
 72             super(context, resource, textViewResourceId, items);
 73             Log.d(TAG, "Adapter初始化开始");
 74             this.items = (ArrayList<HashMap<String, Object>>) items;
 75             this.context = context;
 76
 77             falter = LayoutInflater.from(context);
 78             Log.d(TAG, "Adapter初始化成功");
 79         }
 80
 81         @Override
 82         public int getCount() {
 83             Log.d(TAG, "得到count---" + items.size());
 84             return items.size();
 85         }
 86
 87         @Override
 88         public int getItemViewType(int position) {
 89             HashMap<String, Object> map = items.get(position);
 90             return (Integer) map.get(TYPE);
 91         }
 92
 93         @Override
 94         public View getView(int position, View convertView, ViewGroup parent) {
 95             Log.d(TAG, "getView开始");
 96             int type = getItemViewType(position);
 97             String data = items.get(position).get(DATA) + "";
 98             Log.d(TAG, "获取数据:" + data);
 99             switch (type) {
100             case GROUP:
101                 if (convertView == null) {
102                     convertView = falter.inflate(R.layout.item, null);
103                 }
104                 TextView group = (TextView) convertView.findViewById(R.id.textView);
105                 group.setText(data + "");
106                 group.setTextColor(Color.RED);
107                 break;
108
109             case ITEM:
110                 if (convertView == null) {
111                     convertView = falter.inflate(R.layout.item_1, null);
112                 }
113                 TextView datas = (TextView) convertView.findViewById(R.id.textView);
114                 datas.setText(data);
115                 datas.setTextColor(Color.GREEN);
116                 break;
117             }
118
119             return convertView;
120         }
121
122         @Override
123         public int getViewTypeCount() {
124             return VIEW_TYPE_COUNT;
125         }
126
127     }
128 }

CircleImageView:

  1 package com.zzw.qqgroup;
  2
  3 import android.content.Context;
  4 import android.content.res.TypedArray;
  5 import android.graphics.Bitmap;
  6 import android.graphics.BitmapShader;
  7 import android.graphics.Canvas;
  8 import android.graphics.Color;
  9 import android.graphics.Matrix;
 10 import android.graphics.Paint;
 11 import android.graphics.Paint.Align;
 12 import android.graphics.Rect;
 13 import android.graphics.RectF;
 14 import android.graphics.Shader;
 15 import android.graphics.SweepGradient;
 16 import android.graphics.drawable.BitmapDrawable;
 17 import android.graphics.drawable.ColorDrawable;
 18 import android.graphics.drawable.Drawable;
 19 import android.net.Uri;
 20 import android.text.TextPaint;
 21 import android.util.AttributeSet;
 22 import android.util.FloatMath;
 23 import android.widget.ImageView;
 24
 25 /**
 26  * @author Phil
 27  *
 28  */
 29 public class CircleImageView extends ImageView {
 30
 31     private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;
 32
 33     private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
 34     private static final int COLORDRAWABLE_DIMENSION = 2;
 35
 36     // 圆形边框的厚度默认值。
 37     // 如果是0,则没有天蓝色渐变的边框。
 38     private static final int DEFAULT_BORDER_WIDTH = 1;
 39
 40     private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
 41
 42     private final RectF mDrawableRect = new RectF();
 43     private final RectF mBorderRect = new RectF();
 44
 45     private final Matrix mShaderMatrix = new Matrix();
 46     private final Paint mBitmapPaint = new Paint();
 47     private final Paint mBorderPaint = new Paint();
 48
 49     private int mBorderColor = DEFAULT_BORDER_COLOR;
 50     private int mBorderWidth = DEFAULT_BORDER_WIDTH;
 51
 52     private Bitmap mBitmap;
 53     private BitmapShader mBitmapShader;
 54     private int mBitmapWidth;
 55     private int mBitmapHeight;
 56
 57     private float mDrawableRadius;
 58     private float mBorderRadius;
 59
 60     private boolean mReady;
 61     private boolean mSetupPending;
 62     private final Paint mFlagBackgroundPaint = new Paint();
 63     private final TextPaint mFlagTextPaint = new TextPaint();
 64     private String mFlagText;
 65     private boolean mShowFlag = false;
 66     private Rect mFlagTextBounds = new Rect();
 67
 68     Shader mSweepGradient = null;
 69
 70     public CircleImageView(Context context) {
 71         super(context);
 72
 73         init();
 74     }
 75
 76     public CircleImageView(Context context, AttributeSet attrs) {
 77         this(context, attrs, 0);
 78     }
 79
 80     public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
 81         super(context, attrs, defStyle);
 82
 83         // TypedArray a = context.obtainStyledAttributes(attrs,
 84         // R.styleable.CircleImageView, defStyle, 0);
 85         //
 86         // mBorderWidth =
 87         // a.getDimensionPixelSize(R.styleable.CircleImageView_border_width,
 88         // DEFAULT_BORDER_WIDTH);
 89         // mBorderColor = a.getColor(R.styleable.CircleImageView_border_color,
 90         // DEFAULT_BORDER_COLOR);
 91         //
 92         // a.recycle();
 93
 94         init();
 95     }
 96
 97     private void init() {
 98         super.setScaleType(SCALE_TYPE);
 99         mReady = true;
100
101         if (mSetupPending) {
102             setup();
103             mSetupPending = false;
104         }
105     }
106
107     @Override
108     public ScaleType getScaleType() {
109         return SCALE_TYPE;
110     }
111
112     @Override
113     public void setScaleType(ScaleType scaleType) {
114         if (scaleType != SCALE_TYPE) {
115             throw new IllegalArgumentException(String.format(
116                     "ScaleType %s not supported.", scaleType));
117         }
118     }
119
120     @Override
121     public void setAdjustViewBounds(boolean adjustViewBounds) {
122         if (adjustViewBounds) {
123             throw new IllegalArgumentException(
124                     "adjustViewBounds not supported.");
125         }
126     }
127
128     @Override
129     protected void onDraw(Canvas canvas) {
130         if (getDrawable() == null) {
131             return;
132         }
133
134         canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius,
135                 mBitmapPaint);
136         if (mBorderWidth != 0) {
137             canvas.save();
138             canvas.rotate(20, getWidth() / 2, getHeight() / 2);
139             canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius,
140                     mBorderPaint);
141             canvas.restore();
142         }
143
144         if (mShowFlag && mFlagText != null) {
145             canvas.drawArc(mBorderRect, 40, 100, false, mFlagBackgroundPaint);
146             mFlagTextPaint.getTextBounds(mFlagText, 0, mFlagText.length(),
147                     mFlagTextBounds);
148             canvas.drawText(mFlagText, getWidth() / 2,
149                     (3 + FloatMath.cos((float) (Math.PI * 5 / 18)))
150                             * getHeight() / 4 + mFlagTextBounds.height() / 3,
151                     mFlagTextPaint);
152         }
153
154     }
155
156     @Override
157     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
158         super.onSizeChanged(w, h, oldw, oldh);
159         setup();
160     }
161
162     public int getBorderColor() {
163         return mBorderColor;
164     }
165
166     public void setBorderColor(int borderColor) {
167         if (borderColor == mBorderColor) {
168             return;
169         }
170
171         mBorderColor = borderColor;
172         mBorderPaint.setColor(mBorderColor);
173         invalidate();
174     }
175
176     public int getBorderWidth() {
177         return mBorderWidth;
178     }
179
180     /**
181      * @param borderWidth
182      *            圆形的边框厚度。
183      */
184     public void setBorderWidth(int borderWidth) {
185         if (borderWidth == mBorderWidth) {
186             return;
187         }
188
189         mBorderWidth = borderWidth;
190         setup();
191     }
192
193     @Override
194     public void setImageBitmap(Bitmap bm) {
195         super.setImageBitmap(bm);
196         mBitmap = bm;
197         setup();
198     }
199
200     @Override
201     public void setImageDrawable(Drawable drawable) {
202         super.setImageDrawable(drawable);
203         mBitmap = getBitmapFromDrawable(drawable);
204         setup();
205     }
206
207     @Override
208     public void setImageResource(int resId) {
209         super.setImageResource(resId);
210         mBitmap = getBitmapFromDrawable(getDrawable());
211         setup();
212     }
213
214     @Override
215     public void setImageURI(Uri uri) {
216         super.setImageURI(uri);
217         mBitmap = getBitmapFromDrawable(getDrawable());
218         setup();
219     }
220
221     private Bitmap getBitmapFromDrawable(Drawable drawable) {
222         if (drawable == null) {
223             return null;
224         }
225
226         if (drawable instanceof BitmapDrawable) {
227             return ((BitmapDrawable) drawable).getBitmap();
228         }
229
230         try {
231             Bitmap bitmap;
232
233             if (drawable instanceof ColorDrawable) {
234                 bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION,
235                         COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
236             } else {
237                 bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
238                         drawable.getIntrinsicHeight(), BITMAP_CONFIG);
239             }
240
241             Canvas canvas = new Canvas(bitmap);
242             drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
243             drawable.draw(canvas);
244             return bitmap;
245         } catch (OutOfMemoryError e) {
246             return null;
247         }
248     }
249
250     private void setup() {
251         if (!mReady) {
252             mSetupPending = true;
253             return;
254         }
255
256         if (mBitmap == null) {
257             return;
258         }
259
260         mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP,
261                 Shader.TileMode.CLAMP);
262
263         mBitmapPaint.setAntiAlias(true);
264         mBitmapPaint.setShader(mBitmapShader);
265
266         mBorderPaint.setStyle(Paint.Style.STROKE);
267         mBorderPaint.setAntiAlias(true);
268         mBorderPaint.setColor(mBorderColor);
269         mBorderPaint.setStrokeWidth(mBorderWidth);
270
271         mBitmapHeight = mBitmap.getHeight();
272         mBitmapWidth = mBitmap.getWidth();
273
274         mBorderRect.set(0, 0, getWidth(), getHeight());
275         mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2,
276                 (mBorderRect.width() - mBorderWidth) / 2);
277
278         mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width()
279                 - mBorderWidth, mBorderRect.height() - mBorderWidth);
280         mDrawableRadius = Math.min(mDrawableRect.height() / 2,
281                 mDrawableRect.width() / 2);
282
283         mFlagBackgroundPaint.setColor(Color.BLACK & 0x66FFFFFF);
284         mFlagBackgroundPaint.setFlags(TextPaint.ANTI_ALIAS_FLAG);
285
286         mFlagTextPaint.setFlags(TextPaint.ANTI_ALIAS_FLAG);
287         mFlagTextPaint.setTextAlign(Align.CENTER);
288         mFlagTextPaint.setColor(Color.WHITE);
289         mFlagTextPaint
290                 .setTextSize(getResources().getDisplayMetrics().density * 18);
291
292         mSweepGradient = new SweepGradient(getWidth() / 2, getHeight() / 2,
293                 new int[] { Color.rgb(255, 255, 255), Color.rgb(1, 209, 255) },
294                 null);
295
296         mBorderPaint.setShader(mSweepGradient);
297
298         updateShaderMatrix();
299         invalidate();
300     }
301
302     private void updateShaderMatrix() {
303         float scale;
304         float dx = 0;
305         float dy = 0;
306
307         mShaderMatrix.set(null);
308
309         if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width()
310                 * mBitmapHeight) {
311             scale = mDrawableRect.height() / (float) mBitmapHeight;
312             dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
313         } else {
314             scale = mDrawableRect.width() / (float) mBitmapWidth;
315             dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
316         }
317
318         mShaderMatrix.setScale(scale, scale);
319         mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBorderWidth,
320                 (int) (dy + 0.5f) + mBorderWidth);
321
322         mBitmapShader.setLocalMatrix(mShaderMatrix);
323     }
324
325     public void setShowFlag(boolean show) {
326         mShowFlag = show;
327         invalidate();
328     }
329
330     public void setFlagText(String text) {
331         mFlagText = text;
332         invalidate();
333     }
334 }  

CircleImageView

xml:

item:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical" >
 6
 7     <com.zzw.qqgroup.CircleImageView
 8
 9         android:id="@+id/circleImageView1"
10         android:layout_width="wrap_content"
11         android:layout_height="wrap_content"
12         android:src="@drawable/ic_launcher" />
13
14     <TextView
15         android:id="@+id/textView"
16         android:layout_width="wrap_content"
17         android:layout_height="wrap_content"
18         android:layout_alignBottom="@+id/circleImageView1"
19         android:layout_alignParentRight="true"
20         android:layout_alignParentTop="true"
21         android:layout_marginLeft="37dp"
22         android:textSize="37sp"
23
24         android:layout_toRightOf="@+id/circleImageView1"
25         android:text="TextView" />
26
27 </RelativeLayout>

item_1:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical" >
 6
 7     <com.zzw.qqgroup.CircleImageView
 8         android:id="@+id/circleImageView1"
 9         android:layout_width="wrap_content"
10         android:layout_height="wrap_content"
11         android:src="@drawable/ic_launcher" />
12
13     <TextView
14         android:id="@+id/textView"
15         android:layout_width="wrap_content"
16         android:layout_height="wrap_content"
17         android:textSize="30sp"
18         android:layout_alignBottom="@+id/circleImageView1"
19         android:layout_alignParentRight="true"
20         android:layout_toRightOf="@+id/circleImageView1" />
21
22 </RelativeLayout>
时间: 2024-08-25 12:30:04

QQ分组实现原理(无折叠)的相关文章

【转】QQ传输文件原理参考(来自互联网)

QQ的文件发送是怎样的过程呢?通常,发送文件的计算机首先要通过消息服务器将其IP地址发送给接收计算机,当接收计算机同意接收的确认消息反馈到消息服务器后,消息服务器将据此设置好文件传输对话.随即,发送计算机与接收计算机就会在确定好的端口范围内,建立起TCP或UDP连接开始文件的检索与传输. 在默认状态下,QQ优先采用了UDP(User Data Protocol,用户数据报协议)协议传送数据,而对可靠性要求高的数据通讯系统往往使用TCP协议传输数据.与TCP协议不同,UDP协议并不提供数据传送的验

Android 利用ExpandableListView显示和查询仿QQ分组列表用户信息

在我们的项目开发过程中,经常会对用户的信息进行分组,即通过组来显示用户的信息,同时通过一定的查询条件来显示查询后的相关用户信息,并且通过颜色选择器来设置列表信息的背景颜色. 其中借鉴xiaanming:http://blog.csdn.net/xiaanming/article/details/12684155 下面来看看项目运行后的效果图以及代码结构图: 下面通过代码来实现整个效果. 1.主界面布局activity_main.xml <span style="font-size:18px

CSS+JS仿QQ面板风格的多级折叠下拉菜单

<html> <head> <title>CSS+JS仿QQ面板风格的多级折叠下拉菜单丨石家庄玻璃隔断|石家庄自动门</title> <style type="text/css"> *{ margin:0px; padding:0px; border:0px; } body{ font-size:12px; color:#333;text-align:center;} .mbox{background:#73C2FF; wid

js仿qq分组折叠效果

<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> <style type="text/css"&g

IOS 模拟QQ分组折叠

#define USER_KEY @"users" #define GROUPNAME_KEY @"groupName" @interfaceViewController ()<UITableViewDataSource,UITableViewDelegate> { UITableView *_tableView; NSMutableArray *_dataSource; BOOL expanded; } - (void)initializeDataSo

安卓ExpandableListView实现多组列表,类似于QQ分组

先直接上图, 1:.展开的效果图: 2:后面的是点击收缩的效果图. 3:下面就是代码部分: 我们要定义2个集合用来存储数据,一个是groupItem的数据,一个是childItem的数据 private List<Map<String, Object>> groupList = new ArrayList<Map<String, Object>>();// 分组名称 public List<List<Map<String, Object&g

Servlet 的原理----无脑笔记

Servlet 的原理 最近在啃<<独门架构:Java Web开发应用详解>>.好记性不如烂笔头,更何况自己脑子也不怎么好使.做下笔记,加深印象. 正文: 1.所有的Servlet类必须实现Servlet接口(接口在servlet-api.jar中可以找到) 2.Servlet程序的层次结构: Servlet1,Servlet2.....------>继承HttpServlet------>继承GenericServlet-------->实现Servlet 3.

模拟QQ分组(具有伸缩功能) SimpleExpandableListAdapter 适配器的用法,并且可添加组及其组内数据。

1 package com.lixu.qqfenzu; 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.List; 6 import java.util.Map; 7 8 import android.app.Activity; 9 import android.content.Context; 10 import android.graphics.Color; 11 import an

[转载]MD5加密算法原理

本文转载自: http://blog.csdn.net/forgotaboutgirl/article/details/7258109 需要视频版的可以看一下泰克老林讲的MD5原理 下载地址: 网速太卡,周末上传后补上.... MD5(单向散列算法)的全称是Message-Digest Algorithm 5(信息-摘要算法),经MD2.MD3和MD4发展而来.MD5算法的使用不需要支付任何版权费用. MD5功能: 输入任意长度的信息,经过处理,输出为128位的信息(数字指纹): 不同的输入得到