android - studio - كيفية جعل تخطيط مع زوايا مدورة..؟




xml orientation android (11)

1: تعريف layout_bg.xml في 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: أضف layout_bg.xml كخلفية للتخطيط

android:background="@drawable/layout_bg"

https://code.i-harness.com

كيف يمكنني عمل تخطيط بأركان مستديرة؟ أرغب في تطبيق الزوايا الدائرية على LinearLayout .


أعتقد أن أفضل طريقة للقيام بذلك هي دمج شيئين:

  1. جعل صورة نقطية للتخطيط ، كما هو موضح here .

  2. جعل drawable مقربة من الصورة النقطية كما هو موضح here

  3. ضبط drawable على imageView.

سيعالج هذا الحالات التي فشلت الحلول الأخرى في حلها ، مثل وجود محتوى يحتوي على أركان.

أظن أنه أكثر ملاءمة لمعالجته ، لأنه يظهر طبقة واحدة بدلاً من 2.

الطريقة الوحيدة الأفضل هي إنشاء عرض مخصص تمامًا ، ولكن هذا كثير من التعليمات البرمجية وقد يستغرق الكثير من الوقت. أعتقد أن ما اقترحته هنا هو أفضل ما في العالمين.

في ما يلي مقتطف من كيفية القيام بذلك:

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" . امتلاك فصل سيتم استخدامه لجميع فئات التصميم التي ترغب في توسيعها ، بحيث يتم تقريبها:

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

أفضل وأبسط طريقة هي استخدام card_background drawable في تخطيطك. يتبع هذا أيضًا إرشادات تصميم المواد في Google. فقط قم بتضمين هذا فيك LinearLayout:

android:background="@drawable/card_background"

أضف هذا إلى دليل drawable الخاص بك وقم بتسميته 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>

إليك نسخة من ملف 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)


استخدم CardView في مكتبة دعم android v7. على الرغم من أنه ثقيل بعض الشيء ، إلا أنه يحل جميع المشاكل ، وهو سهل بما فيه الكفاية. ليس مثل طريقة تعيين الخلفية القابلة للسحب ، يمكن أن تقسم المشاهد بنجاح.

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

استخدم CardView للحصول على حواف مدورة لأي تخطيطات. استخدم card_view: cardCornerRadius = "5dp" لمشاهدة البطاقة للحصول على حواف مدورة.

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

لقد اتخذت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>

لقد فعلت هذا الطريق:

فحص لقطة الشاشة:

إنشاء ملف 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>

الآن قم بتطبيق خلفية المستطيل على طريقة العرض :

mView.setBackground(R.drawlable.custom_rectangle);

فعله


بالنسبة إلى واجهة برمجة التطبيقات 21+ ، استخدم "ملفات الفيديو الشخصية"

تمت إضافة لقطة المخطط التفصيلي إلى فصل View في API 21. راجع مستند التدريب هذا أو هذا reference لمزيد من المعلومات.

هذه الميزة المدمجة تجعل الزوايا المدورة سهلة التنفيذ. يعمل على أي عرض أو تخطيط ويدعم لقطة مناسبة.

إليك ما يجب فعله:

  • إنشاء شكل مستدير android:background="@drawable/round_outline" : android:background="@drawable/round_outline"
  • وفقًا للوثائق ، فكل ما عليك فعله هو: android:clipToOutline="true"

للأسف ، يبدو أن هناك خللًا ، ولا يتم التعرف على سمة XML الحالية في الوقت الحالي. لحسن الحظ ، يمكننا ضبط القصاصة في جافا:

  • في النشاط أو الجزء الخاص بك: View.setClipToOutline(true)

ما يبدو عليه:

ملاحظة خاصة حول ImageViews

لا يعمل setClipToOutline() إلا عند تعيين خلفية العرض على شكل قابل للرسم. في حالة وجود شكل الخلفية هذا ، يتعامل العرض مع المخطط التفصيلي للخلفية كحدود لأغراض القطع والتظليل.

هذا يعني أنه إذا كنت ترغب في تقريب الزوايا على ImageView مع setClipToOutline() ، يجب أن تأتي الصورة من android:src بدلاً من android:background (حيث يتم استخدام الخلفية للشكل الدائري). إذا كنت تستخدم الخلفية لتعيين صورتك بدلاً من src ، فيمكنك استخدام طرق العرض المتداخلة هذه:

  • إنشاء تخطيط خارجي مع تعيين الخلفية الخاصة به إلى الشكل الخاص بك drawable
  • التفاف هذا التخطيط حول ImageView الخاص بك (مع عدم وجود الحشو)
  • سيتم الآن قص ImageView (بما في ذلك أي شيء آخر في التخطيط) إلى الشكل الدائري الخاص بالتخطيط الخارجي.

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


If you would like to make your layout rounded, it is best to use the CardView, it provided many features to make the design beautiful
<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>

With this card_view:cardCornerRadius="5dp", you can change the radius.




layout