如何在按下状态时移动按钮文本

时间:2011-10-06 15:51:38

标签: android user-interface button

我为按钮和不同的按钮状态创建了自定义背景。但是现在我达到了一个我无法理解的地步。

当按钮处于正常状态时,它看起来很好。但是当我按下按钮时,我需要将文本向下移动几个像素,因为按钮背景图像移动(实际上感觉就像它在图像上移动一样,因为首先按钮下面有边框,当它处于按下状态时,此边框消失)。请看下面的图片。

按下按钮状态时,如何移动按钮中的按钮文本? (可能以某种方式填充或按钮的布局自定义)

enter image description here

5 个答案:

答案 0 :(得分:5)

在9补丁中设置填充对我来说不起作用。 在触摸侦听器中设置填充是混乱的,在使用按钮的任何地方都会丢失代码。

我选择了子类Button,结果显得相当整洁。在我的情况下,我想偏移图标(drawableLeft)和文本1px左和1px向下。

Subclassed按钮小部件:

package com.myapp.widgets;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.Button;

import com.myapp.R;

public class OffsetButton extends Button {

    public OffsetButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public OffsetButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public OffsetButton(Context context) {
        super(context);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean value = super.onTouchEvent(event);

        if (event.getAction() == MotionEvent.ACTION_UP) {
            setBackgroundResource(R.drawable.btn_normal);
        } else if (event.getAction() == MotionEvent.ACTION_DOWN) {
            setBackgroundResource(R.drawable.btn_pressed);
            setPadding(getPaddingLeft() + 1, getPaddingTop() + 1, getPaddingRight() - 1,
                    getPaddingBottom() - 1);
        }

        return value;
    }
}

并在布局中使用它:

<com.myapp.widgets.OffsetButton
    android:text="@string/click_me"
    android:drawableLeft="@drawable/icon_will_be_offset_too_thats_good" />

很少注意到:

  • 没有使用StateListDrawable作为背景,而是在代码中切换背景。当我尝试使用StateListDrawable时,填充更改和背景更改之间会有小的暂停。那看起来不太好。

  • 设置后台重置填充,因此无需在ACTION_UP案例中调整填充

  • 增加顶部和左侧填充非常重要,同时减少底部和右侧填充。因此内容区域的大小保持不变,内容区域实际上只是移位。

答案 1 :(得分:4)

我自己没有尝试,但是如果你使用九个补丁作为两种状态的背景可绘制,那么你应该考虑在压缩状态下绘制适当的填充框。详情请见here

答案 2 :(得分:3)

您可以在视图上使用填充。您可以将OnTouchListener添加到按钮或视图,如

viewF.setOnTouchListener(new View.OnTouchListener() {  
    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
        if (event.getAction == MotionEvent.ACTION_UP) { 
            //set your padding            
        } else if (event.getAction == MotionEvent.ACTION_DOWN){
            //set your padding            
        }   
        return true; 
    } 
}); 

ontouchlistener会在按下按钮时让你知道,而不是。

答案 3 :(得分:1)

PēterisHaune答案比覆盖setPressed()更糟糕。但是对于在ICS或更低级别的设备上测试您的应用程序并添加按钮作为listview项目,请使用setPressed进行操作。 为了实现这一点,我改进了我的按钮课程:

public class OffsetButton extends Button {

    private static final int OFFSET_IN_DP = 6;
    private int offset_in_px;
    private boolean wasPressed = false;
    private Integer[] defaultPaddings;

    public OffsetButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initView();
    }

    public OffsetButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

    public OffsetButton(Context context) {
        super(context);
        initView();
    }

    private void initView() {
        offset_in_px = (int) DisplayUtil.convertDpToPixel(OFFSET_IN_DP);
    }

    @Override
    public void setPressed(boolean pressed) {
        if (pressed && !wasPressed) {
            changePaddings();
        }
        if (!pressed && wasPressed) {
            resetPaddings();
        }
        super.setPressed(pressed);
    }

    private void changePaddings() {
        defaultPaddings = new Integer[]{getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom()};
        setPadding(getPaddingLeft(), getPaddingTop() + offset_in_px, getPaddingRight(), getPaddingBottom() - offset_in_px);
        wasPressed = true;
    }

    private void resetPaddings() {
        setPadding(defaultPaddings[0], defaultPaddings[1], defaultPaddings[2], defaultPaddings[3]);
        wasPressed = false;
    }

    @Override
    public boolean performClick() {
        resetPaddings();
        return super.performClick();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (isEnabled())
        {
            if (event.getAction() == MotionEvent.ACTION_DOWN && !wasPressed) {
                changePaddings();
            } else if (event.getAction() == MotionEvent.ACTION_UP && wasPressed) {
                resetPaddings();
            }
        }
        return super.onTouchEvent(event);
    }
}

答案 4 :(得分:0)

这可能会起作用:

setPadding(left, top, right, bottom); // Normal
setPadding(left, top + x, right, bottom - x); // Pressed