Ik probeer een weergave te maken in Android met afgeronde hoeken. De oplossing die ik tot nu toe heb gevonden, is om een vorm met afgeronde hoeken te definiëren en deze als achtergrond voor die weergave te gebruiken.
Dit is wat ik deed, definieer een tekenbaar zoals hieronder weergegeven:
<padding
android:top="2dp"
android:bottom="2dp"/>
<corners android:bottomRightRadius="20dp"
android:bottomLeftRadius="20dp"
android:topLeftRadius="20dp"
android:topRightRadius="20dp"/>
Nu heb ik dit als achtergrond voor mijn lay-out gebruikt, zoals hieronder:
<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">
Dit werkt prima, ik zie dat de weergave afgeronde randen heeft.
Maar mijn lay-out heeft veel andere onderliggende weergaven, bijvoorbeeld een ImageView of een MapView
. Wanneer ik een ImageView
in de bovenstaande lay-out plaats, worden de hoeken van de afbeelding niet bijgesneden/bijgesneden, maar lijkt deze vol.
Ik heb andere oplossingen gezien om het te laten werken, zoals uitgelegd hier.
Maar is er een methode om afgeronde hoeken in te stellen voor een weergave en al zijn?
onderliggende weergaven zijn opgenomen in die hoofdweergave die is afgerond
hoeken?
Antwoord 1, autoriteit 100%
Een andere benadering is om een aangepaste lay-outklasse te maken zoals hieronder. Deze lay-out tekent eerst de inhoud naar een offscreen bitmap, maskeert de offscreen bitmap met een afgeronde rechthoek en tekent vervolgens de offscreen bitmap op het eigenlijke canvas.
Ik heb het geprobeerd en het lijkt te werken (tenminste voor mijn eenvoudige testcase). Het heeft natuurlijk invloed op de prestaties in vergelijking met een normale lay-out.
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;
}
}
Gebruik dit als een normale lay-out:
<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>
Antwoord 2, autoriteit 69%
Of je kunt een android.support.v7.widget.CardView
gebruiken zoals:
<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>
Antwoord 3, autoriteit 47%
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>
en binnenin je lay-out
<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>
Antwoord 4, autoriteit 18%
Het antwoord van Jaap van Hengstumwerkt prima, maar ik denk dat het duur is en als we deze methode toepassen op bijvoorbeeld een knop, gaat het aanraakeffect verloren omdat de weergave wordt weergegeven als een bitmap.
Voor mij is de beste methode en de eenvoudigste methode om een masker op de weergave aan te brengen, zoals dat:
@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);
}
Antwoord 5, autoriteit 16%
Maak een xml-bestand met de naam round.xml
in de map drawable
en plak deze inhoud:
<?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>
gebruik vervolgens de round.xml
als background
voor elk item. Dan krijg je afgeronde hoeken.
Antwoord 6, autoriteit 13%
Als u problemen ondervindt bij het toevoegen van aanraakluisteraars aan de lay-out. Gebruik deze lay-out als bovenliggende lay-out.
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);
}
}
als
<?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>
Antwoord 7, autoriteit 8%
Met de Material Components Library is de beste manier om een View
met afgeronde hoeken te maken het gebruik van de MaterialShapeDrawable
.
Maak een ShapeAppearanceModel met aangepaste afgeronde hoeken:
ShapeAppearanceModel shapeAppearanceModelLL1 = new ShapeAppearanceModel()
.toBuilder()
.setAllCorners(CornerFamily.ROUNDED,radius16)
.build();
Maak een MaterialShapeDrawable
:
MaterialShapeDrawable shapeDrawableLL1 = new MaterialShapeDrawable(shapeAppearanceModeLL1);
Als je ook een elevatieOverlay voor het donkere thema wilt toepassen, gebruik dan dit:
MaterialShapeDrawable shapeDrawableLL1 = MaterialShapeDrawable.createWithElevationOverlay(this, 4.0f);
shapeDrawableLL1.setShapeAppearanceModel(shapeAppearanceModelLL1);
Optioneel: pas op de shapeDrawable een achtergrondkleur en een streek toe
shapeDrawableLL1.setFillColor(
ContextCompat.getColorStateList(this,R.color...));
shapeDrawableLL1.setStrokeWidth(2.0f);
shapeDrawableLL1.setStrokeColor(
ContextCompat.getColorStateList(this,R.color...));
Pas tenslotte de shapeDrawable toe als achtergrond in uw LinearLayout
(of andere weergave):
LinearLayout linearLayout1= findViewById(R.id.ll_1);
ViewCompat.setBackground(linearLayout1,shapeDrawableLL1);
Antwoord 8, autoriteit 7%
In Android L kun je gewoon View gebruiken .setClipToOutlineom dat effect te krijgen. In eerdere versies was er geen manier om de inhoud van een willekeurige ViewGroup in een bepaalde vorm te knippen.
Je zult iets moeten bedenken dat je een soortgelijk effect zou geven:
-
Als je alleen afgeronde hoeken in ImageView nodig hebt, kun je een arcering gebruiken om de afbeelding te ‘schilderen’ over de vorm die je als achtergrond gebruikt. Bekijk voor een voorbeeld deze bibliotheek.
-
Als je echt alle kinderen wilt laten knippen, kun je misschien een andere kijk op je lay-out hebben? Eentje met een achtergrond in welke kleur je ook gebruikt, en een rond ‘gat’ in het midden? Je zou zelfs een aangepaste ViewGroup kunnen maken die die vorm over elk kind tekent en de onDraw-methode overschrijft.
Antwoord 9, autoriteit 5%
Maak een xml-bestand onder uw tekenbare map met de volgende code. (De naam van het bestand dat ik heb gemaakt is round_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>
En bewaar deze drawable
als background
voor de weergave waarvan je de afgeronde hoekrand wilt behouden. Laten we het houden voor een LinearLayout
<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>
Antwoord 10, autoriteit 4%
De CardView
werkte voor mij in API 27 in Android Studio 3.0.1. De colorPrimary
werd verwezen in het bestand res/values/colors.xml
en is slechts een voorbeeld. Voor de layout_width van 0dp
wordt deze uitgerekt tot de breedte van de parent. U moet de beperkingen en breedte/hoogte naar wens configureren.
<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>
Antwoord 11, autoriteit 4%
Voor het geval je een bepaalde hoek wilt ronden.
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
}
}
Antwoord 12, autoriteit 3%
Je kunt een androidx.cardview.widget.CardView
als volgt gebruiken:
<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>
OF
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>
en binnenin je lay-out
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/shape">
...
</LinearLayout>
Antwoord 13, autoriteit 3%
Een ronde hoekafbeelding maken met 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)
of als je het in een xml-bestand wilt gebruiken:
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/thumb"
android:layout_width="80dp"
android:layout_height="60dp"
app:shapeAppearanceOverlay="@style/circleImageView"
/>
voeg in style.xml dit toe:
<style name="circleImageView" parent="">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">10%</item>
</style>
Antwoord 14, autoriteit 2%
volg deze tutorial en alle discussies eronder–
http://www. Curious-creature.org/2012/12/11/android-recept-1-image-with-rounded-corners/
volgens dit bericht geschreven door Guy Romain, een van de toonaangevende ontwikkelaars van de volledige Android UI-toolkit, is het mogelijk om een container (en al zijn kindweergaven) met afgeronde hoeken te maken, maar hij legde uit dat het te duur was ( van uitvoeringen van weergaveproblemen).
Ik raad je aan om volgens zijn post te gaan, en als je afgeronde hoeken wilt, implementeer dan afgeronde hoeken ImageView
volgens deze post. dan zou je het in een container met elke achtergrond kunnen plaatsen, en je krijgt het effect dat je wenst.
dat is wat ik uiteindelijk ook deed.
Antwoord 15, autoriteit 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);
}
}
Antwoord 16
Verschil met het antwoord van Jaap van Hengstum:
- Gebruik BitmapShaderin plaats van bitmap maskeren.
- Maak een bitmap slechts één keer.
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);
}
}
17
Probeer deze listing met uw lineaire lay-out het zal helpen
gereedschappen: context = “youractivity”
18
Gebruik vorm xml rectangle.set met de eigenschap onderste of bovenste radius als want.then toepassing die XML als achtergrond om ur view of …. … gebruik gradiënten om het van de code.