diff --git a/.gitignore b/.gitignore
index 315bf71..69c4a60 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,32 +1,32 @@
-# built application files
+Application files
*.apk
*.ap_
-# files for the dex VM
+# Files for the Dalvik VM
*.dex
# Java class files
*.class
-# generated files
+# Generated files
bin/
gen/
+# Gradle files
+.gradle/
+build/
+
# Local configuration file (sdk path, etc)
local.properties
-# Eclipse project files
-.classpath
-.project
-
# Proguard folder generated by Eclipse
proguard/
+# Log Files
+*.log
+
# Intellij project files
*.iml
*.ipr
*.iws
-.idea/
-.gradle/
-
-build
+.idea/
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index e98e660..016278d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,14 +5,14 @@ buildscript {
}
dependencies {
- classpath 'com.android.tools.build:gradle:0.12.+'
+ classpath 'com.android.tools.build:gradle:1.2.2'
classpath 'com.jakewharton.sdkmanager:gradle-plugin:0.12.+'
}
}
ext {
- compileSdkVersion = 19
- buildToolsVersion = "19.1.0"
+ compileSdkVersion = 22
+ buildToolsVersion = "22.0.1"
}
def isReleaseBuild() {
diff --git a/example/build.gradle b/example/build.gradle
index 1dd72de..2a82bc2 100644
--- a/example/build.gradle
+++ b/example/build.gradle
@@ -3,29 +3,29 @@ buildscript {
mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:0.12.+'
+ classpath 'com.android.tools.build:gradle:1.1.0'
}
}
-apply plugin: 'android'
+apply plugin: 'com.android.application'
repositories {
mavenCentral()
}
android {
- compileSdkVersion 19
- buildToolsVersion "19.1"
+ compileSdkVersion 22
+ buildToolsVersion "22.0.1"
defaultConfig {
minSdkVersion 11
- targetSdkVersion 19
+ targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
- runProguard true
+ minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
@@ -33,6 +33,7 @@ android {
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
- compile 'com.android.support:appcompat-v7:19.1.0'
- compile 'com.github.markushi:circlebutton:1.1'
+ compile 'com.android.support:appcompat-v7:22.0.0'
+ //compile 'com.github.markushi:circlebutton:1.1'
+ compile project(':library')
}
diff --git a/example/src/main/java/at/markushi/circlebutton/example/MainActivity.java b/example/src/main/java/at/markushi/circlebutton/example/MainActivity.java
index 705c2d6..2a5b3a1 100644
--- a/example/src/main/java/at/markushi/circlebutton/example/MainActivity.java
+++ b/example/src/main/java/at/markushi/circlebutton/example/MainActivity.java
@@ -8,6 +8,8 @@
import android.view.ViewGroup;
import android.widget.Toast;
+import at.markushi.ui.CheckableCircleButton;
+
public class MainActivity extends ActionBarActivity {
@Override
@@ -20,7 +22,7 @@ protected void onCreate(Bundle savedInstanceState) {
}
}
- public static class PlaceholderFragment extends Fragment implements View.OnClickListener {
+ public static class PlaceholderFragment extends Fragment implements View.OnClickListener, CheckableCircleButton.OnCheckedChangeListener {
public PlaceholderFragment() {
}
@@ -31,7 +33,8 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa
rootView.findViewById(R.id.button0).setOnClickListener(this);
rootView.findViewById(R.id.button1).setOnClickListener(this);
- rootView.findViewById(R.id.button2).setOnClickListener(this);
+ CheckableCircleButton ccb = (CheckableCircleButton) rootView.findViewById(R.id.button2);
+ ccb.setOnCheckedChangeListener(this);
return rootView;
}
@@ -40,6 +43,11 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa
public void onClick(View view) {
Toast.makeText(getActivity(), "Button clicked", Toast.LENGTH_SHORT).show();
}
- }
+ @Override
+ public void onCheckedChanged(CheckableCircleButton button, boolean isChecked) {
+ String state = isChecked ? "checked": "unchecked";
+ Toast.makeText(getActivity(), "Button in " + state +" state", Toast.LENGTH_SHORT).show();
+ }
+ }
}
diff --git a/example/src/main/res/drawable-xhdpi/ic_pause_white_36dp.png b/example/src/main/res/drawable-xhdpi/ic_pause_white_36dp.png
new file mode 100644
index 0000000..72dfa9f
Binary files /dev/null and b/example/src/main/res/drawable-xhdpi/ic_pause_white_36dp.png differ
diff --git a/example/src/main/res/drawable-xhdpi/ic_play_arrow_white_36dp.png b/example/src/main/res/drawable-xhdpi/ic_play_arrow_white_36dp.png
new file mode 100644
index 0000000..043acd8
Binary files /dev/null and b/example/src/main/res/drawable-xhdpi/ic_play_arrow_white_36dp.png differ
diff --git a/example/src/main/res/layout/fragment_main.xml b/example/src/main/res/layout/fragment_main.xml
index 1e584ec..0d0ce0b 100644
--- a/example/src/main/res/layout/fragment_main.xml
+++ b/example/src/main/res/layout/fragment_main.xml
@@ -31,15 +31,18 @@
android:src="@drawable/ic_action_tick"
app:cb_color="#FFBB33" />
-
+ android:src="@drawable/ic_play_arrow_white_36dp"
+ app:cb_pressedRingWidth="8dp"
+ app:cb_checkedSrc="@drawable/ic_pause_white_36dp"
+ app:cb_color="#B48CF4"
+ app:cb_checkedColor="#AF5555"/>
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..0c71e76
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Apr 10 15:27:10 PDT 2013
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
diff --git a/library/build.gradle b/library/build.gradle
index e870fdb..42e268a 100644
--- a/library/build.gradle
+++ b/library/build.gradle
@@ -3,20 +3,20 @@ buildscript {
mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:0.12.+'
+ classpath 'com.android.tools.build:gradle:1.2.2'
}
}
apply plugin: 'android-sdk-manager'
-apply plugin: 'android-library'
+apply plugin: 'com.android.library'
repositories {
mavenCentral()
}
android {
- compileSdkVersion 19
- buildToolsVersion "19.1"
+ compileSdkVersion 22
+ buildToolsVersion "22.0.1"
defaultConfig {
versionName = VERSION_NAME
diff --git a/library/src/main/java/at/markushi/ui/CheckableCircleButton.java b/library/src/main/java/at/markushi/ui/CheckableCircleButton.java
new file mode 100644
index 0000000..15ba66a
--- /dev/null
+++ b/library/src/main/java/at/markushi/ui/CheckableCircleButton.java
@@ -0,0 +1,170 @@
+package at.markushi.ui;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.widget.Checkable;
+
+import at.markushi.circlebutton.R;
+
+public class CheckableCircleButton extends CircleButton implements Checkable {
+ private boolean mChecked = false;
+
+ private int mDefaultColor = Color.RED;
+ private int mCheckedColor = Color.BLUE;
+
+ private Drawable mDefaultDrawable;
+ private Drawable mCheckedDrawable;
+
+ private OnCheckedChangeListener mListener;
+ private boolean mBroadcasting;
+
+ public CheckableCircleButton(Context context) {
+ super(context);
+ }
+
+ public CheckableCircleButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context, attrs);
+ }
+
+ public CheckableCircleButton(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init(context, attrs);
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public CheckableCircleButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ init(context, attrs);
+ }
+
+ @Override
+ public void setPressed(boolean pressed) {
+ super.setPressed(pressed);
+ toggle();
+ }
+
+ @Override
+ public void setChecked(boolean b) {
+ if (mChecked != b) {
+ mChecked = b;
+ setVisualState(mChecked);
+ // Avoid infinite recursions if setChecked() is called from a listener
+ if (mBroadcasting) {
+ return;
+ }
+ mBroadcasting = true;
+ if (mListener != null) {
+ mListener.onCheckedChanged(this, mChecked);
+ }
+ mBroadcasting = false;
+ }
+ }
+
+ @Override
+ public boolean isChecked() {
+ return mChecked;
+ }
+
+ @Override
+ public void toggle() {
+ setChecked(!mChecked);
+ }
+
+ private void init(Context context, AttributeSet attrs) {
+ if (attrs != null) {
+ final TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CircleButton);
+ mDefaultColor = ta.getColor(R.styleable.CircleButton_cb_color, mDefaultColor);
+ ta.recycle();
+
+ final TypedArray ta_ccb = context.obtainStyledAttributes(attrs, R.styleable.CheckableCircleButton);
+ mCheckedColor = ta_ccb.getColor(R.styleable.CircleButton_cb_color, mCheckedColor);
+ mCheckedDrawable = ta_ccb.getDrawable(R.styleable.CheckableCircleButton_cb_checkedSrc);
+ ta_ccb.recycle();
+ }
+ mDefaultDrawable = getDrawable();
+ }
+
+ private void setVisualState(boolean isChecked) {
+ setColor(isChecked ? mCheckedColor: mDefaultColor);
+ setImageDrawable(isChecked ? mCheckedDrawable: mDefaultDrawable);
+ }
+
+ public void setCheckedState(boolean isChecked) {
+ if (mChecked != isChecked) {
+ mChecked = isChecked;
+ setVisualState(mChecked);
+ }
+ }
+
+ public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
+ mListener = listener;
+ }
+
+ public interface OnCheckedChangeListener {
+ void onCheckedChanged(CheckableCircleButton button, boolean isChecked);
+ }
+
+
+ static class SavedState extends BaseSavedState {
+ boolean checked;
+
+ SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ private SavedState(Parcel in) {
+ super(in);
+ checked = (Boolean)in.readValue(null);
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ super.writeToParcel(out, flags);
+ out.writeValue(checked);
+ }
+
+ @Override
+ public String toString() {
+ return "CheckableCircleButton.SavedState{"
+ + Integer.toHexString(System.identityHashCode(this))
+ + " checked=" + checked + "}";
+ }
+
+ public static final Parcelable.Creator CREATOR
+ = new Parcelable.Creator() {
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+
+ @Override
+ public Parcelable onSaveInstanceState() {
+ Parcelable superState = super.onSaveInstanceState();
+ SavedState ss = new SavedState(superState);
+ ss.checked = mChecked;
+ return ss;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Parcelable state) {
+ SavedState ss = (SavedState) state;
+
+ super.onRestoreInstanceState(ss.getSuperState());
+ mChecked = ss.checked;
+ setVisualState(ss.checked);
+ requestLayout();
+ }
+}
diff --git a/library/src/main/java/at/markushi/ui/CircleButton.java b/library/src/main/java/at/markushi/ui/CircleButton.java
index 0e0ca84..79cf41d 100644
--- a/library/src/main/java/at/markushi/ui/CircleButton.java
+++ b/library/src/main/java/at/markushi/ui/CircleButton.java
@@ -1,11 +1,13 @@
package at.markushi.ui;
import android.animation.ObjectAnimator;
+import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
+import android.os.Build;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.ImageView;
@@ -32,7 +34,8 @@ public class CircleButton extends ImageView {
private int pressedRingWidth;
private int defaultColor = Color.BLACK;
private int pressedColor;
- private ObjectAnimator pressedAnimator;
+
+ private OnPressListener mListener;
public CircleButton(Context context) {
super(context);
@@ -49,18 +52,22 @@ public CircleButton(Context context, AttributeSet attrs, int defStyle) {
init(context, attrs);
}
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public CircleButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ init(context, attrs);
+ }
+
@Override
public void setPressed(boolean pressed) {
super.setPressed(pressed);
- if (circlePaint != null) {
- circlePaint.setColor(pressed ? pressedColor : defaultColor);
- }
-
- if (pressed) {
- showPressedRing();
- } else {
- hidePressedRing();
+ if (mListener != null) {
+ if (pressed) {
+ mListener.onPressed(this);
+ } else {
+ mListener.onUnpressed(this);
+ }
}
}
@@ -100,16 +107,6 @@ public void setColor(int color) {
this.invalidate();
}
- private void hidePressedRing() {
- pressedAnimator.setFloatValues(pressedRingWidth, 0f);
- pressedAnimator.start();
- }
-
- private void showPressedRing() {
- pressedAnimator.setFloatValues(animationProgress, pressedRingWidth);
- pressedAnimator.start();
- }
-
private void init(Context context, AttributeSet attrs) {
this.setFocusable(true);
this.setScaleType(ScaleType.CENTER_INSIDE);
@@ -133,15 +130,50 @@ private void init(Context context, AttributeSet attrs) {
}
setColor(color);
-
focusPaint.setStrokeWidth(pressedRingWidth);
- final int pressedAnimationTime = getResources().getInteger(ANIMATION_TIME_ID);
- pressedAnimator = ObjectAnimator.ofFloat(this, "animationProgress", 0f, 0f);
- pressedAnimator.setDuration(pressedAnimationTime);
+
+ setOnPressListener(new DefaultPressListener());
}
private int getHighlightColor(int color, int amount) {
return Color.argb(Math.min(255, Color.alpha(color)), Math.min(255, Color.red(color) + amount),
Math.min(255, Color.green(color) + amount), Math.min(255, Color.blue(color) + amount));
}
+
+ public void setOnPressListener(OnPressListener listener) {
+ mListener = listener;
+ }
+
+ public interface OnPressListener {
+ void onPressed(CircleButton button);
+ void onUnpressed(CircleButton button);
+ }
+
+ public class DefaultPressListener implements OnPressListener {
+ private ObjectAnimator pressedAnimator;
+
+ public DefaultPressListener() {
+ final int pressedAnimationTime = getResources().getInteger(ANIMATION_TIME_ID);
+ pressedAnimator = ObjectAnimator.ofFloat(CircleButton.this, "animationProgress", 0f, 0f);
+ pressedAnimator.setDuration(pressedAnimationTime);
+ }
+
+ @Override
+ public void onPressed(CircleButton button) {
+ if (circlePaint != null) {
+ circlePaint.setColor(pressedColor);
+ }
+ pressedAnimator.setFloatValues(animationProgress, pressedRingWidth);
+ pressedAnimator.start();
+ }
+
+ @Override
+ public void onUnpressed(CircleButton button) {
+ if (circlePaint != null) {
+ circlePaint.setColor(defaultColor);
+ }
+ pressedAnimator.setFloatValues(pressedRingWidth, 0f);
+ pressedAnimator.start();
+ }
+ }
}
diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml
index 747de0a..8ed6b5f 100644
--- a/library/src/main/res/values/attrs.xml
+++ b/library/src/main/res/values/attrs.xml
@@ -4,4 +4,10 @@
+
+
+
+
+
+
\ No newline at end of file