美文网首页
ViewPage实现图片和视频轮播

ViewPage实现图片和视频轮播

作者: FlyFighting | 来源:发表于2020-05-08 16:19 被阅读0次

    最近要写一个广告页展示,开始只要图片,可现在要视频也能轮播,所以就去网上找。 想着能Copy坚决不手写的原则,经过一天苦战,终于决定自己去实现了。

    话不多说,直接开始上实现方式。
    写功能之前,先引入第三方的框架

    implementation 'com.shuyu:GSYVideoPlayer:7.1.3'
    implementation 'com.github.bumptech.glide:glide:4.11.0'
    

    GSYVideoPlayer 是一个基于IJKPlayer(兼容系统MediaPlayer与EXOPlayer2),实现了多功能的视频播放器,想了解更多的可以去百度下,我用这个的目的就是它里面自带缓存。Glide不多说了。

    首先想好思路,要实现Video和Image ,肯定要分不同的界面布局,所以用ViewPage和Fragment来实现。Vp2没有用,大家可以自己去替换着试试。

    ImageFragment ,代码里面有注释

    public class ImageFragment extends Fragment {
    
    private String url;  // 传过来的路径
    private PagerListener finishListener;  //回调监听
    private ImageView imageView;
    private static final int IMAGETIME = 4000; // 默认图片4s切换
    
    public ImageFragment(String imageRes, PagerListener listener) {
        this.url = imageRes;
        this.finishListener = listener;
    }
    public void imgStart(){
        if (imageView!=null) {
            finishListener.currentItem(IMAGETIME);
        }
    }
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.layout_image, null);
        view.setOnClickListener(v->finishListener.onClick());
        imageView = view.findViewById(R.id.image);
        Glide.with(getActivity()).load(url).centerCrop()
                .diskCacheStrategy(DiskCacheStrategy.ALL).into(imageView);
        imgStart();
        return view;
    }
    
    @Override
    public void onDestroy() {
        super.onDestroy();
    
    }
    

    }

    VideoFragment ,代码里面有注释

    public class VideoFragment extends Fragment {
    private  StandardGSYVideoPlayer player;
    private String url;  // 传过来的路径
    private PagerListener finishListener; //回调监听
    
    public VideoFragment(String url, PagerListener listener) {
        this.url = url;
        this.finishListener = listener;
    }
    
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    
    /**
     * 开始播放
     */
    public void startVideo() {
        if (player != null) {
            player.startPlayLogic();
    
            // 这块用的是GSYVideoPlayer 里面的方法 ,下面做判断是因为有的视频时间太短,不饿能准确的回调
            player.setGSYVideoProgressListener((progress, secProgress, currentPosition, duration) -> {
                if (duration < 30*1000) {//总时长小于40S
                    if (progress == 96){
                        finishListener.currentItem(0);
                    }
                }else if (duration < 50*1000) {//总时长小于40S
                    if (progress == 97){
                        finishListener.currentItem(0);
                    }
                }else if (duration < 90*1000){//总时长小于90S
                    if (progress == 98){
                        finishListener.currentItem(0);
                    }
                }else {
                    if (progress == 99){
                        finishListener.currentItem(0);
                    }
                }
            });
    
        }
    }
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.layout_video, null);
        player = view.findViewById(R.id.video_item_player);
        player.setUp(url, true, "");
        player.getTitleTextView().setVisibility(View.GONE);
        player.getBackButton().setOnClickListener(v -> finishListener.onClick());
        player.getFullscreenButton().setVisibility(View.GONE);
        player.getStartButton().setVisibility(View.GONE);
        ImageView imageView = new ImageView(getContext());
        imageView.setImageResource(R.drawable.image8);
        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        player.setThumbImageView(imageView);
    
        startVideo();
        return view;
    }
    
    @Override
    public void onPause() {
        super.onPause();
    }
    
    @Override
    public void onResume() {
        super.onResume();
    }
    
    @Override
    public void onDestroy() {
        super.onDestroy();
        GSYVideoManager.releaseAllVideos();
    }
    

    }

    PagerListener很简单,还是放上吧

    interface PagerListener {
    
    // 监听 这里可以回调一些数据进行处理
    void onClick();
    
    // 切换,同样的根据需求回调fragment数据
    void currentItem(int time);
    }
    

    DataBean是数据 ,里面看下就好了,来自https://www.jianshu.com/p/9db0fd1579b6

    public class DataBean {
    public Integer imageRes;
    public String imageUrl;
    public String title;
    public int viewType;
    
    public DataBean(Integer imageRes, String title, int viewType) {
        this.imageRes = imageRes;
        this.title = title;
        this.viewType = viewType;
    }
    
    public DataBean(String imageUrl, String title, int viewType) {
        this.imageUrl = imageUrl;
        this.title = title;
        this.viewType = viewType;
    }
    
    
    public static List<DataBean> MainActivity() {
        List<DataBean> list = new ArrayList<>();
        list.add(new DataBean("http://vfx.mtime.cn/Video/2019/03/18/mp4/190318231014076505.mp4", "", 2));
        list.add(new DataBean("http://vfx.mtime.cn/Video/2019/03/12/mp4/190312083533415853.mp4", "", 2));
        list.add(new DataBean("https://img.zcool.cn/community/011ad05e27a173a801216518a5c505.jpg", null, 1));
        list.add(new DataBean("https://img.zcool.cn/community/0148fc5e27a173a8012165184aad81.jpg", null, 1));
        list.add(new DataBean("https://img.zcool.cn/community/013c7d5e27a174a80121651816e521.jpg", null, 1));
        list.add(new DataBean("https://img.zcool.cn/community/01b8ac5e27a173a80120a895be4d85.jpg", null, 1));
        list.add(new DataBean("http://vfx.mtime.cn/Video/2019/03/09/mp4/190309153658147087.mp4", "", 2));
        list.add(new DataBean("http://vfx.mtime.cn/Video/2019/03/19/mp4/190319222227698228.mp4", "", 2));
        list.add(new DataBean("https://img.zcool.cn/community/01a85d5e27a174a80120a895111b2c.jpg", null, 1));
        list.add(new DataBean("https://img.zcool.cn/community/01085d5e27a174a80120a8958791c4.jpg", null, 1));
        list.add(new DataBean("https://img.zcool.cn/community/01f8735e27a174a8012165188aa959.jpg", null, 1));
        return list;
    }
    
    public static List<String> getColors(int size) {
        List<String> list = new ArrayList<>();
        for(int i = 0; i < size; i++) {
            list.add(getRandColor());
        }
        return list;
    }
    }
    

    下面就是实现功能了,因为开始代码感觉不会太多,所以我都写在了一页,感觉不够漂亮的可以自己去分下。

    public class MainActivity extends AppCompatActivity implements PagerListener {
    
    // 指示器相关的
    private List<ImageView> mImgList;
    private int img_select;
    private int img_unSelect;
    private static final int IMAGESIZE = 15;
    
    // 界面相关的
    private ViewPager viewpager;
    private LinearLayout linearLayout;
    private List<DataBean> dataBeans;
    private List<Fragment> fragments;
    private MyFragmentAdapter adapter;
    
    private boolean mIsChanged = false;
    private int mCurrentPagePosition = FIRST_ITEM_INDEX;
    private static final int FIRST_ITEM_INDEX = 1;
    // 需要的可以在这块设置成静态内部类,避免内存泄漏
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            viewpager.setCurrentItem(mCurrentPagePosition + 1);
        }
    };
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_vpw);
    
        viewpager = findViewById(R.id.viewpager);
        linearLayout = findViewById(R.id.dot_horizontal);
        dataBeans = DataBean.MainActivity();
        fragments = new ArrayList<>();
    
        int size = dataBeans.size();
    
        mImgList = new ArrayList<>();
        img_select = R.drawable.dot_select;
        img_unSelect = R.drawable.dot_unselect;
    
        for (int i = 0; i < size; i++) {
            ImageView imageView = new ImageView(this);
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
            //为小圆点左右添加间距
            params.leftMargin = 10;
            params.rightMargin = 10;
            //给小圆点一个默认大小
            params.height = IMAGESIZE;
            params.width = IMAGESIZE;
            // 默认第一个开始
            if (i == 0) {
                imageView.setBackgroundResource(img_select);
            } else {
                imageView.setBackgroundResource(img_unSelect);
            }
            //为LinearLayout添加ImageView
            linearLayout.addView(imageView, params);
            mImgList.add(imageView);
        }
    
    
        // 为了实现无限轮播  在fragment的第一个加入dataBeans的最后一个
        if (dataBeans.get(size - 1).viewType == 1) {
            fragments.add(new ImageFragment(dataBeans.get(size - 1).imageUrl, MainActivity.this));
        } else {
            fragments.add(new VideoFragment(dataBeans.get(size - 1).imageUrl, MainActivity.this));
        }
    
        // 这里是正常创建
        for (DataBean dataBean : dataBeans) {
            if (dataBean.viewType == 2) {
                fragments.add(new VideoFragment(dataBean.imageUrl, MainActivity.this));
            } else {
                fragments.add(new ImageFragment(dataBean.imageUrl, MainActivity.this));
            }
        }
    
        // 为了实现无限轮播  在fragment的末尾一个加入dataBeans的第一个
        if (dataBeans.get(0).viewType == 1) {
            fragments.add(new ImageFragment(dataBeans.get(0).imageUrl, MainActivity.this));
        } else {
            fragments.add(new VideoFragment(dataBeans.get(0).imageUrl, MainActivity.this));
        }
    
        adapter = new MyFragmentAdapter(getSupportFragmentManager(), fragments);
        viewpager.setAdapter(adapter);
        viewpager.setCurrentItem(FIRST_ITEM_INDEX, false);
        viewpager.setOffscreenPageLimit(3); //设置预加载的个数
        viewpager.setPageTransformer(false, new ScaleTransformer());
        viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }
    
            @Override
            public void onPageSelected(int position) {
                handler.removeCallbacksAndMessages(null);
                mIsChanged = true;
                if (position >= fragments.size() - 1) {// 末位之后,下次切换跳转到首位(1)
                    mCurrentPagePosition = FIRST_ITEM_INDEX;
                } else if (position <= FIRST_ITEM_INDEX) {// 首位之前,下次切换跳转到末尾(N)
                    mCurrentPagePosition = fragments.size() - 1;
                } else {
                    mCurrentPagePosition = position;
                }
    
                // 开启自动轮播
                Fragment fragment = fragments.get(position);
                if (fragment instanceof VideoFragment) {
                    //视频自动播放
                    VideoFragment videoFragment = (VideoFragment) fragment;
                    videoFragment.startVideo();
                } else {
                    //图片自动倒计时
                    ImageFragment imageFragment = (ImageFragment) fragment;
                    imageFragment.imgStart();
                }
    
                for (int i = 0; i < size; i++) {
                    //选中的页面改变小圆点为选中状态,反之为未选中
                    if (i == mCurrentPagePosition-1) {
                        (mImgList.get(i)).setBackgroundResource(img_select);
                    } else {
                        (mImgList.get(i)).setBackgroundResource(img_unSelect);
                    }
                }
            }
    
            @Override
            public void onPageScrollStateChanged(int state) {
                if (ViewPager.SCROLL_STATE_IDLE == state) {
                    if (mIsChanged) {
                        mIsChanged = false;
                        viewpager.setCurrentItem(mCurrentPagePosition, false);
                    }
                }
            }
        });
    
        // 每次开始先切换一次,保障fragment里面的监听回调获取到,这块可以去了解一下viewpage + fragment切换时 fragment的生命周期
        currentItem(0);
    }
    
    /**
     * 切换viewpage
     */
    Runnable runnable = () -> handler.sendEmptyMessage(0);
    
    
    @Override
    public void currentItem(int time) {
        handler.postDelayed(runnable, time);
    }
    
    @Override
    public void onClick() {
        // 点击处理
        Log.e("TAG", "onClick: 点击了界面" );
    }
    
    
    /**
     * Adapter 简单使用
     */
    public static class MyFragmentAdapter extends FragmentPagerAdapter {
        private List<Fragment> list;
    
        public MyFragmentAdapter(FragmentManager fm, List<Fragment> list) {
            super(fm);
            this.list = list;
        }
    
        @NonNull
        @Override
        public Fragment getItem(int arg0) {
            return list.get(arg0);
        }
    
        @Override
        public int getCount() {
            return list.size();
        }
    
    
    }
    
    /**
     * ViewPager 切换效果
     */
    public static class ScaleTransformer implements ViewPager.PageTransformer {
        private static final float MIN_SCALE = 0.70f;
        private static final float MIN_ALPHA = 0.5f;
    
        @Override
        public void transformPage(View page, float position) {
            if (position < -1 || position > 1) {
                page.setAlpha(MIN_ALPHA);
                page.setScaleX(MIN_SCALE);
                page.setScaleY(MIN_SCALE);
            } else if (position <= 1) { // [-1,1]
                float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
                if (position < 0) {
                    float scaleX = 1 + 0.3f * position;
                    Log.d("google_lenve_fb", "transformPage: scaleX:" + scaleX);
                    page.setScaleX(scaleX);
                    page.setScaleY(scaleX);
                } else {
                    float scaleX = 1 - 0.3f * position;
                    page.setScaleX(scaleX);
                    page.setScaleY(scaleX);
                }
                page.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA));
            }
        }
    }
    }
    

    好了,这样功能就能跑起来了。效果图就不上了,懒得动的直接取源码获取运行
    我的源码

    布局在下面
    activity_vpw

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <androidx.viewpager.widget.ViewPager
            android:id="@+id/viewpager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
        <LinearLayout
            android:id="@+id/dot_horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            android:layout_marginBottom="32dp"
            android:gravity="center"
            android:orientation="horizontal" />
    </FrameLayout>
    </LinearLayout>
    

    layout_image

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    layout_video

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root_ll"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
        android:id="@+id/video_item_player"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    </LinearLayout>
    

    这只是一个Demo,在实际应用时还需要完善,里面还有一些小问题,需要根据自己的需求去更改。

    相关文章

      网友评论

          本文标题:ViewPage实现图片和视频轮播

          本文链接:https://www.haomeiwen.com/subject/xlbfnhtx.html