Ich stimme mit den Kommentaren zu Ihrer Frage: programmatischer Schatten-Effekt eine schlechte Wahl ist, und man konnte den gleichen Effekt mit einem einfachen 9patch (oder einem Satz von ihnen) wie angegeben here erreichen.
BTW Ich war zu neugierig, und ich endete mit einer Lösung nach der Arbeit zu hacken.
Der vorgestellte Code ist ein Test und sollte als einfacher Proof-of-Concept (also bitte nicht nach unten) gedacht sein. Einige der gezeigten Operationen sind ziemlich teuer, und können ernsthaft Auswirkungen auf die Leistungen (Es gibt viele Beispiele herum, schauen here, here, um eine Idee zu bekommen). Es sollte eine letzte Lösung nur für eine Komponente sein, die einmal gezeigt wird.
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);
}
}
Zunächst einmal, um Sie programmatische Schlagschatten zu bekommen haben mit Paint.setShadowLayer(...)
wie angegeben here beschäftigen. Grundsätzlich sollten Sie eine Schattenschicht für das Objekt Paint
definieren, das zum Zeichnen auf die Canvas
Ihrer benutzerdefinierten Ansicht verwendet wird. Leider können Sie kein Paint
Objekt verwenden, um ein NinePatchDrawable zu zeichnen, also müssen Sie es in eine Bitmap konvertieren (1. Hack).Außerdem scheint es so, als könnten Schatten-Layer mit ARGB_8888-Bildern nicht richtig funktionieren. Daher habe ich die einzige Möglichkeit, einen richtigen Schatten zu erhalten, darin gesehen, die Alpha-Maske des angegebenen NinePatchDrawable (2. Hack) direkt unter sich zu zeichnen.
Hier ein paar sshots (getestet auf Android [email protected] und [email protected])
Edit: nur gründlich zu sein, angebracht ich die 9patch im Test verwendeten (platziert in res/drawable/mdpi
)
Ich glaube, Sie ein schwarzes rect die Größe Ihrer Ansicht hat ziehen könnte, und dann auf es Ihrer Ansicht nach zeichnen aber ein wenig nach unten übersetzt und Recht (oder unten und links, was immer du willst). –
Könnten Sie bitte erläutern, wie man das machen könnte? – JackMahoney
'Hier ist ein Beispiel. Ich kann auch kein 9-Patch verwenden. Warum nicht? Es ist der beste und einfachste Ansatz. – JanithaR