最后一页了,原码呢?
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);
}
}。。。
我也想要源码,自己打的,有点问题,没找到错在哪了