上一节我们已经实现了自定义控件和数据的绑定,但是我们发现底部的白点指示器现实的数量和我们摄制的图片数量不一样,如果每次都自己修改的话又会太麻烦,这一节我们就来实现底部指示器根据我们添加的图片的数量来自动动态的去创建并且实现根据页面的滑动动态的切换指示器的焦点
首先我们声明一个viewpager适配器类型的变量然后我们在在设置数据的方法setData内获取它的值,下一步我们创建一个动态添加指示器的方法,把我们获得的PagerAdapter类型的变量放进去,通过他的getCount方法的长度来动态的创建指示器,这个方法里我们用到一个工具类,这个工具类的作用就是像素转换dp工具类
public class SizeUtil {
//像素转dp工具类
public static int dip2px(Context context, float dpvalue){
float scale = context.getResources().getDisplayMetrics().density;
return (int)(dpvalue*scale+0.5f);
}
}
然后下面就是代码
package com.example.viewpager.views;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Adapter;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.example.viewpager.R;
public class LooperPager extends LinearLayout {
private ViewPager viewPager;
private TextView textView;
private LinearLayout linearLayout;
private BindTitleLisener bindTitleLisener = null;//标题,先设为空
private PagerAdapter Adapter = null;//适配器类型的变量
public LooperPager(Context context) {
this(context,null);
}
public LooperPager(Context context, @Nullable AttributeSet attrs) {
this(context,attrs,0);
}
/**
* java必须有一个声明super的构造器,而且必须在开头,所以其他构造器声明的this,、
* 所以无论使用其他哪个构造器都必须要调用该构造器
* @param context
* @param attrs
* @param defStyleAttr
*/
public LooperPager(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//自定义布局绑定当前类,this:当前类,ture:确定绑定
LayoutInflater.from(context).inflate(R.layout.looper_pager,this,true);
inti();
}
/**
*
*/
private void inti() {
intiView();
initEven();
}
/**
* 对页面进行滑动监听的方法
*/
private void initEven() {
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
//切换的回调方法
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
//切换停止的回调方法
public void onPageSelected(int position) {
//当页面切换停止后获得标题
//如果标题不是空的,就设定标题为当前停止的页面标题里的数据
if (bindTitleLisener != null){
textView.setText(bindTitleLisener.getTitle(position));
}
}
@Override
//状态改变的回调方法
public void onPageScrollStateChanged(int state) {
}
});
}
/**
* 获得标题的接口,里面有一个获得标题的抽象方法
*/
public interface BindTitleLisener{
String getTitle(int position);
}
/**
* 设置数据的方法
*/
public void setData(PagerAdapter adapter,BindTitleLisener lisener){
bindTitleLisener = lisener;
viewPager.setAdapter(adapter);
//设定一个适配器类型的变量给下面的方法使用
this.Adapter = adapter;
//可以得到数据的个数,然后根据数据的个数动态的创建圆点,indicater(指示器)
setIndicaterPoint();
}
/**
* 根据适配器的getCount方法的长度来动态的创建指示器
*
*/
private void setIndicaterPoint() {
if (Adapter != null){
int count = Adapter.getCount();
linearLayout.removeAllViews();
for (int i = 0; i < count ; i++) {
View view = new View(getContext());
//设置颜色(Color.parseColor("#ff0000")设置颜色字符串为白色)
view.setBackgroundColor(Color.parseColor("#ffffff"));
//设置指示器大小
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams
(SizeUtil.dip2px(getContext(),5),SizeUtil.dip2px(getContext(),5));
view.setLayoutParams(layoutParams);
//设置指示器之间的间距
layoutParams.setMargins(SizeUtil.dip2px(getContext(),10),0,SizeUtil.dip2px(getContext(),10),0);
//添加到容器里
linearLayout.addView(view);
}
}
}
/**
* 加载view的方法
*/
private void intiView() {
viewPager = findViewById(R.id.viewPager);
textView = findViewById(R.id.looper_title_tv);
linearLayout = findViewById(R.id.looper_point_container_lv);
}
}
到这一步就已经实现根据添加的图片数动态的添加指示器了
下一步,我们根据图片的滑动动态的给指示器添加一个焦点
这个功能也很简单,首先考虑,根据滑动的页面添加焦点,肯定还是在对页面进行滑动监听的方法内实现,我们在页面切换停止的时候给当前页面添加焦点,首先我们在上面的根据页面长度添加指示器的方法内添加代码,我们在循环添加指示器的时候,判断一下如果当前ViewPager页面的位置就是当前添加的指示器的位置,就让当前指示器位置的圆点创建为红色,其他位置为白色。然后我们在页面切换停止的监听方法内调用一下动态添加指示器的方法。这样一来,每一次切换页面都会重新添加一遍圆点指示器,然后方法内就会把当前页面代表的圆点变成红色,动态改变指示器颜色的功能也就实现了
package com.example.viewpager.views;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Adapter;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import com.example.viewpager.R;
public class LooperPager extends LinearLayout {
private ViewPager viewPager;
private TextView textView;
private LinearLayout linearLayout;
private BindTitleLisener bindTitleLisener = null;//标题,先设为空
private PagerAdapter Adapter = null;//适配器类型的变量
public LooperPager(Context context) {
this(context,null);
}
public LooperPager(Context context, @Nullable AttributeSet attrs) {
this(context,attrs,0);
}
/**
* java必须有一个声明super的构造器,而且必须在开头,所以其他构造器声明的this,、
* 所以无论使用其他哪个构造器都必须要调用该构造器
* @param context
* @param attrs
* @param defStyleAttr
*/
public LooperPager(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//自定义布局绑定当前类,this:当前类,ture:确定绑定
LayoutInflater.from(context).inflate(R.layout.looper_pager,this,true);
inti();
}
/**
*
*/
private void inti() {
intiView();
initEven();
}
/**
* 对页面进行滑动监听的方法
*/
private void initEven() {
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
//切换的回调方法
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
//切换停止的回调方法
public void onPageSelected(int position) {
//当页面切换停止后获得标题
//如果标题不是空的,就设定标题为当前停止的页面标题里的数据
if (bindTitleLisener != null){
textView.setText(bindTitleLisener.getTitle(position));
}
//每次页面切换给指示器动态的添加焦点
setIndicaterPoint();
}
@Override
//状态改变的回调方法
public void onPageScrollStateChanged(int state) {
}
});
}
/**
* 获得标题的接口,里面有一个获得标题的抽象方法
*/
public interface BindTitleLisener{
String getTitle(int position);
}
/**
* 设置数据的方法
*/
public void setData(PagerAdapter adapter,BindTitleLisener lisener){
bindTitleLisener = lisener;
viewPager.setAdapter(adapter);
//设定一个适配器类型的变量给下面的方法使用
this.Adapter = adapter;
//可以得到数据的个数,然后根据数据的个数动态的创建圆点,indicater(指示器)
setIndicaterPoint();
}
/**
* 根据适配器的getCount方法的长度来动态的创建指示器
* 同时每次页面切换的时候给当前页面的指示器换色
*/
private void setIndicaterPoint() {
if (Adapter != null){
int count = Adapter.getCount();
linearLayout.removeAllViews();
for (int i = 0; i < count ; i++) {
View view = new View(getContext());
//每次循环添加的时候判断下当前的圆点是否是代表当前页面,如果是就变成红色
if (viewPager.getCurrentItem() == i){
//设置颜色(Color.parseColor("#ff0000")设置颜色字符串为红色)
view.setBackgroundColor(Color.parseColor("#ff0000"));
}else{
//设置颜色(Color.parseColor("#ffffff")设置颜色字符串为白色)
view.setBackgroundColor(Color.parseColor("#ffffff"));
}
//设置指示器大小
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams
(SizeUtil.dip2px(getContext(),5),SizeUtil.dip2px(getContext(),5));
view.setLayoutParams(layoutParams);
//设置指示器之间的间距
layoutParams.setMargins(SizeUtil.dip2px(getContext(),10),0,SizeUtil.dip2px(getContext(),10),0);
//添加到容器里
linearLayout.addView(view);
}
}
}
/**
* 加载view的方法
*/
private void intiView() {
viewPager = findViewById(R.id.viewPager);
textView = findViewById(R.id.looper_title_tv);
linearLayout = findViewById(R.id.looper_point_container_lv);
}
}