Android как рисовать круглые прямоугольники и тени

Я делаю класс extends LinearLayout, я хочу показать Rect следующим образом:

--------------------- => it is round corner | border frame | . | ----------------- | . | | hearder | | . | | - - - - - - - | | . | | center | | . | | | | . | | - - - - - - - | | . | | buttom | | . | ---------------- | . | | . ---------------------- . . . . . . . . . . . . => it is shadow 

И я использовал paintShadow.setShadowLayer (this.radius, 8, 8, Color.GRAY); Тень не круглая.

Поэтому кто знает, как сделать круглый прямоугольник и тень. код:

 @SuppressLint("DrawAllocation") public class CornerLinearLayout extends LinearLayout{ public CornerLinearLayout(Context context,AttributeSet attr){ super(context,attr); init(); } public CornerLinearLayout(Context context) { super(context); init(); // TODO Auto-generated constructor stub } private static final int RADIUS=10; private int frameColor; private int radius; private Path mClip; private int frameWidth; private int headerHeight; private int buttomHeight; private int headerColor; private int buttomColor; private int centerColor; private void init() { this.radius = RADIUS; this.frameColor = 0xFFFFFFFF; this.frameWidth = 4; this.headerHeight = 50; this.buttomHeight = 50; headerColor = 0xFF31234A; buttomColor = 0xFF9ACFFF; centerColor = 0xFF55AACC; this.setBackgroundColor(0); // GradientDrawable gd = new GradientDrawable(); // gd.setStroke(frameWidth, frameColor); // gd.setCornerRadius(radius); // gd.setColor(0); // //gd.setStroke(30, 0xFFFFFFFF); // // setBackgroundDrawable(gd); this.setPadding(frameWidth, frameWidth, frameWidth,frameWidth); // LinearLayout.LayoutParams params = (LayoutParams) this.getLayoutParams(); // params.setMargins(25, 10, 25, 10); } private Paint paintShadow = new Paint(); private Paint paint = new Paint(); public void onDraw(Canvas canvas){ super.onDraw(canvas); RectF rf = new RectF(0,0,this.getWidth()-10,this.getHeight()-5); paintShadow.setShadowLayer(this.radius, 8, 8, Color.GRAY); rf.right -= 3; rf.bottom -= 3; paintShadow.setColor(this.frameColor); paintShadow.setStrokeWidth(5); canvas.drawRoundRect(rf,this.radius,this.radius, paintShadow); paint.setStyle(Paint.Style.FILL); // Rect r = new Rect(5,5,this.getWidth()-5,this.getHeight()-5); if(this.centerColor != 0){ paint.setColor(this.centerColor); // canvas.drawRect(r, paint); rf.right -= 5; rf.left += 5; rf.top += 5; rf.bottom -=5; canvas.drawRoundRect(rf, this.radius, this.radius, paint); } // if(this.headerColor!=0){ // Rect rr = new Rect(10,10,this.getWidth()-5,this.headerHeight-10); // paint.setColor(this.headerColor); // canvas.drawRect(rr, paint); // } // if(this.buttomColor != 0){ // Rect rr = new Rect(10,this.getHeight()-this.buttomHeight,this.getWidth()-3,this.buttomHeight-3); // paint.setColor(this.headerColor); // canvas.drawRect(rr, paint); // } // } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mClip = new Path(); RectF rect = new RectF(0, 0, w, h); mClip.addRoundRect(rect, this.radius, this.radius, Direction.CW); } @Override protected void dispatchDraw(Canvas canvas) { canvas.save(); canvas.clipPath(mClip); super.dispatchDraw(canvas); canvas.restore(); } } 

Я готов поспорить, что ваша проблема заключается в использовании clipPath (). Попробуйте отключить аппаратное ускорение в представлении, и я думаю, вы обнаружите, что он работает так, как ожидалось.

В вашем методе init ():

 setLayerType(LAYER_TYPE_SOFTWARE, null); 

Полезные ссылки:

  • Должен ли я отображать закругленные углы в Android?
  • Аппаратное ускорение – неподдерживаемые методы
  • Метод Canvas clipPath () не работает как ожидается

Используйте графические элементы с девятью патчами . Это сэкономит вам много кода. Ознакомьтесь с некоторыми учебниками для девяти патчей.

Кроме того, посмотрите в своей <SDK folder>/platforms/<android-xx>/data/res , платформы разработки поставляются с множеством готовых графических файлов с девятью патчами по умолчанию, вы можете скопировать их в свое приложение.

Пример кода:

  @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //-- draw with white color-- Paint p = new Paint(); p.setColor(Color.WHITE); //-- set shadow, 5dp down, 5 dp left, with radius of 15 dp-- p.setShadowLayer(10,5,5,Color.BLACK); //-- warning, Honeycomb and above only //-- this will reduce draw performance of view //-- but is required to support drawing filters, like shadow, blur etc setLayerType(LAYER_TYPE_SOFTWARE,p); //--basic shapes don't have round corners yet, so use path-- Path pt = new Path(); //-- round rectangle path with 15dp padding (space for shadow) //-- and 10 dp corner radius pt.addRoundRect(new RectF(15,15,getWidth() - 15 ,getHeight() -15 ), 10,10, Path.Direction.CW); //--draw-- canvas.drawPath(pt,p); } 

Вместо использования setShadowlayer, непосредственно нарисуйте округлый прямоугольник с альфой в цветовом значении, например color = 0x66000000. Для простой черной тени.

Вы можете отрегулировать его, изменив параметр rect а затем приспособив другой рисунок к нему, иначе он будет перезаписан

Есть хороший учебник по этому вопросу, сделанный Роменом Гаем, здесь .

Единственный недостаток, который я нашел, заключается в том, что вам нужно подготовить растровое изображение к тому размеру, который вы хотите использовать, иначе он будет мазать.