Android HBanner 图片视频混合轮播

文章介绍了如何在Android应用中实现图片和视频混合轮播的功能,包括权限申请、使用HBanner开源项目以及处理常见错误。在权限方面,讲解了动态申请读写存储权限的步骤。在功能实现上,提到了HBanner的使用方法和解决轮播不工作的问题。资源文件需放在特定目录下,实际应用中通常需要从后台下载并解压。
摘要由CSDN通过智能技术生成

很多展示类的app,会使用到banner图,其中也不乏想要图片+视频混合轮播的需求,例如客显屏系统,就使用到了该种功能,下面会简单列举实现流程,结尾附带demo源码

(一)权限申请

1.manifest文件

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

2.MainActivity动态注册

2.1 引用permissionX

implementation 'com.guolindev.permissionx:permissionx:1.7.1'

2.2 动态申请

private static final String PERMISSION_WRITE_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE;
private static final String PERMISSION_READ_STORAGE = Manifest.permission.READ_EXTERNAL_STORAGE;
private void initPermission() {
    PermissionX.init(this)
            .permissions(
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE)
            .onExplainRequestReason((scope, deniedList, beforeRequest) -> scope.showRequestReasonDialog(deniedList, "即将申请的权限是程序必须依赖的权限", "确定"))
            .onForwardToSettings((scope, deniedList) -> scope.showForwardToSettingsDialog(deniedList, "您需要去应用程序设置当中手动开启权限", "确定"))
            .request((allGranted, grantedList, deniedList) -> {
                if (allGranted) {
                    //权限全部获取,执行后续操作
                }
            });
}

2.3判断是否已有权限

private boolean hasPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        return checkSelfPermission(PERMISSION_READ_STORAGE) == PackageManager.PERMISSION_GRANTED &&
                checkSelfPermission(PERMISSION_WRITE_STORAGE) == PackageManager.PERMISSION_GRANTED;
    } else {
        return true;
    }
}

(二)使用HBanner

1.将hbanner相关代码复制到工程中

说明:Hbanner是一个开源项目,可以引用代码库,但是对于这种自定义View的库,并不一定所有的设计都符合自己的要求,可能会需要做出一定的本地修改,所以建议如果方便的话就拷贝代码而非引用代码库

2.xml文件

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

    <com.hjly.hbannerdemo.hbanner.view.BannerViewPager
        android:id="@+id/bannerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

3.MainActivity

//定义一个资源文件存储路径
public static String outputDir = "/sdcard/Download/HbannerDemo/resource/";
private HBanner hBanner;
private BannerViewPager bannerView;
bannerView = findViewById(R.id.bannerView);
bannerView.setScrollable(false);
private void init() {
    try {
        if (hBanner != null) {
            hBanner.release();
            hBanner = null;
        }
        try {
            hBanner = HBanner.create(bannerView);
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
        List<MediaFile> mediaFiles = AppUtil.getAllFiles(outputDir);
        if (ListUtil.isEmpty(mediaFiles)) {
            Toast.makeText(this, "本地无媒体数据", Toast.LENGTH_SHORT).show();
            return;
        } else {
            //每隔3秒切换一次图片
            int duration = 3;
            List<SubView> data = new ArrayList<>();
            for (MediaFile mediaFile : mediaFiles) {
                if (mediaFile.getFileName().endsWith("png") || mediaFile.getFileName().endsWith("jpg")) {
                    data.add(new ImageSubView.Builder(getBaseContext())
                            .file(new File(mediaFile.getFilePath()))
                            .gravity(ImageView.ScaleType.FIT_XY)
                            .duration(duration * 1000)
                            .build());
                } else if (mediaFile.getFileName().endsWith("mp4")) {
                    data.add(new VideoSubView.Builder(getBaseContext())
                            .file(new File(mediaFile.getFilePath()))
                            .gravity(VideoViewType.FULL)
                            .playOffset(600)//让缓存图片显示600ms后再播放,可解决videoview启动时候闪烁问题
                            .isSub(false)
                            .build());
                }
            }
            if (data.size() > 0) {
                hBanner.sources(data);
                bannerView.setPageTransformer(true, new DefaultTransformer());
                hBanner.play(true);
            } else {
                Toast.makeText(this, "解析媒体数据为空", Toast.LENGTH_SHORT).show();
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
/**
 * 中断资源播放
 */
private void stopBanner() {
    if (hBanner != null) {
        hBanner.release();
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    stopBanner();
}

关键点:

如果按照上面的写法,在OnCreate中完成初始化之后,直接调用init方法,那么就会轮播功能没有实现,看日志是报了如下的错误

java.lang.IllegalArgumentException: your viewPager has not attached,it will can not get the handler!

这个问题也是列表布局里非常常见的错误,网上百度的说法是,列表数据没有预加载,然后让弄懒加载配置之类的,不过收效甚微

这里可以尝试如下做法

1.Activity实现OnGlobalLayoutListener接口

public class MainActivity extends AppCompatActivity implements ViewTreeObserver.OnGlobalLayoutListener {

2.onCreate

binding.getRoot().getViewTreeObserver().addOnGlobalLayoutListener(this);

3.重写方法

@Override
    public void onGlobalLayout() {
        binding.getRoot().getViewTreeObserver().removeOnGlobalLayoutListener(this);
        init();
    }

说明:实现上述接口一定要在OnCreate中增加addOnGlobalLayoutListener,并且在onGlobalLayout调用对应的removeOnGlobalLayoutListener,否则init方法将会无限重复调用

写在最后:

本demo中实现的功能需要手动将图片、视频资源放置在"/sdcard/Download/HbannerDemo/resource/"目录下,实际中,资源文件需要从后台下载并且通过文件IO操作生成文件夹以及文件并且解压资源到路径下,这里为了方便就节省了该步骤,直接手动创建目录,放置资源文件

至此,功能实现

demo源码

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

邵旺运

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值