ViewPage2广告轮播或者导航页展示
基本属性:翻页动画,设置轮播时间等,展示如下:
- 自定义控件的代码:
/**
* @author 2216264142@qq.com
*/
public class ViewPagerPictureFragment extends BaseFragment<ActivityViewPagerBinding> {
/**
* 根据需求来选择ViewPager2适配器(个人觉得多个不一样的Fragment布局选择适配器1,相同布局不一样的内容用适配器2)
* 默认为1
*/
public static int selectAdapter = 1;
/**
* 创建线程
*/
private final Handler mHandler = new Handler(Looper.getMainLooper());
/**
* 轮播图模拟数据集合
*/
private List<AdvCarouselBean> dataBeanList = new ArrayList<>();
/**
* 设置轮播时间
*/
private long delayTime = 5000;
private final Runnable runnable = new Runnable() {
@Override
public void run() {
//获得轮播图当前的位置
int currentPosition = binding.viewpager2.getCurrentItem();
currentPosition++;
binding.viewpager2.setCurrentItem(currentPosition, true);
mHandler.postDelayed(runnable, delayTime);
}
};
/**
* 设置数据
*
* @param dataBeanList 数据集合
*/
public void setDataBeanList(List<AdvCarouselBean> dataBeanList) {
this.dataBeanList = dataBeanList;
}
/**
* 设置轮播时间
*
* @param delayTime 时间(毫秒)
*/
public void setDelayTime(long delayTime) {
this.delayTime = delayTime;
}
@Override
protected ActivityViewPagerBinding createViewBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return ActivityViewPagerBinding.inflate(inflater, container, false);
}
/**
* 初始化数据
*/
@SuppressLint("SetTextI18n")
@Override
protected void initData() {
//没有数据直接跳出加载布局
if (dataBeanList.size() == 0) {
binding.containerIndicator.setVisibility(View.GONE);
return;
}
mHandler.postDelayed(runnable, delayTime);
//添加适配器
if (selectAdapter == 1) {
//适配器1(利用继承FragmentStateAdapter,创建扩展 FragmentStateAdapter 抽象类的类,并实现 createFragment() 方法以提供)
ViewPagerFragmentStateAdapter viewPagerFragmentStateAdapter = new ViewPagerFragmentStateAdapter(requireActivity(), dataBeanList);
binding.viewpager2.setAdapter(viewPagerFragmentStateAdapter);
} else {
//适配器2(利用继承RecyclerView.Adapter)
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(dataBeanList, requireActivity());
binding.viewpager2.setAdapter(viewPagerAdapter);
}
//设置自定义动画
binding.viewpager2.setPageTransformer(new ViewPageTransformer());
//设置数量
binding.tvPictureNum.setText("" + 1 + "/" + dataBeanList.size());
//注册轮播图的滚动事件监听器
binding.viewpager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
// //轮播时,改变指示点
int current = position % dataBeanList.size();
for (int i = 0; i < dataBeanList.size(); i++) {
if (i == current) {
binding.containerIndicator.getChildAt(i).setBackgroundResource(R.drawable.ic_bule_lens_24);
} else {
binding.containerIndicator.getChildAt(i).setBackgroundResource(R.drawable.ic_baseline_lens_24);
}
}
binding.tvPictureNum.setText("" + (current + 1) + "/" + dataBeanList.size());
}
});
initIndicatorDots();
}
/**
* 动态添加ImageView
* 设置导航标点
*/
private void initIndicatorDots() {
//为指示点添加间距
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(18, 18);
layoutParams.setMarginEnd(3);
for (int i = 0; i < dataBeanList.size(); i++) {
ImageView imageView = new ImageView(requireActivity());
if (i == 0) {
imageView.setBackgroundResource(R.drawable.ic_bule_lens_24);
} else {
imageView.setBackgroundResource(R.drawable.ic_baseline_lens_24);
}
imageView.setLayoutParams(layoutParams);
//将指示点添加进容器
binding.containerIndicator.addView(imageView);
}
}
@Override
public void onDestroy() {
super.onDestroy();
mHandler.removeCallbacks(runnable);
}
}
- 自定义fragment的xml:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="300dp">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
app:cardCornerRadius="10dp"
app:cardElevation="0dp">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center" />
</androidx.cardview.widget.CardView>
<TextView
android:id="@+id/tv_picture_num"
android:background="@drawable/ic_bule_lens_24"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:gravity="center"
android:layout_alignParentEnd="true"
android:textColor="#ffffff" />
<LinearLayout
android:id="@+id/container_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginEnd="5dp"
android:layout_marginBottom="5dp"
android:orientation="horizontal" />
</RelativeLayout>
</layout>
*** 记得添加适配器:**
/**
* @author 2216264142@qq.com
*/
public class ViewPagerFragmentStateAdapter extends FragmentStateAdapter {
//数据源
private final List<AdvCarouselBean> dataBeanList;
public ViewPagerFragmentStateAdapter(@NonNull FragmentActivity fragmentActivity, List<AdvCarouselBean> dataBeanList) {
super(fragmentActivity);
this.dataBeanList = dataBeanList;
}
@NonNull
@Override
public Fragment createFragment(int position) {
int i = position % dataBeanList.size();
return new ViewPagerFragment(dataBeanList.get(i));
}
@Override
public int getItemCount() {
//无限循环
return Integer.MAX_VALUE;
}
}
*** 显示界面:**
/**
* @author 2216264142@qq.com
**/
public class ViewPagerFragment extends BaseFragment<ViewPageBinding> {
AdvCarouselBean bean;
public ViewPagerFragment(AdvCarouselBean bean) {
this.bean = bean;
}
@Override
protected ViewPageBinding createViewBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return ViewPageBinding.inflate(inflater,container,false);
}
@Override
protected void initData() {
binding.setBean(bean);
binding.setLifecycleOwner(this);
}
@BindingAdapter("headImgUrl")
public static void headImgUrl(@NonNull ImageView view, String imgUrl) {
Glide.with(view.getContext())
.load(imgUrl)
.centerCrop()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(view);
}
}
- 显示界面的xml:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="bean"
type="com.example.advcarousel.bean.AdvCarouselBean" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
headImgUrl="@{bean.imgUrl}"
android:id="@+id/imgUrl"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:textSize="20sp"
android:text="@{bean.advTitle}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
- 还有两个指示导航的资源文件drawable:
R.drawable.ic_bule_lens_24
<vector android:height="24dp" android:tint="#2196F3"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2z"/>
</vector>
R.drawable.ic_baseline_lens_24
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2z"/>
</vector>
注意:以上代码中有详细的注释,还不懂的可以问我
- 用法:在你需要的页面中添加
FrameLayout,把上面的ViewPagerPictureFragment放到FrameLayout中就可以了
fragment = new ViewPagerPictureFragment();
//设置数据
fragment.setDataBeanList(list);
getSupportFragmentManager().beginTransaction().replace(R.id.fragment, fragment).commit();
*** 下面附上BaseFragment:**
/**
* @author 2216264142@qq.com
*/
public abstract class BaseFragment<T extends ViewDataBinding> extends Fragment {
/**
* 利用dataBinding,在当前app的build.gradle()文件中的
* defaultConfig{
* dataBinding{
* enabled true
* }
* }
*/
protected T binding;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding =createViewBinding(inflater,container,savedInstanceState);
return binding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initData();
}
/**
* 绑定布局
* @param inflater 父类
* @param container 父类
* @param savedInstanceState 父类
* @return T
*/
protected abstract T createViewBinding(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState);
/**
* 初始化数据
*/
protected abstract void initData();
}
- 最后:该控件是利用bindingData来绑定布局