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、代码注释写的很详细,就不一一说了。
源码下载
相关文章推荐
- Android用两张图片实现简单动画效果
- Android 百分比布局库(percent-support-lib) 解析与扩展
- Android摇一摇(传感器之他用)
- 收集android上开源的酷炫的交互动画和视觉效果:Interactive-animation
- Android流量统计TrafficStats类的使用
- 查看Android ADT Plugin版本的方法
- 查看Android ADT Plugin版本的方法
- android的消息与线程
- Android获取屏幕高度、状态栏高度、标题栏高度
- Android 长按电源键和短按电源键的详细处理流程
- Android存储(一)——SharedPreferences
- Android中不被硬件加速支持的操作
- android数据持久化存储(2)
- [转]Android PopupWindow的使用和分析
- Android开发之assets目录下资源使用总结
- 早来的圣诞礼物!--android 逆向菜鸟速參手冊完蛋版
- Android中attrs.xml文件的使用详解
- android中view的生命周期
- android的Shader
- android之自定义UncaughtExceptionHandler类来处理未捕获异常