ViewPager实现自动轮播效果
来源:互联网 发布:5s是否支持4g网络 编辑:程序博客网 时间:2024/05/01 12:55
花了点时间实现了轮播效果,其中借鉴了一篇博客:轮播效果实现,但是这个里面所有的方法实现都写在一个文件中,真是花费了不少的时间来理清作者思路,这个作者写的内容可以直接拿来使用,我只是将其中的实现模块化实现了,但是只是简单的实现了效果,并没有进行具体的封装,所以仅供参考思路。
1.抽象SingleFragmentActivity类。
参考《Android编程权威指南》中作者的意见,抽象出了一套Fragment的代码用来使用,基本可以实现大多数的情况,代码如下:
SingleFragmentActivity.java
public abstract class SingleFragmentActivity extends AppCompatActivity { protected abstract Fragment createFragment(); @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_fragment); FragmentManager fm = getSupportFragmentManager(); Fragment fragment = fm.findFragmentById(R.id.fragment_container); if (fragment == null) { fragment = createFragment(); fm.beginTransaction() .add(R.id.fragment_container, fragment) .commit(); } }}
其中需要的布局代码很简单:
activity_fragment.xml
"><FrameLayout android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:android="http://schemas.android.com/apk/res/android"/>```
使用的时候也比较简单了,需要实现的活动直接继承SingleFragmentActivity即可,然后实现其createFragment方法即可。这样的话,就可以将Fragment托管到Activity中去使用,其中fragment就可以通过FragmentManager来进行管理了。
2.创建RotationActivity继承SingleFragmentActivity。
正如上面所介绍的,我们需要创建一个轮播的Activity,其继承与SingleFragmentActivity类,实现其中的createFragment方法,所以我们就需要一个Fragment。
RotationActivity.java
public class RotationActivity extends SingleFragmentActivity { @Override protected Fragment createFragment() { return RotationFragment.newInstance(); }}
RotationFragment.java
public static Fragment newInstance() { return new RotationFragment(); } ```
由于我们需要一个Fragment,所以我们创建了一个RotationFragment类(这里只给出了创建该实例的方法,其他方法会逐渐给出),然后用一个静态方法,可以通过该静态方法来创建该实例。
以上的内容都只是基础的,下面才开始要进行主要内容的实现了。
3.使用Asset读取本地图片。
这里我并没有使用网络来加载图片,直接使用了本地的图片,然后通过加载直接使用。
首先创建一个图片的模型类,其中存放了图片的一些信息:
ImageInfo.java
public class ImageInfo { private String mUrl; private String mTitle; private Bitmap mBitmap; public Bitmap getBitmap() { return mBitmap; } public void setBitmap(Bitmap bitmap) { mBitmap = bitmap; } public String getUrl() { return mUrl; } public void setUrl(String url) { mUrl = url; } public String getTitle() { return mTitle; } public void setTitle(String title) { mTitle = title; }}
然后我们需要管理本地的图片,创建一个ImagesManager类:
import android.content.Context;import android.content.res.AssetManager;import android.graphics.BitmapFactory;import java.io.IOException;import java.io.InputStream;import java.util.ArrayList;import java.util.List;/** * Created by leafage on 2017/3/25. */public class ImagesManager {//用来管理图片的信息 private AssetManager mAssets;//用来管理Assets资源 private List<ImageInfo> mImageInfos = new ArrayList<>(); public ImagesManager(Context context) { mAssets = context.getAssets(); loadImages(); } private void loadImages() { String[] imageNames;//用来存储图片的名字 try { imageNames = mAssets.list("rotation_images");//得到images目录下的文件名 for (String name : imageNames) { ImageInfo imageInfo = new ImageInfo(); String fileName = name.split("\\.")[0];//去除文件的后缀 imageInfo.setTitle(fileName); InputStream inputStream = mAssets.open("rotation_images" + "/" + name); imageInfo.setBitmap(BitmapFactory.decodeStream(inputStream)); mImageInfos.add(imageInfo); } } catch (IOException ioe) { ioe.printStackTrace(); } } public List<ImageInfo> getImageInfos() { return this.mImageInfos; }}
这个类使用了asset技术读取本地的图片,然后初始化每个图片信息,比如得到图片的名字、将图片转换成Bitmap类型,然后添加到一个List中,最后可以通过调用getImageInfos方法得到所有的图片模型信息。
4.将图片生成ViewPager所需要的Vew。
由于ViewPager中我们需要一组视图,所以我么可以将上面得到的图片转换成一组View来供ViewPager使用。我将其单独写到了一个类中:
InitImagesViewList.java
import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.widget.ImageView;import android.widget.TextView;import java.util.ArrayList;import java.util.List;/** * Created by leafage on 2017/3/26. */public class InitImagesViewList { private Context mContext; private ImagesManager mImagesManager; public InitImagesViewList(Context context) { mContext = context; mImagesManager = new ImagesManager(context); } public List<View> getImageViewList() {//根据传来的图片信息,初始化生成View List<View> mViews = new ArrayList<>(); List<ImageInfo> imageInfos = mImagesManager.getImageInfos(); for (int i = 0; i < imageInfos.size() + 2; i++) { View view = LayoutInflater.from(mContext).inflate(R.layout.image_title, null); ImageView imageView = (ImageView) view.findViewById(R.id.rotation_image); TextView textView = (TextView) view.findViewById(R.id.rotation_title); if (i == 0) {//第一个放最后一张视图 imageView.setImageBitmap(imageInfos.get(imageInfos.size() - 1).getBitmap()); textView.setText(imageInfos.get(imageInfos.size() - 1).getTitle()); } else { if (i == imageInfos.size() + 1) {//最后一张放第一张 imageView.setImageBitmap(imageInfos.get(0).getBitmap()); textView.setText(imageInfos.get(0).getTitle()); } else {//其他情况就正常放置 imageView.setImageBitmap(imageInfos.get(i - 1).getBitmap()); textView.setText(imageInfos.get(i - 1).getTitle()); } } mViews.add(view); } return mViews; }}
我这里一共有三张图片,但是为了制造从最后一张也可以滑动到第一张图片的效果,就将最后一张图片复制一张放到最前面,拿出第一张图片放到最后面。如果有1、2、3,三张图,构造完之后就是3、1、2、3、1,有五张图片。我们滑动的时候展现在用户面前的就是123,但是当最后一张3继续向右滑动的时候,就会出现1的图片,这时候我们调用ViewPager的setCurrentItem方法,再隐式的跳转到1就行了。
然后我们写一个类用来监听ViewPager事件,然后重写其中的onPageScrollStateChanged方法:
@Override public void onPageScrollStateChanged(int state) { //Log.i("leafage", "onPageScrollStateChanged:" + state); switch (state) { case ViewPager.SCROLL_STATE_IDLE://当停下来的时候 if (mViewPager.getCurrentItem() == 4) { mViewPager.setCurrentItem(1, false); //Log.i("leafage", "最后一个转换成第一个"); } if (mViewPager.getCurrentItem() == 0) { mViewPager.setCurrentItem(3, false); //Log.i("leafage", "第一个转换成最后一个"); } break; case ViewPager.SCROLL_STATE_DRAGGING://滑动中 mIsAutoPlay = false; break; case ViewPager.SCROLL_STATE_SETTLING://手指已经不再继续滑动了 mIsAutoPlay = true; break; default: break; } }
5.设置ViewPager的Adapter。
在Adapter中就需要实现其抽象方法,返回相对应的内容即可。
ViewPagerAdapter.java
import android.support.v4.view.PagerAdapter;import android.util.Log;import android.view.View;import android.view.ViewGroup;import java.util.List;/** * Created by leafage on 2017/3/25. */public class ViewPagerAdapter extends PagerAdapter { private List<View> mViews; /** * 用来存放View视图 * @param mViews */ public ViewPagerAdapter(List<View> Views) { this.mViews = Views; } @Override public int getCount() {//得到view的个数 return mViews.size(); } //判断是否page view与 instantiateItem(ViewGroup, int)返回的object的key 是否相同,以提供给其他的函数使用 //官方建议这样写 @Override public boolean isViewFromObject(View view, Object object) { return view == object; } //创建给定位置的界面 @Override public Object instantiateItem(ViewGroup container, final int position) { View view = mViews.get(position);//得到当前的视图,并添加点击事件 view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.d("leafage", "Onclick : " + position); } }); container.addView(view); return view; } //删除当前位置的视图 @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView(mViews.get(position)); }}
6.实现自动轮播。
上述的步骤完成之后,现在应该可以手动进行滑动了,离我们自动轮播相差不远了。
使用Handler中的postDelayed方法就能够实现。在run方法中进行自动调用即可,其中需要判断一下此时图片有没有被拖动,被拖动的话就不要自动播放了。
@Override public void run() { if (mRotationChangeListener.isAutoPlay()) {//自动播放,说明现在没有手指滑动 int currentItem = mViewPager.getCurrentItem();//得到当前的位置 currentItem = (currentItem % mViewCounts) + 1; mViewPager.setCurrentItem(currentItem); mHandler.postDelayed(this, mDelay); } else {//现在不是自动播放,等待五秒,看看能不能播放了 mHandler.postDelayed(this, 5000); } }
7.设置小圆点指示器。
完成上述的步骤就已经能够自动无限制轮播了,但是还缺少一点就是下面的指示器来展示我们正处于第几个视图中。
原点指示器的话设置两个变大变小的动画,然后在ViewPagwer中的onPageSelected中进行转换调用动画:
public void onPageSelected(int position) { //Log.i("leafage", "onPageSelected :" + position); for (int i = 0; i < mDots; i++) {//遍历一下全部的小圆点,把当前的小圆点设置变大动画,其他的都变小 if (i == position - 1) {//得到当前的小圆点索引值 IndicatorDot.mLinearLayout.getChildAt(i).setBackgroundResource(R.drawable.checked); mAnimatorDot.DotLargen(IndicatorDot.mLinearLayout.getChildAt(i));//变大 IndicatorDot.sState.put(i, true); } else {//如果不是当前的话,如果处于选中状态则改变成为选中状态 if (IndicatorDot.sState.get(i)) { IndicatorDot.mLinearLayout.getChildAt(i).setBackgroundResource(R.drawable.unchecked); mAnimatorDot.DotMinify(IndicatorDot.mLinearLayout.getChildAt(i));//变小 IndicatorDot.sState.put(i, false); } } } }
小圆点的话,共分为两个步骤一个就是动画的设置,一个就是基本属性的设置:
基本属性设置:
public void InitIndicationDot() { for (int i = 0; i < mDots; i++) { LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(mDotWidth, mDotHeight); layoutParams.leftMargin = 15; layoutParams.rightMargin = 15; layoutParams.bottomMargin = 15; layoutParams.topMargin = 15; View view = new View(mContext); view.setBackgroundResource(R.drawable.unchecked); mLinearLayout.addView(view, layoutParams); sState.put(i, false); } sState.put(0, true); }
动画的设置在源码中给出,再次不在羸述。
8.整合所有的功能。
至此,各个模块之间都已经写好了,然后在RotationFragment.java中进行整合调用。
import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v4.app.Fragment;import android.support.v4.view.ViewPager;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import java.util.List;import android.os.Handler;import android.widget.LinearLayout;/** * Created by leafage on 2017/3/25. */public class RotationFragment extends Fragment { private ViewPager mViewPager; private List<View> mViews;//用来存放视图 private InitImagesViewList mInitImagesViewList;//用来初始化信息得到视图 private ViewPagerAdapter mViewPagerAdapter;//用来给ViewPager设置的Adapter private RotationChangeListener mRotationChangeListener;//设置滑动时监听 private boolean isAutoPlay = true;//用来记录现在是不是自动播放,默认是True private Handler mHandler; private AutoPlay mAutoPlay; private LinearLayout mLinearLayout;//用来管理小圆点指示器的线性布局. private IndicatorDot mIndicatorDot;//用来设置小圆点指示器的类。 public static Fragment newInstance() { return new RotationFragment(); } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); mInitImagesViewList = new InitImagesViewList(getContext()); mViews = mInitImagesViewList.getImageViewList(); mViewPagerAdapter = new ViewPagerAdapter(mViews); mHandler = new Handler(); } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_rotation, container, false); mViewPager = (ViewPager) view.findViewById(R.id.viewPager); mLinearLayout = (LinearLayout) view.findViewById(R.id.indicator_dot); mIndicatorDot = new IndicatorDot(getContext(),mLinearLayout, mViews.size() - 2);//减去多余的两张视图 mIndicatorDot.setDots(35,35); mIndicatorDot.InitIndicationDot(); mRotationChangeListener = new RotationChangeListener(getContext(),mViewPager,isAutoPlay,mIndicatorDot.getDots());//设置滚动监听 mViewPager.setAdapter(mViewPagerAdapter);//设置适配器 mViewPager.addOnPageChangeListener(mRotationChangeListener);//设置滑动监听 mViewPager.setCurrentItem(1);//设置开始的下标,也就是第二张图,因为第一张是就是最后一张 mAutoPlay = new AutoPlay(mViewPager,3000,mRotationChangeListener,mHandler,mViews.size()); mHandler.postDelayed(mAutoPlay, 3000); return view; } @Override public void onDestroy() { super.onDestroy(); mHandler.removeCallbacks(mAutoPlay); }}
所有的内容大致就是这样了,没有进行详细的介绍,大致思路已经完全给出。如果不使用本地图片的话,可以采用Glide或者Picasso框架进行动态加载也是可以的。个人认为整体来说没有特别困难的地方,主要是整体的流程和各个模块之间的配合使用。需要了解ViewPager的setCurrentItem使用和OnPageChangeListener中的各个回调方法的回调时间,简单动画的使用以及Handler中的postDelayed使用。基本上就上述各个点需要注意。
整个项目的截图:
源代码:Rotation
- ViewPager实现自动轮播效果
- VIewPager实现自动轮播
- ViewPager+Handler实现图片自动轮播的效果
- ViewPager自动轮播
- ViewPager自动轮播
- viewpager自动轮播
- viewpager自动轮播
- Android实现ViewPager自动轮播
- 如何实现viewpager自动轮播
- viewPager 实现banner图 自动轮播
- ViewPager 实现图片自动轮播
- Viewpager实现图片自动轮播
- ViewPager实现自动轮播图片
- 自动轮播的viewPager实现
- 使用ViewPager实现自动轮播
- ViewPager实现无限自动轮播
- 自定义实现广告自动轮播效果
- android TV开发:使用ViewPager实现图片自动轮播效果
- 在一个千万级的数据库查寻中,如何提高查询效率?
- Win系统svchost进程流量偷跑,如何永久杜绝?
- android:configChanges="keyboardHidden|orientation" 无效
- R语言ggplot2饼状图
- 文章标题:Android常见控件ImageView的使用方法
- ViewPager实现自动轮播效果
- 安卓Android自定义控件之自定义时钟
- SAX与DOM
- 三、Spring4的新功能和增强
- 2.2 常量和变量
- Java多线程 之 类锁与对象锁
- 【LeetCode】461.Hamming Distance_EASY(一)
- vs2010配置安装使用log4cplus日志系统
- bus_register(待续)