Raster Repeat + Rounded Corners

I am trying to create a rounded rectangle and background like repeating bitmaps. I write this way, but I get bitmap images in the corners.

Can anyone help?

background.xml

<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item> <shape> <stroke android:width="1dp" android:color="#FFFFFF" /> <corners android:radius="50dp" /> </shape> </item> <item> <bitmap android:src="@drawable/carbon_4" android:tileMode="repeat" /> </item> </layer-list> 
+6
source share
2 answers

As I understand it, the goal is to have a lined background image with some curved corners. tiled and curved

This is not a perfect pixel, but as close as possible.

first, here are some layouts that I use to draw this button

the_button.xml

 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/wrapper_main" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:background="@drawable/bg_curved_tiled" android:padding="20dp" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="Some Text" /> </FrameLayout> 

and this is used as background

bg_curved_tiled.xml

 <layer-list xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@id/layer_needs_rounding"> <bitmap android:src="@drawable/patch" android:tileMode="repeat" /> </item> <item> <shape android:shape="rectangle" android:useLevel="false" > <stroke android:width="3dp" android:color="#666666" /> <solid android:color="@null" /> <corners android:bottomLeftRadius="@dimen/radius_corner_default" android:bottomRightRadius="@dimen/radius_corner_default" android:radius="@dimen/radius_corner_default" android:topLeftRadius="@dimen/radius_corner_default" android:topRightRadius="@dimen/radius_corner_default" /> </shape> </item> </layer-list> 

At this point you have an image similar to this

enter image description here

As you can see, the tiled raster map sticks out at the corners past a curved shape superimposed on top of it.

So now you need a function that rounds the corners of the bitmap ... I got this elsewhere in stackoverflow

  public static Bitmap createRoundedCornerBitmap(Context context, Bitmap input, float roundPx, boolean squareTL, boolean squareTR, boolean squareBR, boolean squareBL) { if (input == null) { return null; } final int w = input.getWidth(), h = input.getHeight(); Bitmap output = Bitmap.createBitmap(w, h, Config.ARGB_8888); Canvas canvas = new Canvas(output); final int color = 0xff424242; final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, w, h); final RectF rectF = new RectF(rect); paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawRoundRect(rectF, roundPx, roundPx, paint); // draw rectangles over the corners we want to be square if (squareTL) { canvas.drawRect(0, 0, w / 2, h / 2, paint); } if (squareTR) { canvas.drawRect(w / 2, 0, w, h / 2, paint); } if (squareBL) { canvas.drawRect(0, h / 2, w / 2, h, paint); } if (squareBR) { canvas.drawRect(w / 2, h / 2, w, h, paint); } paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(input, 0, 0, paint); return output; } 

Almost there! I hate this part - I have not found a better way to get a Bitmap object that has the actual broken bitmap in it. For example, BitmapDrawable.getBitmap just gives you an individual patch raster image, rather than a tiled re-patch canvas ... bummer. So instead I get a drawing file cache. You have to make sure that the view was fully initialized first (the height and width were defined and aligned accordingly), so the post also processed for viewing.

 private void shaveOffCorners(final ViewGroup view) { view.post(new Runnable() { @Override public void run() { // make all child views invisible before scraping the drawing cache SparseIntArray viewStates = new SparseIntArray(); for(int index = 0; index < view.getChildCount(); ++index) { View child = view.getChildAt(index); viewStates.put(index, child.getVisibility()); child.setVisibility(View.INVISIBLE); } view.buildDrawingCache(); // this is the exact bitmap that is currently rendered to screen. hence, we wanted to // hide all the children so that they don't permanently become part of the background final Bitmap rounded = view.getDrawingCache(); // restore actual visibility states after getting the drawing cache for(int index = 0; index < view.getChildCount(); ++index) { View child = view.getChildAt(index); child.setVisibility(viewStates.get(index)); } view.setBackgroundDrawable(new BitmapDrawable( getResources(), MyImageUtil.createRoundedCornerBitmap( view.getContext(), rounded, getResources().getDimensionPixelSize(R.dimen.radius_corner_default), false, true, true, false))); } }); } 

And as I did, I hope this helps!

If someone knows a less terrible way to accomplish this, please share. Also, if anyone knows how to get a tiled bitmap that is different from clearing the drawing cache, that would also be useful - all hiding and restoring child views is a little flabby.

+2
source

I found this post by Romanin Guy, which makes it much easier to combine the corners in a tiled raster image. Here is a short answer:

 class CurvedAndTiled extends Drawable { private final float mCornerRadius; private final RectF mRect = new RectF(); private final BitmapShader mBitmapShader; private final Paint mTilePaint; CurvedAndTiled( Bitmap bitmap, float cornerRadius) { mCornerRadius = cornerRadius; mBitmapShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); mTilePaint = new Paint(); mTilePaint.setAntiAlias(true); mTilePaint.setShader(mBitmapShader); } @Override protected void onBoundsChange(Rect bounds) { super.onBoundsChange(bounds); mRect.set(0, 0, bounds.width(), bounds.height()); } @Override public void draw(Canvas canvas) { canvas.drawRoundRect(mRect, mCornerRadius, mCornerRadius, mTilePaint); } @Override public int getOpacity() { return PixelFormat.TRANSLUCENT; } @Override public void setAlpha(int alpha) { mTilePaint.setAlpha(alpha); } @Override public void setColorFilter(ColorFilter cf) { mTilePaint.setColorFilter(cf); } } 

You just set your background for viewing as one of these guys and you will be fine.

+5
source

Source: https://habr.com/ru/post/926676/


All Articles