在自定义控件里设置属性的大纲
* 0.在Values创建一个xml资源文件
* 1.在xml资源文件,定义表头和属性
* 2.在构造方法里进行属性的关联
* 3.同步gradle文件,否则在xml布局文件中依然无法引用
* 4.在xml布局文件里进行使用
<resources>
<!--指定这些属性都是谁的,注意这里添加完属性要在自定义View类构造方法中应用-->
<!--注意:写完这个属性之后,布局xml文件要想应用的话,必须同步gradle文件-->
<declare-styleable name="Indicator">
<!--定义控件显示圆的数量 参数format是类型-->
<attr name="setNumber" format="integer"></attr>
<!--定义控件显示圆的半径 参数format是类型-->
<attr name="setRadius" format="integer"></attr>
<!--定义空心圆的颜色 参数format是类型,reference表示什么都能装-->
<attr name="setForeColor" format="color"></attr>
<!--定义控件显示圆的后颜色 参数format是类型,reference表示什么都能装-->
<attr name="setbgColor" format="color"></attr>
</declare-styleable>
</resources>
在MainActivity布局文件中使用时(要先同步gradle才能使用):
<com.zhiyuan3g.indicator.Indicator
android:id="@+id/indicator"
app:setNumber="4"
app:setRadius="10"
app:setForeColor="#FF0800FF"
app:setbgColor="#FFFF0000"
android:layout_width="160dp"
android:layout_height="60dp"
android:layout_alignBottom="@+id/viewPager"
android:layout_centerHorizontal="true"/>
public class Indicator extends View {
//前面的圆
private Paint forePaint;
//后面的圆
private Paint bgPaint;
//规定圆的数量,默认是4个,如果有xml指定的数量,使用指定的
private int number;
//圆的半径,规定默认值为10,如果有xml指定的数量,使用指定的
private int radius;
//定义圆(空心圆)的背景颜色,默认红色,如果有xml指定的数量,使用指定的
private int bgColor;
//定义圆(实心圆)的颜色,默认蓝色,如果有xml指定的数量,使用指定的
private int foreColor;
//移动的偏移量
private float offset;
//在代码中添加我们自定义的View时,所调用的构造方法
public Indicator(Context context) {
super(context);
initPaint();
}
//在XML文件中添加我们自定义的控件时,所调用的方法,多了一个参数
public Indicator(Context context, AttributeSet attrs) {
super(context, attrs);
initPaint();
//引用atts文件下,给自定义控件设置属性,得到typdeArray对象,
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.Indicator);
//使用TypedArray对象,把在自定义控件属性和XML文件里设置的属性进行关联,才算完成
//注意:你在xml文件中设置的类型属性,获取时,也要是对应的类型
number = typedArray.getInteger(R.styleable.Indicator_setNumber, number);
radius = typedArray.getInteger(R.styleable.Indicator_setRadius, radius);
foreColor = typedArray.getInteger(R.styleable.Indicator_setForeColor, foreColor);
bgColor = typedArray.getInteger(R.styleable.Indicator_setbgColor, bgColor);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
initPaint();
}
//参数就是画板,可以直接使用
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
initPaint();
for (int i = 0; i < number; i++) {
//画多个空心圆,为了使圆不要挤在一起,所以对x轴坐标进行动态的修改
canvas.drawCircle(60 + radius * 3 * i, 60, 10, bgPaint);
}
//画前面的圆
canvas.drawCircle(60 + offset, 60, 10, forePaint);
}
private void initPaint() {
//shift+F6可以更改所有对象名
//ctrl+alt+F可以抽取成员变量
//创建画笔的对象
forePaint = new Paint();
//设置抗锯齿
forePaint.setAntiAlias(true);
//设置颜色
forePaint.setColor(foreColor);
//设置样式
forePaint.setStyle(Paint.Style.FILL);
//设置画笔的宽度
forePaint.setStrokeWidth(2);
bgPaint = new Paint();
bgPaint.setAntiAlias(true);
bgPaint.setStyle(Paint.Style.STROKE);
bgPaint.setColor(bgColor);
bgPaint.setStrokeWidth(2);
}
public void setoffset(int position, float positionOffset) {
position %= number;
//因为从一个圆到另一个圆经过3个半径,两个圆各两个半径,中间的间距1个半径
if (!(position == number-1)) {
offset = position * 3 * radius + positionOffset * 3 * radius;
}
//关键一点,重新绘制自定义View的方法,十分有用
invalidate();
}
}
public class MainActivity extends AppCompatActivity {
//创建一个集合用来装ViewPager加载的图片控件
private List<View> views = new ArrayList<>();
private Indicator indicator;
private int[] picture = {R.drawable.a1,R.drawable.a2,R.drawable.a3,R.drawable.a4};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化ViewPager的item数据
initData();
//初始化控件
ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);
//设置ViewPager适配器
viewPager.setAdapter(new MyPagerAdapter());
//设置ViewPager的监听器
viewPager.setOnPageChangeListener(new MyPagerListener());
indicator = (Indicator) findViewById(R.id.indicator);
}
private void initData() {
for (int i = 0; i < 4; i++) {
View inflate = getLayoutInflater().inflate(R.layout.pager_item, null);
ImageView imageView = (ImageView) inflate.findViewById(R.id.imgShow);
imageView.setImageResource(picture[i]);
views.add(inflate);
}
}
//创建Viewpager的适配器,重写四个方法
private class MyPagerAdapter extends PagerAdapter {
//设置ViewPager的item数量
@Override
public int getCount() {
return 10000;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
position %=views.size();
container.removeView(views.get(position));
}
//类似于ListView的Adapter里的GetView,参数1:ViewPager的化身, 参数2:item的位置
@Override
public Object instantiateItem(ViewGroup container, int position) {
position %=views.size();
//从集合里拿对应位置的图片
View view = views.get(position);
//把ImageView对象添加到ViewPager里
container.addView(view);
return view;
}
}
//创建ViewPager的监听事件
private class MyPagerListener implements ViewPager.OnPageChangeListener{
//ViewPager滑动时回调 参数1:item的位置 参数2:偏移的百分比 参数3:偏移量
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
indicator.setoffset(position,positionOffset);
}
//ViewPager选中时回调
@Override
public void onPageSelected(int position) {
}
//ViewPager滑动状态改变时回调
@Override
public void onPageScrollStateChanged(int state) {
}
}