Android用ViewPager实现一个中间大两边小并且带指示器的轮播图,也称画廊效果

2 篇文章 0 订阅

在项目开发中,遇到了一个新需求,要做一个画廊效果的轮播图,要求指示器跟轮播图分离。效果图如下。以前做轮播图都是直接拿第三方的,现在突然做一个这种小众的效果,发现自己不知道怎么做,尤其是这个指示器,后来在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);
    }
}

由于当时的项目没要求做无限轮播和自动轮播的要求,所以我也就没加这些功能,但是实现起来也是非常简单的,如果有需要可以提出来,我有时间可以再去实现该功能

  • 7
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 20
    评论
使用ViewPager实现轮播图的步骤如下: 1. 在布局文件中添加ViewPager控件和指示器(可选)。 ```xml <androidx.viewpager.widget.ViewPager android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="200dp" /> <LinearLayout android:id="@+id/indicator_layout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:orientation="horizontal" /> ``` 2. 创建一个PagerAdapter,设置数据源和页面布局。 ```java public class MyPagerAdapter extends PagerAdapter { private List<Integer> mData; private LayoutInflater mInflater; public MyPagerAdapter(Context context, List<Integer> data) { mData = data; mInflater = LayoutInflater.from(context); } @Override public int getCount() { return mData.size(); } @Override public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { return view == object; } @NonNull @Override public Object instantiateItem(@NonNull ViewGroup container, int position) { View view = mInflater.inflate(R.layout.item_pager, container, false); ImageView imageView = view.findViewById(R.id.image_view); imageView.setImageResource(mData.get(position)); container.addView(view); return view; } @Override public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { container.removeView((View) object); } } ``` 3. 绑定PagerAdapter和ViewPager,并设置ViewPager的滑动监听,以便更新指示器。 ```java ViewPager viewPager = findViewById(R.id.view_pager); MyPagerAdapter adapter = new MyPagerAdapter(this, mData); viewPager.setAdapter(adapter); LinearLayout indicatorLayout = findViewById(R.id.indicator_layout); for (int i = 0; i < mData.size(); i++) { View indicator = new View(this); int size = getResources().getDimensionPixelSize(R.dimen.indicator_size); LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(size, size); lp.leftMargin = i == 0 ? 0 : getResources().getDimensionPixelSize(R.dimen.indicator_margin); indicator.setLayoutParams(lp); indicator.setBackgroundResource(R.drawable.indicator_bg); indicatorLayout.addView(indicator); } viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { super.onPageSelected(position); for (int i = 0; i < mData.size(); i++) { View indicator = indicatorLayout.getChildAt(i); indicator.setSelected(i == position); } } }); ``` 其中,item_pager布局文件中只包含一个ImageView控件,用于显示图片。indicator_bg是指示器的背景,可以自定义。 以上就是使用ViewPager实现轮播图的主要步骤。
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值