Commit 82410f7f by EthanXiang

Initial commit

parents
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.3.1'
testCompile 'junit:junit:4.12'
compile "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.ext.kotlin_version"
}
repositories {
mavenCentral()
}
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in D:\Android\sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
package com.x.leo.circles;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumentation test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.x.leo.circles.test", appContext.getPackageName());
}
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.x.leo.circles">
<application android:allowBackup="true" android:label="@string/app_name"
android:supportsRtl="true">
</application>
</manifest>
package com.x.leo.circles;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
/**
* @作者:XJY
* @创建日期: 2017/3/16 17:46
* @描述:原型头像
* @更新者:${Author}$
* @更新时间:${Date}$
* @更新描述:${TODO}
*/
public class CircleImage extends android.support.v7.widget.AppCompatImageView{
private Paint paint;
public CircleImage(Context context) {
this(context,null);
}
public CircleImage(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint();
}
public CircleImage(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs);
}
private Rect rectSrc = new Rect();
private Rect rectDest = new Rect();
@Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (drawable == null) {
super.onDraw(canvas);
}else{
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
Bitmap b = getCircleBitmap(bitmap, 14);
rectSrc.set(0, 0, b.getWidth(), b.getHeight());
rectDest.set(0,0,getWidth(),getHeight());
paint.reset();
canvas.drawBitmap(b, rectSrc, rectDest, paint);
}
}
private Bitmap getCircleBitmap(Bitmap bitmap, int pixels) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
int x = bitmap.getWidth();
canvas.drawCircle(x / 2, x / 2, x / 2, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
}
package com.x.leo.circles;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
/**
* @作者:My
* @创建日期: 2017/4/11 17:37
* @描述:${TODO}
* @更新者:${Author}$
* @更新时间:${Date}$
* @更新描述:${TODO}
*/
public class CircleProgressBarView extends View {
private int mProgress;
private int mMeasuredHeight;
private int mMeasuredWidth;
private int mStrokeWidth;
private int mRadius;
private int mStrokeBackgroundColor;
private int mProgressColor;
private Paint mPaint;
private BitmapDrawable mCircle;
private boolean mHideSmallCircle = false;
public CircleProgressBarView(Context context) {
this(context, null);
}
public CircleProgressBarView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context, attrs);
}
public CircleProgressBarView(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs);
}
public CircleProgressBarView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
this(context, attrs, defStyleAttr);
}
private void initView(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressBarView);
mProgressColor = typedArray.getColor(R.styleable.CircleProgressBarView_progresscolor, Color.parseColor("#53c792"));
mStrokeBackgroundColor = typedArray.getColor(R.styleable.CircleProgressBarView_backgroundcolor, Color.parseColor("#C5DbD0"));
mRadius = typedArray.getDimensionPixelSize(R.styleable.CircleProgressBarView_radius, 0);
mStrokeWidth = typedArray.getDimensionPixelSize(R.styleable.CircleProgressBarView_strokewidth, DensityUtils.dp2px(getContext(), 5));
typedArray.recycle();
mCircle = (BitmapDrawable) getContext().getResources().getDrawable(R.drawable.cir_inactive);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
mMeasuredHeight = getMeasuredHeight();
mMeasuredWidth = getMeasuredWidth();
}
private RectF oval = new RectF();
@Override
protected void onDraw(Canvas canvas) {
if (mPaint == null) {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.STROKE);
if (mStrokeWidth == 0) {
return;
}
mPaint.setStrokeWidth(mStrokeWidth);
}
if (mRadius == 0) {
mRadius = mMeasuredWidth / 2 - mStrokeWidth / 2 - mStrokeWidth / 2 - 20;
}
mPaint.setColor(mStrokeBackgroundColor);
canvas.drawCircle(mMeasuredWidth / 2, mMeasuredHeight / 2, mRadius, mPaint);
oval.set(mMeasuredWidth / 2 - mRadius, mMeasuredWidth / 2 - mRadius, mMeasuredWidth / 2 + mRadius, mMeasuredWidth / 2 + mRadius);
mPaint.setColor(mProgressColor);
canvas.drawArc(oval, 0, mProgress * 360 / 100, false, mPaint);
if (!mHideSmallCircle) {
float x = getWidth() / 2 + mRadius - mCircle.getIntrinsicWidth() / 2;
float y = getHeight() / 2 - mCircle.getIntrinsicHeight() / 2;
canvas.drawBitmap(mCircle.getBitmap(), x, y, mPaint);
}
}
public int getStrokeWidth() {
return mStrokeWidth;
}
public void setStrokeWidth(int strokeWidth) {
mStrokeWidth = strokeWidth;
}
public int getRadius() {
return mRadius;
}
public void setRadius(int radius) {
mRadius = radius;
}
public int getStrokeBackgroundColor() {
return mStrokeBackgroundColor;
}
public void setStrokeBackgroundColor(int backgroundColor) {
mStrokeBackgroundColor = backgroundColor;
}
public int getProgressColor() {
return mProgressColor;
}
public void setProgressColor(int progressColor) {
mProgressColor = progressColor;
}
public void setProgress(int progress) {
mProgress = progress;
invalidate();
}
public int getProgress() {
return mProgress;
}
public void hideSmallCircle(boolean hide) {
mHideSmallCircle = hide;
}
}
package com.x.leo.circles
import android.animation.Animator
import android.animation.ValueAnimator
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.*
import android.text.TextUtils
import android.util.AttributeSet
import android.view.View
import android.widget.Button
/**
* @作者:XLEO
* @创建日期: 2017/8/18 10:04
* @描述:${TODO}
*
* @更新者:${Author}$
* @更新时间:${Date}$
* @更新描述:${TODO}
* @下一步:
*/
class CircleProgressButton(ctx: Context, attrs: AttributeSet?, defStyleAttr: Int) : Button(ctx, attrs, defStyleAttr) {
private lateinit var circleCenter: PointF
private var innerRadius: Float = 0f
private var outterRadius: Float = 0f
private var outterStrokeWidth: Float = 10f
private var outterInnerSpace: Float = 10f
private var duration: Int = 0
private var mPaint: Paint
private var colorlist: ColorStateList
private var progressBackgroundColor: Int = Color.GRAY
private var progressColor: Int = Color.RED
private var animator: ValueAnimator? = null
private var animatedValue: Int = 0
private var animatorListener: Animator.AnimatorListener? = null
private lateinit var outRect: RectF
private val startAngle: Float = 0f
private var circleAlpha:Float = 1f
init {
val attributes = ctx.obtainStyledAttributes(attrs, R.styleable.CircleProgressButton)
outterInnerSpace = attributes.getDimension(R.styleable.CircleProgressButton_innerOuterSpace, 10f)
outterStrokeWidth = attributes.getDimension(R.styleable.CircleProgressButton_outerStrokeWidth, 10f)
progressBackgroundColor = attributes.getColor(R.styleable.CircleProgressButton_progressBackground, Color.GRAY)
progressColor = attributes.getColor(R.styleable.CircleProgressButton_progressColor, Color.RED)
colorlist = attributes.getColorStateList(R.styleable.CircleProgressButton_circleColorList)
duration = attributes.getInt(R.styleable.CircleProgressButton_duration, 0)
attributes.recycle()
mPaint = Paint(Paint.ANTI_ALIAS_FLAG)
}
constructor(ctx: Context, attrs: AttributeSet?) : this(ctx, attrs, 0)
constructor(ctx: Context) : this(ctx, null)
fun setDuration(duration: Int) {
this.duration = duration
}
override fun setAlpha(alpha: Float) {
circleAlpha = alpha
}
override fun getAlpha(): Float {
return circleAlpha
}
fun setOnAnimatedEnd() {}
fun stopAnimation(){
if(animator != null){
animator!!.end()
animator = null
}
}
override fun setOnClickListener(l: OnClickListener?) {
super.setOnClickListener(object : OnCircleButtonClickListener(l) {
override fun onButtonClick(v: View?) {
}
})
}
fun setAnimationListener(listener: Animator.AnimatorListener) {
animatorListener = listener
}
fun startProgressAnimation() {
if (animator != null) {
animator!!.cancel()
}
animator = ValueAnimator.ofInt(0, duration)
animator!!.duration = duration.toLong()
animator!!.addUpdateListener {
animation ->
animatedValue = animation.animatedValue as Int
invalidate()
}
if (animatorListener != null) {
animator!!.addListener(animatorListener)
}
animator!!.start()
}
fun cancelAnimation(){
if (animator != null && animator!!.isRunning) {
animator!!.cancel()
animator = null
}
}
fun resetProgress(){
animatedValue = 0
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
cancelAnimation()
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec)
circleCenter = PointF(measuredWidth / 2.toFloat(), measuredHeight / 2.toFloat())
outterRadius = if (measuredHeight > measuredWidth) {
measuredWidth / 2 - outterStrokeWidth / 2
} else {
measuredHeight / 2 - outterStrokeWidth / 2
}
innerRadius = outterRadius - outterStrokeWidth / 2 - outterInnerSpace
outRect = RectF(circleCenter.x - outterRadius,
circleCenter.y - outterRadius,
circleCenter.x + outterRadius,
circleCenter.y + outterRadius)
}
override fun onDraw(canvas: Canvas?) {
if (canvas == null) {
return
}
mPaint.style = Paint.Style.STROKE
mPaint.color = progressBackgroundColor
mPaint.strokeWidth = outterStrokeWidth
canvas.drawCircle(circleCenter.x, circleCenter.y, outterRadius, mPaint)
drawProgress(canvas)
mPaint.color = colorlist.getColorForState(drawableState, colorlist.defaultColor)
mPaint.style = Paint.Style.FILL
mPaint.strokeWidth = 0f
mPaint.alpha = (circleAlpha * 255).toInt()
canvas.drawCircle(circleCenter.x, circleCenter.y, innerRadius, mPaint)
if (!TextUtils.isEmpty(text)) {
val textLength = paint.measureText(text.toString())
paint.color = textColors.getColorForState(drawableState,textColors.defaultColor)
paint.textSize = textSize
val rect = Rect()
paint.getTextBounds(text.toString(),0,text.length,rect)
val y = circleCenter.y - rect.top/2
canvas.drawText(text,0,text.length,circleCenter.x - textLength / 2, y,paint)
}
}
private fun drawProgress(canvas: Canvas) {
if (duration == 0) {
return
}
mPaint.color = progressColor
val sweepAngle = animatedValue / duration.toFloat() * 360
canvas.drawArc(outRect, startAngle, sweepAngle, false, mPaint)
}
}
abstract class OnCircleButtonClickListener : View.OnClickListener {
private var listener: View.OnClickListener? = null
constructor(l: View.OnClickListener?) {
listener = l
}
override fun onClick(v: View?) {
onButtonClick(v)
listener?.onClick(v)
}
abstract fun onButtonClick(v: View?)
}
package com.x.leo.circles;
import android.content.Context;
/**
* @作者:My
* @创建日期: 2017/3/27 14:00
* @描述:${TODO}
* @更新者:${Author}$
* @更新时间:${Date}$
* @更新描述:${TODO}
*/
public class DensityUtils {
public static int dp2px(Context context,int size){
float density = context.getResources().getDisplayMetrics().density;
return (int) (size * density + 0.5f);
}
public static int px2dp(Context context,int size){
float density = context.getResources().getDisplayMetrics().density;
return (int) (size / density + 0.5f);
}
public static int px2sp(Context context, float textSize) {
float density = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (textSize / density + 0.5f);
}
public static int sp2px(Context context,int size){
float density = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (size * density + 0.5f);
}
}
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CircleProgressBarView">
<attr name="backgroundcolor" format="color"/>
<attr name="progresscolor" format="color"/>
<attr name="progress" format="integer"/>
<attr name="radius" format="dimension"/>
<attr name="strokewidth" format="dimension"/>
</declare-styleable>
<declare-styleable name="CircleProgressButton">
<attr name="innerOuterSpace" format="dimension"/>
<attr name="outerStrokeWidth" format="dimension"/>
<attr name="duration" format="integer"/>
<attr name="circleColorList" format="color"/>
<attr name="progressBackground" format="color"/>
<attr name="progressColor" format="color"/>
</declare-styleable>
<declare-styleable name="LoadIngView">
<attr name="baseRes" format="reference"/>
<attr name="animateStyle" format="enum">
<enum name="CIRCLE_ANIMATE" value="0"/>
<enum name="CIRCLE_SHANDOW" value="1"/>
<enum name="CIRCLE_SHAKE" value="2"/>
</attr>
<attr name="animateDuration" format="integer"/>
<attr name="outCircleWidth" format="dimension"/>
<attr name="ovalSpanAngle" format="integer"/>
<attr name="openAngle" format="integer"/>
<attr name="outInnerMargin" format="fraction"/>
<attr name="ovalColor" format="color"/>
</declare-styleable>
</resources>
<resources>
<string name="app_name">Circles</string>
</resources>
package com.x.leo.circles;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment