1效果图
2项目结构
3源码:
3.1自定义控件ImageViewGroup
package com.zhh.mybanner;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import com.orhanobut.logger.Logger;
/**
* Created by 16838 on 2018/5/23.
*/
public class ImageViewGroup extends ViewGroup{
// 子视图的个数
private int children;
// 子视图的宽度
private int childwidth;
// 子视图的高度
private int childheight;
// 此时的x值代表的是第一次按下位置的横坐标,每一次移动过程中 移动之前位置的横坐标
private int myX;
// 每张图片的索引
private int index=0;
/**
* 控件在xml文件中声明的时候必须要重写这个
* @param context
* @param attrs
*/
public ImageViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* 测量宽度和高度
* 测量父布局的高度和宽度
* 测量----布局----绘制
* 绘制:针对绘制来说,因为我们是自定义的 ImageViewGroup容器,
* 针对容器的绘制,其实就是容器内子控件的绘制过程,那么我们只需要
* 调用系统自带的绘制,也就是说我们不需要重写该方法,调用系统自带的即可。
*
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 1求出子视图的个数
children=getChildCount();
// 2求出子视图的宽度和高度
if(children==0) {
// 如果子视图的个数是0,则设置ImageViewGroup的高度和宽度是0
setMeasuredDimension(0,0);
}else{
// 测量子视图的宽度和高度
measureChildren(widthMeasureSpec,heightMeasureSpec);
// 拿到第一个子视图,绝对存在
View view = getChildAt(0);
// 3根据子视图的宽度和高度,求出ImageViewGroup的宽度和高度
childheight=view.getMeasuredHeight();
childwidth = view.getMeasuredWidth();
int width = childwidth*children;
// 设置ImageViewGroup的宽高
setMeasuredDimension(width,childheight);
}
}
/**
* 参数 changed 表示ImageViewGroup位置发生改变时时true,不发生改变为false
* 设置子布局的位置
*/
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
if(changed) {
int leftMargin=0;
for(int i= 0; i< children; i++) {
// 当位置改变时设置每个子布局的位置
View view=getChildAt(i);
// 设置子布局的位置
// left 和 top 是控件左边缘和上边缘相对于父类控件左边缘和上边缘的距离。
// right 和 bottom是空间右边缘和下边缘相对于父类控件左边缘和上边缘的距离。
// 所以下面这样计算
view.layout(leftMargin,0,leftMargin+childwidth,childheight);
leftMargin+=childwidth;
}
}
}
/**
* 事件处理
* 事件的传递过程中的调用方法:我们需要 调用 容器的拦截方法 onInterceptTouchEvent
* 针对该方法我们可以理解为 如果说 该方法的返回值为true的时候,那么自定义的ImageViewGroup就会处理此次拦截事件
* 如果说返回的值为false的时候,不会接受此次事件的处理过程,将会继续向下传递事件,我们希望ImageViewGroup处理接收事件,那么我们的
* 返回值就是true,如果是true,真正处理该事件的方法是onTouchEvent
*
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
// 按下一瞬间
case MotionEvent.ACTION_DOWN:
Logger.t("111").d("ACTION_DOWN");
myX= (int) event.getX();
break;
// 移动过程
case MotionEvent.ACTION_MOVE:
// 距离父容器左边的距离,和x轴坐标相等
int moveX = (int) event.getX();
Logger.t("111").d("ACTION_MOVE+move"+moveX);
int distance = moveX - myX;
// scrollTo移动的是坐标,将整个父视图的左上角定为(0,0)
// scrollBy移动的是距离
scrollBy(-distance, 0);
myX=moveX;
break;
// 抬起一瞬间
case MotionEvent.ACTION_UP:
Logger.t("111").d("ACTION_UP");
// 移动的位移,原点减视图左上角坐标 0-左上角坐标
int scrollX = getScrollX();
// 计算索引
index = (scrollX+childwidth/2)/childwidth;
if(index<0) {
//说明此时已经滑到左边第一张图片
index=0;
}else if(index>children-1) {
//说明此时已经滑动到最后一张图片
index=children-1;
}
// scrollTo移动的是坐标,将整个父视图的左上角定为(0,0)
// scrollBy移动的是距离
scrollTo(index * childwidth,0);
break;
default:
break;
}
return true;
}
}
3.2MainActivity的activity_main.xml中引用
<LinearLayout 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=".MainActivity">
<com.zhh.mybanner.ImageViewGroup
android:id="@+id/imageViewGroup"
android:layout_width="match_parent"
android:layout_height="200dp"
>
</com.zhh.mybanner.ImageViewGroup>
</LinearLayout>
3.3MainActivity中放入图片数据
package com.zhh.mybanner;
import android.app.Activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.Menu;
import android.view.MenuItem;
import android.view.ViewGroup;
import android.widget.ImageView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity {
private ImageViewGroup imageViewGroup;
int []images={R.drawable.a1,R.drawable.a2,R.drawable.a3};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageViewGroup = findViewById(R.id.imageViewGroup);
// 拿到手机屏幕的宽度
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels;
// 把图片放到imageViewGroup中
for(int i = 0; i <images.length ; i++) {
ImageView iv =new ImageView(this);
iv.setScaleType(ImageView.ScaleType.FIT_XY);
// 设置的宽度是屏幕宽度,高度包裹
iv.setLayoutParams(new ViewGroup.LayoutParams(width, ViewGroup.LayoutParams.WRAP_CONTENT));
iv.setImageResource(images[i]);
imageViewGroup.addView(iv);
}
}
}
参考视频:
https://www.imooc.com/learn/793
源码下载MyCheckBox—-mybanner
https://download.csdn.net/download/zhaihaohao1/10434975