6

我尝试通过在按钮背景和按钮图标顶部放置一个半透明的 PNG 文件来实现悬停效果(按下按钮时的效果)。不幸的是,按钮背景文件是一个 9-PATCH-PNG,这在这里造成了一些麻烦:它“吞噬”了其图层顶部的所有内容,并且不允许覆盖 9-patch-png 的可拉伸区域(周围的细光线) . 换句话说,9 PATCH PNG 的顶部和左侧边缘的黑线不仅会导致拉伸,还会导致填充行为。

删除 9-Patch-Information 不是一个好的解决方案。

在这里你可以看到我的按钮。蓝色背景是 9 PATCH PNG。按钮周围的细线是不需要的。

替代文字

此图层列表分配给按钮属性“背景”:

<?xml version="1.0" encoding="utf-8"?>
<layer-list
  xmlns:android="http://schemas.android.com/apk/res/android">
  <item
    android:drawable="@drawable/home_btn_bg_blue_without_padding" />
  <item>
    <bitmap
      android:src="@drawable/home_icon_test"
      android:gravity="center" />
  </item>
  <item
    android:drawable="@drawable/layer_black_50" />
</layer-list>

在每个边框上将图层的偏移量设置为“-1”是无效的。你们有什么建议吗?

更新

我尝试了以下建议,这将避免缩放,从这里建议。但也没有用:

<!-- To avoid scaling, the following example uses a <bitmap> element with centered gravity: -->
<item>
  <bitmap android:src="@drawable/image"
          android:gravity="center" />
</item>

我的版本(仍然有 9-patch-png 的可拉伸区域未被发现):

替代文字

<?xml version="1.0" encoding="utf-8"?>
<layer-list
  xmlns:android="http://schemas.android.com/apk/res/android">
  <item
    android:drawable="@drawable/home_btn_bg_blue_hover_without_padding" />
  <item>
    <bitmap
      android:src="@drawable/home_icon_test"
      android:gravity="center" />
  </item>
  <item>
    <bitmap android:src="@drawable/layer_black_100"
          android:height="100dp"
          android:width="100dp"/></item>
</layer-list>

更新 2

这对我有用吗?在Android中使覆盖的图像在触摸时透明?

4

4 回答 4

4

[NeverMind] LayerDrawable.getPadding 的内部注释声称它从列表中的第一个可绘制对象中获取填充。如果此评论说的是真的,您可以通过在列表中的 9 补丁之前放置任意(可能是空的)图像来获得您想要的行为。

然而,快速阅读代码意味着它实际上使用了所有项目填充的总和,这意味着使用默认的 LayerDrawable无法消除您的问题。该语句暗示了解决方案:实现 LayerDrawable 的子类,它覆盖“getPadding”以返回 {0,0,0,0}。您可能必须在代码中初始化您的子类,而不是通过加载 XML 布局,但这并不是特别困难。[/没关系]

更新:上面的解决方案不起作用,因为问题不在于填充本身,而是默认实现将每个图像的边界设置为前面图像的填充之和。换句话说,它强制嵌套,这是大多数人想要的。正确的解决方案仍然是覆盖 LayerDrawable,但您改为替换“onBoundsChange”。一个完整的、经过测试的演示如下:

package com.beekeeper.ninepatchcover;

import android.app.Activity;
import android.graphics.*;
import android.graphics.drawable.*;
import android.os.Bundle;
import android.view.Gravity;
import android.widget.ImageButton;

public class NinePatchCover extends Activity {
  private Drawable mCover0;
  private Drawable mCover1;

  /** Called when the activity is first created. */
  @Override public void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    final Drawable button =
      getResources().getDrawable(android.R.drawable.btn_default);
    final Bitmap iconBitmap =
      BitmapFactory.decodeResource(getResources(),
                                   android.R.drawable.ic_menu_mylocation);
    final BitmapDrawable icon = new BitmapDrawable(iconBitmap);
    icon.setGravity(Gravity.CENTER);
    mCover0 =
      getResources().getDrawable(android.R.drawable.title_bar);
    mCover1 =
      getResources().getDrawable(android.R.drawable.title_bar);

    final LayerDrawable unsolved =
      new LayerDrawable(new Drawable[]{button, icon, mCover0});
    final LayerDrawable solved =
      new MyLayerDrawable(new Drawable[]{button, icon, mCover1,}, mCover1);

    ((ImageButton)findViewById(R.id.uncovered)).setBackgroundDrawable(unsolved);
    ((ImageButton)findViewById(R.id.covered)).setBackgroundDrawable(solved);
  }

  class MyLayerDrawable extends LayerDrawable {
    Drawable mCover;

    public MyLayerDrawable(final Drawable[] layers, final Drawable cover) {
      super(layers);
      mCover = cover;
    }

    @Override protected void onBoundsChange(final Rect bounds) {
      super.onBoundsChange(bounds);
      mCover.setBounds(bounds);
    }
  }
}

使用以下布局/main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical" android:layout_width="fill_parent"
 android:layout_height="fill_parent"
>
 <ImageButton android:id="@+id/uncovered"
  android:layout_width="fill_parent" android:layout_height="wrap_content" />
 <ImageButton android:id="@+id/covered"
  android:layout_width="fill_parent" android:layout_height="wrap_content" />
</LinearLayout>

示例屏幕截图如下:

NinePatchCover 屏幕截图

更新 2:

根据要求,您可以在此处修改它以在代码中初始化选择器。将“mCover1”的初始化替换为以下代码:

final StateListDrawable sld = new StateListDrawable();
sld.addState(new int[]{android.R.attr.state_pressed},
                 new ColorDrawable(0xffff0000));
sld.addState(new int[]{android.R.attr.state_window_focused},
                 new ColorDrawable(0xff00ff00));
sld.addState(new int[]{},
                 getResources().getDrawable(android.R.drawable.title_bar));
mCover1 = sld;

这将在窗口聚焦但未按下按钮的正常情况下显示绿色,按下按钮时显示红色,当窗口未聚焦时默认可绘制(灰色)。(尝试向下拖动“windowshade”通知栏以查看处于未聚焦状态的窗口。)

于 2010-10-08T18:35:55.017 回答
2

我让它工作得很好:

资源/布局/main.xml

...
<ImageButton
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:src="@drawable/button"
    />
...

res/drawable/button.xml

<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/frame" /> 
    <item>
        <bitmap
            android:src="@drawable/tomato"
            android:gravity="center"
            />
    </item>
</layer-list>

frame.9.png 是我的九个补丁-png。番茄是一个基本的 png,它周围是透明的。

这是结果:替代文字

去除番茄周围的透明部分(用粉红色填充):替代文字

编辑 2:这将使番茄完全覆盖 patch-9-png :

<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
    <bitmap
        android:src="@drawable/frame"
        />
    </item>
    <item>
    <bitmap
        android:src="@drawable/tomato"
        />
    </item>
</layer-list>

使用 ImageButton 的另一种方法是,您可以使用 patch-9-png 作为背景,使用“内容”作为按钮的 src。在这种情况下,您需要将该 src 的填充设置为 0

于 2010-09-28T06:27:09.993 回答
2

通过操纵九个补丁,我得到了一个完整的覆盖。不要将底部和右侧(内容)留空,而是尝试用黑色像素完全填充它们。

于 2011-02-18T18:47:39.867 回答
1

我认为这个问题有两种解决方案。

解决方案1:

当您说“悬停效果”时,您是指按下按钮时吗?如果是这种情况,那么您想要使用的按钮背景选择器又名状态列表,其中所选状态与您的正常图像不同:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true"
          android:drawable="@android:color/black" /> <!-- pressed -->
    <item android:drawable="@drawable/home_btn_bg_blue_hover_without_padding" /> <!-- default -->
</selector>

然后将按钮背景设置为该状态列表可绘制 XML。

解决方案2:

虽然您尚未发布原始的九个补丁 PNG,但我怀疑您可以删除表示“填充框”的右侧和底部标记,同时保留左侧和顶部标记,表示2D 图形中记录的“可拉伸区域”文档。这将保留图像的当前拉伸行为,但会删除图像固有的任何填充。然后,您可以根据需要向内部视图添加或删除填充以获得所需的显示。

于 2010-10-07T18:26:25.663 回答