前言:
Android我一直想要做效果Button,終於大海撈針般找到別人寫好的,因此我花了一些時間簡化與整理成一個一個範例。
-MainActivity.java-
import android.widget.CompoundButton; |
import android.widget.SeekBar; |
import android.widget.TextView; |
import android.widget.ToggleButton; |
public class MainActivity extends Activity |
implements CompoundButton.OnCheckedChangeListener, SeekBar.OnSeekBarChangeListener { |
private TButton twitterBtn; |
private TextView shadowHeight; |
private SeekBar shadowHeightBar; |
@Override |
protected void onCreate(Bundle savedInstanceState) { |
super.onCreate(savedInstanceState); |
setContentView(R.layout.activity_main); |
twitterBtn = (TButton) findViewById(R.id.f_twitter_button); |
ToggleButton shadowSwitch = (ToggleButton) findViewById(R.id.enable_shadow_switch); |
shadowHeightBar = (SeekBar) findViewById(R.id.shadow_height_seekbar); |
shadowHeight = (TextView) findViewById(R.id.shadow_height_value); |
shadowSwitch.setOnCheckedChangeListener(this); |
shadowHeightBar.setOnSeekBarChangeListener(this); |
} |
@Override |
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { |
twitterBtn.setShadowEnabled(isChecked); |
updateShadowHeight(shadowHeightBar.getProgress()); |
} |
@Override |
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { |
shadowHeight.setText(progress + "dp"); |
updateShadowHeight(progress); |
} |
private void updateShadowHeight(int height) { |
//Convert from dp to pixel |
int shadowHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, height, getResources().getDisplayMetrics()); |
twitterBtn.setShadowHeight(shadowHeight); |
} |
@Override |
public void onStartTrackingTouch(SeekBar seekBar) { |
} |
@Override |
public void onStopTrackingTouch(SeekBar seekBar) { |
} |
} |
-TButton.java-
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.util.AttributeSet; |
import android.view.MotionEvent; |
import android.view.View; |
import android.widget.Button; |
/** |
* Created by hoang8f on 5/5/14. |
*/ |
public class TButton extends Button 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 TButton(Context context) { |
super(context); |
init(); |
this.setOnTouchListener(this); |
} |
public TButton(Context context, AttributeSet attrs) { |
super(context, attrs); |
init(); |
parseAttrs(context, attrs); |
this.setOnTouchListener(this); |
} |
public TButton(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: |
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); |
} |
private void parseAttrs(Context context, AttributeSet attrs) { |
//Load from custom attributes |
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TButton); |
if (typedArray == null) return; |
for (int i = 0; i < typedArray.getIndexCount(); i++) { |
int attr = typedArray.getIndex(i); |
if (attr == R.styleable.TButton_shadowEnabled) { |
isShadowEnabled = typedArray.getBoolean(attr, true); //Default is true |
} else if (attr == R.styleable.TButton_shadowHeight) { |
mShadowHeight = typedArray.getDimensionPixelSize(attr, R.dimen.fbutton_default_shadow_height); |
} |
} |
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 (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); |
} |
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); |
//上方按下效果 |
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 setShadowHeight(int shadowHeight) {//陰影高度 |
this.mShadowHeight = shadowHeight; |
refresh(); |
} |
} |
-activity_main.xml-
xmlns:fbutton="http://schemas.android.com/apk/res-auto" |
xmlns:tools="http://schemas.android.com/tools" |
android:layout_width="match_parent" |
android:layout_height="match_parent" |
tools:context="com.example.flatbutton.MainActivity" > |
<LinearLayout |
android:id="@+id/LinearLayout1" |
android:layout_width="match_parent" |
android:layout_height="match_parent" |
android:orientation="vertical" > |
<com.example.flatbutton.TButton |
android:id="@+id/f_twitter_button" |
android:layout_width="wrap_content" |
android:layout_height="wrap_content" |
android:layout_margin="20dp" |
android:drawableLeft="@drawable/twitter" |
android:drawablePadding="0dp" |
android:minHeight="80dp" |
android:minWidth="250dp" |
android:paddingLeft="30dp" |
android:paddingRight="20dp" |
android:paddingTop="-5dp" |
android:text="Twitter" |
android:textColor="@android:color/white" /> |
<TextView |
android:id="@+id/shadow_height_label" |
android:layout_width="wrap_content" |
android:layout_height="wrap_content" |
android:layout_margin="5dp" |
android:text="Shadow height: " /> |
<TextView |
android:id="@+id/shadow_height_value" |
android:layout_width="wrap_content" |
android:layout_height="wrap_content" |
android:layout_margin="5dp" |
android:text="4dp" /> |
<SeekBar |
android:id="@+id/shadow_height_seekbar" |
android:layout_width="match_parent" |
android:layout_height="wrap_content" |
android:layout_margin="10dp" |
android:max="10" |
android:progress="4" /> |
<ToggleButton |
android:id="@+id/enable_shadow_switch" |
android:layout_width="wrap_content" |
android:layout_height="wrap_content" |
android:layout_marginRight="16dp" |
android:checked="true" |
android:minHeight="55dp" |
android:text="Shadow" /> |
</LinearLayout> |
</ScrollView> |
效果圖:
原始碼下載:
全站熱搜
留言列表