Android首页无限轮播功能的示例代码
时间:2021-07-08 14:48:37|栏目:Android代码|点击: 次
最近工作不是很忙,也跟大神学习下总结一些小的技术点:
对于一个App几乎都有Banner广告功能,也就是我们常见的轮播图,当然目前市场第三方框架已经非常成熟了,尤其是youth5201314/banner这里有github地址也可以学习下:https://github.com/youth5201314/banner.git
那么下面给大家介绍我的一些总结:
首先分析下轮播图的设计
- 多张轮播图定时效果
- 指示点以及每张图片的文字说明
- 实现无限轮播,可滑动,图片点击事件
开始布局:
<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.yangziling.carousel.MainActivity"> <!--轮播图--> <FrameLayout android:layout_width="match_parent" android:layout_height="200dp"> <android.support.v4.view.ViewPager android:id="@+id/vp" android:layout_width="match_parent" android:layout_height="match_parent"/> <!--指示点和图片标题--> <LinearLayout android:layout_width="match_parent" android:layout_height="35dip" android:layout_gravity="bottom" android:background="#33000000" android:gravity="center" android:orientation="vertical"> <!--图片配文--> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="图片标题" android:textColor="@android:color/white" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="3dip" android:orientation="horizontal" > <!--指示点--> <View android:id="@+id/dot_0" style="@style/view_attr" android:background="@drawable/dot_focused"/> <View android:id="@+id/dot_1" style="@style/view_attr" android:background="@drawable/dot_normal"/> <View android:id="@+id/dot_2" style="@style/view_attr" android:background="@drawable/dot_normal"/> <View android:id="@+id/dot_3" style="@style/view_attr" android:background="@drawable/dot_normal"/> <View android:id="@+id/dot_4" style="@style/view_attr" android:background="@drawable/dot_normal"/> </LinearLayout> </LinearLayout> </FrameLayout> </RelativeLayout>
布局中抽取的view属性:
<style name="view_attr"> <item name="android:layout_width">5dp</item> <item name="android:layout_height">5dp</item> <item name="android:layout_marginLeft">5dp</item> <item name="android:layout_marginRight">5dp</item> </style>
这里我展示的一些图片是在本地的,通过网络框架加载图片原理也是一样的。
这里直接给大家贴出来核心代码:
public class MainActivity extends AppCompatActivity { private ViewPager mMyViewPaper; private List<ImageView> images; private List<View> dots; private int currentItem; private TextView title; private MyAdapter adapter; //当前显示图片的位置 private int localPosition = 0; //图片的id private int[] imageIds = new int[]{R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.e}; //图片的标题 private String[] titles = new String[]{"蓝天白云", "青山绿水", "枯藤老树", "人间仙境", "岛屿大树"}; private TimerTask mTimerTask; //创建一个定时器 private final Timer timer = new Timer(); private ImageView mImageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mMyViewPaper = (ViewPager) findViewById(R.id.vp); //显示的图片 images = new ArrayList<>(); for (int i = 0; i < imageIds.length; i++) { mImageView = new ImageView(this); mImageView.setBackgroundResource(imageIds[i]); images.add(mImageView); } //指示点 dots = new ArrayList<>(); dots.add(findViewById(R.id.dot_0)); dots.add(findViewById(R.id.dot_1)); dots.add(findViewById(R.id.dot_2)); dots.add(findViewById(R.id.dot_3)); dots.add(findViewById(R.id.dot_4)); title = (TextView) findViewById(R.id.title); title.setText(titles[0]); adapter = new MyAdapter(MainActivity.this, images); mMyViewPaper.setAdapter(adapter); mMyViewPaper.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageSelected(int position) { position = position % images.size(); title.setText(titles[position]); dots.get(position).setBackgroundResource(R.drawable.dot_focused); dots.get(localPosition).setBackgroundResource(R.drawable.dot_normal); localPosition = position; currentItem = position; } /** * 页面滑动时回调 */ @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } /** * 当ViewPager状态改变时,回调 */ @Override public void onPageScrollStateChanged(int state) { } }); } /** * 轮播任务 */ @Override protected void onStart() { super.onStart(); mTimerTask = new TimerTask() { @Override public void run() { currentItem = (currentItem + 1) % imageIds.length; mHandler.sendEmptyMessage(0); } }; timer.schedule(mTimerTask, 2000, 2000); } /** * 接收子线程传递的数据 */ private Handler mHandler = new Handler() { public void handleMessage(android.os.Message msg) { //轮播到最后一张图片时,直接跳转至第一页,并且取消滑动效果 if (currentItem % images.size() == 0) { mMyViewPaper.setCurrentItem(currentItem, false); } //非最后一张展示图片的滑动效果 mMyViewPaper.setCurrentItem(currentItem, true); } }; @Override protected void onStop() { super.onStop(); timer.cancel(); } }
自定义了一个Adapter适配器:
public class MyAdapter extends PagerAdapter { private List<ImageView> images; private Context mContext; public MyAdapter(Context context,List<ImageView> images) { this.mContext =context; this.images = images; } //返回Viewpager中的view个数 @Override public int getCount() { return Integer.MAX_VALUE; } //判断instantiateItem中的函数返回的key与一个页面示图是不是代表同一个 //通常直接相等就OK啦 @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } //移除一个固定位置的页面 @Override public void destroyItem(ViewGroup view, int position, Object object) { view.removeView((View) object); } //将固定位置的View添加到Viewgroup中,并创建显示出来 @Override public Object instantiateItem(ViewGroup view, final int position) { ImageView imageView = images.get(position % images.size()); ViewGroup parent = (ViewGroup) imageView.getParent(); //这里是动态添加示图,一个子类只能有一个父类 //判断下如果parent存在一定要记得移除 if (parent != null) { parent.removeView(imageView); } view.addView(imageView); //给图片添加点击事件 imageView.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { Toast.makeText(mContext,"点击了第"+(position % images.size()+1)+"图片",Toast.LENGTH_SHORT).show(); } }); return images.get(position % images.size()); } @Override public int getItemPosition(Object object) { return POSITION_NONE; } }
在这里面也遇到一些问题,做了一些“妥协”,比如说无限轮播的时候发现播放到最后一张时会返回到第一张再次轮播,但是会有那种卡顿的感觉。所以我做了个“妥协的处理”,就是在播放到最后一张时,取消自带的动画效果,直接跳转到第一张,然后进行轮播。
private Handler mHandler = new Handler() { public void handleMessage(android.os.Message msg) { //轮播到最后一张图片时,直接跳转至第一页,并且取消滑动效果 if (currentItem % images.size() == 0) { mMyViewPaper.setCurrentItem(currentItem, false); } //非最后一张展示图片的滑动效果 mMyViewPaper.setCurrentItem(currentItem, true); } };
项目的github地址:https://github.com/yangziling/Carousel.git