Bagaimana saya bisa membuat tata letak dengan sudut bulat? Saya ingin menerapkan sudut bulat untuk saya LinearLayout
.
Bagaimana saya bisa membuat tata letak dengan sudut bulat? Saya ingin menerapkan sudut bulat untuk saya LinearLayout
.
Jawaban:
1: Tentukan layout_bg.xml dalam drawables :
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF"/>
<stroke android:width="3dp" android:color="#B1BCBE" />
<corners android:radius="10dp"/>
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
</shape>
2: Tambahkan layout_bg.xml
sebagai latar belakang ke tata letak Anda
android:background="@drawable/layout_bg"
Element shape doesn't have the required attribute android:layout_height
?
Element shape doesn't have the required attribute android:layout_height
Alasan kesalahan ditampilkan karena layout_bg.xml tidak ada di dalam folder drawable.
Untuk API 21+, Gunakan Tampilan Klip
Kliping garis bundar ditambahkan ke View
kelas di API 21. Lihat dokumen pelatihan ini atau referensi ini untuk informasi lebih lanjut.
Fitur bawaan ini membuat sudut bundar sangat mudah diimplementasikan. Ini berfungsi pada tampilan atau tata letak apa pun dan mendukung kliping yang tepat.
Inilah Yang Harus Dilakukan:
android:background="@drawable/round_outline"
android:clipToOutline="true"
Sayangnya, tampaknya ada bug dan atribut XML ini saat ini tidak dikenali. Untungnya, kita dapat mengatur kliping di Jawa:
View.setClipToOutline(true)
Seperti apa rupanya:
Catatan Khusus Tentang ImageViews
setClipToOutline()
hanya berfungsi ketika latar belakang Tampilan diatur ke bentuk yang dapat digambar. Jika bentuk latar belakang ini ada, Lihat memperlakukan garis besar latar belakang sebagai batas untuk kliping dan tujuan bayangan.
Ini berarti bahwa jika Anda ingin membulatkan sudut pada ImageView dengan setClipToOutline()
, gambar Anda harus berasal android:src
alih-alih android:background
(karena latar belakang digunakan untuk bentuk bulat). Jika Anda HARUS menggunakan latar belakang untuk mengatur gambar Anda alih-alih src, Anda dapat menggunakan solusi tampilan bersarang ini:
src=@drawable...
bukan background=@drawable
? Anda bisa melakukan itu atau membuat sarang ImageView Anda di dalam tampilan wadah yang menampung garis bentuk.
Berikut adalah salinan file XML untuk membuat drawable dengan latar belakang putih, batas hitam, dan sudut bundar:
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#ffffffff"/>
<stroke android:width="3dp"
android:color="#ff000000"
/>
<padding android:left="1dp"
android:top="1dp"
android:right="1dp"
android:bottom="1dp"
/>
<corners android:bottomRightRadius="7dp" android:bottomLeftRadius="7dp"
android:topLeftRadius="7dp" android:topRightRadius="7dp"/>
</shape>
simpan sebagai file xml di direktori drawable, Gunakan seperti Anda menggunakan latar belakang drawable (ikon atau file sumber daya) menggunakan nama sumber dayanya (R.drawable.your_xml_name)
<corners android:radius="7dp" />
:)
Gunakan CardView di perpustakaan dukungan android v7. Meskipun agak berat, ini menyelesaikan semua masalah, dan cukup mudah. Tidak seperti metode latar yang ditetapkan yang dapat digambar, metode ini dapat memotong subview dengan sukses.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardBackgroundColor="@android:color/transparent"
card_view:cardCornerRadius="5dp"
card_view:cardElevation="0dp"
card_view:contentPadding="0dp">
<YOUR_LINEARLAYOUT_HERE>
</android.support.v7.widget.CardView>
Saya telah melakukan ini:
Periksa Tangkapan Layar:
Buat file drawable dengan nama custom_rectangle.xml
di folder drawable :
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="@android:color/white" />
<corners android:radius="10dip" />
<stroke
android:width="1dp"
android:color="@android:color/white" />
</shape>
Sekarang terapkan latar belakang Rectangle pada View :
mView.setBackground(R.drawlable.custom_rectangle);
Selesai
Saya pikir cara yang lebih baik untuk melakukannya adalah menggabungkan 2 hal:
buat bitmap tata letak, seperti yang ditunjukkan di sini .
buat drawed rounded dari bitmap, seperti yang ditunjukkan di sini
atur drawable pada imageView.
Ini akan menangani kasus-kasus yang gagal diselesaikan solusi lain, seperti memiliki konten yang memiliki sudut.
Saya pikir itu juga sedikit lebih ramah GPU, karena ia menunjukkan satu lapisan, bukan 2.
Satu-satunya cara yang lebih baik adalah membuat tampilan yang sepenuhnya dikustomisasi, tetapi itu banyak kode dan mungkin membutuhkan banyak waktu. Saya pikir apa yang saya sarankan di sini adalah yang terbaik dari kedua dunia.
Berikut cuplikan cara melakukannya:
RoundedCornersDrawable.java
/**
* shows a bitmap as if it had rounded corners. based on :
* http://rahulswackyworld.blogspot.co.il/2013/04/android-drawables-with-rounded_7.html
* easy alternative from support library: RoundedBitmapDrawableFactory.create( ...) ;
*/
public class RoundedCornersDrawable extends BitmapDrawable {
private final BitmapShader bitmapShader;
private final Paint p;
private final RectF rect;
private final float borderRadius;
public RoundedCornersDrawable(final Resources resources, final Bitmap bitmap, final float borderRadius) {
super(resources, bitmap);
bitmapShader = new BitmapShader(getBitmap(), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
final Bitmap b = getBitmap();
p = getPaint();
p.setAntiAlias(true);
p.setShader(bitmapShader);
final int w = b.getWidth(), h = b.getHeight();
rect = new RectF(0, 0, w, h);
this.borderRadius = borderRadius < 0 ? 0.15f * Math.min(w, h) : borderRadius;
}
@Override
public void draw(final Canvas canvas) {
canvas.drawRoundRect(rect, borderRadius, borderRadius, p);
}
}
CustomView.java
public class CustomView extends ImageView {
private View mMainContainer;
private boolean mIsDirty=false;
// TODO for each change of views/content, set mIsDirty to true and call invalidate
@Override
protected void onDraw(final Canvas canvas) {
if (mIsDirty) {
mIsDirty = false;
drawContent();
return;
}
super.onDraw(canvas);
}
/**
* draws the view's content to a bitmap. code based on :
* http://nadavfima.com/android-snippet-inflate-a-layout-draw-to-a-bitmap/
*/
public static Bitmap drawToBitmap(final View viewToDrawFrom, final int width, final int height) {
// Create a new bitmap and a new canvas using that bitmap
final Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bmp);
viewToDrawFrom.setDrawingCacheEnabled(true);
// Supply measurements
viewToDrawFrom.measure(MeasureSpec.makeMeasureSpec(canvas.getWidth(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(canvas.getHeight(), MeasureSpec.EXACTLY));
// Apply the measures so the layout would resize before drawing.
viewToDrawFrom.layout(0, 0, viewToDrawFrom.getMeasuredWidth(), viewToDrawFrom.getMeasuredHeight());
// and now the bmp object will actually contain the requested layout
canvas.drawBitmap(viewToDrawFrom.getDrawingCache(), 0, 0, new Paint());
return bmp;
}
private void drawContent() {
if (getMeasuredWidth() <= 0 || getMeasuredHeight() <= 0)
return;
final Bitmap bitmap = drawToBitmap(mMainContainer, getMeasuredWidth(), getMeasuredHeight());
final RoundedCornersDrawable drawable = new RoundedCornersDrawable(getResources(), bitmap, 15);
setImageDrawable(drawable);
}
}
EDIT: menemukan alternatif yang bagus, berdasarkan pustaka "RoundKornersLayouts" . Miliki kelas yang akan digunakan untuk semua kelas tata letak yang ingin Anda perpanjang, untuk dibulatkan:
//based on https://github.com/JcMinarro/RoundKornerLayouts
class CanvasRounder(cornerRadius: Float, cornerStrokeColor: Int = 0, cornerStrokeWidth: Float = 0F) {
private val path = android.graphics.Path()
private lateinit var rectF: RectF
private var strokePaint: Paint?
var cornerRadius: Float = cornerRadius
set(value) {
field = value
resetPath()
}
init {
if (cornerStrokeWidth <= 0)
strokePaint = null
else {
strokePaint = Paint()
strokePaint!!.style = Paint.Style.STROKE
strokePaint!!.isAntiAlias = true
strokePaint!!.color = cornerStrokeColor
strokePaint!!.strokeWidth = cornerStrokeWidth
}
}
fun round(canvas: Canvas, drawFunction: (Canvas) -> Unit) {
val save = canvas.save()
canvas.clipPath(path)
drawFunction(canvas)
if (strokePaint != null)
canvas.drawRoundRect(rectF, cornerRadius, cornerRadius, strokePaint)
canvas.restoreToCount(save)
}
fun updateSize(currentWidth: Int, currentHeight: Int) {
rectF = android.graphics.RectF(0f, 0f, currentWidth.toFloat(), currentHeight.toFloat())
resetPath()
}
private fun resetPath() {
path.reset()
path.addRoundRect(rectF, cornerRadius, cornerRadius, Path.Direction.CW)
path.close()
}
}
Kemudian, di setiap kelas tata letak khusus Anda, tambahkan kode yang mirip dengan yang ini:
class RoundedConstraintLayout : ConstraintLayout {
private lateinit var canvasRounder: CanvasRounder
constructor(context: Context) : super(context) {
init(context, null, 0)
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
init(context, attrs, 0)
}
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
init(context, attrs, defStyle)
}
private fun init(context: Context, attrs: AttributeSet?, defStyle: Int) {
val array = context.obtainStyledAttributes(attrs, R.styleable.RoundedCornersView, 0, 0)
val cornerRadius = array.getDimension(R.styleable.RoundedCornersView_corner_radius, 0f)
val cornerStrokeColor = array.getColor(R.styleable.RoundedCornersView_corner_stroke_color, 0)
val cornerStrokeWidth = array.getDimension(R.styleable.RoundedCornersView_corner_stroke_width, 0f)
array.recycle()
canvasRounder = CanvasRounder(cornerRadius,cornerStrokeColor,cornerStrokeWidth)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
setLayerType(FrameLayout.LAYER_TYPE_SOFTWARE, null)
}
}
override fun onSizeChanged(currentWidth: Int, currentHeight: Int, oldWidth: Int, oldheight: Int) {
super.onSizeChanged(currentWidth, currentHeight, oldWidth, oldheight)
canvasRounder.updateSize(currentWidth, currentHeight)
}
override fun draw(canvas: Canvas) = canvasRounder.round(canvas) { super.draw(canvas) }
override fun dispatchDraw(canvas: Canvas) = canvasRounder.round(canvas) { super.dispatchDraw(canvas) }
}
Jika Anda ingin mendukung atribut, gunakan ini seperti yang tertulis di perpustakaan:
<resources>
<declare-styleable name="RoundedCornersView">
<attr name="corner_radius" format="dimension"/>
<attr name="corner_stroke_width" format="dimension"/>
<attr name="corner_stroke_color" format="color"/>
</declare-styleable>
</resources>
Alternatif lain, yang mungkin lebih mudah untuk sebagian besar kegunaan: gunakan MaterialCardView. Hal ini memungkinkan menyesuaikan sudut membulat, warna dan lebar goresan, dan ketinggian.
Contoh:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false"
tools:context=".MainActivity">
<com.google.android.material.card.MaterialCardView
android:layout_width="100dp" android:layout_height="100dp" android:layout_gravity="center"
app:cardCornerRadius="8dp" app:cardElevation="8dp" app:strokeColor="#f00" app:strokeWidth="2dp">
<ImageView
android:layout_width="match_parent" android:layout_height="match_parent" android:background="#0f0"/>
</com.google.android.material.card.MaterialCardView>
</FrameLayout>
Dan hasilnya:
Perhatikan bahwa ada sedikit masalah artefak di tepi goresan (meninggalkan beberapa piksel konten di sana), jika Anda menggunakannya. Anda dapat melihatnya jika Anda memperbesar. Saya telah melaporkan tentang masalah ini di sini .
EDIT: tampaknya diperbaiki, tetapi tidak pada IDE. Dilaporkan di sini .
Coba ini...
1. buat xml yang dapat ditarik (custom_layout.xml):
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#FFFFFF" />
<stroke
android:width="2dp"
android:color="#FF785C" />
<corners android:radius="10dp" />
</shape>
2. Tambahkan latar belakang tampilan Anda
android:background="@drawable/custom_layout"
Jika Anda ingin membuat tata letak Anda membulat, yang terbaik adalah menggunakan CardView, itu menyediakan banyak fitur untuk membuat desain yang indah.
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".3"
android:text="@string/quote_code"
android:textColor="@color/white"
android:textSize="@dimen/text_head_size" />
</LinearLayout>
</android.support.v7.widget.CardView>
Dengan card_view ini: cardCornerRadius = "5dp", Anda dapat mengubah radius.
Metode terbaik dan paling sederhana adalah dengan memanfaatkan card_background yang dapat digambar dalam tata letak Anda. Ini juga mengikuti pedoman desain materi Google. Cukup sertakan ini di dalam Anda LinearLayout:
android:background="@drawable/card_background"
Tambahkan ini ke direktori Anda yang dapat digambar dan beri nama card_background.xml :
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#BDBDBD"/>
<corners android:radius="5dp"/>
</shape>
</item>
<item
android:left="0dp"
android:right="0dp"
android:top="0dp"
android:bottom="2dp">
<shape android:shape="rectangle">
<solid android:color="#ffffff"/>
<corners android:radius="5dp"/>
</shape>
</item>
</layer-list>
Gunakan CardView untuk mendapatkan tepi bulat untuk tata letak apa pun. Gunakan card_view: cardCornerRadius = "5dp" untuk cardview untuk mendapatkan tepi tata letak bulat.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="15dp"
android:weightSum="1">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".3"
android:text="@string/quote_code"
android:textColor="@color/white"
android:textSize="@dimen/text_head_size" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".7"
android:text="@string/quote_details"
android:textColor="@color/white"
android:textSize="@dimen/text_head_size" />
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
Cara yang lebih baik untuk melakukannya adalah:
background_activity.xml
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:gravity="fill">
<color android:color="@color/black"/>
</item>
<item>
<shape android:gravity="fill">
<solid android:color="@color/white"/>
<corners android:radius="10dip"/>
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
</shape>
</item>
</layer-list>
Ini akan bekerja di bawah API 21 juga, dan memberi Anda sesuatu seperti ini:
Jika Anda bersedia melakukan sedikit usaha lebih banyak kontrol yang lebih baik, maka gunakan android.support.v7.widget.CardView
dengan cardCornerRadius
atributnya (dan atur elevation
atribut untuk 0dp
menyingkirkan drop shadow yang menyertainya dengan cardView). Juga, ini akan bekerja dari level API serendah 15.
Berfungsi untuk mengatur radius sudut secara terprogram
static void setCornerRadius(GradientDrawable drawable, float topLeft,
float topRight, float bottomRight, float bottomLeft) {
drawable.setCornerRadii(new float[] { topLeft, topLeft, topRight, topRight,
bottomRight, bottomRight, bottomLeft, bottomLeft });
}
static void setCornerRadius(GradientDrawable drawable, float radius) {
drawable.setCornerRadius(radius);
}
Menggunakan
GradientDrawable gradientDrawable = new GradientDrawable();
gradientDrawable.setColor(Color.GREEN);
setCornerRadius(gradientDrawable, 20f);
//or setCornerRadius(gradientDrawable, 20f, 40f, 60f, 80f);
view.setBackground(gradientDrawable);
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF"/>
<stroke android:width="3dip" android:color="#B1BCBE" />
<corners android:radius="10dip"/>
<padding android:left="3dip" android:top="3dip" android:right="3dip" android:bottom="3dip" />
</shape>
@ David, cukup beri nilai padding yang sama dengan goresan, sehingga batas dapat terlihat, tanpa memandang ukuran gambar
Saya telah mengambil jawaban @gauravsapiens dengan komentar saya di dalam untuk memberi Anda pemahaman yang wajar tentang apa yang akan mempengaruhi parameter.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Background color -->
<solid android:color="@color/white" />
<!-- Stroke around the background, width and color -->
<stroke android:width="4dp" android:color="@color/drop_shadow"/>
<!-- The corners of the shape -->
<corners android:radius="4dp"/>
<!-- Padding for the background, e.g the Text inside a TextView will be
located differently -->
<padding android:left="10dp" android:right="10dp"
android:bottom="10dp" android:top="10dp" />
</shape>
Jika Anda hanya ingin membuat bentuk yang membulatkan sudut, lepaskan bantalan dan goresan akan berhasil. Jika Anda menghapus solid juga, Anda akan, pada dasarnya, telah membuat sudut bulat pada latar belakang transparan.
Demi menjadi malas, saya telah membuat bentuk di bawahnya, yang hanya merupakan latar belakang putih solid dengan sudut-sudut bulat - selamat menikmati! :)
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Background color -->
<solid android:color="@color/white" />
<!-- The corners of the shape -->
<corners android:radius="4dp"/>
</shape>
Buat xml Anda di drawable, layout_background.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="@color/your_colour" />
<stroke
android:width="2dp"
android:color="@color/your_colour" />
<corners android:radius="10dp" />
</shape>
<--width, color, radius should be as per your requirement-->
dan kemudian, tambahkan ini di layout.xml
android:background="@drawable/layout_background"
Dengan Perpustakaan Komponen Bahan Anda dapat menggunakan MaterialShapeDrawable
untuk menggambar bentuk kustom .
Cukup letakkan LinearLayout di tata letak xml Anda:
<LinearLayout
android:id="@+id/linear_rounded"
android:layout_width="match_parent"
android:layout_height="wrap_content"
..>
<!-- content ..... -->
</LinearLayout>
Kemudian dalam kode Anda, Anda dapat menerapkan ShapeAppearanceModel
. Sesuatu seperti:
float radius = getResources().getDimension(R.dimen.default_corner_radius);
LinearLayout linearLayout= findViewById(R.id.linear_rounded);
ShapeAppearanceModel shapeAppearanceModel = new ShapeAppearanceModel()
.toBuilder()
.setAllCorners(CornerFamily.ROUNDED,radius)
.build();
MaterialShapeDrawable shapeDrawable = new MaterialShapeDrawable(shapeAppearanceModel);
//Fill the LinearLayout with your color
shapeDrawable.setFillColor(ContextCompat.getColorStateList(this,R.color.secondaryLightColor));
ViewCompat.setBackground(linearLayout,shapeDrawable);
Catatan :: ini membutuhkan versi 1.1.0 dari pustaka komponen material.
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:padding="@dimen/_10sdp"
android:shape="rectangle">
<solid android:color="@color/header" />
<corners
android:bottomLeftRadius="@dimen/_5sdp"
android:bottomRightRadius="@dimen/_5sdp"
android:topLeftRadius="@dimen/_5sdp"
android:topRightRadius="@dimen/_5sdp" />