在项目开发中,遇到了一个新需求,要做一个画廊效果的轮播图,要求指示器跟轮播图分离。效果图如下。以前做轮播图都是直接拿第三方的,现在突然做一个这种小众的效果,发现自己不知道怎么做,尤其是这个指示器,后来在GitHub上搜到了一个很好用 指示器实现方案,特地引用进来,非常感谢LinweiJ,帮我完成了功能实现。老规矩,附上指示器的地址:ViewPagerIndicator
1.ViewPagerIndicator的强大我就不过赘述了,自己前去GitHub看使用方法,我只附上效果图
2.clipChildren,先了解这个属性,因为在只用过程中至关重要。clipChild用来定义他的子控件是否要在他应有的边界内进行绘制。 默认情况下,clipChild被设置为true,不允许进行扩展绘制。所以我们要实现画廊效果就要设置该属性为false。而且,这个属性一定是要添加在viewpager所在的直接父布局的
接下来就是mViewpager.setPageTransformer(true, new CardTransformer());这句关键代码,setPageTransformer设置轮播图两边的缩放效果,才能实现画廊效果,下面附上CardTransformer的代码,可以根据自己的需求设置不同的属性值
/**
* Created by zzf on 2017/10/27.
*/
public class CardTransformer implements ViewPager.PageTransformer {
private static final float MAX_SCALE = 1.2f;
private static final float MIN_SCALE = 1.0f;//0.85f
@Override
public void transformPage(View page, float position) {
if (position <= 1) {
// 1.2f + (1-1)*(1.2-1.0)
float scaleFactor = MIN_SCALE + (1 - Math.abs(position)) * (MAX_SCALE - MIN_SCALE);
page.setScaleX(scaleFactor); //缩放效果
if (position > 0) {
page.setTranslationX(-scaleFactor * 2);
} else if (position < 0) {
page.setTranslationX(scaleFactor * 2);
}
page.setScaleY(scaleFactor);
} else {
page.setScaleX(MIN_SCALE);
page.setScaleY(MIN_SCALE);
}
}
}
3.重要的关键的已经说完,前面说了轮播图和指示器分离,是比较少用的情况,所以我自身没做到自己写一个可以实现的指示器,在引用了ViewPagerIndicator以后,只要在xml布局中设置指示器的任意位置,就可以自己决定指示器是在轮播图内,还是分离开来。这里还是非常感谢LinweiJ提供的这么优秀的开源框架。下面附上xml代码:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/img_home_bg"
android:clipChildren="false"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="wrap_content"
android:layout_height="200dp"
android:layout_gravity="center"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:layout_marginTop="30dp"
android:clipChildren="false"
android:overScrollMode="never"></android.support.v4.view.ViewPager>
<com.lwj.widget.viewpagerindicator.ViewPagerIndicator
android:id="@+id/indicator_line"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="10dp"
app:vpi_default_color="@color/whilte"
app:vpi_distance="14dp"
app:vpi_distanceType="BY_DISTANCE"
app:vpi_indicatorType="CIRCLE_LINE"
app:vpi_length="14dp"
app:vpi_radius="3dp" />
<RelativeLayout
android:layout_marginTop="@dimen/dimen_30dp"
android:clipChildren="false"
android:layout_width="match_parent"
android:layout_height="200dp">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager2"
android:layout_width="wrap_content"
android:layout_height="200dp"
android:layout_gravity="center"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:clipChildren="false"
android:overScrollMode="never"></android.support.v4.view.ViewPager>
<com.lwj.widget.viewpagerindicator.ViewPagerIndicator
android:layout_alignParentBottom="true"
android:layout_marginBottom="10dp"
android:id="@+id/indicator_line2"
android:layout_width="match_parent"
android:layout_height="50dp"
app:vpi_default_color="@color/whilte"
app:vpi_distance="14dp"
app:vpi_distanceType="BY_DISTANCE"
app:vpi_indicatorType="CIRCLE_LINE"
app:vpi_length="14dp"
app:vpi_radius="3dp" />
</RelativeLayout>
</LinearLayout>
实现效果
4.接下来就是Java代码的实现逻辑,实现起来还是非常简单的,我给轮播图添加了点击事件监听,可以直接使用
Activity代码:
/**
* Created by zzf on 2018/8/29.
*/
public class BannerActivity extends BaseActivity {
@BindView(R.id.viewpager)
ViewPager mViewpager;
@BindView(R.id.indicator_line)
ViewPagerIndicator mIndicatorLine;
@BindView(R.id.viewpager2)
ViewPager mViewpager2;
@BindView(R.id.indicator_line2)
ViewPagerIndicator mIndicatorLine2;
private BannerAdapter mBannerAdapter;
private BannerAdapter mBannerAdapter2;
@Override
protected BasePresenter createPresenter() {
return null;
}
@Override
public int getLayoutId() {
return R.layout.activity_banner;
}
@Override
public void initView() {
initFirstBanner();
initSecondBanner();
}
private void initSecondBanner() {
mBannerAdapter2 = new BannerAdapter(this, mViewpager2);
mViewpager2.setAdapter(mBannerAdapter2);
mViewpager2.setOffscreenPageLimit(2);//预加载2个
mViewpager2.setPageMargin(30);//设置viewpage之间的间距
mViewpager2.setClipChildren(false);
mViewpager2.setPageTransformer(true, new CardTransformer());
mIndicatorLine2.setViewPager(mViewpager2, 6);
mBannerAdapter2.setItemClickListener(new BannerAdapter.ItemClickListener() {
@Override
public void onItemClick(int index) {
// ToastUtils.showToast("点击了图片" + index);
}
});
mViewpager2.setCurrentItem(0);
}
private void initFirstBanner() {
mBannerAdapter = new BannerAdapter(this, mViewpager);
mViewpager.setAdapter(mBannerAdapter);
mViewpager.setOffscreenPageLimit(2);//预加载2个
mViewpager.setPageMargin(30);//设置viewpage之间的间距
mViewpager.setClipChildren(false);
mViewpager.setPageTransformer(true, new CardTransformer());
mIndicatorLine.setViewPager(mViewpager, 6);
mBannerAdapter.setItemClickListener(new BannerAdapter.ItemClickListener() {
@Override
public void onItemClick(int index) {
// ToastUtils.showToast("点击了图片" + index);
}
});
mViewpager.setCurrentItem(0);
}
}
adapter代码:
/**
* Created by zzf on 2018/7/29.
*/
public class BannerAdapter extends PagerAdapter implements View.OnClickListener, ViewPager.OnPageChangeListener {
private Context mContext;
private ItemClickListener itemClickListener;
private int currentPosition = 0;
public BannerAdapter(Context context, ViewPager viewPager) {
mContext = context;
viewPager.clearOnPageChangeListeners();
viewPager.addOnPageChangeListener(this);
}
public void setItemClickListener(ItemClickListener itemClickListener) {
this.itemClickListener = itemClickListener;
}
@Override
public int getCount() {
return 6;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
View view = LayoutInflater.from(mContext).inflate(R.layout.item_viewpager, null);
ImageView imageView = view.findViewById(R.id.iv_icon);
imageView.setOnClickListener(this);
container.addView(view);
return view;
}
/* @Nullable
@Override
public CharSequence getPageTitle(int position) {
return tabList.get(position);
}*/
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public void onClick(View v) {
if (null != itemClickListener) {
itemClickListener.onItemClick(currentPosition);
}
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
currentPosition = position;
}
@Override
public void onPageScrollStateChanged(int state) {
}
public interface ItemClickListener {
void onItemClick(int index);
}
}
由于当时的项目没要求做无限轮播和自动轮播的要求,所以我也就没加这些功能,但是实现起来也是非常简单的,如果有需要可以提出来,我有时间可以再去实现该功能