Wie kann ich ein Layout mit abgerundeten Ecken erstellen? Ich möchte abgerundete Ecken auf meine anwenden LinearLayout
.
Wie kann ich ein Layout mit abgerundeten Ecken erstellen? Ich möchte abgerundete Ecken auf meine anwenden LinearLayout
.
Antworten:
1: Definieren Sie layout_bg.xml in 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: Fügen Sie layout_bg.xml
Ihrem Layout einen Hintergrund hinzu
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
Der Grund für den Fehler wurde angezeigt, weil sich layout_bg.xml nicht im Zeichenordner befand.
Verwenden Sie für API 21+ Clip-Ansichten
Abgerundete Gliederungsausschnitte wurden der View
Klasse in API 21 hinzugefügt . Siehe dieses Schulungsdokument oder diese Referenz Weitere Informationen finden .
Diese eingebaute Funktion macht abgerundete Ecken sehr einfach zu implementieren. Es funktioniert in jeder Ansicht oder jedem Layout und unterstützt das ordnungsgemäße Ausschneiden.
Folgendes ist zu tun:
android:background="@drawable/round_outline"
android:clipToOutline="true"
Leider scheint es einen Fehler zu geben und dieses XML-Attribut wird derzeit nicht erkannt. Zum Glück können wir den Ausschnitt in Java einstellen:
View.setClipToOutline(true)
Wie es aussieht:
Besonderer Hinweis zu ImageViews
setClipToOutline()
Funktioniert nur, wenn der Hintergrund der Ansicht auf eine Form eingestellt ist, die gezeichnet werden kann. Wenn diese Hintergrundform vorhanden ist, behandelt View den Umriss des Hintergrunds als Rahmen für Beschneidungs- und Schattenzwecke.
Dies bedeutet, dass, wenn Sie die Ecken in einer ImageView mit abrunden möchten setClipToOutline()
, Ihr Bild von android:src
statt stammen muss android:background
(da der Hintergrund für die abgerundete Form verwendet wird). Wenn Sie den Hintergrund verwenden müssen, um Ihr Bild anstelle von src festzulegen, können Sie diese Problemumgehung für verschachtelte Ansichten verwenden:
src=@drawable...
anstelle von gelesen background=@drawable
? Sie können dies entweder tun oder Ihre ImageView in einer Containeransicht verschachteln, die den Formumriss enthält.
Hier ist eine Kopie einer XML-Datei, um eine Zeichnungsdatei mit weißem Hintergrund, schwarzem Rand und abgerundeten Ecken zu erstellen:
<?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>
Speichern Sie es als XML-Datei im Zeichenverzeichnis. Verwenden Sie es so, als würden Sie einen zeichnbaren Hintergrund (Symbol oder Ressourcendatei) unter Verwendung seines Ressourcennamens (R.drawable.your_xml_name) verwenden.
<corners android:radius="7dp" />
:)
Verwenden Sie CardView in der Android v7-Unterstützungsbibliothek. Obwohl es ein bisschen schwer ist, löst es alle Probleme und ist einfach genug. Anders als bei der Set Drawable Background-Methode können Unteransichten erfolgreich abgeschnitten werden.
<?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>
Ich habe so gemacht:
Screenshot überprüfen:
Erstellen Sie eine zeichnbare Datei mit dem Namen custom_rectangle.xml
in einem zeichnbaren Ordner:
<?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>
Wenden Sie nun den Rechteckhintergrund auf Ansicht an :
mView.setBackground(R.drawlable.custom_rectangle);
Erledigt
Ich denke, ein besserer Weg, dies zu tun, besteht darin, zwei Dinge zusammenzuführen:
Erstellen Sie eine Bitmap des Layouts, wie hier gezeigt .
Machen Sie eine abgerundete Zeichnung aus der Bitmap, wie hier gezeigt
Stellen Sie das Zeichen in einer Bildansicht ein.
Dies behandelt Fälle, die andere Lösungen nicht lösen konnten, z. B. Inhalte mit Ecken.
Ich denke, es ist auch ein bisschen GPU-freundlicher, da es eine einzelne Schicht anstelle von 2 zeigt.
Der einzig bessere Weg ist, eine vollständig angepasste Ansicht zu erstellen, aber das ist viel Code und kann viel Zeit in Anspruch nehmen. Ich denke, was ich hier vorgeschlagen habe, ist das Beste aus beiden Welten.
Hier ist ein Ausschnitt davon, wie es gemacht werden kann:
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);
}
}
BEARBEITEN: habe eine nette Alternative gefunden, basierend auf der Bibliothek "RoundKornersLayouts" . Haben Sie eine Klasse, die für alle Layoutklassen verwendet wird, die Sie erweitern möchten, um gerundet zu werden:
//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()
}
}
Fügen Sie dann in jeder Ihrer benutzerdefinierten Layoutklassen Code hinzu, der diesem ähnlich ist:
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) }
}
Wenn Sie Attribute unterstützen möchten, verwenden Sie diese wie in der Bibliothek beschrieben:
<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>
Eine weitere Alternative, die für die meisten Anwendungen möglicherweise einfacher ist: Verwenden Sie MaterialCardView. Es ermöglicht das Anpassen der abgerundeten Ecken, der Strichfarbe und -breite sowie der Höhe.
Beispiel:
<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>
Und das Ergebnis:
Beachten Sie, dass an den Rändern des Strichs ein leichtes Artefaktproblem auftritt (einige Pixel des Inhalts bleiben dort), wenn Sie es verwenden. Sie können es bemerken , wenn Sie die Ansicht vergrößern. Ich habe über dieses Thema berichtet hier .
EDIT: scheint behoben zu sein, aber nicht in der IDE. Berichtet hier .
Versuche dies...
1.Erstellbare XML erstellen (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. Fügen Sie Ihren Ansichtshintergrund hinzu
android:background="@drawable/custom_layout"
Wenn Sie Ihr Layout abrunden möchten, verwenden Sie am besten CardView. Es bietet viele Funktionen, um das Design schön zu machen.
<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>
Mit dieser card_view: cardCornerRadius = "5dp" können Sie den Radius ändern.
Die beste und einfachste Methode wäre zu nutzen macht card_background ziehbar in Ihrem Layout. Dies folgt auch den Richtlinien für das Materialdesign von Google. Fügen Sie dies einfach in Ihr LinearLayout ein:
android:background="@drawable/card_background"
Fügen Sie dies Ihrem Zeichenverzeichnis hinzu und nennen Sie es 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>
Verwenden Sie CardView, um abgerundete Kanten für Layouts zu erhalten. Verwenden Sie card_view: cardCornerRadius = "5dp" für cardview, um abgerundete Layoutkanten zu erhalten.
<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>
Ein besserer Weg wäre:
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>
Dies funktioniert auch unter API 21 und bietet Ihnen Folgendes:
Wenn Sie bereit sind, etwas mehr Aufwand zu betreiben, um die Kontrolle zu verbessern , verwenden Sie android.support.v7.widget.CardView
das cardCornerRadius
Attribut (und setzen Sie das elevation
Attribut 0dp
, um alle zugehörigen Schlagschatten mit cardView zu entfernen). Dies funktioniert auch ab API-Ebene ab 15.
Funktion zum programmgesteuerten Einstellen des Eckenradius
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);
}
Verwenden von
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, geben Sie einfach den gleichen Wert wie der Strich ein, damit der Rand sichtbar ist, unabhängig von der Bildgröße
Ich habe die Antwort von @gauravsapiens mit meinen Kommentaren aufgenommen, um Ihnen eine vernünftige Vorstellung davon zu geben, wie sich die Parameter auswirken werden.
<?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>
Wenn Sie nur eine Form erstellen möchten, die die Ecken abrundet, können Sie die Polsterung und den Strich entfernen. Wenn Sie auch den Volumenkörper entfernen, haben Sie tatsächlich abgerundete Ecken auf einem transparenten Hintergrund erstellt.
Um faul zu sein, habe ich eine Form darunter geschaffen, die nur ein fester weißer Hintergrund mit abgerundeten Ecken ist - viel Spaß! :) :)
<?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>
Erstellen Sie Ihre XML in 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-->
und dann fügen Sie dies in Ihre layout.xml
android:background="@drawable/layout_background"
Mit der Materialkomponenten - Bibliothek können Sie mit der MaterialShapeDrawable
auf individuelle Formen zu zeichnen .
Fügen Sie einfach das LinearLayout in Ihr XML-Layout ein:
<LinearLayout
android:id="@+id/linear_rounded"
android:layout_width="match_parent"
android:layout_height="wrap_content"
..>
<!-- content ..... -->
</LinearLayout>
Dann können Sie in Ihrem Code eine anwenden ShapeAppearanceModel
. Etwas wie:
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);
Hinweis :: Es ist die Version 1.1.0 der Materialkomponentenbibliothek erforderlich .
<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" />