按钮按动效果由三部分组成:按压前背景图、按压后背景图、文字位置的变化
按压前背景图:使用layer-list,在主背景下叠加一层颜色图片,通过设置left/top/right/bottom使其立体
<!--distance、corners这里分别为5dp、10dp,具体可以自定-->
<!--可以变更具体的偏移方向以使其向不同方向立体-->
<layer-list>
<item
android:top="@dimen/distance"
android:left="@dimen/distance">
<shape>
<solid android:color="#779E9E9E"/>
<corners android:radius="@dimen/corners"/>
</shape>
</item>
<item
android:bottom="@dimen/distance"
android:right="@dimen/distance">
<shape>
<solid android:color="@color/blue"/>
<corners android:radius="@dimen/corners"/>
</shape>
</item>
</layer-list>
按压后背景图:将按压前背景中设置的偏移方向全部反过来(原来top的改为bottom、原来left的改为right,其余同理),并将主背景下的颜色图片改为透明,同时也可将主背景的颜色换成淡色的,使效果更好
<layer-list>
<item
android:bottom="@dimen/distance"
android:right="@dimen/distance">
<shape>
<solid android:color="@android:color/transparent"/>
<corners android:radius="@dimen/corners"/>
</shape>
</item>
<item
android:top="@dimen/distance"
android:left="@dimen/distance">
<shape>
<solid android:color="#81D4FA"/>
<corners android:radius="@dimen/corners"/>
</shape>
</item>
</layer-list>
然后就可以用selector将其组装起来应用到按钮的背景
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false">
<!--按压前背景图-->
</item>
<item android:state_pressed="true">
<!--按压后背景图-->
</item>
</selector>
到此,对于无文字的按钮而言,便已经可以了
控制文字位置变化:对按钮而言,整个视觉上的三维实则为为它的二维背景,所以文字并不会处于主背景的中间(这一点,你可通过在按钮的原有内边距基础上,在加上你在相应方向上设置的distance以使其在主背景居中),同时,文字也不会随着主背景的位置变化而变化位置,所以对有文字按钮,需动态的更改文字位置(这里通过动态变化文字内边距来实现,也许有更好的方法)
在按钮的点击中,有多种过程:
- DOWN -> UP(简单的点击)
- DOWN -> MOVE(没有移出按钮) -> UP(按下后稍微移动了一下再抬起)
- DOWN -> MOVE(移出了按钮)(按下后移出了按钮)
故具体的设计思路是:复写按钮所在Activity的dispatchTouchEvent方法,首先检查一次事件中是否发生在了按钮上,若是,则在DOWN事件中将文字设置为按压后的内边距,在UP事件中将文字设置为按压前的内边距;若不是,则在MOVE事件将文字设置为按压前的内边距,同时将按钮的按压状态设置为false,即取消按钮的按压状态。
// needRestore是初值为false的一个boolean变量,用来避免多次执行MOVE事件中的代码
// 10dp为我的按钮原本设置的内边距,5dp为layer-list中设置的distance,15dp即两者之和
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
int[] leftAndTop = new int[2];// [left, top]
button.getLocationInWindow(leftAndTop);
// 检查是否发生在按钮上
if (ev.getX() >= leftAndTop[0] && ev.getX() <= (leftAndTop[0] + button.getWidth()/*right*/) &&
ev.getY() >= leftAndTop[1] && ev.getY() <= (leftAndTop[1] + button.getHeight()/*bottom*/)) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
needRestore = true;
button.setPadding(fromDpToPx(15), fromDpToPx(5), fromDpToPx(10), 0);
break;
case MotionEvent.ACTION_UP:
needRestore = false;
button.setPadding(fromDpToPx(10), 0, fromDpToPx(15), fromDpToPx(5));
break;
}
} else {
if (needRestore) {
needRestore = false;
button.setPadding(fromDpToPx(10), 0, fromDpToPx(15), fromDpToPx(5));
button.setPressed(false);
}
}
return super.dispatchTouchEvent(ev);
}
能力所限,不足之处烦请多多指教!