android ViewPager 仿画廊/图书翻页 与 palette 使用
废话不多说,先来看看完成的效果!
总结实现效果:
- ViewPager 实现无限自动播放
- ViewPager 实现中间大,两边小 [仿画廊效果]
- ViewPager 实现图片叠加[仿图书翻页效果]
- palette 调色板实现识别图片颜色,随着图片的变化来改变背景色的变化
普通ViewPager实现
先不管三七二十一,先吧最基本的ViewPager实现,之后在在基本的ViewPager上修改!
不用复制代码,先看思路就行,底部会给出完整代码!
activity_palette.xml布局: java代码:
viewPager.setAdapter(new BannerAdapter(this, mDrawables));
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.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显示出左右两侧的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;
private static final float MIN_SCALE = 0.80f;
@Override
public void transformPage(@NonNull View view, float position) {
}
}
实现implements ViewPager.PageTransformer重写transformPage()方法,有2个参数
public interface PageTransformer {
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
不滑动状态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;
private static final float MIN_SCALE = 0.80f;
@Override
public void transformPage(@NonNull View view, float position) {
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;
private static final float MIN_SCALE = 0.80f;
@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();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
if (!isDown) {
int page = viewPager.getCurrentItem() + 1;
runOnUiThread(() -> viewPager.setCurrentItem(page));
}
}
};
timer.schedule(timerTask, 0, 2500);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
isDown = true;
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
isDown = false;
}
});
这段代码过于简单,就不看效果了!
仿图书效果
这个效果和仿画廊流程一样,也是对PageTransformer的操作,直接上代码了!
public class StackPageTransformer implements ViewPager.PageTransformer {
private final ViewPager viewPager;
private final float SCALE_VALUE = 1f;
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 + "");
int pageWidth = viewPager.getWidth();
if (position == -1) {
view.setVisibility(View.GONE);
} else {
view.setVisibility(View.VISIBLE);
}
if (position >= 0) {
float translationX;
if (isStack) {
translationX = DEVIATION - (pageWidth) * position;
} else {
translationX = (DEVIATION - pageWidth) * position;
}
Log.i("szjTranslationX", translationX + "");
view.setTranslationX(translationX);
}
if (position == 0) {
view.setScaleX(SCALE_VALUE);
view.setScaleY(SCALE_VALUE);
} else {
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 -> {
int darkMutedColor = palette.getDarkMutedColor(Color.TRANSPARENT);
int lightMutedColor = palette.getLightMutedColor(Color.TRANSPARENT);
int darkVibrantColor = palette.getDarkVibrantColor(Color.TRANSPARENT);
int lightVibrantColor = palette.getLightVibrantColor(Color.TRANSPARENT);
int mutedColor = palette.getMutedColor(Color.TRANSPARENT);
int vibrantColor = palette.getVibrantColor(Color.TRANSPARENT);
Palette.Swatch lightVibrantSwatch = palette.getLightVibrantSwatch();
int hotColor = Color.TRANSPARENT;
if (lightVibrantSwatch != null) {
int rgb = lightVibrantSwatch.getRgb();
hotColor = getTranslucentColor(0.7f, rgb);
}
})).start();
}
然后通过随机图片,设置不同的图片来测试一下管用不管用!
来看看效果:
这里用到了动态代码设置渐变,代码很简单,给大家看看吧
public void setGradualChange(View view, int[] colors, GradientDrawable.Orientation type, int radius) {
GradientDrawable drawable = new GradientDrawable(type, colors);
drawable.setCornerRadius(radius);
view.setBackground(drawable);
}
完整项目
原创不易,您的点赞就是对我最大的支持!!
|