Android 360全景仿写

https://juejin.im/post/6844904116351664135

implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
//自带 glide   +  glide的 transform
implementation 'jp.wasabeef:glide-transformations:4.0.1'
//这个必须加---element== null
implementation 'com.github.bumptech.glide:glide:4.10.0'
//加上这个才可以 有 进度
annotationProcessor 'com.github.bumptech.glide:compiler:4.10.0'

一个大神写的,我转个Java

package com.as.zqfjavasample.formal.customviews;

import android.animation.IntEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.widget.ImageView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import io.reactivex.Completable;
import io.reactivex.CompletableEmitter;
import io.reactivex.CompletableObserver;
import io.reactivex.CompletableOnSubscribe;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.observers.DisposableObserver;
import io.reactivex.schedulers.Schedulers;

/**
 * -----------------------------
 * Created by zqf on 2020/9/29.
 * ---------------------------
 */
public class MyRotateViewJava extends AppCompatImageView {

    private RotateController controller;

    public RotateController getController() {
        return controller;
    }

    public void setController(RotateController controller) {
        this.controller = controller;
    }

    public MyRotateViewJava(Context context) {
        this(context, null);
    }

    public MyRotateViewJava(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyRotateViewJava(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        controller = new RotateController(this, context);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return controller.onTouchEvent(event);
    }

    public interface OnRotateActionListener {
        void onSourceReady();

        void onClick();
    }


    public class RotateController implements LifecycleObserver {


        private CompositeDisposable disposableHelper = new CompositeDisposable();

        private GestureDetector gestureDetector;

        private List<String> motorImageList = new ArrayList<>();

        private boolean isSourceReady = false;

        private Disposable timerDisposable;

        private int currentIndex = 0;

        //累积播放的帧数
        private int accumulate = 0;

        private ValueAnimator anim;

        private boolean isAutoShow = true;

        OnRotateActionListener actionistener;

        public void setActionistener(OnRotateActionListener actionistener) {
            this.actionistener = actionistener;
        }

        private MyRotateViewJava myRotateViewJava;
        private Context context;

        public RotateController(MyRotateViewJava myRotateViewJava, Context context) {
            this.myRotateViewJava = myRotateViewJava;
            this.context = context;

            gestureDetector = new GestureDetector(context, new GestureDetector.OnGestureListener() {
                @Override
                public boolean onDown(MotionEvent e) {
                    return true;
                }

                @Override
                public void onShowPress(MotionEvent e) {

                }

                @Override
                public boolean onSingleTapUp(MotionEvent e) {
                    actionistener.onClick();
                    return true;
                }

                @Override
                public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {

                    if (Math.abs(distanceX) < 1f) {
                        accumulate = 0;
                    } else if (Math.abs(distanceX) < 3f) {
                        if (distanceX > 0) {
                            accumulate = -1;
                        } else if (distanceX < 0) {
                            accumulate = 1;
                        }
                    } else if (distanceX > 0) {
                        if (accumulate < 0) {
                            accumulate = 0;
                        }
                        accumulate--;
                    } else {
                        if (accumulate > 0) {
                            accumulate = 0;
                        }
                        accumulate++;
                    }
                    return true;
                }

                @Override
                public void onLongPress(MotionEvent e) {

                }

                @Override
                public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                    if (Math.abs(velocityX) < 150) {
                        return false;
                    }
                    if (velocityX > 0) {
                        accumulate += 5;
                    } else {
                        accumulate -= 5;
                    }
                    return true;
                }
            });

            gestureDetector.setIsLongpressEnabled(false);

            if (context instanceof AppCompatActivity) {
                AppCompatActivity context1 = (AppCompatActivity) context;
                context1.getLifecycle().addObserver(this);
            }


        }


        private void addIndex() {
            if (isSourceReady) {
                currentIndex++;

                if (currentIndex >= motorImageList.size()) {
                    currentIndex = 0;
                }

                Glide.with(myRotateViewJava).load(motorImageList.get(currentIndex)).dontAnimate()
                        .placeholder(myRotateViewJava.getDrawable()).into(myRotateViewJava);
            }
        }

        private void reduceIndex() {
            if (isSourceReady) {
                currentIndex--;

                if (currentIndex < 0) {
                    currentIndex = motorImageList.size() - 1;
                }

                Glide.with(myRotateViewJava).load(motorImageList.get(currentIndex)).dontAnimate()
                        .placeholder(myRotateViewJava.getDrawable()).into(myRotateViewJava);
            }

        }

        private Completable getFirstImage(String url) {

            CompletableOnSubscribe completableOnSubscribe = new CompletableOnSubscribe() {
                @Override
                public void subscribe(CompletableEmitter e) throws Exception {
                    Glide.with(myRotateViewJava)
                            .load(url)
                            .diskCacheStrategy(DiskCacheStrategy.DATA)
                            .into(myRotateViewJava);
                    e.onComplete();
                }
            };

            return Completable.create(completableOnSubscribe).subscribeOn(AndroidSchedulers.mainThread());
        }

        private Completable getSingleImage(String url) {

            CompletableOnSubscribe completableOnSubscribe = new CompletableOnSubscribe() {
                @Override
                public void subscribe(CompletableEmitter e) throws Exception {
                    Glide.with(myRotateViewJava)
                            .asFile()
                            .load(url)
                            .diskCacheStrategy(DiskCacheStrategy.DATA)
                            .submit();
                    e.onComplete();
                }
            };

            return Completable.create(completableOnSubscribe).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io());
        }


        private void prepareImageSource() {
            List<Completable> actionList = new ArrayList<Completable>();

            for (int i = 0; i < motorImageList.size(); i++) {
                if (i == 0) {
                    actionList.add(getFirstImage(motorImageList.get(i)));
                } else {
                    actionList.add(getSingleImage(motorImageList.get(i)));
                }
            }

            Completable.merge(actionList)
                    .subscribeOn(Schedulers.io())
                    .unsubscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new CompletableObserver() {
                        @Override
                        public void onSubscribe(Disposable d) {
                            disposableHelper.add(d);
                        }

                        @Override
                        public void onComplete() {
                            loadComplete();
                        }

                        @Override
                        public void onError(Throwable e) {

                        }
                    });

        }


        private void loadComplete() {

            if (actionistener == null) {
                return;
            }
            actionistener.onSourceReady();

            if (!isAutoShow) {
                isSourceReady = true;
                initTimer();
                return;
            }

            anim = ValueAnimator.ofObject(new IntEvaluator(), 1, motorImageList.size());
            anim.setDuration(1800);
            anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    int animatedValue = (int) animation.getAnimatedValue();
                    if (currentIndex != animatedValue) {
                        if (animatedValue >= motorImageList.size()) {
                            currentIndex = 0;
                        } else {
                            currentIndex = animatedValue;
                        }

                        Glide.with(myRotateViewJava).load(motorImageList.get(currentIndex)).dontAnimate()
                                .placeholder(myRotateViewJava.getDrawable()).into(myRotateViewJava);
                        if (currentIndex == 0) {
                            isSourceReady = true;
                            initTimer();
                        }

                    }
                }
            });
            anim.start();
        }

        private void initTimer() {
            DisposableObserver<Long> timerDisposable = Observable.interval(40, TimeUnit.MILLISECONDS)
                    .subscribeOn(Schedulers.io())
                    .unsubscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribeWith(new DisposableObserver<Long>() {
                        @Override
                        public void onNext(Long aLong) {
                            if (accumulate > 0) {
                                accumulate--;
                                addIndex();
                            } else if (accumulate < 0) {
                                accumulate++;
                                reduceIndex();
                            }
                        }

                        @Override
                        public void onError(Throwable e) {

                        }

                        @Override
                        public void onComplete() {

                        }
                    });
        }

        private void loadSingleImage(String imageUrl) {
            myRotateViewJava.setScaleType(ImageView.ScaleType.CENTER_CROP);
            Glide.with(myRotateViewJava).load(imageUrl).dontAnimate().into(myRotateViewJava);
        }


        public void loadImageList(List<String> imageList, boolean isAutoShow) {
            this.isAutoShow = isAutoShow;
            if (imageList.size() == 0) {

            } else if (imageList.size() == 1) {
                loadSingleImage(imageList.get(0));
            } else {
                myRotateViewJava.setScaleType(ImageView.ScaleType.FIT_CENTER);
                motorImageList.addAll(imageList);
                prepareImageSource();
            }
        }

        private boolean onTouchEvent(MotionEvent event) {
            if (event != null) {
                if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
                    accumulate = 0;
                }
            }
            myRotateViewJava.getParent().requestDisallowInterceptTouchEvent(true);
            return gestureDetector.onTouchEvent(event);

        }


        @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
        public void onDestroy() {
            disposableHelper.dispose();
            timerDisposable.dispose();
            anim.removeAllUpdateListeners();
            anim.cancel();
        }


    }

}

 

List<String> list = new ArrayList<>();
        list.add(pic0);
        list.add(pic1);
        list.add(pic2);
        list.add(pic3);
        list.add(pic4);
        list.add(pic5);
        list.add(pic6);
        list.add(pic7);
        list.add(pic8);
        list.add(pic9);
        list.add(pic10);
        list.add(pic11);
        list.add(pic12);
        list.add(pic13);
        list.add(pic14);
        list.add(pic15);
        MyRotateViewJava.RotateController controller = mViewBinding.rotateiv.getController();
        controller.loadImageList(list, true);
        controller.setActionistener(new MyRotateViewJava.OnRotateActionListener() {
            @Override
            public void onSourceReady() {

            }

            @Override
            public void onClick() {

            }
        });

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值