最后一页了,原码呢?
import android.content.Context; import android.graphics.Bitmap; import android.graphics.Color; import android.os.Build; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.Gravity; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import com.example.administrator.asapplication.ImageVariable; import com.example.administrator.asapplication.R; import java.util.List; public class ImageBarnnerFramLayout 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 ImageBarnnerFramLayout(@NonNull Context context) { super(context); initImageBarnnerViewGroup(); initDotLinearLayout(); } public ImageBarnnerFramLayout(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); initImageBarnnerViewGroup(); initDotLinearLayout(); } public ImageBarnnerFramLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initImageBarnnerViewGroup(); initDotLinearLayout(); } public void addBitmap( List<Bitmap> list){ for(int i = 0; i<list.size(); i++){ Bitmap bitmap = list.get(i); addBitmapToImageBarnnerViewGroup(bitmap); addDotToLinearlayout(); } } private void addBitmapToImageBarnnerViewGroup(Bitmap bitmap){ ImageView iv = new ImageView(getContext()); iv.setScaleType(ImageView.ScaleType.CENTER_CROP); iv.setLayoutParams(new ViewGroup.LayoutParams(ImageVariable.WIDTH, ImageVariable.HEIGHT/4)); iv.setImageBitmap(bitmap); imageBarnnerViewGroup.addView(iv); } private void addDotToLinearlayout(){ ImageView iv = new ImageView(getContext()); LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); lp.setMargins(5, 5, 5 ,5); iv.setLayoutParams(lp); iv.setImageResource(R.drawable.dot_normal); linearLayout.addView(iv); } /** * 初始化我们自定义图片轮播图功能的核心类 */ private void initImageBarnnerViewGroup(){ imageBarnnerViewGroup = new ImageBarnnerViewGroup(getContext()); FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT); imageBarnnerViewGroup.setLayoutParams(lp); imageBarnnerViewGroup.setBarnnerViewGroupLisnner(this);//这里就是将Lisnner,传递给Framlayout imageBarnnerViewGroup.setLister(this); addView(imageBarnnerViewGroup); } /** * 初始化我们的底部圆点布局 */ private void initDotLinearLayout(){ linearLayout = new LinearLayout(getContext()); FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, 40); linearLayout.setLayoutParams(lp); linearLayout.setOrientation(LinearLayout.HORIZONTAL);//方向:水平居中 linearLayout.setGravity(Gravity.CENTER); linearLayout.setBackgroundColor(Color.RED);//轮播图圆点的背景颜色 addView(linearLayout); FrameLayout.LayoutParams layoutParams = (LayoutParams) linearLayout.getLayoutParams(); layoutParams.gravity = Gravity.BOTTOM; linearLayout.setLayoutParams(layoutParams); //版本3.0以后的用setAlpha(),3.0之前用的是setAlpha(),但是调用者不同 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 clickImageIndex(int pos){ lisenner.clickImageIndex(pos); } public interface FramLayoutLisenner{ void clickImageIndex(int pos); } }
import android.content.Context; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.Scroller; import android.widget.Toast; import java.util.Timer; import java.util.TimerTask; /** * 该类是实现轮播图的核心类 */ public class ImageBarnnerViewGroup extends ViewGroup{ private int children;//子视图的总个数 private int childheight;//子视图的高度 private int childwidth;//子视图的宽度 private int x;//此时x的值,代表第一次按下位置的横坐标,每次轮播图移动都是横坐标移动 private int index = 0;//代表每个图片的索引 private Scroller scroller; /** * 要想实现图片单击事件的获取 * 方法: 利用一个单击变量开关进行判断,在用户离开屏幕的一瞬间, * 我们去判断变量开关来判断用户的操纵是点击还是移动 */ private boolean isClick;//true的时候,代表点击事件;flase代表的不是点击事件 private ImageBarnnerLister lister; public ImageBarnnerLister getLister() { return lister; } public void setLister(ImageBarnnerLister lister) { this.lister = lister; } public interface ImageBarnnerLister{ void clickImageIndex(int pos);//pos代表当前图片的索引值 } private ImageBarnnerViewGroupLisnner barnnerViewGroupLisnner; public ImageBarnnerViewGroupLisnner getBarnnerViewGroupLisnner() { return barnnerViewGroupLisnner; } public void setBarnnerViewGroupLisnner(ImageBarnnerViewGroupLisnner barnnerViewGroupLisnner) { this.barnnerViewGroupLisnner = barnnerViewGroupLisnner; } /** * 要想实现轮播图底部圆点 以及 圆点切换的功能思路: * 1.我们需要自定义一个继承自FrameLayout的布局,利用FrameLayout * 布局的特性(在同一位置放置不同view,最终显示最后一个view),我们就可以实现底部圆点的布局。 * 2.我们需要准备素材,就是底部的素材---圆点。利用Drawable的功能,去实现一个圆点图片的展示。 * 3.我们还需要继承FramLayout 来自定义一个类,在该类的实现过程中,我们去加载我们刚才自定义的 * ImageBarnnerViewGroup核心类 和 步骤2的底部圆点的布局LinearLayout布局来实现。 */ //自动轮播 private boolean isAuto = true;//默认轮播图是开启状态 private Timer timer = new Timer(); private TimerTask task; private Handler autoHandler = new 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; } } }; private void startAuto(){ isAuto = true; } private void stopAuto(){ isAuto = false; } 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) { super(context, attrs, defStyleAttr); initObj(); } private void initObj(){ scroller = new Scroller(getContext()); task = new TimerTask() { @Override public void run() { if(isAuto){//开启轮播图 autoHandler.sendEmptyMessage(0); } } }; timer.schedule(task,100,3000); } @Override public void computeScroll() { super.computeScroll(); if(scroller.computeScrollOffset()){ scrollTo(scroller.getCurrX(),0); invalidate(); } } /** * 我们在自定义ViewGroup方法中,我们必须实现的有 测量=》布局=》绘制 * 测量 就是onMeasure()方法 * 布局 就是onLayout()方法 * 绘制 就是()方法 */ /** * 对于绘制来说,因为我们是自定义ViewGroup容器,针对于容器的绘制 * 其实就是容器内部子控件的绘制过程,调用系统自带的绘制即可。 * 即,对于ViewGroup的绘制过程,我们不需要重写该方法,调用系统自带即可 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); /** * 由于我们实现的ViewGroup容器,那么 * 我们应该知道该容器中的所有子视图。 * 我们想要测量ViewGroup的宽度和高度,那么我们必须先去测量子视图的 * 宽度和高度之和,才能知道ViewGroup的宽度和高度为多少 */ //第1步。求出的子视图的个数 children = getChildCount();//获取子视图的个数 if( children == 0){ //如果子视图个数为0.就不需要求子视图的高度和宽度 setMeasuredDimension(0,0);//测量宽度和高度为0 }else{ //第2步。求出子视图的测量宽度和测量高度 measureChildren(widthMeasureSpec,heightMeasureSpec); //此时,我们第一个子视图的宽度,就是我们第一个ViewGroup的宽度 乘以 子视图的个数 //子视图的高度,就是我们vGroup的高度. View view = getChildAt(0);//因为第一个视图存在的,所以编号为0 //第3步。根据子视图的宽度和高度,来求出ViewGroup的宽度和高度 childheight = view.getMeasuredHeight(); childwidth = view.getMeasuredWidth(); int width = view.getMeasuredWidth() * children;//所有子视图宽度总和 //重新赋值,测量完毕 setMeasuredDimension(width,childheight); } } /** * 继承ViewGroup必须实现布局onLayout方法 * * @param changed 代表ViewGroup布局位置是否发生变化,是则为true,不是则为false */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { if(changed){ int leftMargin = 0; for(int i=0; i<children; i++){ //拿出每个视图 View view = getChildAt(i); //对每个视图的子布局进行布局 view.layout(leftMargin, 0, leftMargin + childwidth, childheight); leftMargin = leftMargin + childwidth; } } } /** * 事件传递过程中的调用方法,我们需要 调用 容器内部的拦截方法 * 针对于该方法,我们可以理解为 该方法的返回值为true,我们自定义的ViewGroup容器就会处理此次拦截事件 * 返回值为flase,我们自定义ViewGroup容器则不会接受此次事件的处理过程,将会向下传递该事件 * 针对于我们自定义的ViewGroup,我们当然希望我们的ViewGroup容器处理接受事件,那么我们的返回值就为true * 如果返回值为true,那么真正处理该事件的方法为onTouch方法 */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return true; } @Override public boolean onTouchEvent(MotionEvent event) { //另一种方法,手势探测类 GestureDetector 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.clickImageIndex(index); }else{ int dx = index * childwidth - scrollx; scroller.startScroll(scrollx,0,dx,0); postInvalidate(); barnnerViewGroupLisnner.selectImage(index); } startAuto(); // scrollTo(index * childwidth, 0); break; default: break; } return true;//返回true,是告诉ViewGroup容器的父容器,我们已经处理好该事件 } public interface ImageBarnnerViewGroupLisnner{ void selectImage(int index); } }
。。。
我也想要源码,自己打的,有点问题,没找到错在哪了