Jak zrobić widok z zaokrąglonymi narożnikami?


94

Próbuję zrobić widok na Androidzie z zaokrąglonymi krawędziami. Rozwiązaniem, które znalazłem do tej pory, jest zdefiniowanie kształtu z zaokrąglonymi narożnikami i użycie go jako tła tego widoku.

Oto, co zrobiłem, zdefiniuj rysunek, jak podano poniżej:

<padding
android:top="2dp"
android:bottom="2dp"/>
<corners android:bottomRightRadius="20dp"
android:bottomLeftRadius="20dp"
android:topLeftRadius="20dp"
android:topRightRadius="20dp"/>

Teraz użyłem tego jako tła dla mojego układu, jak poniżej:

<LinearLayout
        android:orientation="vertical"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginBottom="10dp"
        android:clipChildren="true"
        android:background="@drawable/rounded_corner">

Działa to doskonale, widzę, że widok ma zaokrąglone krawędzie.

Ale mój układ ma wiele innych widoków podrzędnych, na przykład ImageView lub MapView. Kiedy umieszczam ImageViewwewnątrz powyższego układu, rogi obrazu nie są przycinane / przycinane, zamiast tego wydaje się, że jest pełny.

Widziałem inne obejścia, aby działało tak, jak to wyjaśniono tutaj .

Ale czy istnieje metoda ustawiania zaokrąglonych rogów widoku, a wszystkie jego widoki podrzędne są zawarte w tym widoku głównym, który ma zaokrąglone rogi?


Co się stanie, jeśli użyjesz układu niestandardowego rozszerzającego się do LinearLayout i podczas tworzenia jego obiektu iterujesz wszystkie elementy podrzędne tego układu i zastosujesz do nich zaokrąglone obramowanie?
MysticMagicϡ

3
android.support.v7.widget.CardView wydaje się być rozwiązaniem tego
problemu

To rozwiązanie rozwiązało to dla mnie, ale wymaga podklasy: /programming/5574212/android-view-clipping
Aaron


Google ma nowy framework, nowe technologie są lepsze [Jetpack Compose] [1] [1]: stackoverflow.com/questions/6054562/ ...
Ucdemir

Odpowiedzi:


128

Innym podejściem jest utworzenie niestandardowej klasy układu, takiej jak ta poniżej. Ten układ najpierw rysuje zawartość do mapy bitowej poza ekranem, maskuje bitmapę poza ekranem zaokrąglonym prostokątem, a następnie rysuje bitmapę poza ekranem na rzeczywistym płótnie.

Wypróbowałem to i wydaje się, że działa (przynajmniej w moim prostym przypadku testowym). Wpłynie to oczywiście na wydajność w porównaniu do zwykłego układu.

package com.example;

import android.content.Context;
import android.graphics.*;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.widget.FrameLayout;

public class RoundedCornerLayout extends FrameLayout {
    private final static float CORNER_RADIUS = 40.0f;

    private Bitmap maskBitmap;
    private Paint paint, maskPaint;
    private float cornerRadius;

    public RoundedCornerLayout(Context context) {
        super(context);
        init(context, null, 0);
    }

    public RoundedCornerLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

    public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs, defStyle);
    }

    private void init(Context context, AttributeSet attrs, int defStyle) {
        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
        cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, metrics);

        paint = new Paint(Paint.ANTI_ALIAS_FLAG);

        maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
        maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

        setWillNotDraw(false);
    }

    @Override
    public void draw(Canvas canvas) {
        Bitmap offscreenBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas offscreenCanvas = new Canvas(offscreenBitmap);

        super.draw(offscreenCanvas);

        if (maskBitmap == null) {
            maskBitmap = createMask(canvas.getWidth(), canvas.getHeight());
        }

        offscreenCanvas.drawBitmap(maskBitmap, 0f, 0f, maskPaint);
        canvas.drawBitmap(offscreenBitmap, 0f, 0f, paint);
    }

    private Bitmap createMask(int width, int height) {
        Bitmap mask = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
        Canvas canvas = new Canvas(mask);

        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.WHITE);

        canvas.drawRect(0, 0, width, height, paint);

        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        canvas.drawRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, paint);

        return mask;
    }
}

Użyj tego jak normalnego układu:

<com.example.RoundedCornerLayout
    android:layout_width="200dp"
    android:layout_height="200dp">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/test"/>

    <View
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="#ff0000"
        />

</com.example.RoundedCornerLayout>

1
Używam tego układu do widoku obrazu z funkcją powiększania wewnątrz, ale ten układ nie może wykryć słuchacza dotykowego, gdy próbuję powiększyć, jak dodać funkcję odbiornika dotykowego w tym układzie?
Muhammad Nafian Wildana

2
Użyłem tej metody i działa dobrze. Ale kiedy umieszczam EditText wewnątrz układu, ekran nie aktualizuje się po wpisaniu. Kiedy zamykam okno, pojawia się tekst. Ekran jest aktualizowany po zamknięciu klawiatury. Jakieś rozwiązanie tego problemu?
Sajib Acharya

1
Jedynym problemem związanym z tym, gdy używasz go z widokiem Recycler, jest to, że nie czeka na załadowanie całego zestawu elementów. Zaokrągla tylko kilka elementów. Czy jest powód, dla którego tak się dzieje?
Ahmed

2
To nie działa z obrazami ładowanymi z biblioteki glide, które używają przejść zastępczych (lub właściwie innych animowanych elementów potomnych). Mam alternatywne rozwiązanie, ale wymaga ono, aby kolor tła był jednolity. Zobacz gist.github.com/grennis/da9f86870c45f3b8ae00912edb72e868
Greg Ennis

2
Dobre i przydatne rozwiązanie, ale za drogie. RecyclerView z zaledwie sześcioma elementami zawierającymi jeden obraz nie może się płynnie przewijać. I to nie zależy od mocy urządzenia (Samsung S9 czy Wileyfox Swift 2). stackoverflow.com/a/41098690/4399323 to lepsza odpowiedź!
Valentin Yuryev

73

Lub możesz użyć android.support.v7.widget.CardViewpodobnego:

<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    card_view:cardBackgroundColor="@color/white"
    card_view:cardCornerRadius="4dp">

    <!--YOUR CONTENT-->
</android.support.v7.widget.CardView>

Próbowałem tak wielu sposobów, Twój jest najlepszym rozwiązaniem mojego problemu. DZIĘKI!
wizChen

Nie można usunąć elewacji. Działa dobrze, jeśli projekt wymaga elewacji.
Abdalrahman Shatou

1
@AbdalrahmanShatou developer.android.com/reference/android/support/v7/widget/ ... są do tego właściwości. Czy próbowałeś ustawić je na „0”?
rocketspacer

5
Jedną wadą jest to, że nie obsługuje <21 Android api
Itai Spector

52

shape.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <solid android:color="#f6eef1" />

    <stroke
        android:width="2dp"
        android:color="#000000" />

    <padding
        android:bottom="5dp"
        android:left="5dp"
        android:right="5dp"
        android:top="5dp" />

    <corners android:radius="5dp" />

</shape>

i wewnątrz ciebie układ

<LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginBottom="10dp"
        android:clipChildren="true"
        android:background="@drawable/shape">

        <ImageView
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:src="@drawable/your image"
             android:background="@drawable/shape">

</LinearLayout>

3
@Zach: W jaki sposób to się nie udało? Tak samo, jak działała Twoja aplikacja, gdy zadałeś oryginalne pytanie?
LarsH,

2
clipChildren jest bezużyteczny, a widok obrazu nadal wykracza poza widok.
Abdalrahman Shatou

1
Chciałabym dać ci za to nagrodę. Dziękuję
Odys

3
Nie sądzę, aby to podejście zadziałało, gdyby obraz był prostokątny, ponieważ tło zostanie narysowane za zawartością obrazu. Może to działać tylko w przypadku obrazów, które mają przezroczystość i same mają zaokrąglone rogi.
Harsha Vardhan

22

Odpowiedź Jaapa van Hengstuma działa świetnie, ale myślę, że jest droga i jeśli zastosujemy tę metodę na przykład do przycisku, efekt dotyku zostanie utracony, ponieważ widok jest renderowany jako mapa bitowa.

Dla mnie najlepsza i najprostsza metoda polega na nałożeniu maski na widok, tak:

@Override
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
    super.onSizeChanged(width, height, oldWidth, oldHeight);

    float cornerRadius = <whatever_you_want>;
    this.path = new Path();
    this.path.addRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, Path.Direction.CW);
}

@Override
protected void dispatchDraw(Canvas canvas) {
    if (this.path != null) {
        canvas.clipPath(this.path);
    }
    super.dispatchDraw(canvas);
}

Jak tego używać?
Maksim Kniazev

@MaksimKniazev Utwórz podklasę układu, który chcesz (na przykład: FrameLayout), a następnie wklej te dwie metody do tej podklasy i zamień „<cokolwiek_you_want>” na żądaną wartość promienia narożnika (na przykład z zasobów). Otóż ​​to. Czy jest to dla Ciebie wystarczająco jasne, czy potrzebujesz przykładu?
Donkey

Dziękuję bardzo, to naprawdę działa lepiej w przypadku RecyclerView!
Valentin Yuryev

18

Jeśli masz problem z dodawaniem detektorów dotykowych do układu. Użyj tego układu jako układu nadrzędnego.

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Region;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import android.widget.FrameLayout;

public class RoundedCornerLayout extends FrameLayout {
    private final static float CORNER_RADIUS = 6.0f;
    private float cornerRadius;

    public RoundedCornerLayout(Context context) {
        super(context);
        init(context, null, 0);
    }

    public RoundedCornerLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

    public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs, defStyle);
    }

    private void init(Context context, AttributeSet attrs, int defStyle) {
        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
        cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, metrics);
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }


    @Override
    protected void dispatchDraw(Canvas canvas) {
        int count = canvas.save();

        final Path path = new Path();
        path.addRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), cornerRadius, cornerRadius, Path.Direction.CW);
        canvas.clipPath(path, Region.Op.REPLACE);

        canvas.clipPath(path);
        super.dispatchDraw(canvas);
        canvas.restoreToCount(count);
    }


}

tak jak

<?xml version="1.0" encoding="utf-8"?>
<com.example.view.RoundedCornerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:id="@+id/patentItem"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingRight="20dp">
        ... your child goes here
    </RelativeLayout>
</com.example.view.RoundedCornerLayout>

2
Działa dobrze, jeśli na ekranie nie ma wielu animacji, co powoduje, że ekran rysuje się wielokrotnie; ponieważ spowoduje to krytyczne spowolnienie działania. Powinienem wypróbować cardview, który ma wydajną metodę zaokrąglania rogów (nie używaj ścieżki przycinającej ani płótna. RysRoundRect - źle w poniższym API 17, ale użyj porterFilterDuffColor)
Nguyen Tan Dat

18

Utwórz plik xml o nazwie round.xmlw drawablefolderze i wklej następującą zawartość:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
  <solid android:color="#FFFFFF" />
  <stroke android:width=".05dp" android:color="#d2d2d2" />
  <corners android:topLeftRadius="5dp" android:topRightRadius="5dp" android:bottomRightRadius="5dp" android:bottomLeftRadius="5dp"/>
</shape>

następnie użyj round.xmlas backgrounddo dowolnego elementu. Wtedy da ci zaokrąglone rogi.


9

W Androidzie L będziesz mógł po prostu użyć View.setClipToOutline, aby uzyskać ten efekt. W poprzednich wersjach nie było sposobu, aby po prostu przyciąć zawartość losowej grupy ViewGroup do określonego kształtu.

Będziesz musiał pomyśleć o czymś, co dałoby podobny efekt:

  • Jeśli potrzebujesz tylko zaokrąglonych rogów w ImageView, możesz użyć modułu cieniującego, aby „pomalować” obraz na kształcie, którego używasz jako tła. Spójrz na przykład w tej bibliotece .

  • Jeśli naprawdę potrzebujesz, aby wszystkie dzieci zostały obcięte, może możesz spojrzeć na swój układ z innej perspektywy? Taką z tłem w jakimkolwiek używanym kolorze i okrągłą „dziurą” pośrodku? W rzeczywistości można utworzyć niestandardową grupę ViewGroup, która rysuje ten kształt na wszystkich elementach potomnych, nadpisując metodę onDraw.


4

Utwórz plik xml w folderze do rysowania za pomocą następującego kodu. (Nazwa utworzonego przeze mnie pliku to rounded_corner.xml)

rounded_corner.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="#a9c5ac" >
        </solid>

        <!-- view border color and width -->
        <stroke
            android:width="3dp"
            android:color="#1c1b20" >
        </stroke>

        <!-- If you want to add some padding -->
        <padding
            android:left="4dp"
            android:top="4dp"
            android:right="4dp"
            android:bottom="4dp"    >
        </padding>

        <!-- Here is the corner radius -->
        <corners
            android:radius="10dp"   >
        </corners>
    </shape>

I zachowaj to drawablejak backgrounddla widoku, do którego chcesz zachować zaokrągloną krawędź narożną. Zatrzymajmy to naLinearLayout

    <LinearLayout android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/rounded_corner"
            android:layout_centerInParent="true">

            <TextView android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="Hi, This layout has rounded corner borders ..."
                android:gravity="center"
                android:padding="5dp"/>

    </LinearLayout>

3

postępuj zgodnie z tym samouczkiem i całą dyskusją pod nim - http://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/

zgodnie z tym postem napisanym przez Guya Romaina, jednego z czołowych programistów całego zestawu narzędzi Android UI, możliwe jest wykonanie kontenera (i wszystkich jego widoków podrzędnych) z zaokrąglonymi rogami, ale wyjaśnił, że jest to zbyt drogie (z wykonania problemy z renderowaniem).

Radzę ci postępować zgodnie z jego postem, a jeśli chcesz zaokrąglone rogi, zaimplementuj zaokrąglone rogi ImageViewzgodnie z tym postem. następnie możesz umieścić go w pojemniku z dowolnym tłem, a uzyskasz pożądany efekt.

to też ostatecznie zrobiłem.


3

Możesz użyć androidx.cardview.widget.CardViewpodobnego:

<androidx.cardview.widget.CardView
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="wrap_content"       
        app:cardCornerRadius="@dimen/dimen_4"
        app:cardElevation="@dimen/dimen_4"
        app:contentPadding="@dimen/dimen_10">

       ...

</androidx.cardview.widget.CardView>

LUB

shape.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <solid android:color="#f6eef1" />

    <stroke
        android:width="2dp"
        android:color="#000000" />

    <padding
        android:bottom="5dp"
        android:left="5dp"
        android:right="5dp"
        android:top="5dp" />

    <corners android:radius="5dp" />

</shape>

i wewnątrz ciebie układ

<LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/shape">

        ...

</LinearLayout>

3

CardViewPracował dla mnie w API 27 w Android Studio 3.0.1. colorPrimaryZostał wymieniony w res/values/colors.xmlpliku i jest tylko przykładem. Dla parametru layout_width 0dprozciągnie się do szerokości rodzica. Będziesz musiał skonfigurować ograniczenia i szerokość / wysokość do swoich potrzeb.

<android.support.v7.widget.CardView
    android:id="@+id/cardView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:cardCornerRadius="4dp"
    app:cardBackgroundColor="@color/colorPrimary">

    <!-- put your content here -->

</android.support.v7.widget.CardView>

3

W przypadku Biblioteki komponentów materiałów najlepszym sposobem na utworzenie Viewz zaokrąglonymi narożnikami jest użycieMaterialShapeDrawable .

Utwórz model ShapeAppearanceModel z niestandardowymi zaokrąglonymi narożnikami:

ShapeAppearanceModel shapeAppearanceModelLL1 = new ShapeAppearanceModel()
        .toBuilder()
        .setAllCorners(CornerFamily.ROUNDED,radius16)
        .build();

Utwórz MaterialShapeDrawable:

MaterialShapeDrawable shapeDrawableLL1 = new MaterialShapeDrawable(shapeAppearanceModeLL1);

Jeśli chcesz zastosować także ElevationOverlay dla ciemnego motywu, użyj tego:

MaterialShapeDrawable shapeDrawableLL1 = MaterialShapeDrawable.createWithElevationOverlay(this, 4.0f);
shapeDrawableLL1.setShapeAppearanceModel(shapeAppearanceModelLL1);

Opcjonalnie: zastosuj do shapeDrawable kolor tła i obrys

shapeDrawableLL1.setFillColor(
       ContextCompat.getColorStateList(this,R.color...));
 shapeDrawableLL1.setStrokeWidth(2.0f);
 shapeDrawableLL1.setStrokeColor(
       ContextCompat.getColorStateList(this,R.color...));

Na koniec zastosuj shapeDrawable jako tło w swoim LinearLayout(lub innym widoku):

LinearLayout linearLayout1= findViewById(R.id.ll_1);
ViewCompat.setBackground(linearLayout1,shapeDrawableLL1);

wprowadź opis obrazu tutaj


2

Różnica w stosunku do odpowiedzi Jaapa van Hengstuma:

  1. Użyj BitmapShader zamiast maski bitmapowej.
  2. Utwórz bitmapę tylko raz.
public class RoundedFrameLayout extends FrameLayout {
    private Bitmap mOffscreenBitmap;
    private Canvas mOffscreenCanvas;
    private BitmapShader mBitmapShader;
    private Paint mPaint;
    private RectF mRectF;

    public RoundedFrameLayout(Context context) {
        super(context);
        init();
    }

    public RoundedFrameLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public RoundedFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        setWillNotDraw(false);
    }

    @Override
    public void draw(Canvas canvas) {
        if (mOffscreenBitmap == null) {
            mOffscreenBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
            mOffscreenCanvas = new Canvas(mOffscreenBitmap);
            mBitmapShader = new BitmapShader(mOffscreenBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
            mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPaint.setShader(mBitmapShader);
            mRectF = new RectF(0f, 0f, canvas.getWidth(), canvas.getHeight());
        }
        super.draw(mOffscreenCanvas);

        canvas.drawRoundRect(mRectF, 8, 8, mPaint);
    }
}

2
public class RoundedCornerLayout extends FrameLayout {
    private double mCornerRadius;

    public RoundedCornerLayout(Context context) {
        this(context, null, 0);
    }

    public RoundedCornerLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs, defStyle);
    }

    private void init(Context context, AttributeSet attrs, int defStyle) {
        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }

    public double getCornerRadius() {
        return mCornerRadius;
    }

    public void setCornerRadius(double cornerRadius) {
        mCornerRadius = cornerRadius;
    }

    @Override
    public void draw(Canvas canvas) {
        int count = canvas.save();

        final Path path = new Path();
        path.addRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), (float) mCornerRadius, (float) mCornerRadius, Path.Direction.CW);
        canvas.clipPath(path, Region.Op.REPLACE);

        canvas.clipPath(path);
        super.draw(canvas);
        canvas.restoreToCount(count);
    }
}

1

Podane łącze do samouczka wydaje się sugerować, że musisz ustawić właściwości layout_width i layout_height elementów podrzędnych na match_parent.

<ImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent">

1

Aby utworzyć obraz z okrągłym rogiem za pomocą com.google.android.material: material: 1.2.0-beta01

 float radius = context.getResources().getDimension(R.dimen.border_radius_hug);
    shapeAppearanceModel = new ShapeAppearanceModel()
            .toBuilder()
            .setAllCorners(CornerFamily.ROUNDED,radius)
            .build();

imageView.setShapeAppearanceModel(shapeAppearanceModel)

lub jeśli chcesz go użyć w pliku xml:

  <com.google.android.material.imageview.ShapeableImageView
            android:id="@+id/thumb"
            android:layout_width="80dp"
            android:layout_height="60dp"
            app:shapeAppearanceOverlay="@style/circleImageView"
            />

w style.xml dodaj to:

<style name="circleImageView" parent="">
      <item name="cornerFamily">rounded</item>
      <item name="cornerSize">10%</item>
</style>

0

wypróbuj tę właściwość w swoim układzie liniowym, pomoże ona
narzędziom: context = ". youractivity"


0
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) {

        Bitmap roundedBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap
                .getHeight(), Config.ARGB_8888);
        Canvas canvas = new Canvas(roundedBitmap);

        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        final RectF rectF = new RectF(rect);
        final float roundPx = pixels;

        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);

        return roundedBitmap;
    }

0

Na wypadek, gdybyś chciał zaokrąglić jakiś konkretny róg.

fun setCorners() {
        
        val mOutlineProvider = object : ViewOutlineProvider() {
            override fun getOutline(view: View, outline: Outline) {

                val left = 0
                val top = 0;
                val right = view.width
                val bottom = view.height
                val cornerRadiusDP = 16f
                val cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, cornerRadiusDP, resources.displayMetrics).toInt()

                // all corners
                outline.setRoundRect(left, top, right, bottom, cornerRadius.toFloat())

                /* top corners
                outline.setRoundRect(left, top, right, bottom+cornerRadius, cornerRadius.toFloat())*/

                /* bottom corners
                outline.setRoundRect(left, top - cornerRadius, right, bottom, cornerRadius.toFloat())*/

                /* left corners
                outline.setRoundRect(left, top, right + cornerRadius, bottom, cornerRadius.toFloat())*/

                /* right corners
                outline.setRoundRect(left - cornerRadius, top, right, bottom, cornerRadius.toFloat())*/

                /* top left corner
                outline.setRoundRect(left , top, right+ cornerRadius, bottom + cornerRadius, cornerRadius.toFloat())*/

                /* top right corner
                outline.setRoundRect(left - cornerRadius , top, right, bottom + cornerRadius, cornerRadius.toFloat())*/

                /* bottom left corner
                outline.setRoundRect(left, top - cornerRadius, right + cornerRadius, bottom, cornerRadius.toFloat())*/

                /* bottom right corner
                outline.setRoundRect(left - cornerRadius, top - cornerRadius, right, bottom, cornerRadius.toFloat())*/

            }
        }

        myView.apply {
            outlineProvider = mOutlineProvider
            clipToOutline = true
        }
    }

-1

Użyj kształtu w xml z prostokątem. Ustaw właściwość dolnego lub górnego promienia według potrzeb. Następnie zastosuj ten xml jako tło do widoku ur ... lub ... użyj gradientów, aby zrobić to z kodu.


Już to zrobiłem, ale chcesz wiedzieć, czy istnieje lepsza metoda?
Zach

Wnioskodawca wspomniał już o wypróbowaniu tego podejścia w swoim pytaniu.
Michael Krause
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.