仿某看書(shū)app首頁(yè) Banner輪播+背景漸變

PS:最近發(fā)現(xiàn)一個(gè)比較有意思的效果,于是想自己操作實(shí)踐下。效果圖如下:


Banner輪播+背景漸變

作者實(shí)現(xiàn)的效果:


Banner輪播+背景漸變

1. 實(shí)現(xiàn)思路

  • 使用Banner+ 透明的 ImageView 進(jìn)行搭配實(shí)現(xiàn)。

  • 使用Palette來(lái)將Banner中每一個(gè)Bitmap進(jìn)行取色,將最亮的色值取出。

  • 將取出的色值配置到背景ImageView上。

2. 開(kāi)始實(shí)現(xiàn)

1. 導(dǎo)入依賴

//banner依賴
implementation 'com.youth.banner:banner:1.4.10'

//palette依賴
implementation 'com.android.support:palette-v7:23.4.0'

2. 編寫(xiě)xml文件

 <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">

                <ImageView
                    android:id="@+id/view_bg"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="#999999"
                    android:paddingTop="100dp"
                    android:scaleType="fitXY"
                    android:src="@drawable/banner_head_bg"
                    android:visibility="visible" />

                <com.youth.banner.Banner
                    android:id="@+id/view_banner"
                    android:layout_width="match_parent"
                    android:layout_height="150dp"
                    android:layout_marginTop="25dp"
                    app:image_scale_type="fit_xy"
                    app:indicator_height="6dp"
                    app:indicator_width="6dp" />
            </RelativeLayout>

這里ImageVIew使用的圖片如下(透明背景):

  • 下載后創(chuàng)建drawable-xxhdpi文件夾并放入圖片


    image.png

3. 創(chuàng)建數(shù)據(jù)

  //Banner數(shù)據(jù)的集合
    var mBannerList: ArrayList<String> = ArrayList()

  //添加Banner的數(shù)據(jù)
        mBannerList.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556532613936&di=3769695217e3424f18c3d23966ecd4dc&imgtype=0&src=http%3A%2F%2Fpic.90sjimg.com%2Fback_pic%2Fqk%2Fback_origin_pic%2F00%2F04%2F19%2F70e2846ebc02ae10161f25bf7f5461a1.jpg");
        mBannerList.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556532665664&di=9ead9eb8a9fe2af9a01b0dd39f3e41f4&imgtype=0&src=http%3A%2F%2Fbpic.588ku.com%2Fback_pic%2F05%2F37%2F28%2F475a43591370453.jpg");
        mBannerList.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556532613934&di=0be1c6bbf0441bd19ef6d4e3ce799263&imgtype=0&src=http%3A%2F%2Fpic96.nipic.com%2Ffile%2F20160430%2F7036970_215739900000_2.jpg");
        mBannerList.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556532613936&di=4dd453940f49d9801826e6b820490957&imgtype=0&src=http%3A%2F%2Fpic161.nipic.com%2Ffile%2F20180410%2F26429156_154754410034_2.jpg");
        mBannerList.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1556532613935&di=39c387012e3d8fa2eef90129eaf83c5c&imgtype=0&src=http%3A%2F%2Fpic25.nipic.com%2F20121211%2F7031681_170238437383_2.jpg");

  • 創(chuàng)建實(shí)體類用來(lái)存放通過(guò)Palette獲取到的每個(gè)Banner的色值
Palette介紹
  • 它能讓你從圖像中提取突出的顏色。這個(gè)類能提取以下幾種顏色:
  1. Vibrant (充滿活力的)
  2. Vibrant dark (充滿活力的黑)
  3. Vibrant light (充滿活力的亮)
  4. Muted (柔和的)
  5. Muted dark (柔和的黑)
  6. Muted lighr (柔和的亮)
package com.lcz.coolweatherjetpack;

/**
 * 作者:Lichenzge
 * 時(shí)間:2019/3/12 13:33
 * 描述:banner圖片顏色漸變Bean
 * <p>
 * Vibrant (有活力)
 * Vibrant dark(有活力 暗色)
 * Vibrant light(有活力 亮色)
 * Muted (柔和)
 * Muted dark(柔和 暗色)
 * Muted light(柔和 亮色)
 */
public class ColorInfo {
    private String imgUrl;
    private int vibrantColor = 0xFF999999;
    private int vibrantDarkColor = 0xFF999999;
    private int vibrantLightColor = 0xFF999999;
    private int mutedColor = 0xFF999999;
    private int mutedDarkColor = 0xFF999999;
    private int mutedLightColor = 0xFF999999;

    public String getImgUrl() {
        return imgUrl;
    }

    public void setImgUrl(String imgUrl) {
        this.imgUrl = imgUrl;
    }


    public int getVibrantColor() {
        return vibrantColor;
    }


    public void setVibrantColor(int vibrantColor) {
        this.vibrantColor = vibrantColor;
    }

    public int getVibrantDarkColor() {
        return vibrantDarkColor;
    }

    public void setVibrantDarkColor(int vibrantDarkColor) {
        this.vibrantDarkColor = vibrantDarkColor;
    }

    public int getVibrantLightColor() {
        return vibrantLightColor;
    }

    public void setVibrantLightColor(int vibrantLightColor) {
        this.vibrantLightColor = vibrantLightColor;
    }

    public int getMutedColor() {
        return mutedColor;
    }

    public void setMutedColor(int mutedColor) {
        this.mutedColor = mutedColor;
    }

    public int getMutedDarkColor() {
        return mutedDarkColor;
    }

    public void setMutedDarkColor(int mutedDarkColor) {
        this.mutedDarkColor = mutedDarkColor;
    }

    public int getMutedLightColor() {
        return mutedLightColor;
    }

    public void setMutedLightColor(int mutedLightColor) {
        this.mutedLightColor = mutedLightColor;
    }
}

  • 創(chuàng)建集合用來(lái)存放數(shù)據(jù)
//存放Banner背景顏色的集合
    var mColorList: ArrayList<ColorInfo> = ArrayList()
  • 將Banner中的每一條數(shù)據(jù)都存儲(chǔ)集合中,方便后續(xù)通過(guò)Palette進(jìn)行取色。
  count = mBannerList.size
        mColorList.clear()

        for (i in 0..count + 1) {
            val info = ColorInfo()
            if (i == 0) {
                info.imgUrl = mBannerList.get(count - 1)
            } else if (i == count + 1) {
                info.imgUrl = mBannerList.get(0)
            } else {
                info.imgUrl = mBannerList.get(i - 1)
            }
            mColorList.add(info)
        }

數(shù)據(jù)都創(chuàng)建完成后就可以創(chuàng)建Banner的圖片加載器了~

4. 創(chuàng)建Banner圖片加載器,并使用Palette獲取Banner圖片色值并進(jìn)行保存

Palette取色方法:

  • 取出來(lái)的值為RGB值
   //獲取Palette 調(diào)色板
        // 這里的bitmap就是需要取色的圖片
        val palette = Palette.from(bitmap).generate()
        //充滿活力的色調(diào)
        val Vibrantrgb = palette.getVibrantSwatch()!!.rgb
        //充滿活力的亮色調(diào)
        val LightVibrantrgb = palette.getLightVibrantSwatch()!!.rgb
        //充滿活力的暗色調(diào)
        val DarkVibrantrgb = palette.getDarkVibrantSwatch()!!.rgb
        //柔和的色調(diào)
        val Mutedrgb = palette.getMutedSwatch()!!.rgb
        //柔和的亮色調(diào)
        val LightMutedrgb = palette.getLightMutedSwatch()!!.rgb
        //柔和的暗色調(diào)
        val DarkMutedrgb = palette.getDarkMutedSwatch()!!.rgb

創(chuàng)建BannerImageLoader類:

package com.lcz.coolweatherjetpack

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Bitmap
import android.widget.ImageView
import androidx.palette.graphics.Palette
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.Target
import com.youth.banner.loader.ImageLoader


/**
 * @author: Lichengze
 * @e-mail:lcz3466601343@163.com
 * @time: 2021/1/11 16:01 星期一
 * @description:
 */
class BannerImageLoader : ImageLoader {

    //存放Banner數(shù)據(jù)和顏色的集合
    var colorList: ArrayList<ColorInfo> = ArrayList()

    constructor(colorList: ArrayList<ColorInfo>) : super() {
        this.colorList = colorList
    }

    @SuppressLint("CheckResult")
    override fun displayImage(context: Context?, path: Any?, imageView: ImageView?) {
        if (path != null) {
            //設(shè)置Imageview的Pinging值 (美觀)
            imageView!!.setPadding(30, 0, 30, 0);

            Glide.with(context!!).asBitmap().load(path.toString())
                //通過(guò)listener監(jiān)聽(tīng)方法 將Banner中的每一張網(wǎng)絡(luò)圖片轉(zhuǎn)換為Bitmap,并通過(guò)Bitmap進(jìn)行取值
                .listener(object : RequestListener<Bitmap> {
                    override fun onLoadFailed(
                        e: GlideException?,
                        model: Any?,
                        target: Target<Bitmap>?,
                        isFirstResource: Boolean
                    ): Boolean {
                        return false
                    }

                    override fun onResourceReady(
                        resource: Bitmap?,
                        model: Any?,
                        target: Target<Bitmap>?,
                        dataSource: DataSource?,
                        isFirstResource: Boolean
                    ): Boolean {
                        setColorList(resource!!, path.toString())
                        return false
                    }
                    //通過(guò)RequestOptions.bitmapTransform(RoundedCorners(20)) 設(shè)置圖片為圓角
                }).apply(RequestOptions.bitmapTransform(RoundedCorners(20))).into(imageView!!);
        }
    }

    //將Banner中的每一張圖片進(jìn)行取值,并存放到ColorInfo類中
    private fun setColorList(bitmap: Bitmap, imgUrl: String) {
        if (colorList == null) {
            return
        }
        //初始化Palette
        val palette = Palette.from(bitmap).generate()
        for (i in 0 until colorList.size) {
            if (colorList.get(i).getImgUrl().equals(imgUrl)) { // imgUrl作為識(shí)別標(biāo)志
                if (palette.getVibrantSwatch() != null) {
                    //獲取充滿活力的色調(diào)
                    colorList.get(i).setVibrantColor(palette.getVibrantSwatch()!!.getRgb())
                }
                if (palette.getDarkVibrantSwatch() != null) {
                    colorList.get(i).setVibrantDarkColor(palette.getDarkVibrantSwatch()!!.getRgb())
                }
                if (palette.getLightVibrantSwatch() != null) {
                    colorList.get(i).setVibrantLightColor(
                        palette.getLightVibrantSwatch()!!.getRgb()
                    )
                }
                if (palette.getMutedSwatch() != null) {
                    colorList.get(i).setMutedColor(palette.getMutedSwatch()!!.getRgb())
                }
                if (palette.getDarkMutedSwatch() != null) {
                    colorList.get(i).setMutedDarkColor(palette.getDarkMutedSwatch()!!.getRgb())
                }
                if (palette.getLightVibrantSwatch() != null) {
                    colorList.get(i).setMutedLightColor(palette.getLightVibrantSwatch()!!.getRgb())
                }
            }
        }
    }


    /**
     * Vibrant (有活力)
     * Vibrant dark(有活力 暗色)
     * Vibrant light(有活力 亮色)
     * Muted (柔和)
     * Muted dark(柔和 暗色)
     * Muted light(柔和 亮色)
     */
    fun getVibrantColor(position: Int): Int {
        return colorList[position].vibrantColor
    }

    fun getVibrantDarkColor(position: Int): Int {
        return colorList[position].vibrantDarkColor
    }

    fun getVibrantLightColor(position: Int): Int {
        return colorList[position].vibrantLightColor
    }

    fun getMutedColor(position: Int): Int {
        return colorList[position].mutedColor
    }

    fun getMutedDarkColor(position: Int): Int {
        return colorList[position].mutedDarkColor
    }

    fun getMutedLightColor(position: Int): Int {
        return colorList[position].mutedLightColor
    }
}

在加載器中將色值取出并存放到集合中,接下來(lái)就可以在Banner的每次滑動(dòng)中把對(duì)應(yīng)的色值配對(duì)到背景中了。

5. 監(jiān)聽(tīng)Banner滑動(dòng),根據(jù)下標(biāo)獲取對(duì)應(yīng)色值,將顏色配置到背景ImageView中。

通過(guò)Banner的setOnPageChangeListener進(jìn)行監(jiān)聽(tīng)

  • onPageScrolled:滾動(dòng)中

  • onPageSelected:滾動(dòng)選擇中

在監(jiān)聽(tīng)中使用通過(guò)ColorUtils 獲取當(dāng)前banner和下一個(gè)banner的色值。并將獲取到的值配對(duì)到背景和狀態(tài)欄中。

  var IsInit = true

    private fun initView() {
        binding!!.viewBanner.setOnPageChangeListener(object : ViewPager.OnPageChangeListener {
            override fun onPageScrolled(
                position: Int,
                positionOffset: Float,
                positionOffsetPixels: Int
            ) {
                if (positionOffset > 1) { //會(huì)出現(xiàn)極個(gè)別大于1的數(shù)據(jù)
                    return
                }
                //修正position,解決兩頭顏色錯(cuò)亂,來(lái)自Banner控件源碼
                if (position === 0) {
                    position == count
                }
                if (position > count) {
                    position == 1
                }
                if (count > 0) {
                    val pos = (position + 1) % count //很關(guān)鍵
                    //通過(guò)ColorUtils 獲取當(dāng)前banner的Vibrant顏色值
                    val vibrantColor = ColorUtils.blendARGB(
                        imageLoader.getVibrantColor(pos),
                        imageLoader.getVibrantColor(pos + 1),
                        positionOffset
                    )
                    //給背景和狀態(tài)欄都配置顏色
                    binding!!.viewBg.setBackgroundColor(vibrantColor)

                }
            }

            override fun onPageSelected(position: Int) {
                if (IsInit) { // 第一次,延時(shí)加載才能拿到顏色
                    IsInit = false
                    Handler().postDelayed(Runnable {
                        LogUtils.d("第一次加載")
                        val vibrantColor: Int = imageLoader.getVibrantColor(1)
                        binding!!.viewBg.setBackgroundColor(vibrantColor)

                    }, 500)
                }
            }

            override fun onPageScrollStateChanged(state: Int) {

            }

        })


 /**
     * 設(shè)置狀態(tài)欄顏色
     *
     * @param activity
     */
    fun setStatusBarColor(activity: Activity, color: Int) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            val window: Window = activity.window
            //狀態(tài)欄改變顏色。
            window.setStatusBarColor(color)
            //狀態(tài)欄改變顏色。
            LogUtils.d("color:$color")
        }
    }

6. 將加載器使用到Banner中。

 binding!!.viewBanner.setImageLoader(imageLoader)
            //設(shè)置圖片集合
            .setImages(mBannerList)
            //設(shè)置banner動(dòng)畫(huà)效果
            // banner.setBannerAnimation(Transformer.DepthPage);
            //設(shè)置輪播時(shí)間
            .setDelayTime(3000)
            //banner設(shè)置方法全部調(diào)用完畢時(shí)最后調(diào)用
            .start()

3. 總結(jié)

  • Banner輪播+背景漸變整體實(shí)現(xiàn)效果不難,重點(diǎn)在于通過(guò)Palette取色完成后,在滑動(dòng)的監(jiān)聽(tīng)中通過(guò)ColorUtils將數(shù)據(jù)轉(zhuǎn)換并配對(duì)到背景中。

  • 參考文章:Android仿喜馬拉雅banner顏色漸變

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 抽屜菜單 MaterialDrawer★7582 - 安卓抽屜效果實(shí)現(xiàn)方案 Side-Menu.Android★3...
    devdabug閱讀 7,114評(píng)論 0 100
  • 用兩張圖告訴你,為什么你的 App 會(huì)卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 14,025評(píng)論 2 59
  • 久違的晴天,家長(zhǎng)會(huì)。 家長(zhǎng)大會(huì)開(kāi)好到教室時(shí),離放學(xué)已經(jīng)沒(méi)多少時(shí)間了。班主任說(shuō)已經(jīng)安排了三個(gè)家長(zhǎng)分享經(jīng)驗(yàn)。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,822評(píng)論 16 22
  • 今天感恩節(jié)哎,感謝一直在我身邊的親朋好友。感恩相遇!感恩不離不棄。 中午開(kāi)了第一次的黨會(huì),身份的轉(zhuǎn)變要...
    余生動(dòng)聽(tīng)閱讀 10,869評(píng)論 0 11
  • 可愛(ài)進(jìn)取,孤獨(dú)成精。努力飛翔,天堂翱翔。戰(zhàn)爭(zhēng)美好,孤獨(dú)進(jìn)取。膽大飛翔,成就輝煌。努力進(jìn)取,遙望,和諧家園??蓯?ài)游走...
    趙原野閱讀 3,508評(píng)論 1 1

友情鏈接更多精彩內(nèi)容