Изменить фоновое изображение, но сохранить возможность рисования для просмотра Android xml

#android #imageview #android-drawable #android-bitmap #android-framelayout

#Android #imageview #android-drawable #android-растровое изображение #android-framelayout

Вопрос:

У меня есть Framelayout, у которого есть несколько закругленных углов в XML-файле, который можно рисовать

 <?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>
 

Внутри FrameLayout у меня есть 2 TextViews и ImageView, которые программно загружаются с растровым изображением. Проблема в том, что я перепробовал все, чтобы придать ImageView те же закругленные углы, что и FrameLayout, поэтому я решил заменить ImageView другим простым представлением (как FrameLayout или что-то в этом роде) и установить растровое изображение в качестве фона представления. Это тоже не сработало.

Итак, есть ли какой-либо способ в представлении установить возможность рисования с помощью углов в xml, а позже программно изменить фон с помощью растрового изображения, чтобы каким-то образом сохранить закругленные углы при загрузке нового изображения? Спасибо

Ответ №1:

Решение

Шаг 1. Перейдите в res/values папку, создайте XML-файл с именем 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>
 

Шаг 2. Создайте класс, который расширяется из AppCompatImageView, с именем 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);
    }
}
 

Шаг 3. Используйте его из файла макета.

 <?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>
 

Результат

введите описание изображения здесь

Выгода

  • Вы можете установить радиус угла для верхнего левого, верхнего правого, нижнего правого, нижнего левого.
  • Работа с библиотекой Glide, Picasso

Ограничения

  • Тип масштаба либо CENTER_CROP, либо FIT_XY

Комментарии:

1. Это очень хорошее решение. Но есть ли способ избежать Java и сделать это только с помощью xml?? Я имею в виду… whatsapp и другие делают это, расширяя Imageview?

2. @james04 Я не думаю, что стандартный Android ImageView поддерживает эту функцию, поэтому в Github есть много библиотек, где разработчики должны расширять ImageView, чтобы настраивать их внешний вид и поведение.

3. Не могли бы вы помочь мне сделать то же самое в видеообзоре? Спасибо!!

4. @james04 В Stackoverflow один вопрос относится к одной проблеме, поэтому я думаю, вы можете создать новый вопрос о VideoView, потому что ответ может отличаться при использовании VideoView. Кстати, рад вам помочь.

Ответ №2:

Вы можете использовать библиотеки для достижения этой цели легко. Но есть и другой способ сделать. Вы можете использовать свое изображение в CardView. Когда вы устанавливаете функцию cardCornerRadius, углы изображения, которые накладываются на углы cardview, также будут закруглены.

Или попробуйте это

     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);
 

Комментарии:

1. Проблема в том, что я не хочу, чтобы каждый угол был круглым. Например, только вверху справа и внизу слева.!