原Github地址:https://github.com/hoang8f/android-flat-button
使用方法:
1.加入gradle依赖:
compile 'info.hoang8f:fbutton:1.0.5'
2.加入FButton的java文件:
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.os.Build;
import android.support.v7.widget.AppCompatButton;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import info.hoang8f.fbutton.R;
/**
* Created by hoang8f on 5/5/14.
*/
public class FButton extends AppCompatButton implements View.OnTouchListener {
//Custom values
private boolean isShadowEnabled = true;
private int mButtonColor;
private int mShadowColor;
private int mShadowHeight;
private int mCornerRadius;
//Native values
private int mPaddingLeft;
private int mPaddingRight;
private int mPaddingTop;
private int mPaddingBottom;
//Background drawable
private Drawable pressedDrawable;
private Drawable unpressedDrawable;
boolean isShadowColorDefined = false;
public FButton(Context context) {
super(context);
init();
this.setOnTouchListener(this);
}
public FButton(Context context, AttributeSet attrs) {
super(context, attrs);
init();
parseAttrs(context, attrs);
this.setOnTouchListener(this);
}
public FButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
parseAttrs(context, attrs);
this.setOnTouchListener(this);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
//Update background color
refresh();
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
updateBackground(pressedDrawable);
this.setPadding(mPaddingLeft, mPaddingTop + mShadowHeight, mPaddingRight, mPaddingBottom);
break;
case MotionEvent.ACTION_MOVE:
Rect r = new Rect();
view.getLocalVisibleRect(r);
if (!r.contains((int) motionEvent.getX(), (int) motionEvent.getY() + 3 * mShadowHeight) &&
!r.contains((int) motionEvent.getX(), (int) motionEvent.getY() - 3 * mShadowHeight)) {
updateBackground(unpressedDrawable);
this.setPadding(mPaddingLeft, mPaddingTop + mShadowHeight, mPaddingRight, mPaddingBottom + mShadowHeight);
}
break;
case MotionEvent.ACTION_OUTSIDE:
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
updateBackground(unpressedDrawable);
this.setPadding(mPaddingLeft, mPaddingTop + mShadowHeight, mPaddingRight, mPaddingBottom + mShadowHeight);
break;
}
return false;
}
private void init() {
//Init default values
isShadowEnabled = true;
Resources resources = getResources();
if (resources == null) return;
mButtonColor = resources.getColor(R.color.fbutton_default_color);
mShadowColor = resources.getColor(R.color.fbutton_default_shadow_color);
mShadowHeight = resources.getDimensionPixelSize(R.dimen.fbutton_default_shadow_height);
mCornerRadius = resources.getDimensionPixelSize(R.dimen.fbutton_default_conner_radius);
}
private void parseAttrs(Context context, AttributeSet attrs) {
//Load from custom attributes
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FButton);
if (typedArray == null) return;
for (int i = 0; i < typedArray.getIndexCount(); i++) {
int attr = typedArray.getIndex(i);
if (attr == R.styleable.FButton_shadowEnabled) {
isShadowEnabled = typedArray.getBoolean(attr, true); //Default is true
} else if (attr == R.styleable.FButton_buttonColor) {
mButtonColor = typedArray.getColor(attr, R.color.fbutton_default_color);
} else if (attr == R.styleable.FButton_shadowColor) {
mShadowColor = typedArray.getColor(attr, R.color.fbutton_default_shadow_color);
isShadowColorDefined = true;
} else if (attr == R.styleable.FButton_shadowHeight) {
mShadowHeight = typedArray.getDimensionPixelSize(attr, R.dimen.fbutton_default_shadow_height);
} else if (attr == R.styleable.FButton_cornerRadius) {
mCornerRadius = typedArray.getDimensionPixelSize(attr, R.dimen.fbutton_default_conner_radius);
}
}
typedArray.recycle();
//Get paddingLeft, paddingRight
int[] attrsArray = new int[]{
android.R.attr.paddingLeft, // 0
android.R.attr.paddingRight, // 1
};
TypedArray ta = context.obtainStyledAttributes(attrs, attrsArray);
if (ta == null) return;
mPaddingLeft = ta.getDimensionPixelSize(0, 0);
mPaddingRight = ta.getDimensionPixelSize(1, 0);
ta.recycle();
//Get paddingTop, paddingBottom
int[] attrsArray2 = new int[]{
android.R.attr.paddingTop, // 0
android.R.attr.paddingBottom,// 1
};
TypedArray ta1 = context.obtainStyledAttributes(attrs, attrsArray2);
if (ta1 == null) return;
mPaddingTop = ta1.getDimensionPixelSize(0, 0);
mPaddingBottom = ta1.getDimensionPixelSize(1, 0);
ta1.recycle();
}
public void refresh() {
int alpha = Color.alpha(mButtonColor);
float[] hsv = new float[3];
Color.colorToHSV(mButtonColor, hsv);
hsv[2] *= 0.8f; // value component
//if shadow color was not defined, generate shadow color = 80% brightness
if (!isShadowColorDefined) {
mShadowColor = Color.HSVToColor(alpha, hsv);
}
//Create pressed background and unpressed background drawables
if (this.isEnabled()) {
if (isShadowEnabled) {
pressedDrawable = createDrawable(mCornerRadius, Color.TRANSPARENT, mButtonColor);
unpressedDrawable = createDrawable(mCornerRadius, mButtonColor, mShadowColor);
} else {
mShadowHeight = 0;
pressedDrawable = createDrawable(mCornerRadius, mShadowColor, Color.TRANSPARENT);
unpressedDrawable = createDrawable(mCornerRadius, mButtonColor, Color.TRANSPARENT);
}
} else {
Color.colorToHSV(mButtonColor, hsv);
hsv[1] *= 0.25f; // saturation component
int disabledColor = mShadowColor = Color.HSVToColor(alpha, hsv);
// Disabled button does not have shadow
pressedDrawable = createDrawable(mCornerRadius, disabledColor, Color.TRANSPARENT);
unpressedDrawable = createDrawable(mCornerRadius, disabledColor, Color.TRANSPARENT);
}
updateBackground(unpressedDrawable);
//Set padding
this.setPadding(mPaddingLeft, mPaddingTop + mShadowHeight, mPaddingRight, mPaddingBottom + mShadowHeight);
}
private void updateBackground(Drawable background) {
if (background == null) return;
//Set button background
if (Build.VERSION.SDK_INT >= 16) {
this.setBackground(background);
} else {
this.setBackgroundDrawable(background);
}
}
private LayerDrawable createDrawable(int radius, int topColor, int bottomColor) {
float[] outerRadius = new float[]{radius, radius, radius, radius, radius, radius, radius, radius};
//Top
RoundRectShape topRoundRect = new RoundRectShape(outerRadius, null, null);
ShapeDrawable topShapeDrawable = new ShapeDrawable(topRoundRect);
topShapeDrawable.getPaint().setColor(topColor);
//Bottom
RoundRectShape roundRectShape = new RoundRectShape(outerRadius, null, null);
ShapeDrawable bottomShapeDrawable = new ShapeDrawable(roundRectShape);
bottomShapeDrawable.getPaint().setColor(bottomColor);
//Create array
Drawable[] drawArray = {bottomShapeDrawable, topShapeDrawable};
LayerDrawable layerDrawable = new LayerDrawable(drawArray);
//Set shadow height
if (isShadowEnabled && topColor != Color.TRANSPARENT) {
//unpressed drawable
layerDrawable.setLayerInset(0, 0, 0, 0, 0); /*index, left, top, right, bottom*/
} else {
//pressed drawable
layerDrawable.setLayerInset(0, 0, mShadowHeight, 0, 0); /*index, left, top, right, bottom*/
}
layerDrawable.setLayerInset(1, 0, 0, 0, mShadowHeight); /*index, left, top, right, bottom*/
return layerDrawable;
}
//Setter
public void setShadowEnabled(boolean isShadowEnabled) {
this.isShadowEnabled = isShadowEnabled;
setShadowHeight(0);
refresh();
}
public void setButtonColor(int buttonColor) {
this.mButtonColor = buttonColor;
refresh();
}
public void setShadowColor(int shadowColor) {
this.mShadowColor = shadowColor;
isShadowColorDefined = true;
refresh();
}
public void setShadowHeight(int shadowHeight) {
this.mShadowHeight = shadowHeight;
refresh();
}
public void setCornerRadius(int cornerRadius) {
this.mCornerRadius = cornerRadius;
refresh();
}
public void setFButtonPadding(int left, int top, int right, int bottom) {
mPaddingLeft = left;
mPaddingRight = right;
mPaddingTop = top;
mPaddingBottom = bottom;
refresh();
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
refresh();
}
//Getter
public boolean isShadowEnabled() {
return isShadowEnabled;
}
public int getButtonColor() {
return mButtonColor;
}
public int getShadowColor() {
return mShadowColor;
}
public int getShadowHeight() {
return mShadowHeight;
}
public int getCornerRadius() {
return mCornerRadius;
}
}
3.创建attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="FButton">
<attr name="shadowEnabled" format="boolean" />
<attr name="buttonColor" format="color" />
<attr name="shadowColor" format="color" />
<attr name="shadowHeight" format="dimension" />
<attr name="cornerRadius" format="dimension" />
</declare-styleable>
</resources>
4.创建 color.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
<color name="fbutton_default_color">#3eadeb</color>
<color name="fbutton_default_shadow_color">#ff3493c8</color>
//Color Swatches provided by http://designmodo.github.io/Flat-UI/
<color name="fbutton_color_turquoise">#1abc9c</color>
<color name="fbutton_color_green_sea">#16a085</color>
<color name="fbutton_color_emerald">#2ecc71</color>
<color name="fbutton_color_nephritis">#27ae60</color>
<color name="fbutton_color_peter_river">#3498db</color>
<color name="fbutton_color_belize_hole">#2980b9</color>
<color name="fbutton_color_amethyst">#9b59b6</color>
<color name="fbutton_color_wisteria">#8e44ad</color>
<color name="fbutton_color_wet_asphalt">#34495e</color>
<color name="fbutton_color_midnight_blue">#2c3e50</color>
<color name="fbutton_color_sun_flower">#f1c40f</color>
<color name="fbutton_color_orange">#f39c12</color>
<color name="fbutton_color_carrot">#e67e22</color>
<color name="fbutton_color_pumpkin">#d35400</color>
<color name="fbutton_color_alizarin">#e74c3c</color>
<color name="fbutton_color_pomegranate">#c0392b</color>
<color name="fbutton_color_clouds">#ecf0f1</color>
<color name="fbutton_color_silver">#bdc3c7</color>
<color name="fbutton_color_concrete">#95a5a6</color>
<color name="fbutton_color_asbestos">#7f8c8d</color>
<color name="fbutton_color_transparent">@android:color/transparent</color>
</resources>
5.创建 dimens.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="fbutton_default_conner_radius">8dp</dimen>
<dimen name="fbutton_default_padding_left">10dp</dimen>
<dimen name="fbutton_default_padding_right">10dp</dimen>
<dimen name="fbutton_default_padding_top">5dp</dimen>
<dimen name="fbutton_default_padding_bottom">5dp</dimen>
<dimen name="fbutton_default_shadow_height">4dp</dimen>
</resources>
6.使用:
在layout中的根节点加入
xmlns:fbutton="http://schemas.android.com/apk/res-auto"
接着使用
<com.example.administrator.button_demo.FButton
android:id="@+id/btn"
android:onClick="btn_clicked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
fbutton:buttonColor="@color/fbutton_color_alizarin"
fbutton:shadowColor="@color/fbutton_color_silver"
fbutton:shadowEnabled="true"
fbutton:shadowHeight="2dp"
fbutton:cornerRadius="105dp"
/>
注意那个com.example.administrator.button_demo,要改成自己的包