Saya mencoba membuat tampilan di android dengan ujung membulat. Solusi yang saya temukan sejauh ini adalah mendefinisikan bentuk dengan sudut membulat dan menggunakannya sebagai latar belakang tampilan tersebut.
Inilah yang saya lakukan, tentukan drawable seperti yang diberikan di bawah ini:
<padding
android:top="2dp"
android:bottom="2dp"/>
<corners android:bottomRightRadius="20dp"
android:bottomLeftRadius="20dp"
android:topLeftRadius="20dp"
android:topRightRadius="20dp"/>
Sekarang saya menggunakan ini sebagai latar belakang tata letak saya seperti di bawah ini:
<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">
Ini berfungsi dengan sangat baik, saya dapat melihat bahwa pemandangan memiliki tepi yang membulat.
Tapi tata letak saya memiliki banyak tampilan anak lain di dalamnya, katakanlah ImageView atau MapView
. Ketika saya menempatkan bagian ImageView
dalam tata letak di atas, sudut gambar tidak terpotong / dipotong, melainkan tampak penuh.
Saya telah melihat solusi lain untuk membuatnya berfungsi seperti yang dijelaskan di sini .
Namun apakah ada metode untuk menyetel sudut membulat untuk suatu tampilan dan semua tampilan turunannya dimuat dalam tampilan utama yang memiliki sudut membulat tersebut?
Jawaban:
Pendekatan lainnya adalah dengan membuat kelas tata letak khusus seperti di bawah ini. Tata letak ini pertama-tama menggambar kontennya ke bitmap di luar layar, menutupi bitmap di luar layar dengan persegi bulat, lalu menggambar bitmap di luar layar di kanvas yang sebenarnya.
Saya mencobanya dan tampaknya berhasil (setidaknya untuk testcase sederhana saya). Ini tentu saja akan mempengaruhi kinerja dibandingkan dengan tata letak biasa.
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; } }
Gunakan ini seperti tata letak normal:
<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>
sumber
Atau Anda dapat menggunakan
android.support.v7.widget.CardView
sejenisnya:<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>
sumber
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>
dan di dalam tata letak Anda
<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>
sumber
Jawaban Jaap van Hengstum bekerja dengan baik namun menurut saya itu mahal dan jika kita menerapkan metode ini pada Tombol misalnya, efek sentuhan hilang karena tampilan dirender sebagai bitmap.
Bagi saya metode terbaik dan paling sederhana adalah menerapkan mask pada tampilan, seperti itu:
@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); }
sumber
Jika Anda mengalami masalah saat menambahkan pendengar sentuh ke tata letak. Gunakan tata letak ini sebagai tata letak induk.
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); } }
sebagai
<?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>
sumber
Buat file xml bernama
round.xml
dalamdrawable
folder dan tempel konten ini:<?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>
lalu gunakan
round.xml
sebagaibackground
untuk item apa pun. Maka itu akan memberi Anda sudut membulat.sumber
Di Android L, Anda hanya bisa menggunakan View.setClipToOutline untuk mendapatkan efek itu. Di versi sebelumnya, tidak ada cara untuk hanya memotong konten ViewGroup acak dalam bentuk tertentu.
Anda harus memikirkan sesuatu yang akan memberi Anda efek serupa:
Jika Anda hanya membutuhkan sudut membulat di ImageView, Anda bisa menggunakan shader untuk 'melukis' gambar di atas bentuk yang Anda gunakan sebagai latar belakang. Lihat perpustakaan ini sebagai contoh.
Jika Anda benar-benar ingin setiap anak dipotong, mungkin Anda dapat melihat tata letak Anda lagi? Satu dengan latar belakang warna apa pun yang Anda gunakan, dan 'lubang' bundar di tengah? Anda sebenarnya bisa membuat ViewGroup kustom yang menggambar bentuk itu di atas setiap turunan yang mengganti metode onDraw.
sumber
Buat file xml di bawah folder drawable Anda dengan kode berikut. (Nama file yang saya buat adalah 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>
Dan menjaga ini
drawable
sebagaibackground
untuk tampilan yang Anda ingin menyimpan perbatasan sudut bulat. Mari kita simpan untuk aLinearLayout
<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>
sumber
ikuti tutorial ini dan semua diskusi di bawahnya - http://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/
menurut posting ini yang ditulis oleh Guy Romain, salah satu pengembang terkemuka dari seluruh toolkit UI Android, dimungkinkan untuk membuat wadah (dan semua pandangan anaknya) dengan sudut membulat, tetapi dia menjelaskan bahwa itu terlalu mahal (dari kinerja masalah rendering).
Saya akan merekomendasikan Anda untuk pergi sesuai dengan postingnya, dan jika Anda ingin sudut membulat, maka terapkan sudut membulat
ImageView
sesuai dengan posting ini. kemudian, Anda dapat menempatkannya di dalam wadah dengan latar belakang apa pun, dan Anda akan mendapatkan pengaruh yang Anda inginkan.itulah yang saya lakukan juga pada akhirnya.
sumber
Anda dapat menggunakan
androidx.cardview.widget.CardView
seperti ini:<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>
ATAU
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>
dan di dalam tata letak Anda
<LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/shape"> ... </LinearLayout>
sumber
Ini
CardView
berfungsi untuk saya di API 27 di Android Studio 3.0.1. ItucolorPrimary
direferensikan dalamres/values/colors.xml
file dan hanya sebuah contoh. Untuk layout_width-0dp
nya akan meregang ke lebar induknya. Anda harus mengkonfigurasi batasan dan lebar / tinggi sesuai kebutuhan Anda.<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>
sumber
Dengan Perpustakaan Komponen Bahan, cara terbaik untuk membuat
View
dengan sudut membulat adalah dengan menggunakanMaterialShapeDrawable
.Buat ShapeAppearanceModel dengan sudut membulat khusus:
ShapeAppearanceModel shapeAppearanceModelLL1 = new ShapeAppearanceModel() .toBuilder() .setAllCorners(CornerFamily.ROUNDED,radius16) .build();
Buat
MaterialShapeDrawable
:MaterialShapeDrawable shapeDrawableLL1 = new MaterialShapeDrawable(shapeAppearanceModeLL1);
Jika Anda ingin menerapkan juga elevationOverlay untuk tema gelap, gunakan ini:
MaterialShapeDrawable shapeDrawableLL1 = MaterialShapeDrawable.createWithElevationOverlay(this, 4.0f); shapeDrawableLL1.setShapeAppearanceModel(shapeAppearanceModelLL1);
Opsional: terapkan pada shapeDrawable warna latar belakang dan guratan
shapeDrawableLL1.setFillColor( ContextCompat.getColorStateList(this,R.color...)); shapeDrawableLL1.setStrokeWidth(2.0f); shapeDrawableLL1.setStrokeColor( ContextCompat.getColorStateList(this,R.color...));
Terakhir, terapkan shapeDrawable sebagai latar belakang di
LinearLayout
(atau tampilan lain) Anda:sumber
Perbedaan dari jawaban Jaap van Hengstum:
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); } }
sumber
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); } }
sumber
Tautan tutorial yang Anda sediakan tampaknya menyarankan Anda untuk menyetel properti layout_width dan layout_height, dari elemen anak Anda ke match_parent.
<ImageView android:layout_width="match_parent" android:layout_height="match_parent">
sumber
Untuk membuat gambar sudut bulat menggunakan 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)
atau jika Anda ingin menggunakannya dalam file xml:
<com.google.android.material.imageview.ShapeableImageView android:id="@+id/thumb" android:layout_width="80dp" android:layout_height="60dp" app:shapeAppearanceOverlay="@style/circleImageView" />
di style.xml tambahkan ini:
<style name="circleImageView" parent=""> <item name="cornerFamily">rounded</item> <item name="cornerSize">10%</item> </style>
sumber
coba properti ini dengan tata letak linier Anda, ini akan membantu
alat: konteks = ". aktivitas Anda"
sumber
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; }
sumber
Jika Anda ingin melewati beberapa sudut tertentu.
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 } }
sumber
Gunakan bentuk dalam xml dengan persegi panjang. Atur properti radius bawah atau atas sebagai keinginan. Kemudian terapkan xml itu sebagai latar belakang ke tampilan Anda .... atau ... gunakan gradien untuk melakukannya dari kode.
sumber