扩展Android View类以添加阴影
我想扩展LinearLayout
,以便在绘制布局时在其下面添加阴影。我玩过覆盖onDraw
的方法,但我有点失落。任何帮助,甚至图书馆的建议,将不胜感激!扩展Android View类以添加阴影
下面是我试图实现的投影视图示例。我不相信我可以在这里使用九个补丁,因为我需要视图的内容在白框内。这意味着我需要知道边界与PNG结束之间的距离。但是我相信不同的屏幕密度意味着这个距离将永远是相同的PX但不是相同的DP。
所以很清楚,我需要一种扩展View类的方法,以便在添加到布局时在其下绘制阴影。请不要XML或9Patch解决方案。
感谢
杰克
我同意你的问题的意见:方案阴影效果的影响是一个不错的选择,你可以实现一个简单的9patch(或一组人)相同的效果就像说here。
顺便说一句,我太好奇了,下班后我就结束了黑客解决方案。
给出的代码是一个测试,并应旨在作为一个简单证明了概念(所以请不要downvote)。有些所示的操作是相当昂贵,并可能在表演严重影响(有很多例子身边,看here,here得到一个想法)。它应该是最后的手段解决方案只适用于一次显示的组件。
public class BalloonView extends TextView {
protected NinePatchDrawable bg;
protected Paint paint;
protected Rect padding = new Rect();
protected Bitmap bmp;
public BalloonView(Context context) {
super(context);
init();
}
public BalloonView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public BalloonView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
@SuppressLint("NewApi")
protected void init() {
// decode the 9patch drawable
bg = (NinePatchDrawable) getResources().getDrawable(R.drawable.balloon);
// get paddings from the 9patch and apply them to the View
bg.getPadding(padding);
setPadding(padding.left, padding.top, padding.right, padding.bottom);
// prepare the Paint to use below
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.rgb(255,255,255));
paint.setStyle(Style.FILL);
// this check is needed in order to get this code
// working if target SDK>=11
if(Build.VERSION.SDK_INT >= 11)
setLayerType(View.LAYER_TYPE_SOFTWARE, paint);
// set the shadowLayer
paint.setShadowLayer(
padding.left * .2f, // radius
0f, // blurX
padding.left * .1f, // blurY
Color.argb(128, 0, 0, 0) // shadow color
);
}
@Override
protected void onDraw(Canvas canvas) {
int w = getMeasuredWidth();
int h = getMeasuredHeight();
// set 9patch bounds according to view measurement
// NOTE: if not set, the drawable will not be drawn
bg.setBounds(0, 0, w, h);
// this code looks expensive: let's do once
if(bmp == null) {
// it seems like shadowLayer doesn't take into account
// alpha channel in ARGB_8888 sources...
bmp = Bitmap.createBitmap(w, h, Config.ARGB_8888);
// draw the given 9patch on the brand new bitmap
Canvas tmp = new Canvas(bmp);
bg.draw(tmp);
// extract only the alpha channel
bmp = bmp.extractAlpha();
}
// this "alpha mask" has the same shape of the starting 9patch,
// but filled in white and **with the dropshadow**!!!!
canvas.drawBitmap(bmp, 0, 0, paint);
// let's paint the 9patch over...
bg.draw(canvas);
super.onDraw(canvas);
}
}
首先,为了得到纲领性阴影,你必须处理Paint.setShadowLayer(...)
喜欢说here。基本上你应该定义一个阴影层对于Paint
对象用于绘制您的自定义视图的Canvas
。不幸的是,你不能使用Paint
对象来绘制一个NinePatchDrawable,所以你需要将它转换成一个Bitmap(1st hack)。此外,看起来阴影图层无法在ARGB_8888图像中正常工作,所以为了获得适当的阴影,我发现的唯一方法是绘制给定的NinePatchDrawable(第2个黑客)的alpha蒙版,它位于其下方。
这里有一对夫妇sshots的(在Android [email protected]和[email protected]测试)
编辑:只是要彻底,我连着在测试中使用的9patch (放置在res/drawable/mdpi
)
感谢您的回答我会尝试一下。但我不同意9Patch。 9Patch的非伸缩区域对于每个屏幕密度都不会缩放,因此它们在高密度屏幕上会显得更小 - 因此,阴影区域会更小,我不知道在哪里放置容器的儿童填充物 – JackMahoney 2013-02-21 00:58:50
@JackMahoney对不起但你错了。只要看看上面的截图:有2个不同的**真实设备**:320x480 | mdpi,720x1280 | xhdpi。在这两种情况下使用相同的9patch。您可以在每个sshot中以像素为单位来测量气球的圆角,并且您会注意到在xhdpi上的宽度比在mdpi上宽2倍。还有填充物(在9patch中定义)相应地放大。 – 2013-02-21 10:33:32
@ a.bertucci你能为我添加一个示例项目吗? – linker 2013-08-27 17:45:10
尝试这种技术。
container_dropshadow.xml
`
<!-- Drop Shadow Stack -->
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#00CCCCCC" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#10CCCCCC" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#20CCCCCC" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#30CCCCCC" />
</shape>
</item>
<item>
<shape>
<padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
<solid android:color="#50CCCCCC" />
</shape>
</item>
<!-- Background -->
<item>
<shape>
<solid android:color="@color/white" />
<corners android:radius="3dp" />
</shape>
</item>
然后,你可以把它应用到一个XML布局像
的LinearLayout的android背景:背景=“@ drawable/container_dropshadow“
`
嗯,这看起来有点烦躁。你能解释一下这背后的想法吗?看起来你刚刚堆叠了一系列相互重叠的盒子。这不会创建渐变。 – JackMahoney 2013-02-19 04:07:38
我觉得问题是你的一面,迈克尔还提出了一个逻辑。但你告诉了请详细说明。我也提出了一个建议方式。但你告诉同样的事情请解释。首先你在谷歌搜索。很多东西在那里。如果你找不到确切的解决方案,那么来堆栈溢出,然后提出你的问题。我们无法发送完整的代码片段来完成您的工作。感谢您的理解。所有最好的:) – AndroidEnthusiastic 2013-02-19 06:16:05
答案是错误的。每个项目的填充是相同的,所以它创建一个纯色而不是一个渐变 – JackMahoney 2013-02-20 09:19:25
这是丢弃阴影的任何东西,或者布局,按钮等 background.xml的最简单的方法
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item >
<shape
android:shape="rectangle">
<solid android:color="@android:color/darker_gray" />
<corners android:radius="5dp"/>
</shape>
</item>
<item android:right="1dp" android:left="1dp" android:bottom="2dp">
<shape
android:shape="rectangle">
<solid android:color="@android:color/white"/>
<corners android:radius="5dp"/>
</shape>
</item>
</layer-list>
在main.xml中
<LineaLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/background"
/>
喜欢这个解决方案!对
这也不创建一个渐变,只有一个纯色。 – 2016-04-22 15:27:49
我想你可以绘制一个黑色矩形具有视图的大小,然后在它上面画出你的看法,但翻译一点点的向下和向右(或者向下和向左,不管你想要什么)。 – 2013-02-18 07:10:10
请你详细说明一下如何做到这一点? – JackMahoney 2013-02-19 04:07:58
'这是一个例子。我无法使用9贴片“ 为什么不能?这是最好和最简单的方法。 – JanithaR 2013-02-20 04:34:27