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

Android漲姿勢(shì)知識(shí)點(diǎn)之你沒(méi)用過(guò)的BadgeDrawable

 更新時(shí)間:2022年09月03日 08:51:02   作者:yechaoa  
現(xiàn)在Android中有許多的應(yīng)用仿蘋(píng)果的在應(yīng)用圖標(biāo)上顯示小紅點(diǎn),下面這篇文章主要給大家介紹了關(guān)于Android漲姿勢(shì)知識(shí)點(diǎn)之你沒(méi)用過(guò)的BadgeDrawable的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下

1.前言

通常情況下,我們?cè)谧鲂〖t點(diǎn)效果的時(shí)候,會(huì)有兩種選擇:

自定義BadgeView,然后設(shè)置給目標(biāo)Viewxml寫(xiě)一個(gè)View,然后設(shè)置shape

有的同學(xué)可能會(huì)想,能實(shí)現(xiàn)不就行了嗎,是的,代碼優(yōu)不優(yōu)雅的不重要,代碼和人只要有一個(gè)能跑就行…

不過(guò),今天來(lái)介紹一種不同的方式來(lái)實(shí)現(xiàn)小紅點(diǎn)效果,或許會(huì)讓你眼前一亮~

2.效果

3.簡(jiǎn)介

  • 用途:給View添加動(dòng)態(tài)顯示信息(小紅點(diǎn)提示效果)
  • app主題需使用Theme.MaterialComponents.*
  • api 要求18+ 也就Android 4.3以上(api等級(jí)對(duì)應(yīng)關(guān)系見(jiàn)文末)

4.實(shí)現(xiàn)拆解

4.1TabLayout

xml:

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:background="#FFFAF0"
        android:textAllCaps="false"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/include"
        app:tabIndicator="@drawable/shape_tab_indicator"
        app:tabIndicatorColor="@color/colorPrimary"
        app:tabIndicatorFullWidth="false"
        app:tabMaxWidth="200dp"
        app:tabMinWidth="100dp"
        app:tabMode="fixed"
        app:tabSelectedTextColor="@color/colorPrimary"
        app:tabTextColor="@color/gray">

        <com.google.android.material.tabs.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Android" />

        <com.google.android.material.tabs.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Kotlin" />

        <com.google.android.material.tabs.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Flutter" />

    </com.google.android.material.tabs.TabLayout>

kotlin:

    private fun initTabLayout() {
        // 帶數(shù)字小紅點(diǎn)
        mBinding.tabLayout.getTabAt(0)?.let {
            it.orCreateBadge.apply {
                backgroundColor = ContextCompat.getColor(this@BadgeDrawableActivity, R.color.red)
                badgeTextColor = ContextCompat.getColor(this@BadgeDrawableActivity, R.color.white)
                number = 6
            }
        }

        // 不帶數(shù)字小紅點(diǎn)
        mBinding.tabLayout.getTabAt(1)?.let {
            it.orCreateBadge.apply {
                backgroundColor = ContextCompat.getColor(this@BadgeDrawableActivity, R.color.red)
                badgeTextColor = ContextCompat.getColor(this@BadgeDrawableActivity, R.color.white)
            }
        }
    }

4.2.TextView

xml:

    <TextView
        android:id="@+id/tv_badge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:text="小紅點(diǎn)示例"
        android:textAllCaps="false"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tab_layout" />

kotlin:

    private fun initTextView() {
        // 在視圖樹(shù)變化
        mBinding.tvBadge.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                BadgeDrawable.create(this@BadgeDrawableActivity).apply {
                    badgeGravity = BadgeDrawable.TOP_END
                    number = 6
                    backgroundColor = ContextCompat.getColor(this@BadgeDrawableActivity, R.color.colorPrimary)
                    isVisible = true
                    BadgeUtils.attachBadgeDrawable(this, mBinding.tvBadge)
                }
                mBinding.tvBadge.viewTreeObserver.removeOnGlobalLayoutListener(this)
            }
        })
    }

4.3.Button

xml:

    <FrameLayout
        android:id="@+id/fl_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:padding="10dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tv_badge">

        <com.google.android.material.button.MaterialButton
            android:id="@+id/mb_badge"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button小紅點(diǎn)示例" />

    </FrameLayout>

kotlin:

    private fun initButton() {
        mBinding.mbBadge.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
            @SuppressLint("UnsafeOptInUsageError")
            override fun onGlobalLayout() {
                BadgeDrawable.create(this@BadgeDrawableActivity).apply {
                    badgeGravity = BadgeDrawable.TOP_START
                    number = 6
                    backgroundColor = ContextCompat.getColor(this@BadgeDrawableActivity, R.color.red)
                    // MaterialButton本身有間距,不設(shè)置為0dp的話,可以設(shè)置badge的偏移量
                    verticalOffset = 15
                    horizontalOffset = 10
                    BadgeUtils.attachBadgeDrawable(this, mBinding.mbBadge, mBinding.flBtn)
                }
                mBinding.mbBadge.viewTreeObserver.removeOnGlobalLayoutListener(this)
            }
        })
    }

關(guān)于MaterialButton的使用及解析可查看:Android MaterialButton使用詳解,告別shape、selector

4.4.ImageView

xml:

    <FrameLayout
        android:id="@+id/fl_img"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:padding="10dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/fl_btn">

        <com.google.android.material.imageview.ShapeableImageView
            android:id="@+id/siv_badge"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:contentDescription="Image小紅點(diǎn)示例"
            android:src="@mipmap/ic_avatar" />

    </FrameLayout>

kotlin:

    private fun initImageView() {
        mBinding.sivBadge.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
            @SuppressLint("UnsafeOptInUsageError")
            override fun onGlobalLayout() {
                BadgeDrawable.create(this@BadgeDrawableActivity).apply {
                    badgeGravity = BadgeDrawable.TOP_END
                    number = 99999
                    // badge最多顯示字符,默認(rèn)999+ 是4個(gè)字符(帶'+'號(hào))
                    maxCharacterCount = 3
                    backgroundColor = ContextCompat.getColor(this@BadgeDrawableActivity, R.color.red)
                    BadgeUtils.attachBadgeDrawable(this, mBinding.sivBadge, mBinding.flImg)
                }
                mBinding.sivBadge.viewTreeObserver.removeOnGlobalLayoutListener(this)
            }
        })
    }

關(guān)于ShapeableImageView的使用及解析可查看:Android ShapeableImageView使用詳解,告別shape、三方庫(kù)

4.5.BottomNavigationView

xml:

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/navigation_view"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:layout_marginStart="0dp"
        android:layout_marginEnd="0dp"
        android:background="?android:attr/windowBackground"
        app:itemBackground="@color/colorPrimary"
        app:itemIconTint="@color/white"
        app:itemTextColor="@color/white"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:menu="@menu/navigation" />

kotlin:

    private fun initNavigationView() {
        mBinding.navigationView.getOrCreateBadge(R.id.navigation_home).apply {
            backgroundColor = ContextCompat.getColor(this@BadgeDrawableActivity, R.color.red)
            badgeTextColor = ContextCompat.getColor(this@BadgeDrawableActivity, R.color.white)
            number = 9999
        }
    }

TabLayout和BottomNavigationView源碼中直接提供了創(chuàng)建BadgeDrawable的api,未提供的使用BadgeUtils

5.常用API整理

API描述
backgroundColor背景色
badgeTextColor文本顏色
alpha透明度
number顯示的提示數(shù)字
maxCharacterCount最多顯示字符數(shù)量(99+包括‘+’號(hào))
badgeGravity顯示位置
horizontalOffset水平方向偏移量
verticalOffset垂直方向偏移量
isVisible是否顯示

6.源碼解析

來(lái)一段最簡(jiǎn)單的代碼示例看看:

BadgeDrawable.create(this@BadgeDrawableActivity).apply {
    // ...
    BadgeUtils.attachBadgeDrawable(this, mBinding.mbBadge, mBinding.flBtn)
}

不難發(fā)現(xiàn),有兩個(gè)關(guān)鍵點(diǎn):

  • BadgeDrawable.create
  • BadgeUtils.attachBadgeDrawable

下面繼續(xù)跟一下,看看源碼里究竟是做了什么

6.1.BadgeDrawable.create

create實(shí)際調(diào)用的是構(gòu)造方法:

  private BadgeDrawable(@NonNull Context context) {
    this.contextRef = new WeakReference<>(context);
    ThemeEnforcement.checkMaterialTheme(context);
    Resources res = context.getResources();
    badgeBounds = new Rect();
    shapeDrawable = new MaterialShapeDrawable();

    badgeRadius = res.getDimensionPixelSize(R.dimen.mtrl_badge_radius);
    badgeWidePadding = res.getDimensionPixelSize(R.dimen.mtrl_badge_long_text_horizontal_padding);
    badgeWithTextRadius = res.getDimensionPixelSize(R.dimen.mtrl_badge_with_text_radius);

    textDrawableHelper = new TextDrawableHelper(/* delegate= */ this);
    textDrawableHelper.getTextPaint().setTextAlign(Paint.Align.CENTER);
    this.savedState = new SavedState(context);
    setTextAppearanceResource(R.style.TextAppearance_MaterialComponents_Badge);
  }

構(gòu)造方法里有這么一行:ThemeEnforcement.checkMaterialTheme(context); 檢測(cè)Material主題,如果不是會(huì)直接拋出異常

  private static void checkTheme(
      @NonNull Context context, @NonNull int[] themeAttributes, String themeName) {
    if (!isTheme(context, themeAttributes)) {
      throw new IllegalArgumentException(
          "The style on this component requires your app theme to be "
              + themeName
              + " (or a descendant).");
    }
  }

這也是上面為什么說(shuō)主題要使用Theme.MaterialComponents.*

然后創(chuàng)建了一個(gè)文本繪制幫助類(lèi),TextDrawableHelper

比如設(shè)置文本居中:textDrawableHelper.getTextPaint().setTextAlign(Paint.Align.CENTER);

其他的就是text屬性的獲取和設(shè)置,跟我們平時(shí)設(shè)置一毛一樣,比較好理解。

繪制文本之后怎么顯示出來(lái)呢?繼續(xù)跟attachBadgeDrawable。

6.2.BadgeUtils.attachBadgeDrawable

    public static void attachBadgeDrawable(@NonNull BadgeDrawable badgeDrawable, @NonNull View anchor, @Nullable FrameLayout customBadgeParent) {
        setBadgeDrawableBounds(badgeDrawable, anchor, customBadgeParent);
        if (badgeDrawable.getCustomBadgeParent() != null) {
            badgeDrawable.getCustomBadgeParent().setForeground(badgeDrawable);
        } else {
            if (USE_COMPAT_PARENT) {
                throw new IllegalArgumentException("Trying to reference null customBadgeParent");
            }
            anchor.getOverlay().add(badgeDrawable);
        }
    }

這里先是判斷badgeDrawable.getCustomBadgeParent() != null,這個(gè)parent view的類(lèi)型就是FrameLayout,不為空的情況下,層級(jí)前置。

為空的情況下先是判斷了if (USE_COMPAT_PARENT),這里其實(shí)是對(duì)api level的判斷

    static {
        USE_COMPAT_PARENT = VERSION.SDK_INT < 18;
    }

核心代碼:

anchor.getOverlay().add(badgeDrawable);

如果有同學(xué)做過(guò)類(lèi)似全局添加View的需求,這行代碼就看著比較熟悉了。

ViewOverlay,視圖疊加,也可以理解為浮層,在不影響子view的情況下,可以添加、刪除View,這個(gè)api就是android 4.3加的,這也是為什么前面說(shuō)api 要求18+。

ok,至此關(guān)于BadgeDrawable的使用和源碼解析就介紹完了。

7.Github

https://github.com/yechaoa/MaterialDesign

8.相關(guān)文檔

附:Android開(kāi)發(fā)版本和API等級(jí)對(duì)應(yīng)關(guān)系

Platform VersionAPI LevelVERSION_CODE
13.0(beta)  
12.032S_V2
12.031S
11.030R
10.029Q
9.028P
8.127O_MR1
8.026O
7.125N_MR1
7.024N
6.023M
5.122LOLLIPOP_MR1
5.021LOLLIPOP
4.4w20KITKAT_WATCH
4.419KITKAT
4.318JELLY_BEAN_MR2
4.217JELLY_BEAN_MR1
4.116JELLY_BEAN
4.0.315ICE_CREAM_SANDWICH_MR1
4.014ICE_CREAM_SANDWICH
3.213HONEYCOMB_MR2
3.112HONEYCOMB_MR1
3.011HONEYCOMB
2.3.3-2.3.410GINGERBREAD_MR1
2.3.0-2.3.29GINGERBREAD
2.28FROYO
2.17ECLAIR_MR1
2.0.16ECLAIR_0_1
2.05ECLAIR
1.64DONUT
1.53CUPCAKE
1.12BASE_1_1
1.01BASE

總結(jié) 

到此這篇關(guān)于Android漲姿勢(shì)知識(shí)點(diǎn)之BadgeDrawable的文章就介紹到這了,更多相關(guān)Android BadgeDrawable詳解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論