私はあなたの質問に対するコメントに同意します:プログラムによるドロップシャドウ効果は悪い選択であり、ここで述べたような単純な9パッチ(またはそれらのセット)で同じ効果を達成することができます。
ところで、私はあまりにも興味があり、仕事の後に解決策をハッキングすることで終わりました。
提示されたコードはテストであり、単純な概念実証として意図されている必要があります(したがって、反対票を投じないでください)。示されている操作の一部は非常に高価であり、パフォーマンスに深刻な影響を与える可能性があります(周りには多くの例があります。ここを参照してください。アイデアを得るにはここを参照してください)。これは、たまに表示されるコンポーネントの最後の手段となるはずです。
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(...)
で説明するように対処する必要があります。基本的に、カスタムビューの描画に使用されるオブジェクトのシャドウレイヤーを定義する必要があります。残念ながら、オブジェクトを使用してNinePatchDrawableを描画することはできないため、オブジェクトをビットマップに変換する必要があります(最初のハック)。さらに、シャドウレイヤーはARGB_8888画像では正しく機能しないようです。したがって、適切なシャドウを取得するために私が見つけた唯一の方法は、指定されたNinePatchDrawable(2番目のハック)のアルファマスクをそのすぐ下に描画することでした。Paint
Canvas
Paint
これがいくつかのショットです(Android 2.3.3@mdpiおよび4.2.2@xhdpiでテスト済み)
編集:念のため、テストで使用した9パッチを添付しました(に配置res/drawable/mdpi
)