Làm thế nào để tạo một chế độ xem với các góc tròn?


94

Tôi đang cố tạo một khung nhìn trong Android với các cạnh tròn. Giải pháp mà tôi tìm thấy cho đến nay là xác định một hình dạng có các góc tròn và sử dụng nó làm nền của khung nhìn đó.

Đây là những gì tôi đã làm, xác định một drawable như dưới đây:

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

Bây giờ tôi đã sử dụng cái này làm nền cho bố cục của mình như dưới đây:

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

Điều này hoạt động hoàn toàn tốt, tôi có thể thấy rằng chế độ xem có các cạnh tròn.

Nhưng bố cục của tôi có nhiều chế độ xem con khác trong đó, chẳng hạn như ImageView hoặc a MapView. Khi tôi đặt một ImageViewbên trong bố cục trên, các góc của hình ảnh không bị cắt / xén, thay vào đó nó xuất hiện đầy đủ.

Tôi đã thấy các cách giải quyết khác để làm cho nó hoạt động như giải thích ở đây .

Nhưng có phương pháp nào để đặt các góc tròn cho một khung nhìn và tất cả các khung nhìn con của nó được chứa trong khung nhìn chính có các góc tròn đó không?


Điều gì sẽ xảy ra nếu bạn sử dụng Bố cục tùy chỉnh mở rộng đến LinearLayout và trong khi đối tượng của nó được tạo, hãy lặp lại tất cả các phần tử con của Bố cục đó và áp dụng nền đường viền tròn cho chúng?
MysticMagicϡ

3
android.support.v7.widget.CardView dường như là giải pháp cho điều này
rocketspacer

Giải pháp này đã giải quyết được nó cho tôi, nhưng yêu cầu phân lớp: /programming/5574212/android-view-clipping
Aaron

Điều này có trả lời câu hỏi của bạn không? Thêm đường viền cho hình ảnh tròn hình ảnh android
dùng4157124

Google có khuôn khổ mới, công nghệ mới tốt hơn [Jetpack Compose] [1] [1]: stackoverflow.com/questions/6054562/…
Ucdemir

Câu trả lời:


128

Một cách tiếp cận khác là tạo một lớp bố cục tùy chỉnh như bên dưới. Bố cục này trước tiên vẽ nội dung của nó vào một bitmap ngoài màn hình, che dấu bitmap ngoài màn hình bằng một hình chữ nhật tròn và sau đó vẽ bitmap ngoài màn hình trên canvas thực tế.

Tôi đã thử nó và nó có vẻ hoạt động (ít nhất là đối với testcase đơn giản của tôi). Tất nhiên nó sẽ ảnh hưởng đến hiệu suất so với một bố cục thông thường.

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

Sử dụng điều này như một bố cục bình thường:

<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
Tôi đang sử dụng bố cục này cho chế độ xem ảnh với chức năng thu phóng bên trong, nhưng bố cục này không thể phát hiện trình nghe cảm ứng khi tôi cố gắng thu phóng, làm cách nào để thêm chức năng nghe cảm ứng trong bố cục này?
Muhammad Nafian Wildana

2
Tôi đã sử dụng phương pháp này và hoạt động tốt. Nhưng khi tôi đặt một EditText bên trong bố cục, màn hình không cập nhật khi tôi nhập vào. Khi tôi đóng cửa sổ, văn bản sẽ hiển thị. Màn hình đang được cập nhật sau khi tôi đóng bàn phím. Bất kỳ sửa chữa cho điều này?
Sajib Acharya

1
Chỉ có một vấn đề với điều này khi bạn sử dụng nó với chế độ xem Recycler là nó không phải chờ đợi bộ mục hoàn chỉnh được tải. Và vòng chỉ một vài mục. Có một lý do để điều này xảy ra?
Ahmed

2
Điều này không hoạt động với các hình ảnh được tải từ thư viện lướt sử dụng chuyển tiếp giữ chỗ (Hoặc thực tế là bất kỳ trẻ em hoạt hình nào khác). Tôi có một giải pháp thay thế nhưng nó yêu cầu màu nền của bạn phải là một màu đồng nhất. Xem gist.github.com/grennis/da9f86870c45f3b8ae00912edb72e868
Greg Ennis

2
Giải pháp tốt và hữu ích nhưng quá đắt. RecyclerView chỉ với sáu phần tử chứa một hình ảnh không thể cuộn trơn tru. Và nó không phụ thuộc vào nguồn thiết bị (Samsung S9 hoặc Wileyfox Swift 2). stackoverflow.com/a/41098690/4399323 là câu trả lời hay hơn!
Valentin Yuryev

73

Hoặc bạn có thể sử dụng android.support.v7.widget.CardViewnhư sau:

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

Tôi đã thử rất nhiều cách, của bạn là giải pháp tốt nhất cho vấn đề của tôi. CẢM ƠN!
wizChen

Không thể xóa độ cao. Hoạt động tốt nếu thiết kế yêu cầu cao độ.
Abdalrahman Shatou

1
@AbdalrahmanShatou developer.android.com/reference/android/support/v7/widget/… có các thuộc tính cho điều đó. Bạn đã thử đặt chúng thành "0" chưa?
rocketspacer

5
Một nhược điểm là nó không hỗ trợ <21 android api là
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>

và bên trong bạn bố trí

<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: Nó không hoạt động theo cách nào? Giống như cách ứng dụng của bạn hoạt động khi bạn hỏi câu hỏi ban đầu?
LarsH

2
clipChildren là vô dụng và hình ảnh vẫn mở rộng ra bên ngoài khung nhìn.
Abdalrahman Shatou

1
Tôi ước tôi có thể cho bạn một khoản tiền thưởng cho điều đó. Cảm ơn bạn
Odys

3
Tôi không nghĩ rằng cách tiếp cận này sẽ hiệu quả nếu hình ảnh là hình chữ nhật, vì nền sẽ được vẽ đằng sau nội dung của hình ảnh. Điều này có thể chỉ hoạt động với hình ảnh có độ trong suốt và bản thân chúng có các góc tròn.
Harsha Vardhan

22

Câu trả lời của Jaap van Hengstum hoạt động tuyệt vời tuy nhiên tôi nghĩ nó đắt và nếu chúng ta áp dụng phương pháp này trên một Nút chẳng hạn, hiệu ứng cảm ứng sẽ bị mất vì chế độ xem được hiển thị dưới dạng bitmap.

Đối với tôi, phương pháp tốt nhất và đơn giản nhất là đắp mặt nạ trên khung nhìn, như sau:

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

Làm thế nào để sử dụng cái này?
Maksim Kniazev

@MaksimKniazev Tạo một lớp con của bố cục bạn muốn (ví dụ: FrameLayout), sau đó dán hai phương thức này vào lớp con này và thay thế '<w Anything_you_want>' bằng giá trị bán kính góc mong muốn của bạn (từ tài nguyên chẳng hạn). Đó là nó. Nó đã đủ rõ ràng cho bạn chưa hay bạn cần một ví dụ?
Donkey

Cảm ơn bạn rất nhiều, nó thực sự hoạt động tốt hơn cho RecyclerView!
Valentin Yuryev

18

Nếu bạn đang gặp sự cố khi thêm trình nghe cảm ứng vào bố cục. Sử dụng bố cục này làm bố cục mẹ.

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


}

như

<?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
Nó hoạt động tốt nếu không có nhiều hoạt ảnh trên màn hình, khiến màn hình vẽ đi vẽ lại nhiều lần; vì nó sẽ làm chậm hiệu suất nghiêm trọng. Nên cố gắng cardview, trong đó có một phương pháp góc tròn hiệu quả (không sử dụng clipping đường dẫn hoặc canvas.drawRoundRect - xấu trong dưới API 17, nhưng sử dụng porterFilterDuffColor)
Nguyễn Tấn Đạt

18

Tạo một tệp xml được gọi round.xmltrong drawablethư mục và dán nội dung này:

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

sau đó sử dụng round.xmlas backgroundcho bất kỳ mục nào. Sau đó, nó sẽ cung cấp cho bạn các góc tròn.


9

Trong Android L, bạn sẽ có thể chỉ sử dụng View.setClipToOutline để có được hiệu ứng đó. Trong các phiên bản trước, không có cách nào để cắt nội dung của một ViewGroup ngẫu nhiên theo một hình dạng nhất định.

Bạn sẽ phải nghĩ ra thứ gì đó sẽ mang lại cho bạn một hiệu ứng tương tự:

  • Nếu bạn chỉ cần các góc tròn trong ImageView, bạn có thể sử dụng công cụ đổ bóng để 'vẽ' hình ảnh lên hình dạng bạn đang sử dụng làm nền. Hãy xem thư viện này để làm ví dụ.

  • Nếu bạn thực sự cần mọi trẻ em được cắt bớt, có thể bạn có thể xem một cách khác về bố cục của mình? Một cái với nền là bất kỳ màu gì bạn đang sử dụng, và một cái 'lỗ' tròn ở giữa? Bạn thực sự có thể tạo một ViewGroup tùy chỉnh để vẽ hình dạng đó trên mọi trẻ em ghi đè phương thức onDraw.


4

Tạo tệp xml trong thư mục có thể vẽ của bạn với mã sau. (Tên của tệp tôi đã tạo là round_corner.xml)

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

Và giữ này drawablenhư backgroundđối với quan điểm mà bạn muốn giữ lại biên giới góc tròn. Hãy giữ nó cho mộtLinearLayout

    <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

làm theo hướng dẫn này và tất cả các cuộc thảo luận bên dưới nó - http://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/

Theo bài đăng này được viết bởi Guy Romain, một trong những nhà phát triển hàng đầu của toàn bộ bộ công cụ giao diện người dùng Android, có thể tạo một vùng chứa (và tất cả các chế độ xem con của anh ấy) với các góc tròn, nhưng anh ấy giải thích rằng nó quá đắt (từ màn trình diễn của vấn đề kết xuất).

Tôi sẽ khuyên bạn nên làm theo bài đăng của anh ấy và nếu bạn muốn các góc tròn, thì hãy triển khai các góc tròn ImageViewtheo bài đăng này. sau đó, bạn có thể đặt nó bên trong một thùng chứa với bất kỳ nền nào và bạn sẽ nhận được ảnh hưởng như mong muốn.

đó là những gì tôi cũng đã làm cuối cùng.


3

Bạn có thể sử dụng androidx.cardview.widget.CardViewnhư vậy:

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

HOẶC LÀ

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>

và bên trong bạn bố trí

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

        ...

</LinearLayout>

3

Hoạt CardViewđộng đối với tôi trong API 27 trong Android Studio 3.0.1. Đã colorPrimaryđược tham chiếu trong res/values/colors.xmltệp và chỉ là một ví dụ. Đối với layout_width của 0dpnó sẽ kéo dài đến chiều rộng của cha mẹ. Bạn sẽ phải định cấu hình các ràng buộc và chiều rộng / chiều cao theo nhu cầu của mình.

<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

Với Thư viện Thành phần Vật liệu, cách tốt nhất để tạo một Viewvới các góc tròn là sử dụng MaterialShapeDrawable.

Tạo một ShapeAppearanceModel với các góc tròn tùy chỉnh:

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

Tạo một MaterialShapeDrawable:

MaterialShapeDrawable shapeDrawableLL1 = new MaterialShapeDrawable(shapeAppearanceModeLL1);

Nếu bạn cũng muốn áp dụng lớp phủ cho chủ đề tối, hãy sử dụng cái này:

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

Tùy chọn: áp dụng cho hình dạng Có thể vẽ màu nền và nét vẽ

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

Cuối cùng áp dụng shapeDrawable làm nền trong LinearLayout(hoặc chế độ xem khác) của bạn:

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

nhập mô tả hình ảnh ở đây


2

Sự khác biệt với câu trả lời của Jaap van Hengstum:

  1. Sử dụng BitmapShader thay vì bitmap mặt nạ.
  2. Tạo bitmap chỉ một lần.
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

Liên kết hướng dẫn bạn cung cấp dường như gợi ý rằng bạn cần đặt các thuộc tính layout_width và layout_height của các phần tử con của bạn thành match_parent.

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

1

Để tạo hình ảnh góc tròn bằng 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)

hoặc nếu bạn muốn sử dụng nó trong tệp xml:

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

trong style.xml thêm cái này:

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

0

hãy thử thuộc tính này với bố cục tuyến tính của bạn, nó sẽ giúp
các công cụ: 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

Trong trường hợp bạn muốn làm tròn một số góc cụ thể.

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

Sử dụng hình dạng trong xml với hình chữ nhật. Đặt thuộc tính bán kính dưới hoặc trên theo ý muốn. Sau đó áp dụng xml đó làm nền cho chế độ xem ur .... hoặc ... sử dụng gradient để thực hiện điều đó từ mã.


Tôi đã làm điều đó rồi, nhưng muốn biết liệu có phương pháp nào tốt hơn không?
Zach

Người yêu cầu đã đề cập đến việc thử cách tiếp cận này trong câu hỏi của mình.
Michael Krause
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.