Android实现轮播图片效果
本文实例为大家分享了Android实现轮播图片效果的具体代码,供大家参考,具体内容如下
一、原理
首先,将这些要轮播的图片和一些文本分别放置在不同的数据集合中,程序启动的时候默认显示一组图片和文本数据,然后启动一个定时器,每隔一段时间便替换掉显示的图片和文本数据,同时加入一些动画效果,已达到轮播的特效。同时,我们也要实现手指滑动图片达到轮播的效果。
二、实现
1、程序启动界面MainActivity
public class MainActivity extends AppCompatActivity implements ImageBannerFramLayout.FramLayoutLisenner{ private ImageBannerFramLayout mGroup; private int[] ids = new int[] { R.drawable.i1,//图片资源1 R.drawable.i2,//图片资源2 }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //计算当前手机宽度 DisplayMetrics displayMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); int width = displayMetrics.widthPixels; mGroup = (ImageBannerFramLayout) findViewById(R.id.image_group); mGroup.setLisenner(this); List<Bitmap> list = new ArrayList<>(); for (int i = 0; i < ids.length; i++) { Bitmap bitmap = BitmapFactory.decodeResource(getResources(),ids[i]); list.add(bitmap); } mGroup.addBitmaps(list); } @Override public void chickImageIndex(int pos) { Toast.makeText(this,"索引值 = " + pos,Toast.LENGTH_SHORT).show(); } }
2、新建包view下面新建两个类
1)新建ImageBarnnerViewGroup类继承自ViewGroup
public class ImageBarnnerViewGroup extends ViewGroup { private int children;//我们View Group的子视图总个数 private int childwidth;//子视图的宽度 private int childheight;//子视图的高度 private int x;//此时的x的值代表的是第一次按下的位置的横坐标,每一次移动过的过程中 移动之前的位置横坐标 private int index = 0;//代表名为每张图片的索引 private Scroller scroller; /** * 利用一个单击变量开关进行判断,离开屏幕的一瞬间判断用户的操作是点击 */ private boolean isClick;//true的时候点击事件,false的时候不是点击事件 private ImageBarnnerLister lister; private ImageBarnnerViewGroupLisnner barnnerViewGroupLisnner; public ImageBarnnerLister getLister() { return lister; } public void setLister(ImageBarnnerLister lister) { this.lister = lister; } public ImageBarnnerViewGroupLisnner getBarnnerViewGroupLisnner() { return barnnerViewGroupLisnner; } public void setBarnnerViewGroupLisnner(ImageBarnnerViewGroupLisnner barnnerViewGroupLisnner) { this.barnnerViewGroupLisnner = barnnerViewGroupLisnner; } public interface ImageBarnnerLister { void chickImageIndex(int pos);//pos代表的是我们当前的图片的具体索引值 } /** * 实现轮播图底部圆点切换效果 * 自定义一个继承自FragmenLayou布局,利用FragmeLayout布局特性 */ //自动轮播 private boolean isAuto = true;//默认情况下开启轮播 private Timer timer = new Timer(); private TimerTask timerTask; @SuppressLint("HandlerLeak") private android.os.Handler autohandler = new android.os.Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 0://我们需要图片的自动轮播 if (++index >= children) {//如果是最后一张图片,从第一张开始 index = 0; } scrollTo(childwidth * index,0); barnnerViewGroupLisnner.selectImage(index); break; default: } } }; private void startAuto() { isAuto = true; } private void stopAuto() { isAuto = false; } /** * 采用Timer,TimerTask,Handler三者结合的方式来实现自动轮播 */ public ImageBarnnerViewGroup(Context context) { super(context); initObj(); } public ImageBarnnerViewGroup(Context context, AttributeSet attrs) { super(context, attrs); initObj(); } public ImageBarnnerViewGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); initObj(); } private void initObj() { scroller = new Scroller(getContext()); timerTask = new TimerTask() { @Override public void run() { if (isAuto) {//开启轮播图 autohandler.sendEmptyMessage(0); } } }; timer.schedule(timerTask,100,3000); } @Override public void computeScroll() { super.computeScroll(); if (scroller.computeScrollOffset()) { scrollTo(scroller.getCurrX(),0); invalidate();//重绘 } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //1.求出子视图的个数 children = getChildCount();//我们可以知道自试图的个数 if (0 == children) { setMeasuredDimension(0,0); } else { measureChildren(widthMeasureSpec, heightMeasureSpec); //此时我们以第一个子视图=为基准,也就是说我们的View Group View view = getChildAt(0); childwidth = view.getMeasuredWidth(); childheight = view.getMeasuredHeight(); int width = view.getMeasuredWidth() * children; setMeasuredDimension(width,childheight); } //2.测量子视图的宽度和高度 //3.根据子视图的狂赌和高度,求出该ViewGroup的宽度和高度 } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return super.onInterceptTouchEvent(ev); } /** * 用两种方式来实现轮播图的手动轮播 * 1,利用scrollTo,scrollBy 完成轮播图的手动轮播 * 1,利用Scroller 对象完成轮播图的手动效果 * @param event * @return */ @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN://表示用户按下的一瞬间 stopAuto();//停止图片轮播 if (!scroller.isFinished()) { scroller.abortAnimation(); } isClick = true; x=(int)event.getX(); break; case MotionEvent.ACTION_MOVE://表示用户按下之后在屏幕上移动的过程 int moveX = (int) event.getX(); int distance = moveX - x; scrollBy(-distance,0); x = moveX; isClick = false; break; case MotionEvent.ACTION_UP://标识的是用户抬起的一瞬间 int scrollX = getScrollX(); index = (scrollX + childwidth / 2) / childwidth; if (index < 0) { //已经滑动到了最左边 index = 0; } else if (index > children - 1) {//说明已经滑动到了最右边 index = children - 1; } if (isClick) { //点击事件 lister.chickImageIndex(index); } else { int dx = index * childwidth - scrollX; scroller.startScroll(scrollX,0,dx,0); postInvalidate(); barnnerViewGroupLisnner.selectImage(index); } startAuto();//开启图片轮播 break; default: } return true; //返回true的目的是告诉该View Group容器的父View 我们已经处理好了该事件 } @Override protected void onLayout(boolean b, int i, int i1, int i2, int i3) { if (b) { int lefrMargin = 0; for (int j = 0; j < children; j++) { View view = getChildAt(j); view.layout(lefrMargin,0,lefrMargin + childwidth,childheight); lefrMargin += childwidth; } } } public interface ImageBarnnerViewGroupLisnner{ void selectImage(int index); } }
2)新建ImageBannerFramLayout类继承自FrameLayout实现两个接口
public class ImageBannerFramLayout extends FrameLayout implements ImageBarnnerViewGroup.ImageBarnnerViewGroupLisnner,ImageBarnnerViewGroup.ImageBarnnerLister{ private ImageBarnnerViewGroup imageBarnnerViewGroup; private LinearLayout linearLayout; private FramLayoutLisenner lisenner; public FramLayoutLisenner getLisenner() { return lisenner; } public void setLisenner(FramLayoutLisenner lisenner) { this.lisenner = lisenner; } public ImageBannerFramLayout(@NonNull Context context) { super(context); initImageBarnnerViewGroup(); initDotLinearlayout(); } public ImageBannerFramLayout(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); initImageBarnnerViewGroup(); initDotLinearlayout(); } public ImageBannerFramLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initImageBarnnerViewGroup(); initDotLinearlayout(); } public void addBitmaps(List<Bitmap> list) { for (int i = 0; i < list.size(); i++) { Bitmap bitmap = list.get(i); addBitmapToImageBarnnerViewGroup(bitmap); addDotToLinearlayout(); } } private void addDotToLinearlayout() { ImageView iv = new ImageView(getContext()); LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams (LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.MATCH_PARENT); layoutParams.setMargins(5,5,5,5); iv.setLayoutParams(layoutParams); iv.setImageResource(R.drawable.dot_normal); linearLayout.addView(iv); } private void addBitmapToImageBarnnerViewGroup(Bitmap bitmap) { ImageView imageView = new ImageView(getContext()); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); imageView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT)); imageView.setImageBitmap(bitmap); imageBarnnerViewGroup.addView(imageView); } //初始化自定义图片轮播功能核心类 private void initImageBarnnerViewGroup() { imageBarnnerViewGroup = new ImageBarnnerViewGroup(getContext()); FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams (FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT); imageBarnnerViewGroup.setLayoutParams(layoutParams); imageBarnnerViewGroup.setBarnnerViewGroupLisnner(this);//将linsnner传递给Framlayout imageBarnnerViewGroup.setLister(this); addView(imageBarnnerViewGroup); } //初始化底部圆点布局 private void initDotLinearlayout() { linearLayout = new LinearLayout(getContext()); FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams (FrameLayout.LayoutParams.MATCH_PARENT, 40); linearLayout.setLayoutParams(layoutParams); linearLayout.setOrientation(LinearLayout.HORIZONTAL); linearLayout.setGravity(Gravity.CENTER); linearLayout.setBackgroundColor(Color.RED); addView(linearLayout); FrameLayout.LayoutParams layoutParams1 = (LayoutParams) linearLayout.getLayoutParams(); layoutParams.gravity = Gravity.BOTTOM; linearLayout.setLayoutParams(layoutParams1); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { linearLayout.setAlpha(0.5f); } else { linearLayout.getBackground().setAlpha(100); } } @Override public void selectImage(int index) { int count = linearLayout.getChildCount(); for (int i = 0;i < count; i++) { ImageView iv = (ImageView) linearLayout.getChildAt(i); if (i == index) { iv.setImageResource(R.drawable.dot_select); } else { iv.setImageResource(R.drawable.dot_normal); } } } @Override public void chickImageIndex(int pos) { lisenner.chickImageIndex(pos); } public interface FramLayoutLisenner{ void chickImageIndex(int pos); } }
3、程序布局页面activity_main
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.example.tony.imagegroup.view.ImageBannerFramLayout android:id="@+id/image_group" android:layout_width="match_parent" android:layout_height="200dp"> </com.example.tony.imagegroup.view.ImageBannerFramLayout> </RelativeLayout>
4、新建两个drawable资源文件dot_normal.xml和dot_select.xml,实现轮播图底部小圆点
不同的是前者颜色为白色后者为黑色
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solid android:color="@android:color/white"/> <size android:height="10dp" android:width="10dp"/> </shape>
三、运行结果
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持猪先飞。
相关文章
- 下面我们来看一篇关于Android子控件超出父控件的范围显示出来方法,希望这篇文章能够帮助到各位朋友,有碰到此问题的朋友可以进来看看哦。 <RelativeLayout xmlns:an...2016-10-02
Android开发中findViewById()函数用法与简化
findViewById方法在android开发中是获取页面控件的值了,有没有发现我们一个页面控件多了会反复研究写findViewById呢,下面我们一起来看它的简化方法。 Android中Fin...2016-09-20- 如果我们的项目需要做来电及短信的功能,那么我们就得在Android模拟器开发这些功能,本来就来告诉我们如何在Android模拟器上模拟来电及来短信的功能。 在Android模拟...2016-09-20
- 夜神android模拟器如何设置代理呢?对于这个问题其实操作起来是非常的简单,下面小编来为各位详细介绍夜神android模拟器设置代理的方法,希望例子能够帮助到各位。 app...2016-09-20
- 为了增强android应用的用户体验,我们可以在一些Button按钮上自定义动态的设置一些样式,比如交互时改变字体、颜色、背景图等。 今天来看一个通过重写Button来动态实...2016-09-20
- 如果我们要在Android应用APP中加载html5页面,我们可以使用WebView,本文我们分享两个WebView加载html5页面实例应用。 实例一:WebView加载html5实现炫酷引导页面大多...2016-09-20
- 深入理解Android中View和ViewGroup从组成架构上看,似乎ViewGroup在View之上,View需要继承ViewGroup,但实际上不是这样的。View是基类,ViewGroup是它的子类。本教程我们深...2016-09-20
- 下面我们来看一篇关于Android自定义WebView网络视频播放控件开发例子,这个文章写得非常的不错下面给各位共享一下吧。 因为业务需要,以下代码均以Youtube网站在线视...2016-10-02
- java开发的Android应用,性能一直是一个大问题,,或许是Java语言本身比较消耗内存。本文我们来谈谈Android 性能优化之MemoryFile文件读写。 Android匿名共享内存对外A...2016-09-20
- TextView默认是横着显示了,今天我们一起来看看Android设置TextView竖着显示如何来实现吧,今天我们就一起来看看操作细节,具体的如下所示。 在开发Android程序的时候,...2016-10-02
android.os.BinderProxy cannot be cast to com解决办法
本文章来给大家介绍关于android.os.BinderProxy cannot be cast to com解决办法,希望此文章对各位有帮助呀。 Android在绑定服务的时候出现java.lang.ClassCastExc...2016-09-20- 这篇文章主要介绍了Android 实现钉钉自动打卡功能的步骤,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下...2021-03-15
- 下面我们来看一篇关于Android 开发之布局细节对比:RTL模式 ,希望这篇文章对各位同学会带来帮助,具体的细节如下介绍。 前言 讲真,好久没写博客了,2016都过了一半了,赶紧...2016-10-02
- 首先如果要在程序中使用sdcard进行存储,我们必须要在AndroidManifset.xml文件进行下面的权限设置: 在AndroidManifest.xml中加入访问SDCard的权限如下: <!--...2016-09-20
- 下面来给各位简单的介绍一下关于Android开发之PhoneGap打包及错误解决办法,希望碰到此类问题的同学可进入参考一下哦。 在我安装、配置好PhoneGap项目的所有依赖...2016-09-20
用Intel HAXM给Android模拟器Emulator加速
Android 模拟器 Emulator 速度真心不给力,, 现在我们来介绍使用 Intel HAXM 技术为 Android 模拟器加速,使模拟器运行度与真机比肩。 周末试玩了一下在Eclipse中使...2016-09-20- 在安卓开发时我碰到一个问题就是需要实现全屏,但又需要我们来判断出用户是使用了全屏或非全屏了,下面我分别找了两段代码,大家可参考。 先来看一个android屏幕全屏实...2016-09-20
Android开发中布局中的onClick简单完成多控件时的监听的利与弊
本文章来为各位介绍一篇关于Android开发中布局中的onClick简单完成多控件时的监听的利与弊的例子,希望这个例子能够帮助到各位朋友. 首先在一个控件加上这么一句:and...2016-09-20Ubuntu 系统下安装Android开发环境 Android Studio 1.0 步骤
Android Studio 是一个Android开发环境,基于IntelliJ IDEA. 类似 Eclipse ADT,Android Studio 提供了集成的 Android 开发工具用于开发和调试,可以在Linux,Mac OS X,Window...2016-09-20- 这篇文章主要为大家详细介绍了Android实现简单用户注册案例,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-05-26