Köşeleri yuvarlatılmış bir düzeni nasıl yapabilirim? Yuvarlatılmış köşeleri uygulamak istiyorum LinearLayout
.
Köşeleri yuvarlatılmış bir düzeni nasıl yapabilirim? Yuvarlatılmış köşeleri uygulamak istiyorum LinearLayout
.
Yanıtlar:
1: Çekmecelerde layout_bg.xml dosyasını tanımlayın :
<?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: layout_bg.xml
Düzeninize arka plan olarak ekleyin
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
Hatanın görünmesinin nedeni, layout_bg.xml dosyasının çekilebilir klasörün içinde olmaması nedeniyle.
API 21+ için Klip Görünümlerini Kullanın
Yuvarlak anahat kırpması View
API 21'deki sınıfa . Daha fazla bilgi için bu eğitim belgesine veya bu referansa bakın.
Bu yerleşik özellik, yuvarlatılmış köşelerin uygulanmasını çok kolaylaştırır. Herhangi bir görünüm veya düzen üzerinde çalışır ve uygun kırpmayı destekler.
Yapılacaklar:
android:background="@drawable/round_outline"
android:clipToOutline="true"
Ne yazık ki, bir hata var gibi görünüyor ve bu XML özelliği şu anda tanınmıyor. Neyse ki, Java'da kırpma ayarlayabiliriz:
View.setClipToOutline(true)
Ne gibi görünüyor:
ImageViews Hakkında Özel Not
setClipToOutline()
yalnızca Görünüm'ün arka planı çekilebilir bir şekle ayarlandığında çalışır. Bu arka plan şekli varsa, Görünüm arka planın anahatlarını kırpma ve gölgeleme amaçları için kenarlık olarak kabul eder.
Bu, bir ImageView üzerindeki köşeleri yuvarlamak istiyorsanız setClipToOutline()
, görüntünüzün android:src
yerine gelmesi gerektiği anlamına gelir android:background
(arka plan yuvarlak şekil için kullanıldığından). Görüntünüzü src yerine ayarlamak için arka plan kullanmanız GEREKİRSE, bu iç içe görünümler geçici çözümünü kullanabilirsiniz:
src=@drawable...
yerine notumu okudun background=@drawable
mu? Bunu yapabilir veya ImageView'inizi şekil anahattını tutan bir kapsayıcı görünümü içine yerleştirebilirsiniz.
İşte beyaz bir arka plan, siyah kenarlık ve yuvarlatılmış köşelerle çizilebilir bir oluşturmak için bir XML dosyasının kopyası:
<?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>
onu çekilebilir dizine xml dosyası olarak kaydedin, Kaynak adını (R.drawable.your_xml_name) kullanarak herhangi bir çekilebilir arka plan (simge veya kaynak dosyası) kullanır gibi kullanın
<corners android:radius="7dp" />
Android v7 destek kitaplığında CardView kullanın. Biraz ağır olmasına rağmen, tüm problemleri çözüyor ve yeterince kolay. Set çekilebilir arka plan yöntemi gibi değil, alt görünümleri başarıyla kırpabilir.
<?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>
Bu şekilde yaptım:
Ekran Görüntüsünü Kontrol Et:
Oluşturmak çekilebilir ile adlı dosyayı custom_rectangle.xml
içinde çekilebilir klasörde:
<?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>
Şimdi uygulamak Dikdörtgen arka plan üzerinde Görünüm :
mView.setBackground(R.drawlable.custom_rectangle);
Bitti
Bunu yapmanın daha iyi bir yolunun 2 şeyi birleştirmek olduğunu düşünüyorum:
burada gösterildiği gibi düzenin bir bitmap'ini yapın .
burada gösterildiği gibi bitmapten yuvarlak bir çizilebilir yapın
çizilebilir bir imageView üzerinde ayarlayın.
Bu, köşeleri olan içeriğe sahip olmak gibi diğer çözümlerin çözemediği durumları ele alacaktır.
Bence 2 yerine tek bir katman gösterdiği için biraz daha GPU dostu.
Tek daha iyi bir yol, tamamen özelleştirilmiş bir görünüm oluşturmaktır, ancak bu çok fazla kod içerir ve çok zaman alabilir. Burada önerdiğim şeyin her iki dünyanın da en iyisi olduğunu düşünüyorum.
İşte nasıl yapılabileceğine dair bir pasaj:
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: "RoundKornersLayouts" kütüphanesi dayalı güzel bir alternatif bulundu . Genişletmek ve yuvarlamak istediğiniz tüm sınıflar için kullanılacak bir sınıfınız olsun:
//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()
}
}
Ardından, özelleştirilmiş düzen sınıflarınızın her birine, buna benzer bir kod ekleyin:
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) }
}
Öznitelikleri desteklemek istiyorsanız, bunu kütüphanede yazıldığı gibi kullanın:
<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>
Çoğu kullanım için daha kolay olabilecek başka bir alternatif: MaterialCardView kullanın. Yuvarlatılmış köşeleri, kontur rengini, genişliğini ve yüksekliği özelleştirmeye izin verir.
Misal:
<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>
Ve sonuç:
Kullanıyorsanız konturun kenarlarında hafif bir artefakt sorunu olduğunu unutmayın (içeriğin bazı piksellerini orada bırakır). Yakınlaştırırsanız fark edebilirsiniz. Burada bu sorun hakkında rapor verdim .
EDIT: sabit gibi görünüyor, ancak IDE üzerinde değil. Burada bildirildi .
Bunu dene...
1. çekilebilir xml (custom_layout.xml) oluşturun:
<?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. görünüm arka planınızı ekleyin
android:background="@drawable/custom_layout"
Düzeninizi yuvarlamak istiyorsanız, CardView'ı kullanmak en iyisidir, tasarımı güzelleştirmek için birçok özellik sağladı.
<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>
Bu card_view: cardCornerRadius = "5dp" ile yarıçapı değiştirebilirsiniz.
En iyi ve en basit yöntem, card_background özelliğini mizanpajınızda çizilebilir yapmaktır . Bu ayrıca Google'ın malzeme tasarımı yönergelerini de takip eder. Sadece bunu LinearLayout'a ekleyin:
android:background="@drawable/card_background"
Bunu çekilebilir dizininize ekleyin ve card_background.xml olarak adlandırın :
<?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>
Herhangi bir düzen için yuvarlak kenarlar elde etmek için CardView kullanın. Yuvarlatılmış düzen kenarlarını elde etmek için kart görünümü için card_view: cardCornerRadius = "5dp" kullanın .
<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>
Bunu yapmanın daha iyi bir yolu:
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>
Bu, API 21'in altında da çalışır ve size böyle bir şey verir:
Biraz daha fazla çaba daha iyi kontrol etmek istiyorsanız android.support.v7.widget.CardView
, cardCornerRadius
niteliğiyle kullanın (ve cardView ile eşlik eden alt gölgeden kurtulmak için elevation
özniteliği ayarlayın 0dp
). Ayrıca, bu API düzeyi 15 gibi düşük bir seviyede çalışacaktır.
Programlı köşe köşe yarıçapını ayarlama işlevi
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);
}
kullanma
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, dolguyu kontur ile aynı değere koyun, böylece kenarlık görülebilir, görüntü boyutu ne olursa olsun
@Gauravsapiens, parametrelerin ne etkileyeceğine dair makul bir kavrayış vermek için yorumlarımla cevap aldım.
<?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>
Sadece köşeleri yuvarlayan bir şekil oluşturmak istiyorsanız, dolgu ve konturu kaldırmak işe yarayacaktır. Katıyı da kaldırırsanız, aslında şeffaf bir arka plan üzerinde yuvarlatılmış köşeler oluşturmuş olursunuz.
Tembel olmak uğruna altında, yuvarlatılmış köşeleri olan düz beyaz bir arka plan olan altında bir şekil yarattım - tadını çıkarın! :)
<?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>
Xml'nizi çekilebilir olarak oluşturun, 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-->
ve sonra bunu layout.xml
android:background="@drawable/layout_background"
Malzeme Bileşenleri Kütüphanesi ile özel şekiller çizmekMaterialShapeDrawable
için kullanabilirsiniz .
LinearLayout'u xml düzeninize koymanız yeterlidir:
<LinearLayout
android:id="@+id/linear_rounded"
android:layout_width="match_parent"
android:layout_height="wrap_content"
..>
<!-- content ..... -->
</LinearLayout>
Sonra kodunuzda bir ShapeAppearanceModel
. Gibi bir şey:
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);
Not :: Malzeme bileşenleri kitaplığının 1.1.0 sürümünü gerektirir .
<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" />