├── .gitignore ├── .gradle └── 2.8 │ └── taskArtifacts │ ├── cache.properties │ ├── cache.properties.lock │ ├── fileHashes.bin │ ├── fileSnapshots.bin │ ├── outputFileStates.bin │ └── taskArtifacts.bin ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── dk │ │ └── ui │ │ └── circlelist │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── dk │ │ │ └── ui │ │ │ └── circlelist │ │ │ ├── MainActivity.java │ │ │ ├── MatrixView.java │ │ │ └── RoundImageView.java │ └── res │ │ ├── drawable │ │ ├── p1.jpg │ │ ├── p2.jpg │ │ └── p3.jpg │ │ ├── layout │ │ ├── activity_main.xml │ │ └── view_list_item.xml │ │ ├── menu │ │ └── menu_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── dk │ └── ui │ └── circlelist │ └── ExampleUnitTest.java ├── build.gradle ├── build └── intermediates │ └── dex-cache │ └── cache.xml ├── circlelist.gif ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | #Android generated 2 | bin 3 | gen 4 | 5 | #Eclipse 6 | .project 7 | .classpath 8 | .settings 9 | 10 | #IntelliJ IDEA 11 | .idea 12 | *.iml 13 | *.ipr 14 | *.iws 15 | out 16 | 17 | #Maven 18 | target 19 | release.properties 20 | pom.xml.* 21 | 22 | #Ant 23 | build.xml 24 | local.properties 25 | proguard.cfg 26 | 27 | #OSX 28 | .DS_Store 29 | -------------------------------------------------------------------------------- /.gradle/2.8/taskArtifacts/cache.properties: -------------------------------------------------------------------------------- 1 | #Sun Feb 28 14:02:46 CST 2016 2 | -------------------------------------------------------------------------------- /.gradle/2.8/taskArtifacts/cache.properties.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmeteor/CircleList/bc7e467861dadc471feb873368e24c7928c8801e/.gradle/2.8/taskArtifacts/cache.properties.lock -------------------------------------------------------------------------------- /.gradle/2.8/taskArtifacts/fileHashes.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmeteor/CircleList/bc7e467861dadc471feb873368e24c7928c8801e/.gradle/2.8/taskArtifacts/fileHashes.bin -------------------------------------------------------------------------------- /.gradle/2.8/taskArtifacts/fileSnapshots.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmeteor/CircleList/bc7e467861dadc471feb873368e24c7928c8801e/.gradle/2.8/taskArtifacts/fileSnapshots.bin -------------------------------------------------------------------------------- /.gradle/2.8/taskArtifacts/outputFileStates.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmeteor/CircleList/bc7e467861dadc471feb873368e24c7928c8801e/.gradle/2.8/taskArtifacts/outputFileStates.bin -------------------------------------------------------------------------------- /.gradle/2.8/taskArtifacts/taskArtifacts.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmeteor/CircleList/bc7e467861dadc471feb873368e24c7928c8801e/.gradle/2.8/taskArtifacts/taskArtifacts.bin -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Demo 2 | 3 | Rebuild the project for Android Studio 4 | 5 | ![Examples list](/circlelist.gif) -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.2" 6 | 7 | defaultConfig { 8 | applicationId "com.dk.ui.circlelist" 9 | minSdkVersion 15 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:23.1.1' 26 | compile 'com.android.support:design:23.1.1' 27 | } 28 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\DK\Documents\SDK/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/dk/ui/circlelist/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.dk.ui.circlelist; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/dk/ui/circlelist/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.dk.ui.circlelist; 2 | 3 | import java.lang.reflect.Field; 4 | 5 | import android.app.Activity; 6 | import android.os.Bundle; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.AbsListView; 11 | import android.widget.BaseAdapter; 12 | import android.widget.ImageView; 13 | import android.widget.ListView; 14 | import android.widget.AbsListView.OnScrollListener; 15 | 16 | public class MainActivity extends Activity { 17 | 18 | private ListView listview; 19 | private int[] images = new int[]{R.drawable.p1, R.drawable.p2, R.drawable.p3}; 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_main); 25 | listview = (ListView) findViewById(R.id.lv); 26 | listview.setAdapter(new MyAdapter()); 27 | listview.setClipToPadding(false); 28 | listview.setClipChildren(false); 29 | listview.setOnScrollListener(new OnScrollListener() { 30 | 31 | @Override 32 | public void onScrollStateChanged(AbsListView view, int scrollState) { 33 | 34 | } 35 | 36 | @Override 37 | public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 38 | for (int i = 0; i < listview.getChildCount(); i++) { 39 | listview.getChildAt(i).invalidate(); 40 | } 41 | } 42 | }); 43 | } 44 | 45 | class MyAdapter extends BaseAdapter { 46 | 47 | @Override 48 | public int getCount() { 49 | return 9999; 50 | } 51 | 52 | @Override 53 | public Object getItem(int position) { 54 | return null; 55 | } 56 | 57 | @Override 58 | public long getItemId(int position) { 59 | return 0; 60 | } 61 | 62 | @Override 63 | public View getView(int position, View convertView, ViewGroup parent) { 64 | if (convertView == null) { 65 | MatrixView m = (MatrixView) LayoutInflater.from(MainActivity.this).inflate(R.layout.view_list_item, null); 66 | m.setParentHeight(listview.getHeight()); 67 | convertView = m; 68 | } 69 | ImageView imageView = (ImageView) convertView.findViewById(R.id.image); 70 | imageView.setImageResource(images[position % images.length]); 71 | 72 | return convertView; 73 | } 74 | 75 | } 76 | 77 | @Deprecated 78 | public void changeGroupFlag(Object obj) throws Exception { 79 | Field[] f = obj.getClass().getSuperclass().getSuperclass().getSuperclass().getDeclaredFields(); // 获得成员映射数组 80 | for (Field tem : f) { 81 | if (tem.getName().equals("mGroupFlags")) { 82 | tem.setAccessible(true); 83 | Integer mGroupFlags = (Integer) tem.get(obj); 84 | int newGroupFlags = mGroupFlags & 0xfffff8; 85 | tem.set(obj, newGroupFlags); 86 | } 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /app/src/main/java/com/dk/ui/circlelist/MatrixView.java: -------------------------------------------------------------------------------- 1 | package com.dk.ui.circlelist; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Matrix; 6 | import android.util.AttributeSet; 7 | import android.widget.LinearLayout; 8 | 9 | public class MatrixView extends LinearLayout { 10 | private int h = 0; 11 | private float fullAngelFactor = 30f; 12 | private float fullScaleFactor=1; 13 | public MatrixView(Context context, AttributeSet attrs) { 14 | super(context, attrs); 15 | } 16 | 17 | public void setParentHeight(int height) { 18 | h = height; 19 | } 20 | 21 | @Override 22 | protected void dispatchDraw(Canvas canvas) { 23 | canvas.save(); 24 | int top = getTop(); 25 | 26 | float rotate = calculateAngel(top, h); 27 | float scale = calcuylateScale(top, h); 28 | 29 | Matrix m = canvas.getMatrix(); 30 | m.preTranslate(-2 / getWidth(), -2 / getHeight()); 31 | m.postScale(scale, scale); 32 | m.postTranslate(2 / getWidth(), 2 / getHeight()); 33 | m.postRotate(rotate); 34 | canvas.concat(m); 35 | super.dispatchDraw(canvas); 36 | canvas.restore(); 37 | } 38 | 39 | @Override 40 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 41 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 42 | } 43 | 44 | private float calculateAngel(int top, int h) { 45 | float result = 0f; 46 | if (top < h / 2f) { 47 | result = (top - (h / 2f)) / (h / 2f) * fullAngelFactor; 48 | } else if (top > h / 2f) { 49 | result = (top - (h / 2f)) / (h / 2f) * fullAngelFactor; 50 | } 51 | return result; 52 | } 53 | 54 | private float calcuylateScale(int top, int h) { 55 | float result = 0f; 56 | 57 | result = (1f - 1f/2f*Math.abs((top - h / 2f)) / (h / 2f)) * fullScaleFactor; 58 | return result; 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/dk/ui/circlelist/RoundImageView.java: -------------------------------------------------------------------------------- 1 | package com.dk.ui.circlelist; 2 | 3 | import android.content.Context; 4 | import android.graphics.BitmapShader; 5 | import android.graphics.Canvas; 6 | import android.graphics.Matrix; 7 | import android.graphics.Paint; 8 | import android.graphics.RectF; 9 | import android.graphics.Shader; 10 | import android.graphics.drawable.BitmapDrawable; 11 | import android.util.AttributeSet; 12 | import android.widget.ImageView; 13 | 14 | /** 15 | * 16 | * @author Dean.Ding 17 | * 18 | * It override ImageView's onDraw , so , some ImageView's origin function can not work: 1. 19 | * DrawMatrix is disabled 2. CropToPadding is useless 3. It will be always work in 20 | * CenterCrop mode!!!!!! 21 | * 22 | */ 23 | public class RoundImageView extends ImageView { 24 | 25 | private float xRadius = 10; 26 | private float yRadius = 10; 27 | private Paint paint = new Paint(); 28 | 29 | public RoundImageView(Context context) { 30 | super(context); 31 | } 32 | 33 | public RoundImageView(Context context, AttributeSet attrs) { 34 | super(context, attrs); 35 | } 36 | 37 | public float getxRadius() { 38 | return xRadius; 39 | } 40 | 41 | public void setxRadius(float xRadius) { 42 | this.xRadius = xRadius; 43 | } 44 | 45 | public float getyRadius() { 46 | return yRadius; 47 | } 48 | 49 | public void setyRadius(float yRadius) { 50 | this.yRadius = yRadius; 51 | } 52 | 53 | @SuppressWarnings("deprecation") 54 | @Override 55 | protected void onDraw(Canvas canvas) { 56 | // java.lang.ClassCastException: android.graphics.drawable.TransitionDrawable cannot be cast 57 | // to android.graphics.drawable.BitmapDrawable 58 | BitmapShader shader; 59 | if (getDrawable() instanceof BitmapDrawable) { 60 | BitmapDrawable bitmapDrawable = (BitmapDrawable)getDrawable(); 61 | // clip 62 | shader = new BitmapShader(bitmapDrawable.getBitmap(), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); 63 | RectF rect = new RectF(0.0f, 0.0f, getWidth(), getHeight()); 64 | int width = bitmapDrawable.getBitmap().getWidth(); 65 | int height = bitmapDrawable.getBitmap().getHeight(); 66 | RectF src = null; 67 | if (((float)width) / height > 1) { 68 | src = new RectF(0.0f, 0.0f, height, height); 69 | } else { 70 | src = new RectF(0.0f, 0.0f, width, width); 71 | } 72 | Matrix matrix = canvas.getMatrix(); 73 | matrix.setRectToRect(src, rect, Matrix.ScaleToFit.CENTER); 74 | shader.setLocalMatrix(matrix); 75 | 76 | // 抗锯齿 77 | paint.setAntiAlias(true); 78 | paint.setShader(shader); 79 | // draw round circle for HeadImage or other 80 | canvas.drawRoundRect(rect, this.getWidth() / 2, this.getHeight() / 2, paint); 81 | // canvas.drawRoundRect(rect, xRadius, yRadius / 2, paint); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/p1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmeteor/CircleList/bc7e467861dadc471feb873368e24c7928c8801e/app/src/main/res/drawable/p1.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/p2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmeteor/CircleList/bc7e467861dadc471feb873368e24c7928c8801e/app/src/main/res/drawable/p2.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/p3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmeteor/CircleList/bc7e467861dadc471feb873368e24c7928c8801e/app/src/main/res/drawable/p3.jpg -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmeteor/CircleList/bc7e467861dadc471feb873368e24c7928c8801e/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmeteor/CircleList/bc7e467861dadc471feb873368e24c7928c8801e/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmeteor/CircleList/bc7e467861dadc471feb873368e24c7928c8801e/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmeteor/CircleList/bc7e467861dadc471feb873368e24c7928c8801e/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkmeteor/CircleList/bc7e467861dadc471feb873368e24c7928c8801e/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 16dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | CircleList 3 | Settings 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 14 |