欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

背景圓角

Shape

對(duì)于一般的背景,我們可以直接使用shape,這種方法天生支持設(shè)置四角不同的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在代碼層的實(shí)現(xiàn)為GradientDrawable,可以直接在代碼層構(gòu)建圓角背景

內(nèi)容圓角

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

有人發(fā)文說(shuō),可以通過(guò)outline.setConvexPath方法,實(shí)現(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)過(guò)實(shí)測(cè),這樣寫(xiě)是不行的,準(zhǔn)確的來(lái)說(shuō),在大部分系統(tǒng)上是不行的(MIUI上可以,我不知道是該夸它兼容性太好了還是該吐槽它啥,我的測(cè)試機(jī)用的小米,這導(dǎo)致我在最后的測(cè)試階段才發(fā)現(xiàn)這個(gè)問(wèn)題)

指出錯(cuò)誤方法后,讓我們來(lái)看看正確解法有哪些

CardView

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

有人可能要問(wèn)了,CardView不是只支持四角相同radius嗎?別急,且看我靈機(jī)一動(dòng)想出來(lái)的神奇嵌套大法

神奇嵌套大法

既然一個(gè)CardView只能設(shè)一個(gè)radius,那我多用幾個(gè)CardView嵌套是否能解決問(wèn)題呢?

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

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

上面的例子沒(méi)有嵌套,因?yàn)榱硪贿厸](méi)有圓角,那么如果我們需要上半部分為12dp的圓角,下半部分為6dp的圓角,我們可以這樣操作

手法和上面的例子一樣,不過(guò)我們?cè)谧钔鈱釉偾短滓粋€(gè)CardView,并且將其圓角設(shè)為較小的那個(gè)圓角大小6dp,將里面的CardView的圓角設(shè)置成較大的那個(gè)圓角大小12dp,具體實(shí)現(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ì)上就是大圓角套小圓角,大圓角的裁切范圍更大,會(huì)覆蓋小圓角裁切的范圍,從視覺(jué)上看就實(shí)現(xiàn)了兩邊的不同圓角

那么如果我們想進(jìn)一步實(shí)現(xiàn)三邊不同圓角或者四邊不同圓角呢?原理和上面是一樣的,只不過(guò)嵌套和占位會(huì)變得更加復(fù)雜,記住一個(gè)原則,小圓角在外,大圓角在內(nèi)即可,我直接把具體實(shí)現(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)容都是圖片,所以我們也可以直接對(duì)圖片進(jìn)行裁切,此時(shí)我們就可以自定義ImageView來(lái)將圖片裁剪出不同大小的圓角

clipPath

先說(shuō)這個(gè)方法的缺點(diǎn),那就是無(wú)法使用抗鋸齒,這一點(diǎn)缺陷注定了它無(wú)法被正式使用,但我們還是來(lái)看看他是如何實(shí)現(xiàn)的

首先,我們需要重寫(xiě)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,從左上順時(shí)針到左下)
    path.addRoundRect(0f, 0f, w.toFloat(), h.toFloat(), radii, Path.Direction.CW)
}

接著我們重寫(xiě)onDraw方法

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

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

PorterDuff

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

當(dāng)然,這種方法也有它的缺點(diǎn),那就是不能使用硬件加速,但相比無(wú)法使用抗鋸齒而言,這點(diǎn)缺點(diǎn)也就不算什么了

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

init {
    setLayerType(LAYER_TYPE_SOFTWARE, null)
}

然后重寫(xiě)onSizeChanged方法,在這個(gè)方法中,我們需要確定Path,構(gòu)造出相應(yīng)大小的BitmapCanvas,這倆是用來(lái)獲取原始無(wú)圓角的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!!)
}

接著我們重寫(xiě)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方法,獲取到原始無(wú)圓角的Bitmap,然后繪制Path,再通過(guò)PorterDuff的疊加效果繪制我們剛剛得到的原始Bitmap,由于PorterDuff.Mode.SRC_IN的效果是取兩層繪制交集,顯示上層,所以我們最終便獲得了一個(gè)帶圓角的圖片

截圖問(wèn)題

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

總結(jié)

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

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

相關(guān)文章

  • 深入分析Android加載so文件源碼

    深入分析Android加載so文件源碼

    這篇文章主要介紹了深入分析Android加載so文件源碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • android實(shí)現(xiàn)常駐通知欄遇到的問(wèn)題及解決辦法

    android實(shí)現(xiàn)常駐通知欄遇到的問(wèn)題及解決辦法

    這篇文章主要介紹了android實(shí)現(xiàn)常駐通知欄遇到的問(wèn)題及解決辦法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06
  • Android中實(shí)現(xiàn)密碼的隱藏和顯示的示例

    Android中實(shí)現(xiàn)密碼的隱藏和顯示的示例

    本篇文章主要介紹了Android中實(shí)現(xiàn)密碼的隱藏和顯示的示例,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2017-09-09
  • Android仿簡(jiǎn)書(shū)動(dòng)態(tài)searchview搜索欄效果

    Android仿簡(jiǎn)書(shū)動(dòng)態(tài)searchview搜索欄效果

    這篇文章主要為大家詳細(xì)介紹了Android仿簡(jiǎn)書(shū)動(dòng)態(tài)searchview效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • Android自定義帶動(dòng)畫(huà)效果的圓形ProgressBar

    Android自定義帶動(dòng)畫(huà)效果的圓形ProgressBar

    這篇文章主要為大家詳細(xì)介紹了Android自定義帶動(dòng)畫(huà)效果的圓形ProgressBar,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • Android 數(shù)據(jù)庫(kù)SQLite 寫(xiě)入SD卡的方法

    Android 數(shù)據(jù)庫(kù)SQLite 寫(xiě)入SD卡的方法

    如果手機(jī)沒(méi)有root,數(shù)據(jù)庫(kù)文件是無(wú)法查看到的,不方便調(diào)試。最好的辦法是把數(shù)據(jù)庫(kù)寫(xiě)進(jìn)SD卡。通過(guò)本文給大家介紹Android 數(shù)據(jù)庫(kù)SQLite 寫(xiě)入SD卡的方法,需要的朋友參考下吧
    2016-04-04
  • Android搜索框通用版

    Android搜索框通用版

    這篇文章主要為大家詳細(xì)介紹了Android搜索框通用版的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-06-06
  • Android6.0 消息機(jī)制原理解析

    Android6.0 消息機(jī)制原理解析

    這篇文章主要為大家詳細(xì)介紹了Android6.0 消息機(jī)制原理,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Android自定義流式布局實(shí)現(xiàn)淘寶搜索記錄

    Android自定義流式布局實(shí)現(xiàn)淘寶搜索記錄

    這篇文章主要為大家詳細(xì)介紹了Android自定義流式布局實(shí)現(xiàn)淘寶搜索記錄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-10-10
  • Android解析Intent Filter的方法

    Android解析Intent Filter的方法

    這篇文章主要介紹了Android解析Intent Filter的方法,較為詳細(xì)的分析了Intent解析的原理與相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07

最新評(píng)論