james04
james04

Reputation: 1920

Change background image but keep drawable to a view android xml

I have a Framelayout which has some rounded corners through a drawable xml file

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle" >

    <!-- View background color -->
    <solid
            android:color="@color/colorPrimary" >
    </solid>

    <!-- The radius makes the corners rounded -->
    <corners
        android:topLeftRadius="20dp"
        android:bottomRightRadius="20dp" >
    </corners>
</shape>

Inside the FrameLayout i have 2 TextViews and an imageView which gets loaded with a bitmap programmatically. The problem is that i have tried everything to give the ImageView same rounded corners as the FrameLayout so i decided to replace the ImageView with another simple View (as FrameLayout or smth) and set the bitmap image as a background of the view. This didn't work either.

So is there any way in a view to set the drawable with the corners in the xml, and when later programmatically change the background with a bitmap to keep somehow the rounded corners with the new image loaded? Thank you

Upvotes: 1

Views: 559

Answers (2)

Son Truong
Son Truong

Reputation: 14173

Solution

Step 1. Go to res/values folder, create a xml file named attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="RoundedImageView">
        <attr name="topLeftCorner" format="dimension" />
        <attr name="topRightCorner" format="dimension" />
        <attr name="bottomRightCorner" format="dimension" />
        <attr name="bottomLeftCorner" format="dimension" />
    </declare-styleable>
</resources>

Step 2. Create a class that extends from AppCompatImageView, named RoundedImageView

public class RoundedImageView extends AppCompatImageView {

    private final Path path = new Path();
    private final float[] radii = new float[8];
    private final RectF rect = new RectF();

    public RoundedImageView(@NonNull Context context) {
        this(context, null);
    }

    public RoundedImageView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundedImageView);
        try {
            int topLeftCorner = a.getDimensionPixelSize(R.styleable.RoundedImageView_topLeftCorner, 0);
            int topRightCorner = a.getDimensionPixelSize(R.styleable.RoundedImageView_topRightCorner, 0);
            int bottomRightCorner = a.getDimensionPixelSize(R.styleable.RoundedImageView_bottomRightCorner, 0);
            int bottomLeftCorner = a.getDimensionPixelSize(R.styleable.RoundedImageView_bottomLeftCorner, 0);
            radii[0] = topLeftCorner;
            radii[1] = topLeftCorner;
            radii[2] = topRightCorner;
            radii[3] = topRightCorner;
            radii[4] = bottomRightCorner;
            radii[5] = bottomRightCorner;
            radii[6] = bottomLeftCorner;
            radii[7] = bottomLeftCorner;
        } finally {
            a.recycle();
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        rect.left = 0;
        rect.top = 0;
        rect.right = getWidth();
        rect.bottom = getHeight();
        path.rewind();
        path.addRoundRect(rect, radii, Path.Direction.CW);
        canvas.clipPath(path);
        super.onDraw(canvas);
    }
}

Step 3. Use it from layout file.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#F00"
    android:gravity="center">

    <com.example.roundedimageview.RoundedImageView
        android:id="@+id/imageView"
        android:layout_width="240dp"
        android:layout_height="240dp"
        android:layout_gravity="center"
        android:scaleType="centerCrop"
        android:src="@drawable/ic_android"
        app:bottomRightCorner="20dp"
        app:topLeftCorner="20dp" />
</FrameLayout>

Result

enter image description here

Benefit

  • You can set the corner radius for top-left, top-right, bottom-right, bottom-left.

  • Work with Glide, Picasso library

Limitations

Upvotes: 1

S.Grain
S.Grain

Reputation: 182

You can use libraries to achieve it easily. But there is an other way to do. You can use your image within CardView. When you set cardCornerRadius feature the image corners which overlaying the cardview's corners will be rounded too.

Or try this

    ImageView yourImageView = findViewById(R.id.yourImageView);

    Bitmap bitmap =((BitmapDrawable) ResourcesCompat.getDrawable(R.drawable.anyPicture)).getBitmap();
    Bitmap roundedImageBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
    Canvas canvas=new Canvas(roundedImageBitmap);
    Paint paint = new Paint();
    paint.setAntiAlias(true);
    paint.setShader(new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
    canvas.drawRoundRect((new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight())), 100, 100, paint); // You can adjust the roundness here

    yourimageView.setImageBitmap(roundedImageBitmap);

Upvotes: 0

Related Questions