我尝试通过在按钮背景和按钮图标上放置一个半透明的PNG文件来实现悬停效果(按下按钮时的效果)。不幸的是,按钮背景文件是一个9-PATCH-PNG,这会引起一些麻烦:它“吞下”其顶层的所有东西,并且不允许覆盖九个补丁png的可伸展区域(细线周围) 。 换句话说,9 PATCH PNG的上边缘和左边缘的黑线不仅会导致拉伸,还会导致填充行为。
删除9-Patch-Information不是一个好的解决方案。
在这里你可以看到我的按钮。蓝色背景是9 PATCH PNG。按钮周围的细线是不需要的。
此图层列表分配给按钮属性“background”:
<?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”无效。你们有什么建议吗?
更新
我试过跟随,{strong 3}}建议避免缩放。但是也没有用:
<!-- 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
这对我有用吗? here
答案 0 :(得分:4)
[没关系] LayerDrawable.getPadding的内部注释声称它从列表中的第一个drawable获取填充。如果这个评论说实话,你可以通过在列表中的9补丁之前放置一个任意(可能是空的)图像来获得你想要的行为。
然而,快速阅读代码意味着它实际上使用了所有项目填充的 sum ,这意味着没有办法消除你的问题使用默认的LayerDrawable < / strong>即可。该语句暗示了解决方案:实现LayerDrawable的子类,它覆盖“getPadding”以返回{0,0,0,0}。您可能必须在代码中初始化子类,而不是通过加载XML布局,但这并不是特别困难。 [/没关系]
更新: 上面的解决方案不起作用,因为问题不在于填充本身,而是默认实现将每个图像的 bounds 设置为前面图像的填充之和。换句话说,它强制执行嵌套,这是大多数人想要的。正确的解决方案仍然是覆盖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);
}
}
}
使用以下layout / 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>
示例屏幕截图如下:
更新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”通知栏以查看窗口处于未聚焦状态。)
答案 1 :(得分:2)
我工作得很好:
RES /布局/ main.xml中
...
<ImageButton
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:src="@drawable/button"
/>
...
RES /抽拉/ 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。番茄是一种具有透明度的基本品。
结果如下:
去除番茄周围的透明部分(填充粉红色):
编辑2: 这将使番茄完全覆盖补丁-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作为背景,使用“content”作为按钮的src。在这种情况下,您需要为该src
设置填充为0答案 2 :(得分:2)
我通过操纵九个补丁获得了完整的叠加效果。不要将底部和右侧(内容)留空,而是尝试用黑色像素完全填充它们。
答案 3 :(得分:1)
我认为这个问题有两种解决方案。
解决方案1:
当您说“悬停效果”时,您的意思是按下按钮时?如果是这种情况,那么您想要使用的是selector a.k.a. state list用于按钮背景,其中所选状态与您的正常图像不同:
<?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 Graphics Doc。这将保留图像的当前拉伸行为,但删除图像固有的任何填充。然后,您可以根据需要在内部视图中添加或删除填充,以获得所需的显示。