web-dev-qa-db-ja.com

角の丸いレイアウトを作るには?

角の丸いレイアウトを作成する方法丸みを帯びた角をLinearLayoutに適用したいです。

421
Addy

1:drawablesに layout_bg.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="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を追加する

Android:background="@drawable/layout_bg"
870
Gaurav Arora

API 21以降の場合、クリップビューを使用

丸いアウトラインクリッピングは、API 21のViewクラスに追加されました。詳細については、this training doc またはthis reference を参照してください。

この内蔵機能により、角の丸い角を簡単に実装できます。あらゆるビューやレイアウトで機能し、適切なクリッピングをサポートします。

ここにすべきことは:

  • 丸みを帯びた形状のドロアブルを作成し、それをビューの背景として設定します。Android:background="@drawable/round_outline"
  • ドキュメントによると、あなたがする必要があるのはこれだけです:Android:clipToOutline="true"

残念ながら、 バグ のようであり、そしてこのXML属性は現在認識されていません。幸運にも、Javaでクリッピングを設定することができます。

  • あなたの活動や断片の中で:View.setClipToOutline(true)

外観は次のとおりです。

enter image description here

ImageViewに関する特記事項

setClipToOutline()は、ビューの背景がシェイプ描画可能に設定されている場合にのみ機能します。この背景形状が存在する場合、Viewは背景の輪郭をクリッピングおよびシャドウイングの目的で境界として扱います。

つまり、ImageViewの隅をsetClipToOutline()で丸めたい場合は、画像はAndroid:srcではなくAndroid:backgroundから来る必要があります(丸みを帯びた形状に背景が使用されるため)。 srcの代わりに背景を使用して画像を設定する必要がある場合は、このネストされたビューの回避策を使用できます。

  • 背景を描画可能な形に設定して外側のレイアウトを作成します。
  • (レイアウトなしで)ImageViewの周りにそのレイアウトをラップします。
  • ImageView(レイアウトの他の部分も含む)は外側のレイアウトの丸みを帯びた形状に切り取られます。
85
hungryghost

これは、白い背景、黒い枠線、角の丸いドロウアブルを作成するためのXMLファイルのコピーです。

 <?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>

描画可能なディレクトリにxmlファイルとして保存します。リソース名(R.drawable.your_xml_name)を使用して描画可能な背景(アイコンまたはリソースファイル)を使用するのと同じように使用します。

56
kyogs

私はこのようにしました:

スクリーンショットをチェックする:

Relative layout Background

drawable フォルダーにcustom_rectangle.xmlという名前の 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>

長方形の背景 on 表示 を適用します。

mView.setBackground(R.drawlable.custom_rectangle);

完了

25
Hiren Patel

Android v7サポートライブラリのCardViewを使用してください。それは少し重いですが、それはすべての問題を解決し、そして十分に簡単です。 set drawable backgroundメソッドとは異なり、サブビューを正常に切り取ることができます。

<?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>
24
Evan JIANG

私はそれを行うためのより良い方法は2つのことをマージすることだと思います:

  1. here のように、レイアウトのビットマップを作成します。

  2. here のように、ビットマップから丸い描画可能な図形を作成します。

  3. imageViewにドロウアブルを設定します。

これは、コーナーを持つコンテンツを持つなど、他のソリューションでは解決できなかったケースを処理します。

2ではなく単層で表示されるので、もう少しGPUにやさしいと思います。

唯一の良い方法は、完全にカスタマイズされたビューを作成することですが、それは多くのコードであり、時間がかかるかもしれません。私がここで提案したのは両方の長所の中で一番だと思います。

これがどのように行われることができるかの抜粋です:

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);
    }

}

編集: "RoundKornersLayouts"ライブラリ に基づいて、ニースの代替を見つけました。丸めて、拡張したいすべてのレイアウトクラスに使用されるクラスを用意します。

//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()
    }

}

次に、カスタマイズした各レイアウトクラスに、次のようなコードを追加します。

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) }

}

属性をサポートしたい場合は、ライブラリに書かれているようにこれを使用してください。

<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>

もう1つの方法は、ほとんどの用途では簡単かもしれません:MaterialCardViewを使用します。丸みのある角、線の色と幅、および高さをカスタマイズできます。

例:

<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>

そしてその結果:

enter image description here

あなたがそれを使用するなら、ストロークの端にわずかなアーティファクト問題があることに注意してください(そこにコンテンツのいくつかのピクセルを残す)。ズームインすると気付くでしょう。この問題について私は報告しました here

20

これを試して...

1.create - drawable xml (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.ビューの背景を追加します

Android:background="@drawable/custom_layout"
10

それを行うより良い方法は次のとおりです。

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>

これはAPI 21の下でも機能し、次のようになります。

Result


もう少し努力して制御を改善したい場合は、cardCornerRadius属性を付けてAndroid.support.v7.widget.CardViewを使用します(そしてcardViewで付随するドロップシャドウを削除するにはelevation属性を0dpに設定します)。また、これは15という低いAPIレベルでも機能します。

5
Abdul Wasae

あなたがあなたのレイアウトを丸くしたいならば、それはデザインを美しくするためにCardViewを使うことが最善です、それは多くの機能を提供しました。

<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>

このcard_view:cardCornerRadius = "5dp"を使えば、半径を変更することができます。

5

レイアウトの丸みを帯びた縁にするには、CardViewを使用してください。 card_view:cardCornerRadius = "5dp" cardviewを使用して、丸みを帯びたレイアウトエッジを取得します。

<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>
4
vishnuc156
<?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、ストロークと同じ値をパディングするだけで、画像サイズに関係なく境界線を表示できます

3
paezinc

最も簡単で簡単な方法は、レイアウトに card_background drawableを使用することです。これはグーグルの材料設計ガイドラインにも従う。あなたの中にこれを含めるだけです。

Android:background="@drawable/card_background"

これを描画可能ディレクトリに追加して、 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>
3

プログラムで角半径を設定するための関数

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);
}

を使う

GradientDrawable gradientDrawable = new GradientDrawable();
gradientDrawable.setColor(Color.GREEN);
setCornerRadius(gradientDrawable, 20f);
//or setCornerRadius(gradientDrawable, 20f, 40f, 60f, 80f); 

view.setBackground(gradientDrawable);
3
Phan Van Linh

私は@gauravsapiens答えを私のコメントと一緒に取って、あなたにパラメータが何をもたらすのかについての合理的な不安を与えます。

<?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>

角を丸める図形を作成するだけの場合は、パディングとストロークを削除してください。ソリッドも削除すると、事実上、透明な背景に丸みを帯びた角が作成されます。

怠け者のために、私はその下に丸みを帯びた角を持つ単色の白い背景である図形を作成しました - お楽しみください! :)

<?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>
1
ZooMagic
Create your 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-->

Finally in your layout.xml file write below line

 Android:background="@drawable/layout_background"
0
 <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" />
0
keval patel