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 }
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>