android ViewPager 进阶(仿画廊/图书翻页) 与 palette 使用 (含完整Demo)
Posted android超级兵
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android ViewPager 进阶(仿画廊/图书翻页) 与 palette 使用 (含完整Demo)相关的知识,希望对你有一定的参考价值。
android ViewPager 仿画廊/图书翻页 与 palette 使用
废话不多说,先来看看完成的效果!
总结实现效果:
- ViewPager 实现无限自动播放
- ViewPager 实现中间大,两边小 [仿画廊效果]
- ViewPager 实现图片叠加[仿图书翻页效果]
- palette 调色板实现识别图片颜色,随着图片的变化来改变背景色的变化
普通ViewPager实现
先不管三七二十一,先吧最基本的ViewPager实现,之后在在基本的ViewPager上修改!
不用复制代码,先看思路就行,底部会给出完整代码!
activity_palette.xml布局:
java代码:
//设置适配器
viewPager.setAdapter(new BannerAdapter(this, mDrawables));
//Pager之间的间距
viewPager.setPageMargin(20);
//预加载
viewPager.setOffscreenPageLimit(3);
//默认第一张图 左右都有图
viewPager.setCurrentItem(1);
BannerAdapter 适配器:
public class BannerAdapter extends PagerAdapter {
private int[] mData;
private Context mContext;
public BannerAdapter(Context ctx, int[] data) {
this.mContext = ctx;
this.mData = data;
}
@Override
public int getCount() {
return mData.length;// 返回数据的个数
}
@Override
public Object instantiateItem(final ViewGroup container, final int position) {//子View显示
View view = View.inflate(container.getContext(), R.layout.banner_item_layout, null);
ImageView imageView = view.findViewById(R.id.iv_icon);
imageView.setImageResource(mData[position]);
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(mContext, "当前条目:" + position, Toast.LENGTH_SHORT).show();
}
});
container.addView(view);//添加到父控件
return view;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;// 过滤和缓存的作用
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);//从viewpager中移除掉
}
}
先来看看目前的效果:
就是一个很简单的ViewPager没什么好说的!
思路分析:
要想完成画廊的效果,那么必须吧viewPager分为以下几步骤:
- 让ViewPager显示出左右两侧的View
- 无限滑动
- 自定义ViewPager 滑动动画,滑动过程中中间大,两边小
- 自动播放
那就来根据思路实现效果吧 :
让ViewPager显示出左右两侧的View
来看看效果:
无限滑动
这个也是真 的简单,直接取%即可实现
来看看效果:
中间大,两边小效果
要想实现这个效果,就要来介绍本篇重中之重! ViewPager.PageTransformer
ViewPager.PageTransformer
先来看使用:
viewPager.setPageTransformer(true, new ScaleTransformer());
- 参数一: 是否逆转,我没看出有什么效果,懂这个参数的记得在评论区留言哦!
- 参数二: 用来控制ViewPager 动画的
public class ScaleTransformer implements ViewPager.PageTransformer {
private static final float MAX_SCALE = 1.0f;//0缩放
private static final float MIN_SCALE = 0.80f;//0.85缩放
@Override
public void transformPage(@NonNull View view, float position) {
}
}
实现implements ViewPager.PageTransformer重写transformPage()方法,有2个参数
/**
* A PageTransformer is invoked whenever a visible/attached page is scrolled.
* This offers an opportunity for the application to apply a custom transformation
* to the page views using animation properties.
*
* <p>As property animation is only supported as of Android 3.0 and forward,
* setting a PageTransformer on a ViewPager on earlier platform versions will
* be ignored.</p>
*/
public interface PageTransformer {
/**
* Apply a property transformation to the given page.
*
* @param page Apply the transformation to this page
* @param position Position of page relative to the current front-and-center
* position of the pager. 0 is front and center. 1 is one full
* page position to the right, and -1 is one page position to the left.
*/
void transformPage(@NonNull View page, float position);
}
这个方法在onPageScrolled页面滑动的过程中回调
@CallSuper
protected void onPageScrolled(int position, float offset, int offsetPixels) {
....省略.......
if (mPageTransformer != null) {
....省略.......
mPageTransformer.transformPage(child, transformPos);
}
}
mCalledSuper = true;
}
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就介绍到这里!
先简简单单修改代码,先看看效果:
public class ScaleTransformer implements ViewPager.PageTransformer {
private static final float MAX_SCALE = 1.0f;//0缩放
private static final float MIN_SCALE = 0.80f;//0.85缩放
@Override
public void transformPage(@NonNull View view, float position) {
//position != 0 表示左侧和右侧的view
if (position != 0) {
view.setScaleX(MIN_SCALE);
view.setScaleY(MIN_SCALE);
} else {
view.setScaleX(MAX_SCALE);
view.setScaleY(MAX_SCALE);
}
}
}
效果:
可以看到,要实现的效果已经渐渐接近了!
在加上滑动时候放大缩小即可
public class ScaleTransformer implements ViewPager.PageTransformer {
private static final float MAX_SCALE = 1.0f;//0缩放
private static final float MIN_SCALE = 0.80f;//0.85缩放
@Override
public void transformPage(@NonNull View view, float position) {
if (position < 1) {
float scaleFactor = MIN_SCALE + (1 - Math.abs(position)) * (MAX_SCALE - MIN_SCALE);
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
} else {
view.setScaleX(MIN_SCALE);
view.setScaleY(MIN_SCALE);
}
}
}
这里涉及到一个小算法
float scaleFactor = MIN_SCALE + (1 - Math.abs(position)) * (MAX_SCALE - MIN_SCALE);
指的就是变化过程中view的大小
这段代码要细细的品味一下!!!很关键!!
来看看湿滑的效果:
无限自己滚动
这段代码也是简单的很:
直接上代码不多贝贝:
//用来记录是否按压,如果按压,则不滚动
boolean isDown ;
Timer timer = new Timer();
//定时器播放ViewPager
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
if (!isDown) {
//获取到当前的位置
int page = viewPager.getCurrentItem() + 1;
runOnUiThread(() -> viewPager.setCurrentItem(page));
}
}
};
// 每2.5秒执行一次
timer.schedule(timerTask, 0, 2500);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//viewPager滑动的时候,设置不让滚动
isDown = true;
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
//ViewPager不点击了让滚动
isDown = false;
}
});
这段代码过于简单,就不看效果了!
仿图书效果
这个效果和仿画廊流程一样,也是对PageTransformer的操作,直接上代码了!
public class StackPageTransformer implements ViewPager.PageTransformer {
private final ViewPager viewPager;
private final float SCALE_VALUE = 1f;
//View 之间的偏移量
private final float DEVIATION = 60f;
//旋转
private final float ROTATION = 60f;
//图片是否叠加【默认不叠加】
private final boolean isStack = false;
public StackPageTransformer(ViewPager viewPager) {
this.viewPager = viewPager;
}
@Override
public void transformPage(@NonNull View view, float position) {
Log.i("szjPosition2", position + "");
/*
* 当不滑动状态下:
* position = -1 左侧View
* position = 0 当前View
* position = 1 右侧View
*
* 当滑动状态下:
* 向左滑动: [ position < 0 && position > -1]
* 左侧View position < -1
* 当前View 0 ~ -1
* 右侧View 1 ~ 0
*
* 向右滑动:[position > 0 && position < 1 ]
* 左侧View -1 < position < 0
* 当前View 0 ~ 1
* 右侧View position > 1
*/
int pageWidth = viewPager.getWidth();
//隐藏左侧侧的view
if (position == -1) {
view.setVisibility(View.GONE);
} else {
view.setVisibility(View.VISIBLE);
}
//当前View和右侧的View [让右侧View和当前View叠加起来]
if (position >= 0) {
float translationX;
//这里不要晕! 改变isStack来看看效果吧!!
if (isStack) {
translationX = DEVIATION - (pageWidth) * position;
} else {
translationX = (DEVIATION - pageWidth) * position;
}
Log.i("szjTranslationX", translationX + "");
view.setTranslationX(translationX);
}
//当前view
if (position == 0) {
view.setScaleX(SCALE_VALUE);
view.setScaleY(SCALE_VALUE);
} else {
//左侧已经隐藏了,所以这里值的是右侧View的偏移量
float scaleFactor = Math.min(SCALE_VALUE - position * 0.1f, SCALE_VALUE);
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
}
//向左滑动
if (position < 0 && position > -1) {
//旋转
view.setRotation(ROTATION * position);
view.setAlpha(1 - Math.abs(position));
} else {
//透明度 其他状态不设置透明度
view.setAlpha(1);
}
//向右滑动
if (position > 0 && position < 1) {
view.setRotation(0);
}
}
}
看看效果:
palette 调色板
先添加依赖:
implementation 'com.android.support:palette-v7:26.0.0-alpha1'
简单介绍:
palette 传入一张Bitmap,然后他会通过图片像素点来分析出颜色占比,提取出你需要的颜色!!
使用:
public void initPalette(Bitmap bitmap) {
new Thread(() -> Palette.from(bitmap).generate(palette -> {
//以RGB压缩整数的形式从调色板返回静音和深色。
int darkMutedColor = palette.getDarkMutedColor(Color.TRANSPARENT);
//暗 柔和 [以RGB压缩整数的形式从调色板返回静音和浅色。]
int lightMutedColor = palette.getLightMutedColor(Color.TRANSPARENT);
//暗 鲜艳 [以RGB压缩整数的形式从调色板返回深色和鲜艳的颜色。]
int darkVibrantColor = palette.getDarkVibrantColor(Color.TRANSPARENT);
//量 鲜艳 [以RGB压缩整数的形式从调色板返回明亮的颜色。]
int lightVibrantColor = palette.getLightVibrantColor(Color.TRANSPARENT);
//柔和 [将调色板中的静音颜色作为RGB压缩整数返回。]
int mutedColor = palette.getMutedColor(Color.TRANSPARENT);
//以RGB压缩整数形式返回调色板中最鲜艳的颜色。
int vibrantColor = palette.getVibrantColor(Color.TRANSPARENT);
//从调色板中返回一个明亮且充满活力的样例。可能为空。
Palette.Swatch lightVibrantSwatch = palette.getLightVibrantSwatch();
int hotColor = Color.TRANSPARENT;
if (lightVibrantSwatch != null) {
//谷歌推荐的:图片的整体的颜色rgb的混合痔---主色调
int rgb = lightVibrantSwatch.getRgb();
hotColor = getTranslucentColor(0.7f, rgb);
}
// 拿到颜色 这里就可以给View 设置颜色了
})).start();
}
然后通过随机图片,设置不同的图片来测试一下管用不管用!
来看看效果:
这里用到了动态代码设置渐变,代码很简单,给大家看看吧
/**
* TODO 设置渐变颜色
*
* @param view 需要设置的View
* @param colors 渐变颜色
* @param type 渐变位置 例如:GradientDrawable.Orientation.LEFT_RIGHT 从左到右
* @param radius 圆角
*/
public void setGradualChange(View view, int[] colors, GradientDrawable.Orientation type, int radius) {
GradientDrawable drawable = new GradientDrawable(type, colors);
drawable.setCornerRadius(radius);
view.setBackground(drawable);
}
原创不易,您的点赞就是对我最大的支持!!
以上是关于android ViewPager 进阶(仿画廊/图书翻页) 与 palette 使用 (含完整Demo)的主要内容,如果未能解决你的问题,请参考以下文章
android 卡片画廊效果及RecycleView、ViewPager、ScrollView之前的冲突解决