android ViewPager 仿画廊/图书翻页 与 palette 使用
废话不多说,先来看看完成的效果!
总结实现效果:
ViewPager 实现无限自动播放
ViewPager 实现中间大,两边小 [仿画廊效果]
ViewPager 实现图片叠加[仿图书翻页效果]
palette 调色板实现识别图片颜色,随着图片的变化来改变背景色的变化
普通ViewPager实现
先不管三七二十一,先吧最基本的ViewPager实现,之后在在基本的ViewPager上修改!
不用复制代码,先看思路就行,底部会给出完整代码!
activity_palette.xml布局:
1//设置适配器
2viewPager.setAdapter(new BannerAdapter(this, mDrawables));
3
4//Pager之间的间距
5viewPager.setPageMargin(20);
6
7//预加载
8viewPager.setOffscreenPageLimit(3);
9
10//默认第一张图 左右都有图
11viewPager.setCurrentItem(1);
12复制代码
BannerAdapter 适配器:
1public class BannerAdapter extends PagerAdapter {
2 private int[] mData;
3 private Context mContext;
4
5 public BannerAdapter(Context ctx, int[] data) {
6 this.mContext = ctx;
7 this.mData = data;
8 }
9
10 @Override
11 public int getCount() {
12 return mData.length;// 返回数据的个数
13 }
14
15 @Override
16 public Object instantiateItem(final ViewGroup container, final int position) {//子View显示
17 View view = View.inflate(container.getContext(), R.layout.banner_item_layout, null);
18 ImageView imageView = view.findViewById(R.id.iv_icon);
19 imageView.setImageResource(mData[position]);
20
21 imageView.setOnClickListener(new View.OnClickListener() {
22 @Override
23 public void onClick(View view) {
24 Toast.makeText(mContext, "当前条目:" + position, Toast.LENGTH_SHORT).show();
25 }
26 });
27
28 container.addView(view);//添加到父控件
29 return view;
30 }
31
32 @Override
33 public boolean isViewFromObject(View view, Object object) {
34 return view == object;// 过滤和缓存的作用
35 }
36
37 @Override
38 public void destroyItem(ViewGroup container, int position, Object object) {
39 container.removeView((View) object);//从viewpager中移除掉
40 }
41}
42复制代码
先来看看目前的效果:
思路分析:
要想完成画廊的效果,那么必须吧viewPager分为以下几步骤:
让ViewPager显示出左右两侧的View
无限滑动
自定义ViewPager 滑动动画,滑动过程中中间大,两边小
自动播放
那就来根据思路实现效果吧 :
让ViewPager显示出左右两侧的View
这个也是真 的简单,直接取%即可实现
来看看效果:
ViewPager.PageTransformer
先来看使用:
1viewPager.setPageTransformer(true, new ScaleTransformer());
2复制代码
参数一: 是否逆转,我没看出有什么效果,懂这个参数的记得在评论区留言哦!
参数二: 用来控制ViewPager 动画的
1public class ScaleTransformer implements ViewPager.PageTransformer {
2 private static final float MAX_SCALE = 1.0f;//0缩放
3 private static final float MIN_SCALE = 0.80f;//0.85缩放
4
5
6 @Override
7 public void transformPage(@NonNull View view, float position) {
8
9 }
10}
11复制代码
实现implements ViewPager.PageTransformer重写transformPage()方法,有2个参数
1 /**
2 * A PageTransformer is invoked whenever a visible/attached page is scrolled.
3 * This offers an opportunity for the application to apply a custom transformation
4 * to the page views using animation properties.
5 *
6 * <p>As property animation is only supported as of Android 3.0 and forward,
7 * setting a PageTransformer on a ViewPager on earlier platform versions will
8 * be ignored.</p>
9 */
10 public interface PageTransformer {
11 /**
12 * Apply a property transformation to the given page.
13 *
14 * @param page Apply the transformation to this page
15 * @param position Position of page relative to the current front-and-center
16 * position of the pager. 0 is front and center. 1 is one full
17 * page position to the right, and -1 is one page position to the left.
18 */
19 void transformPage(@NonNull View page, float position);
20 }
21复制代码
这个方法在onPageScrolled页面滑动的过程中回调
1@CallSuper
2 protected void onPageScrolled(int position, float offset, int offsetPixels) {
3
4 ....省略.......
5
6 if (mPageTransformer != null) {
7 ....省略.......
8
9 mPageTransformer.transformPage(child, transformPos);
10 }
11 }
12
13 mCalledSuper = true;
14 }
15复制代码
transformPage参数:
参数一: 当前view
参数二:当前view的位置
这里比较抽象,画张图看看
红色当前View
蓝色 左侧View
黄色 右侧View
不滑动状态position变化:
| 红色 | 蓝色 | 黄色 |
|---|---|---|
| position = -1 | position = 0 | position = 1 |
滑动状态position变化:
| 状态 | 红色 | 蓝色 | 黄色 |
|---|---|---|---|
| 左滑动 | position < -1 | 0 < position < -1 | 1 < position < 0 |
| 右滑动 | -1 < position < 0 | 0 < position < 1 | position > 1 |
先来打印一下看看position的值:
好了,position就介绍到这里!
先简简单单修改代码,先看看效果:
1public class ScaleTransformer implements ViewPager.PageTransformer {
2 private static final float MAX_SCALE = 1.0f;//0缩放
3 private static final float MIN_SCALE = 0.80f;//0.85缩放
4
5
6 @Override
7 public void transformPage(@NonNull View view, float position) {
8 //position != 0 表示左侧和右侧的view
9 if (position != 0) {
10 view.setScaleX(MIN_SCALE);
11 view.setScaleY(MIN_SCALE);
12 } else {
13 view.setScaleX(MAX_SCALE);
14 view.setScaleY(MAX_SCALE);
15 }
16 }
17}
18复制代码
效果:
在加上滑动时候放大缩小即可
1public class ScaleTransformer implements ViewPager.PageTransformer {
2 private static final float MAX_SCALE = 1.0f;//0缩放
3 private static final float MIN_SCALE = 0.80f;//0.85缩放
4 @Override
5 public void transformPage(@NonNull View view, float position) {
6
7 if (position < 1) {
8 float scaleFactor = MIN_SCALE + (1 - Math.abs(position)) * (MAX_SCALE - MIN_SCALE);
9
10 view.setScaleX(scaleFactor);
11
12 view.setScaleY(scaleFactor);
13 } else {
14 view.setScaleX(MIN_SCALE);
15 view.setScaleY(MIN_SCALE);
16 }
17 }
18}
19复制代码
这里涉及到一个小算法
1 float scaleFactor = MIN_SCALE + (1 - Math.abs(position)) * (MAX_SCALE - MIN_SCALE);
2复制代码
指的就是变化过程中view的大小
这段代码要细细的品味一下!!!很关键!!
来看看湿滑的效果:
无限自己滚动
这段代码也是简单的很:
直接上代码不多贝贝:
1//用来记录是否按压,如果按压,则不滚动
2boolean isDown ;
3
4Timer timer = new Timer();
5
6 //定时器播放ViewPager
7 TimerTask timerTask = new TimerTask() {
8 @Override
9 public void run() {
10 if (!isDown) {
11 //获取到当前的位置
12 int page = viewPager.getCurrentItem() + 1;
13 runOnUiThread(() -> viewPager.setCurrentItem(page));
14 }
15 }
16 };
17 // 每2.5秒执行一次
18 timer.schedule(timerTask, 0, 2500);
19
20
21 viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
22 @Override
23 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
24 //viewPager滑动的时候,设置不让滚动
25 isDown = true;
26 }
27
28 @Override
29 public void onPageSelected(int position) {
30
31 }
32
33 @Override
34 public void onPageScrollStateChanged(int state) {
35 //ViewPager不点击了让滚动
36 isDown = false;
37 }
38 });
39复制代码
这段代码过于简单,就不看效果了!
仿图书效果
这个效果和仿画廊流程一样,也是对PageTransformer的操作,直接上代码了!
1public class StackPageTransformer implements ViewPager.PageTransformer {
2 private final ViewPager viewPager;
3
4 private final float SCALE_VALUE = 1f;
5
6 //View 之间的偏移量
7 private final float DEVIATION = 60f;
8
9 //旋转
10 private final float ROTATION = 60f;
11
12 //图片是否叠加【默认不叠加】
13 private final boolean isStack = false;
14
15
16 public StackPageTransformer(ViewPager viewPager) {
17 this.viewPager = viewPager;
18 }
19
20 @Override
21 public void transformPage(@NonNull View view, float position) {
22 Log.i("szjPosition2", position + "");
23
24 /*
25 * 当不滑动状态下:
26 * position = -1 左侧View
27 * position = 0 当前View
28 * position = 1 右侧View
29 *
30 * 当滑动状态下:
31 * 向左滑动: [ position < 0 && position > -1]
32 * 左侧View position < -1
33 * 当前View 0 ~ -1
34 * 右侧View 1 ~ 0
35 *
36 * 向右滑动:[position > 0 && position < 1 ]
37 * 左侧View -1 < position < 0
38 * 当前View 0 ~ 1
39 * 右侧View position > 1
40 */
41
42 int pageWidth = viewPager.getWidth();
43
44 //隐藏左侧侧的view
45 if (position == -1) {
46 view.setVisibility(View.GONE);
47 } else {
48 view.setVisibility(View.VISIBLE);
49 }
50
51 //当前View和右侧的View [让右侧View和当前View叠加起来]
52 if (position >= 0) {
53 float translationX;
54 //这里不要晕! 改变isStack来看看效果吧!!
55 if (isStack) {
56 translationX = DEVIATION - (pageWidth) * position;
57 } else {
58 translationX = (DEVIATION - pageWidth) * position;
59 }
60 Log.i("szjTranslationX", translationX + "");
61 view.setTranslationX(translationX);
62 }
63
64 //当前view
65 if (position == 0) {
66 view.setScaleX(SCALE_VALUE);
67 view.setScaleY(SCALE_VALUE);
68 } else {
69 //左侧已经隐藏了,所以这里值的是右侧View的偏移量
70 float scaleFactor = Math.min(SCALE_VALUE - position * 0.1f, SCALE_VALUE);
71 view.setScaleX(scaleFactor);
72 view.setScaleY(scaleFactor);
73 }
74
75 //向左滑动
76 if (position < 0 && position > -1) {
77 //旋转
78 view.setRotation(ROTATION * position);
79 view.setAlpha(1 - Math.abs(position));
80 } else {
81 //透明度 其他状态不设置透明度
82 view.setAlpha(1);
83 }
84
85 //向右滑动
86 if (position > 0 && position < 1) {
87 view.setRotation(0);
88 }
89 }
90}
91复制代码
看看效果:
palette 调色板
先添加依赖:
1implementation 'com.android.support:palette-v7:26.0.0-alpha1'
2复制代码
简单介绍:
palette 传入一张Bitmap,然后他会通过图片像素点来分析出颜色占比,提取出你需要的颜色!!
使用:
1public void initPalette(Bitmap bitmap) {
2 new Thread(() -> Palette.from(bitmap).generate(palette -> {
3 //以RGB压缩整数的形式从调色板返回静音和深色。
4 int darkMutedColor = palette.getDarkMutedColor(Color.TRANSPARENT);
5
6 //暗 柔和 [以RGB压缩整数的形式从调色板返回静音和浅色。]
7 int lightMutedColor = palette.getLightMutedColor(Color.TRANSPARENT);
8
9 //暗 鲜艳 [以RGB压缩整数的形式从调色板返回深色和鲜艳的颜色。]
10 int darkVibrantColor = palette.getDarkVibrantColor(Color.TRANSPARENT);
11
12 //量 鲜艳 [以RGB压缩整数的形式从调色板返回明亮的颜色。]
13 int lightVibrantColor = palette.getLightVibrantColor(Color.TRANSPARENT);
14
15 //柔和 [将调色板中的静音颜色作为RGB压缩整数返回。]
16 int mutedColor = palette.getMutedColor(Color.TRANSPARENT);
17
18 //以RGB压缩整数形式返回调色板中最鲜艳的颜色。
19 int vibrantColor = palette.getVibrantColor(Color.TRANSPARENT);
20
21
22 //从调色板中返回一个明亮且充满活力的样例。可能为空。
23 Palette.Swatch lightVibrantSwatch = palette.getLightVibrantSwatch();
24
25 int hotColor = Color.TRANSPARENT;
26 if (lightVibrantSwatch != null) {
27 //谷歌推荐的:图片的整体的颜色rgb的混合痔---主色调
28 int rgb = lightVibrantSwatch.getRgb();
29 hotColor = getTranslucentColor(0.7f, rgb);
30 }
31
32 // 拿到颜色 这里就可以给View 设置颜色了
33
34 })).start();
35 }
36复制代码
然后通过随机图片,设置不同的图片来测试一下管用不管用!
来看看效果:
1 /**
2 * TODO 设置渐变颜色
3 *
4 * @param view 需要设置的View
5 * @param colors 渐变颜色
6 * @param type 渐变位置 例如:GradientDrawable.Orientation.LEFT_RIGHT 从左到右
7 * @param radius 圆角
8 */
9 public void setGradualChange(View view, int[] colors, GradientDrawable.Orientation type, int radius) {
10 GradientDrawable drawable = new GradientDrawable(type, colors);
11 drawable.setCornerRadius(radius);
12 view.setBackground(drawable);
13 }
14复制代码
完整项目:https://gitee.com/lanyangyangzzz/android_ui
原创不易,您的点赞就是对我最大的支持!!
推荐阅读
耗时一周,我解决了微信 Matrix 增量编译的 Bug,已提 PR
Android QMUI实战:实现APP换肤功能,并自动适配手机深色模式
公众号徐公回复黑马,获取 Android 学习视频 公众号徐公回复徐公666,获取简历模板,教你如何优化简历,走近大厂 公众号徐公回复面试,可以获得面试常见算法,剑指 ofer 题解 公众号徐公回复马士兵,可以获得马士兵学习视频一份