最终效果:
(最终效果录屏后转成gif时色彩有些误差还在闪烁,直接在手机上运行是没有这种情况的。)
思路:获取轮播图当前图片的主题色并且设置给背景
首先简单写一个轮播图
因为会用到网络图片先申请权限
<uses-permission android:name="android.permission.INTERNET" /> <!-- 访问网络权限 -->
引入轮播图和图片显示依赖
implementation 'com.github.bumptech.glide:glide:4.9.0'
implementation 'com.youth.banner:banner:2.0.10'
编写轮播布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:id="@+id/ll_bg"
android:layout_width="fill_parent"
android:layout_height="200dp"
android:orientation="vertical">
<com.youth.banner.Banner
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_margin="15dp" />
</LinearLayout>
</LinearLayout>
加载显示轮播图
private LinearLayout mLlBg;
private Banner mBanner;
private List<BannerBean> mBannerBeans;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
mLlBg = findViewById(R.id.ll_bg);
mBanner = findViewById(R.id.banner);
initBanner();
}
private void initBanner() {
//模拟数据
mBannerBeans = new ArrayList<>();
mBannerBeans.add(new BannerBean(1, "http://p1.music.126.net/yG5m3OK4ZBBeOIkSftmjcQ==/109951165905030496.jpg?imageView&quality=89"));
mBannerBeans.add(new BannerBean(2, "http://p1.music.126.net/ETIySI2MCkINdRWDFK_QQQ==/109951165905559297.jpg?imageView&quality=89"));
mBannerBeans.add(new BannerBean(3, "http://p1.music.126.net/zzAHDSg9nWA90dJL0U6rRQ==/109951165906140657.jpg?imageView&quality=89"));
mBannerBeans.add(new BannerBean(4, "http://p1.music.126.net/Ly3Qh10IMv5_yjDwQTlxvA==/109951165905725276.jpg?imageView&quality=89"));
mBannerBeans.add(new BannerBean(5, "http://p1.music.126.net/bOg67Q_MhDgMK3xK9BRTPA==/109951165905708968.jpg?imageView&quality=89"));
//自定义适配器
MyBannerAdapter myBannerAdapter = new MyBannerAdapter(mBannerBeans, this);
mBanner.setAdapter(myBannerAdapter)
.isAutoLoop(true)//自动切换
.setDelayTime(2000)//轮播时间
.setBannerRound(10)//圆角
.setIndicator(new RectangleIndicator(this));//设置指示器;
}
class MyBannerAdapter extends BannerAdapter<BannerBean, MyBannerAdapter.BannerViewHolder> {
private Context mContext;
public MyBannerAdapter(List<BannerBean> data, Context context) {
super(data);
this.mContext = context;
}
@Override
public BannerViewHolder onCreateHolder(ViewGroup parent, int viewType) {
ImageView imageView = new ImageView(parent.getContext());
//设置为match_parent 这个是viewpager2要求
imageView.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
return new BannerViewHolder(imageView);
}
@Override
public void onBindView(BannerViewHolder holder, BannerBean data, int position, int size) {
Glide.with(mContext)
.load(data.thumb)
.centerCrop()
.into(holder.imageView);
}
class BannerViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
public BannerViewHolder(@NonNull ImageView view) {
super(view);
this.imageView = view;
}
}
}
到这第一步测试的轮播图就显示完成了。
获取轮播图片的颜色并生成线性背景
为了获取颜色我们使用android的palette,它能获取图片中的多种颜色,在实际情况中根据需求使用特定颜色
- vibrant(鲜艳色)
- dark vibrant(鲜艳色中的暗色)
- light vibrant(鲜艳色中的亮色)
- muted(柔和色)
- dark muted(柔和色中的暗色)
- light muted(柔和色中的亮色)
使用palette首先加入依赖:
implementation 'androidx.palette:palette:1.0.0'
因为palette需要图片为bitmap,所以首先通过glide把网络图片转为bitmap(子线程中操作)
//把网络图片转成bitmap
myBitmap = Glide.with(MainActivity3.this)
.asBitmap()
.load(banner.thumb)//图片链接
.submit(50, 50)
.get();
通过palette获取bitmap中颜色
Palette.from(myBitmap).generate(new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(Palette palette) {
if (palette == null) return;
//不一定取得到某些特定的颜色,这里通过取多种颜色来避免取不到颜色的情况
if (palette.getDarkVibrantColor(Color.TRANSPARENT) != Color.TRANSPARENT) {
//使用鲜艳色中的暗色和鲜艳色生成线性背景
createLinearGradientBitmap(banner.id, palette.getDarkVibrantColor(Color.TRANSPARENT), palette.getVibrantColor(Color.TRANSPARENT));
} else if (palette.getDarkMutedColor(Color.TRANSPARENT) != Color.TRANSPARENT) {
//使用柔和色中的暗色和柔和色生成线性背景
createLinearGradientBitmap(banner.id, palette.getDarkMutedColor(Color.TRANSPARENT), palette.getMutedColor(Color.TRANSPARENT));
} else {
//使用柔和色中的亮色和鲜艳色中的亮色生成线性背景
createLinearGradientBitmap(banner.id, palette.getLightMutedColor(Color.TRANSPARENT), palette.getLightVibrantColor(Color.TRANSPARENT));
}
}
});
通过获取的两种颜色创建线性背景,为了以后轮播图播放图和背景对应,用map保存生成的bitmap
Bitmap bgBitmap = null;
Canvas mCanvas = null;
Paint mPaint = null;
//创建线性渐变背景色
private void createLinearGradientBitmap(int id, int color1, int color2) {
try {
//通过这三个基础色进行渐变
int bgColors[] = new int[3];
bgColors[0] = color1;
bgColors[1] = color2;
bgColors[2] = Color.WHITE;
bgBitmap = Bitmap.createBitmap(mLlBg.getWidth(), mLlBg.getHeight(), Bitmap.Config.ARGB_4444);
mCanvas = new Canvas();
mPaint = new Paint();
mCanvas.setBitmap(bgBitmap);
mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
//纵向的线性渐变
LinearGradient gradient = new LinearGradient(0, 0, 0, bgBitmap.getHeight(), bgColors, null, Shader.TileMode.CLAMP);
mPaint.setShader(gradient);
//绘制矩形
RectF rectF = new RectF(0, 0, bgBitmap.getWidth(), bgBitmap.getHeight());
mCanvas.drawRect(rectF, mPaint);
mBgBitmaps.put(id, bgBitmap);
bgBitmap = null;
} catch (Exception e) {
}
}
到这我们已经把渐变背景根据id对应起来存储到了map中。
根据当前轮播显示的图片改变背景
首先监听banner的切换
//轮播图切换监听
mBanner.addOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
BannerBean data = mBannerBeans.get(position);
showBgBitmap(data.id);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
展示相应的背景
//根据当前轮播图id设置背景
private void showBgBitmap(int id) {
if (mBgBitmaps != null && mBgBitmaps.size() > 0) {
BitmapDrawable bitmapDrawable = new BitmapDrawable(mBgBitmaps.get(id));
mLlBg.setBackground(bitmapDrawable);
}
}
完整代码
public class MainActivity3 extends AppCompatActivity {
private LinearLayout mLlBg;
private Banner mBanner;
private List<BannerBean> mBannerBeans;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
mLlBg = findViewById(R.id.ll_bg);
mBanner = findViewById(R.id.banner);
initBanner();
}
private void initBanner() {
//模拟数据
mBannerBeans = new ArrayList<>();
mBannerBeans.add(new BannerBean(1, "http://p1.music.126.net/yG5m3OK4ZBBeOIkSftmjcQ==/109951165905030496.jpg?imageView&quality=89"));
mBannerBeans.add(new BannerBean(2, "http://p1.music.126.net/ETIySI2MCkINdRWDFK_QQQ==/109951165905559297.jpg?imageView&quality=89"));
mBannerBeans.add(new BannerBean(3, "http://p1.music.126.net/zzAHDSg9nWA90dJL0U6rRQ==/109951165906140657.jpg?imageView&quality=89"));
mBannerBeans.add(new BannerBean(4, "http://p1.music.126.net/Ly3Qh10IMv5_yjDwQTlxvA==/109951165905725276.jpg?imageView&quality=89"));
mBannerBeans.add(new BannerBean(5, "http://p1.music.126.net/bOg67Q_MhDgMK3xK9BRTPA==/109951165905708968.jpg?imageView&quality=89"));
//采集每个图片的颜色
setBgBitmap(mBannerBeans);
//自定义适配器
MyBannerAdapter myBannerAdapter = new MyBannerAdapter(mBannerBeans, this);
mBanner.setAdapter(myBannerAdapter)
.isAutoLoop(true)//自动切换
.setDelayTime(2000)//轮播时间
.setBannerRound(10)//圆角
.setIndicator(new RectangleIndicator(this));//设置指示器;
//轮播图切换监听
mBanner.addOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
BannerBean data = mBannerBeans.get(position);
showBgBitmap(data.id);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
//根据当前轮播图id设置背景
private void showBgBitmap(int id) {
if (mBgBitmaps != null && mBgBitmaps.size() > 0) {
BitmapDrawable bitmapDrawable = new BitmapDrawable(mBgBitmaps.get(id));
mLlBg.setBackground(bitmapDrawable);
}
}
//存放各个轮播图对应的背景颜色
HashMap<Integer, Bitmap> mBgBitmaps;
private void setBgBitmap(List<BannerBean> banners) {
mBgBitmaps = new HashMap<>();
//子线程中操作
new Thread() {
public void run() {
Bitmap myBitmap;
for (BannerBean banner : banners) {
try {
//把网络图片转成bitmap
myBitmap = Glide.with(MainActivity3.this)
.asBitmap()
.load(banner.thumb)
.submit(50, 50)
.get();
Palette.from(myBitmap).generate(new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(Palette palette) {
if (palette == null) return;
//不一定取得到某些特定的颜色,这里通过取多种颜色来避免取不到颜色的情况
if (palette.getDarkVibrantColor(Color.TRANSPARENT) != Color.TRANSPARENT) {
//使用鲜艳色中的暗色和鲜艳色生成线性背景
createLinearGradientBitmap(banner.id, palette.getDarkVibrantColor(Color.TRANSPARENT), palette.getVibrantColor(Color.TRANSPARENT));
} else if (palette.getDarkMutedColor(Color.TRANSPARENT) != Color.TRANSPARENT) {
//使用柔和色中的暗色和柔和色生成线性背景
createLinearGradientBitmap(banner.id, palette.getDarkMutedColor(Color.TRANSPARENT), palette.getMutedColor(Color.TRANSPARENT));
} else {
//使用柔和色中的亮色和鲜艳色中的亮色生成线性背景
createLinearGradientBitmap(banner.id, palette.getLightMutedColor(Color.TRANSPARENT), palette.getLightVibrantColor(Color.TRANSPARENT));
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
}.start();
}
Bitmap bgBitmap = null;
Canvas mCanvas = null;
Paint mPaint = null;
//创建线性渐变背景色
private void createLinearGradientBitmap(int id, int color1, int color2) {
try {
//通过这三个基础色进行渐变
int bgColors[] = new int[3];
bgColors[0] = color1;
bgColors[1] = color2;
bgColors[2] = Color.WHITE;
bgBitmap = Bitmap.createBitmap(mLlBg.getWidth(), mLlBg.getHeight(), Bitmap.Config.ARGB_4444);
mCanvas = new Canvas();
mPaint = new Paint();
mCanvas.setBitmap(bgBitmap);
mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
//纵向的线性渐变
LinearGradient gradient = new LinearGradient(0, 0, 0, bgBitmap.getHeight(), bgColors, null, Shader.TileMode.CLAMP);
mPaint.setShader(gradient);
//绘制矩形
RectF rectF = new RectF(0, 0, bgBitmap.getWidth(), bgBitmap.getHeight());
mCanvas.drawRect(rectF, mPaint);
mBgBitmaps.put(id, bgBitmap);
//首先显示第一个图片的背景
if (1 == id)
mLlBg.setBackground(new BitmapDrawable(bgBitmap));
bgBitmap = null;
} catch (Exception e) {
}
}
}
class MyBannerAdapter extends BannerAdapter<BannerBean, MyBannerAdapter.BannerViewHolder> {
private Context mContext;
public MyBannerAdapter(List<BannerBean> data, Context context) {
super(data);
this.mContext = context;
}
@Override
public BannerViewHolder onCreateHolder(ViewGroup parent, int viewType) {
ImageView imageView = new ImageView(parent.getContext());
//设置为match_parent 这个是viewpager2要求
imageView.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
return new BannerViewHolder(imageView);
}
@Override
public void onBindView(BannerViewHolder holder, BannerBean data, int position, int size) {
Glide.with(mContext)
.load(data.thumb)
.centerCrop()
.into(holder.imageView);
}
class BannerViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
public BannerViewHolder(@NonNull ImageView view) {
super(view);
this.imageView = view;
}
}
}
总结
到这里功能已经全部实现了,轮播图的背景可以根据轮播图当前图片的改变而改变,为了美观你也可以获取到的不同颜色来生成线性背景看哪一个好看……。如果需求不是轮播图,只是根据单张图片来改变背景颜色或者主题颜色也可以修改下使用。