0

我的问题如下:

我有ImageView一个背景。背景是可绘制的,根据状态绘制不同的图像。

context_menu_button.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

<!-- Focused -->
<item android:drawable="@drawable/button_round_focused" 
    android:state_focused="true"/>

<!-- Pressed -->
<item android:drawable="@drawable/button_round_focused" 
    android:state_pressed="true"/>

<!-- Normal -->
<item android:drawable="@android:color/transparent"/>

</selector>

然后我有一个作为star icon背景context_menu_button应用的:

<ImageView
    android:id="@+id/btnStar"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/context_menu_button"
    android:focusable="true"
    android:src="@drawable/icon_star"  />

图像button_round_focused实际上非常大,因为它是具有非常微妙渐变的图像。正常状态下没有图像(透明色)。这就是上面的 XML 的样子(聚焦状态):

星形图标

这个背景的大小给我带来了一些麻烦。绘制星形图标时,会考虑背景来计算星形图标的面积。因此,当我对齐两个或多个与此相似的图标时,它们彼此之间的距离很远。

<ImageView
    android:id="@+id/btnStar"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/context_menu_button"
    android:focusable="true"
    android:src="@drawable/icon_star" />

<ImageView
    android:id="@+id/btnShare"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/context_menu_button"
    android:focusable="true"
    android:src="@drawable/icon_share" />

<ImageView
    android:id="@+id/btnRate"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/context_menu_button"
    android:focusable="true"
    android:src="@drawable/icon_rate" />

星级分享率

我的解决方案是设置左边的负边距,所以它们被关闭在一起。

负边距的明星份额率

然而,这个解决方案引起了另一个问题。现在项目重叠:

星重叠

共享重叠

速率重叠

现在,例如,当我尝试单击项目共享(中间的按钮)时,实际上是第三个被单击的按钮,因为它们是重叠的。

ImageView我理想的解决方案是不考虑应用到 an 的背景来计算它应用到的项目的面积。像这样的东西:

有背景的明星出界

换句话说,背景可能会超出ImageView.

我认为这可以解决问题,但我一直在阅读文档,但找不到与此相关的任何内容。任何其他想法将不胜感激(尽管不可能改变 bakground 的大小)。

谢谢你的帮助。

4

1 回答 1

0

最后,我设法解决了这个问题。我所做的是以下内容:

1) 移除了按钮的背景。

背景是这个问题的根本原因。没有背景,一切都按预期进行。

2) 以编程方式管理在获得焦点或单击时显示背后的背景和图标。

为了做到这一点,我做的第一件事就是改变布局。我将所有图标(星号、分享、评分)放在一个FrameLayout. 我还附加了一个带有可绘制 button_round_focused 的 ImageView(上面显示的光环)。这个想法是当图标获得焦点时将此图像移动到右侧图标。由于图像位于图标之前,其Z-index较低,因此将绘制在图标后面。

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="85dp"
    android:gravity="left|center_vertical" >

    <ImageView
        android:id="@+id/button_round_focused"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/button_round_focused"
        android:visibility="invisible" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent" >

        <!-- Favorite button -->

        <ImageView
            android:id="@+id/btnFav"
            style="@style/MediaDetailsStarButton"
            android:contentDescription="@string/star" />

        <!-- Share button -->

        <ImageView
            android:id="@+id/btnShare"
            style="@style/MediaDetailsShareButton"
            android:contentDescription="@string/share" />

        <!-- Rate button -->

        <ImageView
            android:id="@+id/btnRate"
            style="@style/MediaDetailsRateButton"
            android:contentDescription="@string/to_rate" />
    </LinearLayout>

</FrameLayout>

重新定义布局后,我编写了必要时将光环移动到正确位置的逻辑。当图标获得焦点时移动它相对容易。我在每个图标上附加了一个OnFocusChangeListener这样的:

icon.setOnFocusChangeListener(new View.OnFocusChangeListener() {

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus) {
            btnRoundFocused.setX(center(v));
            btnRoundFocused.setVisibility(View.VISIBLE);
        } else {
            btnRoundFocused.setVisibility(View.INVISIBLE);
        }
    }
});

该方法center()计算 的右 X 坐标btnRoundFocused,因此图标和背景都居中。

private float center(View v) {
    int middle = btnRoundFocused.getWidth() / 2;
    return v.getX() + (v.getWidth() / 2) - middle;
}

然后,当单击图标时,我也做了同样的事情。这更困难。我必须做的是:当一个图标被点击时,显示背景一段时间然后隐藏它。

private void withButtonPressed(View v, IButtonAction action) {
    buttonPressed(v);
    action.execute(v);
    buttonUnpressed(v);
}

protected void buttonPressed(View v) {
    btnRoundFocused.setX(center(v));
    btnRoundFocused.setVisibility(View.VISIBLE);
    v.setActivated(true);
}

protected void buttonUnpressed(final View v) {
    new Handler().post(new Runnable() {

        private final int ELLAPSE_TIME = 250;

        @Override
        public void run() {
            try {
                Thread.sleep(ELLAPSE_TIME);
                v.setActivated(false);
                btnRoundFocused.setVisibility(View.INVISIBLE);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
}

interface IButtonAction {
    void execute(View v);
}

我定义了一个withButtonPressed()接收IButtonAction. IButtonAction实现了对应图标(星号、分享、评分)的业务逻辑。withButtonPressed() 将背景设置在正确的位置,显示背景一段时间(250 毫秒),然后再次隐藏。

最后,我还必须在图标的可绘制对象中添加一个新状态,激活状态(例如,*icon_share.xml*)。图标是一个 XML,根据其状态具有多个可绘制对象(当它被聚焦或单击时为黑色图标,在正常状态下为灰色图标)。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- Activated -->
    <item android:drawable="@drawable/ico_share_focused"
        android:state_activated="true"/>

    <!-- Focused -->
    <item android:drawable="@drawable/ico_share_focused" 
        android:state_focused="true"/>

    <!-- Normal -->
    <item android:drawable="@drawable/ico_share"/>

</selector>

就是这样。我不知道是否有更好的方法来解决这个问题,但至少这有效。希望对其他面临类似问题的人有所帮助。

于 2013-07-30T21:34:50.163 回答