最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Android如何實現(xiàn)不同大小的圓角

 更新時間:2023年08月10日 08:40:45   作者:dreamgyf  
在開發(fā)過程中,設計常常會有一些比較炫酷的想法,比如兩邊不一樣大小的圓角啦,甚至四角的radius各不相同,對于這種情況我們該怎么實現(xiàn)呢,本文小編就和大家來聊聊,需要的朋友可以參考下

背景圓角

Shape

對于一般的背景,我們可以直接使用shape,這種方法天生支持設置四角不同的radius,比如:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#8358FF" />
    <corners
        android:bottomLeftRadius="10dp"
        android:bottomRightRadius="20dp"
        android:topLeftRadius="30dp"
        android:topRightRadius="40dp" />
</shape>

小貼士:shape在代碼層的實現(xiàn)為GradientDrawable,可以直接在代碼層構(gòu)建圓角背景

內(nèi)容圓角

很多情況下,設置背景的四邊不同圓角并不能滿足我們,大多數(shù)情況下,我們需要連著里面的內(nèi)容一起切圓角,這里我們需要先指正一下網(wǎng)上的一個錯誤寫法

有人發(fā)文說,可以通過outline.setConvexPath方法,實現(xiàn)四角不同radius,如下:

outline?.setConvexPath(
    Path().apply {
        addRoundRect(
            0f, 0f, width.toFloat(), height.toFloat(),
            floatArrayOf(
                topLeftRadius,
                topLeftRadius,
                topRightRadius,
                topRightRadius,
                bottomRightRadius,
                bottomRightRadius,
                bottomLeftRadius,
                bottomLeftRadius
            ),
            Path.Direction.CCW
        )
    }
)

經(jīng)過實測,這樣寫是不行的,準確的來說,在大部分系統(tǒng)上是不行的(MIUI上可以,我不知道是該夸它兼容性太好了還是該吐槽它啥,我的測試機用的小米,這導致我在最后的測試階段才發(fā)現(xiàn)這個問題)

指出錯誤方法后,讓我們來看看正確解法有哪些

CardView

說到切內(nèi)容圓角,我們自然而然會去想到CardView,其實CardView的圓角也是通過Outline實現(xiàn)的

有人可能要問了,CardView不是只支持四角相同radius嗎?別急,且看我靈機一動想出來的神奇嵌套大法

神奇嵌套大法

既然一個CardView只能設一個radius,那我多用幾個CardView嵌套是否能解決問題呢?

舉個最簡單的例子,比如說設計想要上半部分為12dp的圓角,下半部分沒有圓角,我們需要一個輔助View,讓他的頂部和父布局的底部對齊,然后設置成圓角大小的高度或者margin,接著使用CardView,讓它的底部對齊這個輔助View的底部,再設置一個圓角大小的padding,這樣,由于CardView超出了父布局的邊界,所以底部的圓角不會顯示出來,再由于我們設置了恰好的padding,所以CardView里面的內(nèi)容也能完整展示,可謂完美,實例如下:

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <Space
        android:id="@+id/guideline"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginTop="12dp"
        app:layout_constraintTop_toBottomOf="parent" />
    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:cardBackgroundColor="@android:color/transparent"
        app:cardCornerRadius="12dp"
        app:cardElevation="0dp"
        app:contentPaddingBottom="12dp"
        app:layout_constraintBottom_toBottomOf="@+id/guideline">
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:adjustViewBounds="true"
            android:background="#8358FF" />
    </androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>

上面的例子沒有嵌套,因為另一邊沒有圓角,那么如果我們需要上半部分為12dp的圓角,下半部分為6dp的圓角,我們可以這樣操作

手法和上面的例子一樣,不過我們在最外層再嵌套一個CardView,并且將其圓角設為較小的那個圓角大小6dp,將里面的CardView的圓角設置成較大的那個圓角大小12dp,具體實現(xiàn)如下:

<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:cardBackgroundColor="@android:color/transparent"
    app:cardCornerRadius="6dp"
    app:cardElevation="0dp"
    app:layout_constraintTop_toTopOf="parent">
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <Space
            android:id="@+id/guideline"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_marginTop="12dp"
            app:layout_constraintTop_toBottomOf="parent" />
        <androidx.cardview.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:cardBackgroundColor="@android:color/transparent"
            app:cardCornerRadius="12dp"
            app:cardElevation="0dp"
            app:contentPaddingBottom="12dp"
            app:layout_constraintBottom_toTopOf="@+id/guideline">
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="300dp"
                android:adjustViewBounds="true"
                android:background="#8358FF" />
        </androidx.cardview.widget.CardView>
    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

本質(zhì)上就是大圓角套小圓角,大圓角的裁切范圍更大,會覆蓋小圓角裁切的范圍,從視覺上看就實現(xiàn)了兩邊的不同圓角

那么如果我們想進一步實現(xiàn)三邊不同圓角或者四邊不同圓角呢?原理和上面是一樣的,只不過嵌套和占位會變得更加復雜,記住一個原則,小圓角在外,大圓角在內(nèi)即可,我直接把具體實現(xiàn)貼在下面,各位自取即可:

  • 三邊不同圓角(左下6dp,左上12dp,右上24dp)
<androidx.constraintlayout.widget.ConstraintLayout 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">
    <Space
        android:id="@+id/guideline"
        android:layout_width="6dp"
        android:layout_height="match_parent"
        app:layout_constraintStart_toEndOf="parent" />
    <androidx.cardview.widget.CardView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:cardBackgroundColor="@android:color/transparent"
        app:cardCornerRadius="6dp"
        app:cardElevation="0dp"
        app:contentPaddingRight="6dp"
        app:layout_constraintEnd_toEndOf="@+id/guideline"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">
        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <Space
                android:id="@+id/guideline2"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_marginTop="12dp"
                app:layout_constraintTop_toBottomOf="parent" />
            <androidx.cardview.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:cardBackgroundColor="@android:color/transparent"
                app:cardCornerRadius="12dp"
                app:cardElevation="0dp"
                app:contentPaddingBottom="12dp"
                app:layout_constraintBottom_toTopOf="@+id/guideline2">
                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent">
                    <Space
                        android:id="@+id/guideline3"
                        android:layout_width="0dp"
                        android:layout_height="match_parent"
                        android:layout_marginEnd="24dp"
                        app:layout_constraintEnd_toStartOf="parent" />
                    <Space
                        android:id="@+id/guideline4"
                        android:layout_width="match_parent"
                        android:layout_height="0dp"
                        android:layout_marginTop="24dp"
                        app:layout_constraintTop_toBottomOf="parent" />
                    <androidx.cardview.widget.CardView
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        app:cardBackgroundColor="@android:color/transparent"
                        app:cardCornerRadius="24dp"
                        app:cardElevation="0dp"
                        app:contentPaddingBottom="24dp"
                        app:contentPaddingLeft="24dp"
                        app:layout_constraintBottom_toBottomOf="@+id/guideline4"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="@+id/guideline3">
                        <ImageView
                            android:layout_width="match_parent"
                            android:layout_height="300dp"
                            android:adjustViewBounds="true"
                            android:background="#8358FF" />
                    </androidx.cardview.widget.CardView>
                </androidx.constraintlayout.widget.ConstraintLayout>
            </androidx.cardview.widget.CardView>
        </androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
  • 四邊不同圓角(左下6dp,左上12dp,右上24dp,右下48dp)
<androidx.constraintlayout.widget.ConstraintLayout 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">
    <Space
        android:id="@+id/guideline"
        android:layout_width="6dp"
        android:layout_height="match_parent"
        app:layout_constraintStart_toEndOf="parent" />
    <androidx.cardview.widget.CardView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:cardBackgroundColor="@android:color/transparent"
        app:cardCornerRadius="6dp"
        app:cardElevation="0dp"
        app:contentPaddingRight="6dp"
        app:layout_constraintEnd_toEndOf="@+id/guideline"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">
        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <Space
                android:id="@+id/guideline2"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_marginTop="12dp"
                app:layout_constraintTop_toBottomOf="parent" />
            <androidx.cardview.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:cardBackgroundColor="@android:color/transparent"
                app:cardCornerRadius="12dp"
                app:cardElevation="0dp"
                app:contentPaddingBottom="12dp"
                app:layout_constraintBottom_toTopOf="@+id/guideline2">
                <androidx.constraintlayout.widget.ConstraintLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent">
                    <Space
                        android:id="@+id/guideline3"
                        android:layout_width="0dp"
                        android:layout_height="match_parent"
                        android:layout_marginEnd="24dp"
                        app:layout_constraintEnd_toStartOf="parent" />
                    <Space
                        android:id="@+id/guideline4"
                        android:layout_width="match_parent"
                        android:layout_height="0dp"
                        android:layout_marginTop="24dp"
                        app:layout_constraintTop_toBottomOf="parent" />
                    <androidx.cardview.widget.CardView
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        app:cardBackgroundColor="@android:color/transparent"
                        app:cardCornerRadius="24dp"
                        app:cardElevation="0dp"
                        app:contentPaddingBottom="24dp"
                        app:contentPaddingLeft="24dp"
                        app:layout_constraintBottom_toBottomOf="@+id/guideline4"
                        app:layout_constraintEnd_toEndOf="parent"
                        app:layout_constraintStart_toStartOf="@+id/guideline3">
                        <androidx.constraintlayout.widget.ConstraintLayout
                            android:layout_width="match_parent"
                            android:layout_height="match_parent">
                            <Space
                                android:id="@+id/guideline5"
                                android:layout_width="0dp"
                                android:layout_height="match_parent"
                                android:layout_marginEnd="48dp"
                                app:layout_constraintEnd_toStartOf="parent" />
                            <Space
                                android:id="@+id/guideline6"
                                android:layout_width="match_parent"
                                android:layout_height="0dp"
                                android:layout_marginBottom="48dp"
                                app:layout_constraintBottom_toTopOf="parent" />
                            <androidx.cardview.widget.CardView
                                android:layout_width="0dp"
                                android:layout_height="wrap_content"
                                app:cardBackgroundColor="@android:color/transparent"
                                app:cardCornerRadius="48dp"
                                app:cardElevation="0dp"
                                app:contentPaddingLeft="48dp"
                                app:contentPaddingTop="48dp"
                                app:layout_constraintEnd_toEndOf="parent"
                                app:layout_constraintStart_toStartOf="@+id/guideline5"
                                app:layout_constraintTop_toTopOf="@+id/guideline6">
                                <ImageView
                                    android:layout_width="match_parent"
                                    android:layout_height="300dp"
                                    android:adjustViewBounds="true"
                                    android:background="#8358FF" />
                            </androidx.cardview.widget.CardView>
                        </androidx.constraintlayout.widget.ConstraintLayout>
                    </androidx.cardview.widget.CardView>
                </androidx.constraintlayout.widget.ConstraintLayout>
            </androidx.cardview.widget.CardView>
        </androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>

自定義ImageView

由于大部分裁切內(nèi)容的需求,其中的內(nèi)容都是圖片,所以我們也可以直接對圖片進行裁切,此時我們就可以自定義ImageView來將圖片裁剪出不同大小的圓角

clipPath

先說這個方法的缺點,那就是無法使用抗鋸齒,這一點缺陷注定了它無法被正式使用,但我們還是來看看他是如何實現(xiàn)的

首先,我們需要重寫ImageViewonSizeChanged方法,為我們的Path確定路線

override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
    super.onSizeChanged(w, h, oldw, oldh)
    path.reset()
    //這里的radii便是我們自定義的四邊圓角大小的數(shù)組(size為8,從左上順時針到左下)
    path.addRoundRect(0f, 0f, w.toFloat(), h.toFloat(), radii, Path.Direction.CW)
}

接著我們重寫onDraw方法

override fun onDraw(canvas: Canvas) {
    canvas.clipPath(path)
    super.onDraw(rawBitmapCanvas)
}

網(wǎng)上有的教程說要設置PaintFlagsDrawFilter,但實際上就算為這個PaintFlagsDrawFilter設置了Paint.ANTI_ALIAS_FLAG抗鋸齒屬性也沒用,抗鋸齒只在使用了Paint的情況下才可以生效

PorterDuff

既然clipPath無法使用抗鋸齒,那我們可以換一條路線曲線救國,那就是使用PorterDuff

當然,這種方法也有它的缺點,那就是不能使用硬件加速,但相比無法使用抗鋸齒而言,這點缺點也就不算什么了

首先,我們要在構(gòu)造方法中禁用硬件加速

init {
    setLayerType(LAYER_TYPE_SOFTWARE, null)
}

然后重寫onSizeChanged方法,在這個方法中,我們需要確定Path,構(gòu)造出相應大小的BitmapCanvas,這倆是用來獲取原始無圓角的Bitmap

override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
    super.onSizeChanged(w, h, oldw, oldh)
    path.reset()
    path.addRoundRect(0f, 0f, w.toFloat(), h.toFloat(), radii, Path.Direction.CW)
    rawBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
    rawBitmapCanvas = Canvas(rawBitmap!!)
}

接著我們重寫onDraw方法

private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
private val xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
override fun onDraw(canvas: Canvas) {
    val rawBitmap = rawBitmap ?: return
    val rawBitmapCanvas = rawBitmapCanvas ?: return
    super.onDraw(rawBitmapCanvas)
    canvas.drawPath(path, paint)
    paint.xfermode = xfermode
    canvas.drawBitmap(rawBitmap, 0f, 0f, paint)
    paint.xfermode = null
}

這里,我們調(diào)用父類的onDraw方法,獲取到原始無圓角的Bitmap,然后繪制Path,再通過PorterDuff的疊加效果繪制我們剛剛得到的原始Bitmap,由于PorterDuff.Mode.SRC_IN的效果是取兩層繪制交集,顯示上層,所以我們最終便獲得了一個帶圓角的圖片

截圖問題

如果想要將View截圖成Bitmap,在Android 8.0及以上系統(tǒng)中我們可以使用PixelCopy,此時使用CardViewOutline裁切的圓角不會有任何問題,而在Android 8.0以下的系統(tǒng)中,通常我們是構(gòu)建一個帶BitmapCanvas,然后對要截圖的View調(diào)用draw方法達成截圖效果,而在這種情況下,使用CardViewOutline裁切的圓角便會出現(xiàn)無效的情況(截圖出來的Bitmap中,圓角沒了),這種情況的出現(xiàn)似乎也和硬件加速有關(guān),針對這種問題,我個人的想法是準備兩套布局,8.0以上使用CardViewOutline,截圖使用PixelCopy,8.0以下使用PorterDuff方案直接裁切圖片,最大程度避免性能損耗

總結(jié)

以上就是我本人目前對Android實現(xiàn)不同大小的圓角的一些想法和遇到的問題,至于CardView嵌套會不會帶來什么性能問題,我目前并沒有做驗證,各位小伙伴有什么更好的解決方案,歡迎在評論區(qū)指出,大家一起集思廣益。

到此這篇關(guān)于詳解Android如何實現(xiàn)不同大小的圓角的文章就介紹到這了,更多相關(guān)Android實現(xiàn)不同大小的圓角內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

四子王旗| 陆良县| 司法| 丰台区| 婺源县| 鹤庆县| 旌德县| 塔河县| 定结县| 青冈县| 云林县| 博兴县| 江口县| 宁城县| 海门市| 大埔县| 晴隆县| 杂多县| 稷山县| 内丘县| 广宗县| 收藏| 友谊县| 宜兴市| 云霄县| 五大连池市| 天峻县| 昌宁县| 石泉县| 南投县| 波密县| 中西区| 鲁甸县| 习水县| 龙口市| 常宁市| 永春县| 英吉沙县| 酉阳| 乐昌市| 集贤县|