#1 效果图
#2 Demo地址
http://download.csdn.net/detail/baopengjian/9901113
#3 原理
1) ViewPager实现左右滑动
2)handler实现定时消息
3)数据集List第0个添加真实数据最后一个,最后一个添加真实数据的第0个(List = 真实数据最后一个+真实数据集合+真实数据第一个)实现缓存的数据结构;
4)ViewPager的无动画切换View的API:setCurrentItem(position,false)实现 当最后或第一个时切换到相同视图,从而实现“无限轮播”的错觉
#4 Demo特点:
1)封装性强,集成速度快(关键代码2行,xml中引入封装Fragment即可)
2)轮播图的停止,启动自维护;
3)支持异步
4)修改方便,点击事件、轮播图的Pager均可修改
#5 代码
1)使用轮播图的MainActivity
xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.bpj.demo.MainActivity">
<fragment
android:id="@+id/fragment_viewpager_cycle"
android:name="com.bpj.demo.ViewPagerCycleFragment"
android:layout_width="match_parent"
android:layout_height="180dp"/>
<Button
android:onClick="refreshData"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:layout_below="@id/fragment_viewpager_cycle"
android:text="refreshData"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
MainActivity
public class MainActivity extends AppCompatActivity {
private ViewPagerCycleFragment mFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFragment = (ViewPagerCycleFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_viewpager_cycle);
Log.i("MainActivity", ">>>> ThreadId =" + Thread.currentThread().getId());
initData();
}
public void refreshData(View v) {
initData();
}
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mFragment.setData(list, new ViewPagerCycleFragment.CycleViewClickListener() {
@Override
public void onImageClick(ViewPagerCycleBean info, int position, View imageView) {
Toast.makeText(MainActivity.this, " >>> position" + position, Toast.LENGTH_SHORT).show();
}
});
mFragment.startRoll(3000);
}
};
@Override
protected void onDestroy() {
mHandler.removeCallbacksAndMessages(null);
super.onDestroy();
}
List<ViewPagerCycleBean> list;
private List<ViewPagerCycleBean> initData() {
new Thread() {
@Override
public void run() {
super.run();
try {
Thread.sleep(1000);
list = new ArrayList<>();
Random r = new Random();
int size = r.nextInt(10);
Log.i("MainActivity", ">>> size " + size);
// int size = 1;
for (int i = 0; i < size; i++) {
ViewPagerCycleBean bean = new ViewPagerCycleBean(i);
list.add(bean);
}
mHandler.sendEmptyMessage(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
return null;
}
}
2)封装了轮播图的Fragment
public class ViewPagerCycleFragment extends Fragment implements ViewPager.OnPageChangeListener {
private static final int ROLL = 100; // 转动
private static final int WAIT = 101; // 等待
private ViewPager viewPager;
private LinearLayout indicatorLayout;
private List<View> mViews = new ArrayList<>();
private boolean isScrolling = false;
private int time = 3000; // 默认轮播时间
private int currentPosition = 0; // 轮播当前位置
private long releaseTime = 0; // 手指松开、页面不滚动时间,防止手机松开后短时间进行切换
private CycleViewClickListener mListener;
private List<ViewPagerCycleBean> mDatas;
private ViewPagerAdapter mAdapter;
private ImageView[] indicators;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.i("Fragment",">>> handleMessage");
if (msg.what == ROLL && mViews.size() != 0) {
if (!isScrolling) {
int max = mViews.size() + 1;
int position = (currentPosition + 1) % mViews.size();
viewPager.setCurrentItem(position, true);
if (position == max) { // 最后一页时回到第一页
viewPager.setCurrentItem(1, false);
}
}
releaseTime = System.currentTimeMillis();
mHandler.removeCallbacks(runnable);
mHandler.postDelayed(runnable, time);
return;
}
if (msg.what == WAIT && mViews.size() != 0) {
mHandler.removeCallbacks(runnable);
mHandler.postDelayed(runnable, time);
}
}
};
final Runnable runnable = new Runnable() {
@Override
public void run() {
if (getActivity() != null && !getActivity().isFinishing()) {
long now = System.currentTimeMillis();
// 检测上一次滑动时间与本次之间是否有触击(手滑动)操作,有的话等待下次轮播
if (now - releaseTime > time - 500) {
mHandler.sendEmptyMessage(ROLL);
} else {
mHandler.sendEmptyMessage(WAIT);
}
}
}
};
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = LayoutInflater.from(getActivity()).inflate(
R.layout.view_cycle_viewpager_contet, null);
viewPager = view.findViewById(R.id.viewPager);
viewPager.setOffscreenPageLimit(3);
indicatorLayout = view.findViewById(R.id.layout_viewpager_indicator);
setIndicatorCenter();
return view;
}
public void setIndicatorCenter() {
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
params.addRule(RelativeLayout.CENTER_HORIZONTAL);
indicatorLayout.setLayoutParams(params);
}
public void setData(List<ViewPagerCycleBean> datas,CycleViewClickListener listener) {
Activity activity = getActivity();
if(activity == null || activity.isFinishing() || !isVisible()){
return;
}
if (datas == null || datas.isEmpty()) {
return;
}
mListener = listener;
mViews = getCycleViews(datas);
// 设置指示器
indicators = new ImageView[datas.size()];
indicatorLayout.removeAllViews();
for (int i = 0; i < datas.size(); i++) {
View view = LayoutInflater.from(getActivity()).inflate(
R.layout.view_cycle_viewpager_indicator, null);
indicators[i] = view.findViewById(R.id.image_indicator);
indicatorLayout.addView(view);
}
mAdapter = new ViewPagerAdapter();
// 默认指向第一项,下方viewPager.setCurrentItem将触发重新计算指示器指向
setIndicator(0);
viewPager.setOffscreenPageLimit(3);
viewPager.setOnPageChangeListener(this);
viewPager.setAdapter(mAdapter);
viewPager.setCurrentItem(1);
}
private List<View> getCycleViews(List<ViewPagerCycleBean> datas) {
mDatas = new ArrayList<>();
if(datas.size()>1){
mDatas.add(datas.get(datas.size() - 1));
mDatas.addAll(datas);
mDatas.add(datas.get(0));
}else{
mDatas.addAll(datas);
}
List<View> list = new ArrayList<>();
for (ViewPagerCycleBean bean : mDatas) {
TextView tv = new TextView(getContext());
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
tv.setLayoutParams(params);
tv.setGravity(Gravity.CENTER);
tv.setBackgroundColor(Color.GREEN);
tv.setText(String.valueOf(bean.getPosition()));
tv.setTextSize(40);
tv.setTextColor(Color.RED);
list.add(tv);
}
return list;
}
private boolean isRooll = false;
public void startRoll(int time) {
if(mAdapter == null ||mViews == null ||mViews.size() <= 1){
return;
}
this.time = time;
releaseTime = 0;
if(isRooll){
return;
}else{
mHandler.postDelayed(runnable, time);
isRooll = true;
}
}
@Override
public void onPause() {
super.onPause();
stopRoll();
}
@Override
public void onResume() {
super.onResume();
startRoll(time);
}
public void stopRoll(){
if(isRooll){
mHandler.removeCallbacksAndMessages(null);
}
isRooll = false;
}
/**
* 设置指示器
*
* @param selectedPosition 默认指示器位置
*/
private void setIndicator(int selectedPosition) {
for (int i = 0; i < indicators.length; i++) {
indicators[i].setBackgroundResource(R.drawable.icon_point);
}
if (indicators.length > selectedPosition)
indicators[selectedPosition].setBackgroundResource(R.drawable.icon_point_pre);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
int max = mViews.size() - 1;
currentPosition = position;
if (position == 0) {
currentPosition = max - 1;
} else if (position == max) {
currentPosition = 1;
}
int position1 = currentPosition - 1;
setIndicator(position1);
}
@Override
public void onPageScrollStateChanged(int state) {
if (state == 1) { // viewPager在滚动
isScrolling = true;
return;
} else if (state == 0) { // viewPager滚动结束
releaseTime = System.currentTimeMillis();
viewPager.setCurrentItem(currentPosition, false);
}
isScrolling = false;
}
private class ViewPagerAdapter extends PagerAdapter {
@Override
public int getCount() {
return mViews.size();
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public View instantiateItem(ViewGroup container, final int position) {
View v = mViews.get(position);
if (mListener != null) {
v.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ViewPagerCycleBean bean = mDatas.get(position);
mListener.onImageClick(bean, bean.getPosition(), v);
}
});
}
container.addView(v);
return v;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
/**
* 轮播控件的监听事件
*
* @author minking
*/
public static interface CycleViewClickListener {
/**
* 单击图片事件
*
* @param position a
* @param imageView
*/
public void onImageClick(ViewPagerCycleBean info, int position, View imageView);
}
}
view_cycle_viewpager_contet.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_viewager_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<LinearLayout
android:id="@+id/layout_viewpager_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_margin="1dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingBottom="6dp"
android:paddingRight="6dp"></LinearLayout>
</RelativeLayout>
view_cycle_viewpager_indicator.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="@+id/image_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:scaleType="fitXY"/>
</LinearLayout>