您的位置:首页 > 移动开发 > Android开发

Android ViewPager 焦点图轮播

2016-03-22 17:39 651 查看

Android ViewPager 焦点图轮播

目前很多App都用了焦点图,假如你喜欢玩LoL那么掌上英雄联盟绝对是你的最爱,假如你看新闻网易新闻客户端绝对是首选,他们首页中就运用了焦点图。废话不多说,来看看怎么实现焦点图轮播。

1、首先上图,有效果才有动力。





2、代码实现

2.1首先自定义一个viewpager类 BaseViewPager, 设置其是否可以滚动

public class BaseViewPager extends ViewPager {

private boolean isScroll = true;

public BaseViewPager(Context context) {
super(context);
}

public BaseViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}

/**
* 设置是否可滚动
* @param enable
*/
public void setScrollable(boolean enable) {
this.isScroll = enable;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (isScroll) {
return super.onInterceptTouchEvent(ev);
} else {
return false;
}
}
}


2.2 定义一个类CycleViewPagerHandler 为了防止内存泄漏,定义外部类,防止内部类对外部类的引用

public class CycleViewPagerHandler  extends Handler{
private Context context;

public CycleViewPagerHandler(Context context) {
this.context = context;
}
}


2.3 自定义一个Fragment类 CycleViewPager 用于实现viewpager轮播

public class CycleViewPager extends Fragment {
@butterknife.Bind(R.id.viewPager)
BaseViewPager viewPager;
@butterknife.Bind(R.id.title_indicator)
TextView titleIndicator;
@butterknife.Bind(R.id.dot_indicator)
LinearLayout dotIndicator;
@butterknife.Bind(R.id.foot)
RelativeLayout foot;

private BaseViewPager parentViewPager;
private CycleViewPagerHandler handler;
private CycleViewPagerListener listener;
private List<AdInfo> infos;
private List<ImageView> imageViews = new ArrayList<ImageView>();
private ImageView[] indicators; //底部圆点指示器
private ViewPagerAdapter adapter;
private CycleViewPagerListener cycleViewPagerListener;

private int time = 5000; //默认循播时间
private int currentPosition = 0; //当前轮播位置
private boolean isCycle = false; //是否循环
private boolean isWheel = false; //是否循环
private boolean isScrolling = false; //viewpager是否滚动着
private long releaseTime = 0; //手指松开、页面不滚动时间,防止手机松开后短时间进行切换
private int WHEEL = 100;        //转动
private int WHEEL_WAIT = 101;   //等待

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.layout_cycleviewpager, container, false);
butterknife.ButterKnife.bind(this, view);
handler = new CycleViewPagerHandler(getActivity()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == WHEEL && imageViews.size() != 0) {
if (!isScrolling) {  //viewpager滚动着
int max = imageViews.size() + 1; //最后一页
int position = (currentPosition + 1) % imageViews.size(); //当前位置
viewPager.setCurrentItem(position, true);
if (position == max) { //最后一页时回到第一页
viewPager.setCurrentItem(1, false);
}
}
releaseTime = System.currentTimeMillis();
handler.removeCallbacks(runnable);
handler.postDelayed(runnable, time); //五秒后执行
return;
}
if (msg.what == WHEEL_WAIT && imageViews.size() != 0) {
handler.removeCallbacks(runnable);
handler.postDelayed(runnable, time);
}
}
};
return view;
}

/**
* 检测上一次滑动时间与本次之间是否有触击(手滑动)操作,有的话等待下次轮播
*/
final Runnable runnable = new Runnable() {
@Override
public void run() {
if (getActivity() != null && !getActivity().isFinishing() && isWheel) {
long now = System.currentTimeMillis();
if (now - releaseTime > time - 500) {
handler.sendEmptyMessage(WHEEL); //正在转动
} else {
handler.sendEmptyMessage(WHEEL_WAIT); //等待转动
}
}
}
};

/**
* 设置数据
*
* @param views        存放imageview集合
* @param list         广告消息
* @param listener     轮播点击监听
* @param showPosition 默认显示位置
*/
public void setData(List<ImageView> views, List<AdInfo> list, CycleViewPagerListener listener, int showPosition) {
this.listener = listener;
infos = list;
this.imageViews.clear();
if (views.size() == 0) {
foot.setVisibility(View.GONE); //如果为0,则隐藏
return;
}
for (ImageView item : views) {
this.imageViews.add(item);
}
int ivSize = views.size();
indicators = new ImageView[ivSize]; //设置圆点图片集合
if (isCycle) { // 如果循环,则减少两个小点, 反之多两个点
indicators = new ImageView[ivSize - 2];
}
dotIndicator.removeAllViews();
for (int i = 0; i < indicators.length; i++) { //设置小点
View view = LayoutInflater.from(getActivity()).inflate(R.layout.layout_indicator, null);
indicators[i] = (ImageView) view.findViewById(R.id.image_indicator);
dotIndicator.addView(view);
}

adapter = new ViewPagerAdapter();

// 默认指向第一项,下方viewPager.setCurrentItem将触发重新计算指示器指向
setIndicator(0);
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(3);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

}

@Override
public void onPageSelected(int position) {
int max = imageViews.size() - 1;
int mPosition = position;
currentPosition = position;
if (isCycle) {
if (position == 0) { //当位置在第一页时,
currentPosition = max - 1;
} else if (position == max) { //当位置在最后一页时,滑到最后一页
currentPosition = 1;
}
mPosition = currentPosition - 1;
}
Log.i("Hlh", "  " + position + "-----" +currentPosition);
setIndicator(mPosition); //设置显示哪一页
}

@Override
public void onPageScrollStateChanged(int state) {
if (state == 1) {   //viewpager滚动着
isScrolling = true;
return;
} else if (state == 0) { //viewpager滚动结束
if (parentViewPager != null) {
parentViewPager.setScrollable(true);
}
releaseTime = System.currentTimeMillis();   //释放时间
viewPager.setCurrentItem(currentPosition, false); //页面滚动到指定页
}
isScrolling = false;
}
});
//如果指示位置在最后一页,则跳转到第一页
if (showPosition < 0 || showPosition >= views.size()) {
showPosition = 0;
}
if (isCycle) {
showPosition = showPosition + 1;
}
viewPager.setCurrentItem(showPosition);
}

/**
* 设置是否循环
*
* @param isCycle
*/
public void setCycle(boolean isCycle) {
this.isCycle = isCycle;
}

public boolean isCycle() {
return isCycle;
}

/**
* 设置是否轮播, 轮播一定是循环的。
*
* @param isWheel
*/
public void setIsWheel(boolean isWheel) {
this.isWheel = isWheel;
isCycle = true;
if (isWheel) {
handler.postDelayed(runnable, time);
}
}

public boolean isWheel() {
return isWheel;
}

/**
* 设置轮播暂停时间,即没多少秒切换到下一张视图.默认5000ms
*
* @param time 毫秒为单位
*/
public void setTime(int time) {
this.time = time;
}

/**
* 刷新数据,当外部视图更新后,通知刷新数据
*/
public void refreshData() {
if (adapter != null) {
adapter.notifyDataSetChanged();
}
}

/**
* 隐藏CycleViewPager
*/
public void hide() {
foot.setVisibility(View.GONE);
}

/**
* 返回内置的viewpager
* @return viewPager
*/
public BaseViewPager getViewPager() {
return viewPager;
}

/**
* 设置viewpager是否滚动
* @param enable
*/
public void setScrollable(boolean enable) {
viewPager.setScrollable(enable);
}

/**
* 返回当前位置,循环时需要注意返回的position包含之前在views最前方与最后方加入的视图,即当前页面试图在views集合的位置
* @return
*/
public int getCurrentPostion() {
return currentPosition;
}

/**
* 释放指示器高度,可能由于之前指示器被限制了高度,此处释放
*/
public void releaseHeight() {
getView().getLayoutParams().height = RelativeLayout.LayoutParams.MATCH_PARENT;
refreshData();
}

/**
* 指示器
*
* @param showPosition
*/
private void setIndicator(int showPosition) {
for (int i = 0; i < indicators.length; i++) {
indicators[i].setBackgroundResource(R.drawable.dot_unselected); //设置小圆点
}
if (indicators.length > showPosition) {
indicators[showPosition].setBackgroundResource(R.drawable.dot_selected); //设置当前页的小圆点
titleIndicator.setText(infos.get(showPosition).getContent()); //设置当前页的标题
}
}

//设置指示器居中,默认指示器在右方
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);
dotIndicator.setLayoutParams(params);
}

/**
* 如果当前页面嵌套在另一个viewPager中,为了进行滚动时阻断父Viewpager滚动,可以阻止父viewpager滚动事件
* 父ViewPager需要实现ParentViewPager中的setScrollable方法
*
* @param parentViewPager
*/
public void disableParentViewPagerTouchEvent(BaseViewPager parentViewPager) {
if (parentViewPager != null) {
parentViewPager.setScrollable(false);
}
}

/**
* 轮播控件监听事件
*/
public static interface CycleViewPagerListener {
/**
* 图片点击事件
*
* @param info      广告实体
* @param position  当前位置
* @param imageView 图片
*/
public void onImageClick(AdInfo info, int position, View imageView);
}

/**
* 页面适配器
*/
public class ViewPagerAdapter extends PagerAdapter {
@Override
public int getCount() {
return imageViews.size();
}

@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);
}

@Override
public Object instantiateItem(ViewGroup container, int position) {
final ImageView imageView = imageViews.get(position); //拿到当前图片
if (listener != null) {
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onImageClick(infos.get(currentPosition - 1), currentPosition, imageView);
}
});
}
container.addView(imageView);
return imageView;
}

@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}

@Override
public void onDestroyView() {
super.onDestroyView();
butterknife.ButterKnife.unbind(this);
}
}


2.4 定义布局文件activity_main.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.hlh.cycleviewpager.MainActivity">

<fragment
android:id="@+id/cycleviewpager_content"
android:name="com.hlh.cycleviewpager.view.CycleViewPager"
android:layout_width="match_parent"
android:layout_height="180dp"
android:tag="fr"/>
</RelativeLayout>


2.5、主界面中设置图片路径

public class MainActivity extends AppCompatActivity {

private CycleViewPager cycleViewPager;
private List<AdInfo> list = new ArrayList<AdInfo>();
private List<ImageView> views = new ArrayList<ImageView>();
private String[] imageUrls = {"http://img.taodiantong.cn/v55183/infoimg/2013-07/130720115322ky.jpg", "http://pic30.nipic.com/20130626/8174275_085522448172_2.jpg",
"http://pic18.nipic.com/20111215/577405_080531548148_2.jpg",
"http://pic15.nipic.com/20110722/2912365_092519919000_2.jpg",
"http://pic.58pic.com/58pic/12/64/27/55U58PICrdX.jpg"};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}

private void initView() {
cycleViewPager = (CycleViewPager) getSupportFragmentManager().findFragmentById(R.id.cycleviewpager_content);

for (int i = 0; i < imageUrls.length; i++) {
AdInfo info = new AdInfo();
info.setUrl(imageUrls[i]);
info.setContent("很喜欢");
list.add(info);
}

//将最后一个imageview加入到view集合中
views.add(getImageView(list.get(list.size() - 1).getUrl()));
for (int i = 0; i < list.size(); i++) {
views.add(getImageView(list.get(i).getUrl()));
}
//第一个
views.add(getImageView(list.get(0).getUrl()));

cycleViewPager.setCycle(true); //设置循环,设置data钱设置, 即是否可以从最后一页滑到第一页
cycleViewPager.setData(views, list, listener, 0);
cycleViewPager.setIsWheel(true); //设置轮播
cycleViewPager.setTime(4000); //设置轮播时间
cycleViewPager.setIndicatorCenter(); //设置圆点居中
}

public ImageView getImageView(String url) {
ImageView imageView = (ImageView) LayoutInflater.from(this).inflate(R.layout.item_cycle_viewpager, null);
Picasso.with(this).load(url).into(imageView);
return imageView;
}

private CycleViewPager.CycleViewPagerListener listener = new CycleViewPager.CycleViewPagerListener() {
@Override
public void onImageClick(AdInfo info, int position, View imageView) {
Toast.makeText(MainActivity.this, position + "----" + info.getContent(), Toast.LENGTH_SHORT).show();
}
};

}


3、代码注释写的很详细,就不一一说了。

源码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: