文章目录
在Android项目程序设计中,首页轮播图是个很常见的功能,在之前的文章中,教了大家如何使用第三方库来快速实现轮播图(教程地址在文章末尾给出),今天教大家手把手来撸一个轮播图
1. build.gradle添加依赖:
图片显示,采用Glide来加载网络图片
implementation 'com.github.bumptech.glide:glide:4.12.0'
2. AndroidManifest.xml中添加网络访问权限
<uses-permission android:name="android.permission.INTERNET" />
3. 编写 布局文件
activity_banner.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="200dp">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="@+id/indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="10dp"
android:orientation="horizontal" />
</RelativeLayout>
4. 编写Banner适配器
BannerAdapter.java
public class BannerAdapter extends RecyclerView.Adapter<BannerAdapter.BannerViewHolder> {
private List<String> imageUrls;
private Context context;
public BannerAdapter(Context context, List<String> imageUrls) {
this.context = context;
this.imageUrls = imageUrls;
}
@NonNull
@Override
public BannerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
ImageView imageView = new ImageView(context);
imageView.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
return new BannerViewHolder(imageView);
}
@Override
public void onBindViewHolder(@NonNull BannerViewHolder holder, int position) {
// 使用实际位置加载图片
int realPosition = position % imageUrls.size();
// 这里使用Glide加载图片,需要添加Glide依赖
Glide.with(context)
.load(imageUrls.get(realPosition))
.into(holder.imageView);
holder.imageView.setOnClickListener(v -> {
// 处理图片点击事件
if (onItemClickListener != null) {
onItemClickListener.onItemClick(realPosition);
}
});
}
@Override
public int getItemCount() {
// 返回一个很大的数,实现无限循环
return Integer.MAX_VALUE;
}
static class BannerViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
public BannerViewHolder(@NonNull View itemView) {
super(itemView);
imageView = (ImageView) itemView;
}
}
// 点击事件接口
public interface OnItemClickListener {
void onItemClick(int position);
}
private OnItemClickListener onItemClickListener;
public void setOnItemClickListener(OnItemClickListener listener) {
this.onItemClickListener = listener;
}
}
这里注意:在方法onBindViewHolder
中,Glide加载图片,需要添加Glide依赖
5. 自定义Banner视图
BannerView.java
public class BannerView extends RelativeLayout {
private ViewPager2 viewPager;
private LinearLayout indicator;
private List<ImageView> indicatorDots;
private Handler handler;
private static final int SCROLL_TIME = 3000; // 自动滚动间隔
private boolean isAutoScroll = true;
public BannerView(Context context) {
super(context);
init(context);
}
public BannerView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context) {
// 加载布局
LayoutInflater.from(context).inflate(R.layout.activity_banner, this, true);
viewPager = findViewById(R.id.viewPager);
indicator = findViewById(R.id.indicator);
indicatorDots = new ArrayList<>();
handler = new Handler(Looper.getMainLooper());
}
public void setImages(List<String> imageUrls) {
// 设置适配器
BannerAdapter adapter = new BannerAdapter(getContext(), imageUrls);
viewPager.setAdapter(adapter);
// 设置初始位置到中间
viewPager.setCurrentItem(Integer.MAX_VALUE / 2, false);
// 创建指示器
createIndicators(imageUrls.size());
// 设置页面切换监听
viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
updateIndicator(position % imageUrls.size());
}
});
// 开始自动滚动
startAutoScroll();
}
private void createIndicators(int count) {
indicator.removeAllViews();
indicatorDots.clear();
for (int i = 0; i < count; i++) {
ImageView dot = new ImageView(getContext());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
dpToPx(8), dpToPx(8));
params.setMargins(dpToPx(4), 0, dpToPx(4), 0);
dot.setLayoutParams(params);
dot.setImageResource(R.drawable.dot_normal);
indicator.addView(dot);
indicatorDots.add(dot);
}
// 设置第一个点为选中状态
if (!indicatorDots.isEmpty()) {
indicatorDots.get(0).setImageResource(R.drawable.dot_selected);
}
}
private void updateIndicator(int position) {
for (int i = 0; i < indicatorDots.size(); i++) {
indicatorDots.get(i).setImageResource(
i == position ? R.drawable.dot_selected : R.drawable.dot_normal);
}
}
private void startAutoScroll() {
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (isAutoScroll && viewPager != null) {
viewPager.setCurrentItem(viewPager.getCurrentItem() + 1);
handler.postDelayed(this, SCROLL_TIME);
}
}
}, SCROLL_TIME);
}
public void stopAutoScroll() {
isAutoScroll = false;
handler.removeCallbacksAndMessages(null);
}
private int dpToPx(int dp) {
return (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, dp,
getResources().getDisplayMetrics());
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
stopAutoScroll();
}
}
6. 定义圆点指示器的drawable资源
- dot_normal.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#80FFFFFF" />
<size
android:width="8dp"
android:height="8dp" />
</shape>
- dot_selected.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#FFFFFF" />
<size
android:width="8dp"
android:height="8dp" />
</shape>
这里注意:dot_normal.xml和dot_selected.xml创建在res
下的drawable
中,而不是res
下的layout
中
7. 在需要使用轮播图中的Activity中使用
- MainActivity.java
public class MainActivity extends AppCompatActivity {
private BannerView bannerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bannerView = findViewById(R.id.banner_view);
// 准备图片URL列表
List<String> imageUrls = new ArrayList<>();
imageUrls.add("https://img0.baidu.com/it/u=2673431480,3550145287&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=211");
imageUrls.add("https://img1.baidu.com/it/u=1588549273,1647024151&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=312");
imageUrls.add("https://img2.baidu.com/it/u=3920432635,2105461872&fm=253&fmt=auto&app=138&f=JPEG?w=1600&h=500");
imageUrls.add("https://img1.baidu.com/it/u=921161528,741350508&fm=253&fmt=auto&app=138&f=PNG?w=658&h=380");
imageUrls.add("https://img2.baidu.com/it/u=611817443,624986336&fm=253&fmt=auto&app=138&f=JPEG?w=1280&h=407");
// 设置图片
bannerView.setImages(imageUrls);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (bannerView != null) {
bannerView.stopAutoScroll();
}
}
}
这里注意:一定要在Activity
生命周期的onDestroy()
中调用 bannerView.stopAutoScroll()
方法
- activity_main.xml
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="200dp">
<com.app.skill.sharing.views.BannerView
android:id="@+id/banner_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</androidx.appcompat.widget.LinearLayoutCompat>
com.app.skill.sharing.views.BannerView
:这里自定义控件的使用为:包名+类名。具体根据自己自定义控件存放的位置而定,在编辑器中输入Ban…,跟使用系统自带控件一样,编辑器会智能提示
扫描二维码关注公众号,回复:
17610679 查看本文章

8. 运行效果图
9. 视频教程
- Androidstudio轮播图Banner实现 :https://www.bilibili.com/video/BV18B4y1R7gy/?vd_source=984bb03f768809c7d33f20179343d8c8