Android Banner

Posted 真菜啊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Banner相关的知识,希望对你有一定的参考价值。

前面写了使用ViewPager和ViewPager2实现Banner的方式,今天来用Compose实现一下。
Compose相对于前两种,优势极其明显,就两个字简单!简单!还是他妈的简单
话不多说,上代码。

引入依赖

implementation("androidx.compose.foundation:foundation:1.4.3")  
implementation("androidx.compose.foundation:foundation-layout:1.4.3")

版本匹配

当前最新的compose版本匹配kotlin的1.8.10,所以需要修改下项目根目录下的build.gradle文件和模块下的build.gradle文件
根目录下的build.gradle

plugins   
    id \'com.android.application\' version \'7.4.2\' apply false  
    id \'com.android.library\' version \'7.4.2\' apply false  
    id \'org.jetbrains.kotlin.android\' version \'1.8.10\' apply false  

模块下的build.gradle文件

android   
    // ...
    compileOptions   
        sourceCompatibility JavaVersion.VERSION_1_8  
        targetCompatibility JavaVersion.VERSION_1_8  
      
    kotlinOptions   
        jvmTarget = \'1.8\'  
      
    buildFeatures   
        compose true  
      
    composeOptions   
        kotlinCompilerExtensionVersion \'1.4.3\'  
      
    packagingOptions   
        resources   
            excludes += \'/META-INF/AL2.0,LGPL2.1\'  
          
    

代码实现

class MainActivity : ComponentActivity()   
    override fun onCreate(savedInstanceState: Bundle?)   
        super.onCreate(savedInstanceState)  
        setContent   
            BannerTheme   
                // A surface container using the \'background\' color from the theme  
                Surface(  
                    modifier = Modifier.fillMaxSize(),  
                    color = MaterialTheme.colorScheme.background  
                )   
                    Banner(bannerItems = DataStore.getBanner())  
                  
                          
  
  
@OptIn(ExperimentalFoundationApi::class)  
@Composable  
fun Banner(bannerItems: List<BannerItem>)   
    val pagerState = rememberPagerState()  
  
    HorizontalPager(  
        pageCount = bannerItems.size,  
        state = pagerState,  
        modifier = Modifier  
            .height(180.dp)  
            .fillMaxWidth()  
            .padding(16.dp)  
    )  index ->  
        BannerItem(bannerItems[index])  
      
  
  
@Composable  
fun BannerItem(banner: BannerItem)   
    Card(  
        modifier = Modifier  
            .fillMaxWidth()  
            .height(180.dp)  
            .clip(RoundedCornerShape(16.dp))  
            .padding(8.dp)  
    )   
        Image(  
            painter = painterResource(id = banner.id),  
            contentDescription = banner.desc,  
            contentScale = ContentScale.FillWidth  
        )  
      

完成,so easy!!!

Android三方框架banner实现轮播图

关于

  本篇使用的是基于viewpager2的一个开源banner,性能、生命周期都有保障,就是有一点小的功能需要我们自己去修改。本篇也是作为简易音乐博客系列之一。

效果图

在这里插入图片描述

第一步,添加引用

  在工程build下添加仓库maven:

allprojects {
    repositories {
        google()
        jcenter()
        maven { url "https://s01.oss.sonatype.org/content/groups/public" }
    }
}

  在项目build下添加banner和viewpager2的引用:

    implementation 'io.github.youth5201314:banner:2.2.2'
    implementation "androidx.viewpager2:viewpager2:1.0.0"

第二步,新增实体类及测试数据

public class DataBean implements Serializable {
    public String imageUrl;
    public String title;
    public String url;


    public DataBean(String imageUrl, String title) {
        this.imageUrl = imageUrl;
        this.title = title;

    }

    public void setImageUrl(String imageUrl) {
        this.imageUrl = imageUrl;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public void setTitle(String title) {
        this.title = title;
    }


    public String getImageUrl() {
        return imageUrl;
    }

    public String getTitle() {
        return title;
    }


    public static List<DataBean> getTestData() {
        List<DataBean> list = new ArrayList<>();
        list.add(new DataBean("https://dfzximg02.dftoutiao.com/news/20210401/20210401222253_acbd3f414dc150c4cf25d91dcac0cf36_1_mwpm_03201609.jpeg", "标题0" ));
        list.add(new DataBean("https://dfzximg02.dftoutiao.com/news/20210401/20210401222253_acbd3f414dc150c4cf25d91dcac0cf36_2_mwpm_03201609.jpeg", "标题1" ));
        list.add(new DataBean("https://dfzximg02.dftoutiao.com/news/20210401/20210401221040_d2957dc25d3878b4fdf0816289cde4fd_1_mwpm_03201609.png", "标题2"));
        list.add(new DataBean("http://cn.bing.com/th?id=OHR.FooledYa_EN-CN7497696381_1920x1080.jpg", "标题3"));
        list.add(new DataBean("https://dfzximg02.dftoutiao.com/news/20210401/20210401222006_3a2f89e1dbaa16f8a7f7754e00d8bf77_1_mwpm_03201609.jpeg", "标题4"));
        return list;
    }

}

第三步,添加banner实例控件,修改主界面代码

  修改主界面布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <com.youth.banner.Banner
        android:id="@+id/banner"
        android:layout_width="match_parent"
        android:layout_height="160dp"
        android:layout_marginStart="15dp"
        android:layout_marginTop="15dp"
        android:layout_marginEnd="15dp" />
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="跳转页面"
        />



</LinearLayout>

  修改MainActivity.java,简单使用banner轮播功能:

public class MainActivity extends AppCompatActivity {


    Banner banner;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();

    }

    private void initView() {
        findViewById(R.id.button).setOnClickListener(v -> {
            Intent intent = new Intent(this,Main2Activity.class);
            startActivity(intent);
        });

        banner = findViewById(R.id.banner);

    }

    private void initData() {
         //banner自带图片轮播的适配器
         banner.setAdapter(new BannerImageAdapter<DataBean>(DataBean.getTestData()) {

             @Override
             public void onBindView(BannerImageHolder holder, DataBean data, int position, int size) {
                 Glide.with(holder.imageView)
                         .load(data.imageUrl)
                         .thumbnail(Glide.with(holder.itemView).load(R.drawable.loading))//加载成功前显示一个loading的加载
                         //.apply(RequestOptions.bitmapTransform(new RoundedCorners(30)))  //设置图片圆角
                         .into(holder.imageView);
                         //关于glide的引用添加:
                         //implementation 'com.github.bumptech.glide:glide:4.11.0'
                        //annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
                         
             }
         }).addBannerLifecycleObserver(this)//添加生命周期观察者
                 .setIntercept(false) //是否要拦截事件
                 .setBannerRound(10f) //圆角
                 .setIndicator(new CircleIndicator(this)) //圆形指示器 还支持条形指示器等
                 .setOnBannerListener(new OnBannerListener() {
                     @Override
                     public void OnBannerClick(Object data, int position) {
                        Toast.makeText(MainActivity.this,"位置"+position+"",Toast.LENGTH_SHORT).show();
                     }
                 }) ;
    }


}

自定义图片+标题轮播图

  到这,基本的轮播功能已经实现了,但是很多轮播图可能还需要有标题,即图片+标题,就要自己编写适配器继承BannerAdapter,首先编写一个banner_title_image.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="match_parent">

    <ImageView
        android:id="@+id/bannerImage"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop" />

    <TextView
        android:id="@+id/bannerTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@null"
        android:ellipsize="marquee"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:gravity="center_vertical"
        android:paddingRight="5dp"
        android:paddingBottom="1dp"
        android:singleLine="true"
        android:textColor="#ffffff"
        android:layout_alignParentEnd="true"
        android:layout_alignParentBottom="true"/>
</RelativeLayout>

  第二步,编写TitleHolder继承ViewHolder:

public class TitleHolder extends RecyclerView.ViewHolder {
    public ImageView imageView;
    public TextView textView;

    public TitleHolder(@NonNull View itemView) {
        super(itemView);
        imageView = itemView.findViewById(R.id.bannerImage);
        textView = itemView.findViewById(R.id.bannerTitle);
    }
}

  第三步,编写ImageTitleAdapter继承banner三方提供的BannerAdapter:

/**
 * banner轮播图适配器 图片+标题
 */

public class ImageTitleAdapter extends BannerAdapter<DataBean,TitleHolder> {


    public ImageTitleAdapter(List<DataBean> datas) {
        super(datas);
    }


    @Override
    public TitleHolder onCreateHolder(ViewGroup parent, int viewType) {
       return new TitleHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.banner_title_image,parent,false));

    }

    @Override
    public void onBindView(TitleHolder holder, DataBean data, int position, int size) {
        Glide.with(holder.imageView)
                .load(data.imageUrl)
                .thumbnail(Glide.with(holder.itemView).load(R.drawable.loading))
                .into(holder.imageView);
        holder.textView.setText(data.title);
    }


}

  第四步,修改MainActivity.java:

 private void initData() {
         banner.setAdapter(new ImageTitleAdapter(DataBean.getTestData())).addBannerLifecycleObserver(this)//添加生命周期观察者
                 .setIntercept(false) //是否要拦截事件
                 .setBannerRound(10f) //圆角
                 .setIndicator(new RectangleIndicator(this)) //线条指示器
                 .setIndicatorHeight(5)
                 .setIndicatorWidth(6,6) //选中下宽度是否一致
                 .setIndicatorGravity(IndicatorConfig.Direction.CENTER)
                 .setOnBannerListener(new OnBannerListener() {
                     @Override
                     public void OnBannerClick(Object data, int position) {
                        Toast.makeText(MainActivity.this,"位置"+position+"",Toast.LENGTH_SHORT).show();
                     }
                 }) ;
    }

效果图

在这里插入图片描述

你以为到这里就结束了??

  正常情况下使用这个三方轮播图已经结束了,毕竟效果啥的都实现了,但是实际使用中还是发现一些问题,比如在fragment中使用的时候进行fragment切换,再回来就会从头加载轮播,这怎么行,暂时解决办法是在fragmetnt下(自己选的只能被迫自己解决问题):

//定义一个int保存当前轮播位置
 private static  int potsition = 0;
 
 @Override
    public void onPause() {
        super.onPause();
        potsition = banner.getViewPager2().getCurrentItem(); //用提供的banner.getCurrentItem()获取不到
    }
      @Override
    public void onResume() {
        super.onResume();
        if (potsition != 0&&banner !=null){
        //从选中位置开始轮播
            banner.setStartPosition(potsition);
        }
    }

补充

  后面发型是因为我在母体Activity中通过开启事务后FragmentTransaction.replace()方法替换fragment(本质上还是调用了remove造成了移除fragment_main碎片,重新新增fragment_main碎片导致fragment_main反复调用onpause->onStop->…onResume()导致的轮播图重新实例化)

 FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction transaction = fm.beginTransaction();
        //切换布局
        transaction.replace(R.id.frame_main,fragment);
        transaction.commit();

  本篇文章到此结束,有问题欢迎批评指正,觉得不错的也请点个赞奥

以上是关于Android Banner的主要内容,如果未能解决你的问题,请参考以下文章

Android三方框架banner实现轮播图

如何为Android应用设置Smart Banner?

banner无限轮播

Android----banner使用详解

Android----------- Banner2 广告图片轮播ViewPager2实现

Android----------- Banner2 广告图片轮播ViewPager2实现