Я согласен с замечаниями по вашему вопросу: программный DropShadow эффект плохой выбор, и вы могли бы добиться того же эффекта с помощью простого 9patch (или набор из них), как заявил here.
BTW Мне было слишком любопытно, и я закончил с взломом решения после работы.
Представленный код является тестом и должен быть предназначен как простая доказательная концепция (так что, пожалуйста, не делайте снизу). Некоторые из приведенных операций: довольно дорогие, и может серьезно повлиять на характеристики (Существует много примеров, посмотрите 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 (1-й взлом).Кроме того, кажется, что теневые слои не могут нормально работать с изображениями ARGB_8888, поэтому единственным способом, который я нашел для того, чтобы получить правильную тень, было рисование альфа-маски данного NinePatchDrawable (2-го взлома) чуть ниже самого себя.
Вот несколько sshots (проверено на Android [email protected] и [email protected])
Edit: просто быть тщательным, я прикрепил 9patch, используемый в тесте (помещенных в res/drawable/mdpi
)
Я думаю, вы могли бы нарисовать черный прямоугольник, который имеет размер вашей точки зрения, а затем поверх него обратить ваше мнение, но перевел немного на вниз и вправо (или вниз и влево, независимо от того, что вы хотите). –
Не могли бы вы рассказать, как можно это сделать? – JackMahoney
'Вот пример. Я не могу использовать 9-патч либо Почему бы и нет? Это лучший и простой подход. – JanithaR