Pertanyaan Cara membuat tampilan di android dengan sudut membulat


Saya mencoba membuat tampilan di android dengan ujung bulat. Solusi yang saya temukan sejauh ini adalah mendefinisikan bentuk dengan sudut membulat dan menggunakannya sebagai latar belakang pandangan itu.

Inilah yang saya lakukan, tentukan drawable seperti yang diberikan di bawah ini

<padding
android:top="2dp"
android:bottom="2dp"/>
<corners android:bottomRightRadius="20dp"
android:bottomLeftRadius="20dp"
android:topLeftRadius="20dp"
android:topRightRadius="20dp"/>

Sekarang saya menggunakan ini sebagai latar belakang untuk tata letak saya seperti di bawah ini

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

Ini bekerja baik-baik saja, saya dapat melihat bahwa pandangan itu memiliki tepian yang membulat.

Tapi tata letak saya punya banyak pandangan anak lain di dalamnya. Katakan ImageView atau MapView. Ketika saya menempatkan ImageView di dalam tata letak di atas, sudut-sudut gambar tidak dipotong / dipotong, tetapi tampak penuh.

Saya telah melihat cara lain untuk membuatnya bekerja seperti yang dijelaskan sini.

Tetapi apakah ada metode untuk menetapkan sudut bulat untuk melihat dan semua   pandangan anak terkandung dalam tampilan utama yang telah dibulatkan   sudut?

Terima kasih.


49
2017-09-27 12:41


asal


Jawaban:


Pendekatan lain adalah membuat kelas tata letak khusus seperti yang ada di bawah ini. Tata letak ini pertama kali menarik isinya ke bitmap offscreen, menutupi bitmap offscreen dengan rect bulat dan kemudian menggambar bitmap offscreen pada kanvas yang sebenarnya.

Saya mencobanya dan tampaknya berhasil (setidaknya untuk testcase sederhana saya). Ini tentu saja akan mempengaruhi kinerja dibandingkan dengan tata letak biasa.

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

Gunakan ini seperti tata letak normal:

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

97
2017-10-05 08:57



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>

dan di dalam tata letak Anda

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

32
2017-10-03 06:46



Atau Anda bisa menggunakan android.support.v7.widget.CardView seperti ini:

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

31
2018-05-13 01:45



Jika Anda mengalami masalah saat menambahkan pendengar sentuhan ke tata letak. Gunakan tata letak ini sebagai tata letak induk.

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


}

sebagai

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

16
2018-02-08 10:04



buat xml round.xml di folder drawable

<solid android:color="#FFFFFF" />
<stroke android:width=".05dp" android:color="#d2d2d2" />
<corners android:topLeftRadius="5dp" android:topRightRadius="5dp" android:bottomLeftRadius="5dp" android:bottomRightRadius="5dp" />

kemudian gunakan round.xml sebagai latar belakang untuk item .. Kemudian akan memberikan sudut bulat


8
2017-10-04 05:00



Di Android L Anda hanya dapat menggunakan Lihat.setClipToOutline untuk mendapatkan efek itu. Di versi sebelumnya tidak ada cara untuk hanya menjiplak konten dari ViewGroup acak dalam bentuk tertentu.

Anda harus memikirkan sesuatu yang akan memberi Anda efek yang sama:

  • Jika Anda hanya membutuhkan sudut membulat di ImageView, Anda dapat menggunakan shader untuk 'melukis' gambar di atas bentuk yang Anda gunakan sebagai latar belakang. Melihat perpustakaan ini untuk sebuah contoh.

  • Jika Anda benar-benar membutuhkan setiap anak untuk dijepitkan, mungkin Anda bisa melihat lagi tata letak Anda? Satu dengan latar belakang warna apa pun yang Anda gunakan, dan 'lubang' bundar di tengah? Anda benar-benar dapat membuat ViewGroup kustom yang menggambar bentuk itu di atas setiap anak yang mengesampingkan metode onDraw.


6
2017-10-03 15:55



Jawaban Jaap van Hengstum bekerja dengan baik namun saya pikir itu mahal dan jika kita menerapkan metode ini pada Tombol misalnya, efek sentuhan hilang karena tampilan dirender sebagai bitmap.

Bagi saya metode terbaik dan yang paling sederhana adalah menerapkan topeng pada tampilan, seperti itu:

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

4
2017-12-12 10:26



ikuti tutorial ini dan semua diskusi di bawahnya - http://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/

menurut posting ini ditulis oleh Guy Romain, salah satu pengembang terkemuka dari seluruh toolkit UI Android, adalah mungkin untuk membuat wadah (dan semua pandangan anaknya) dengan sudut membulat, tetapi ia menjelaskan bahwa itu terlalu mahal (dari pertunjukan masalah render).

Saya akan merekomendasikan Anda untuk pergi sesuai dengan jabatannya, dan jika Anda ingin sudut bulat, lalu terapkan sudut bulat ImageView menurut posting ini. kemudian, Anda dapat menempatkannya di dalam wadah dengan latar belakang apa pun, dan Anda akan mendapatkan pengaruh yang Anda inginkan.

itulah yang saya lakukan juga akhirnya.


2
2017-10-03 18:29