5 Commits 8556e741d8 ... db29be57ea

Author SHA1 Message Date
  LAPTOP-K69FCNBP\crius db29be57ea Merge branch 'master' of http://116.62.119.248:10082/cheng_zq/EffectDemo into lwz_ 2 years ago
  LAPTOP-K69FCNBP\crius b591f876c1 Merge branch 'master' of http://116.62.119.248:10082/cheng_zq/EffectDemo into lwz_ 2 years ago
  LAPTOP-K69FCNBP\crius f9ea5b7804 Merge branch 'master' of http://116.62.119.248:10082/cheng_zq/EffectDemo into lwz_ 2 years ago
  LAPTOP-K69FCNBP\crius 6feaea07ec 点图发声 2 years ago
  LAPTOP-K69FCNBP\crius d8175b6462 视频点播 2 years ago

+ 9 - 6
app/src/main/AndroidManifest.xml

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
-    package="com.xunao.effectdemo">
+    package="com.xunao.effectdemo" >
 
     <uses-sdk tools:overrideLibrary="com.qmuiteam.qmui" />
 
@@ -31,8 +31,8 @@
         android:roundIcon="@mipmap/ic_launcher_round"
         android:supportsRtl="true"
         android:theme="@style/AppTheme"
-        android:usesCleartextTraffic="true">
-        <activity android:name=".activity.MainActivity">
+        android:usesCleartextTraffic="true" >
+        <activity android:name=".activity.MainActivity" >
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
 
@@ -77,7 +77,7 @@
             android:name=".receiver.MyService"
             android:enabled="true"
             android:exported="false"
-            android:process=":pushcore">
+            android:process=":pushcore" >
             <intent-filter>
                 <action android:name="cn.jiguang.user.service.action" />
             </intent-filter>
@@ -86,7 +86,7 @@
         <receiver
             android:name=".receiver.PushMessageReceiver"
             android:enabled="true"
-            android:exported="false">
+            android:exported="false" >
             <intent-filter>
                 <action android:name="cn.jpush.android.intent.RECEIVE_MESSAGE" />
 
@@ -98,7 +98,7 @@
             android:name="cn.jiguang.union.ads.service.JAdFileProvider"
             android:authorities="${applicationId}.JAdFileProvider"
             android:exported="false"
-            android:grantUriPermissions="true">
+            android:grantUriPermissions="true" >
             <meta-data
                 android:name="android.support.FILE_PROVIDER_PATHS"
                 android:resource="@xml/jpush_file_paths" />
@@ -135,6 +135,9 @@
         <activity
             android:name=".activity.VideoDemandActivity"
             android:screenOrientation="landscape" />
+        <activity
+            android:name=".activity.AudioActivity"
+            android:screenOrientation="landscape" />
     </application>
 
 </manifest>

+ 92 - 0
app/src/main/java/com/xunao/effectdemo/activity/AudioActivity.java

@@ -0,0 +1,92 @@
+package com.xunao.effectdemo.activity;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
+import androidx.viewpager.widget.ViewPager;
+
+import android.os.Bundle;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.xunao.effectdemo.R;
+import com.xunao.effectdemo.adapter.AudioDemandAdapter;
+import com.xunao.effectdemo.adapter.VideoDemandAdapter;
+import com.xunao.effectdemo.fragment.AudioDemandFragment;
+import com.xunao.effectdemo.fragment.VideoDemandFragment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AudioActivity extends FragmentActivity {
+
+    private ViewPager viewPager;
+
+    private String[][] datas = {{"a", "b", "c"}, {"d", "e", "f"}};
+
+    private List<Fragment> list;
+    private AudioDemandAdapter adapter;
+
+    private int selectedNum = 0;
+    private TextView tvNumAudio;
+    private int length;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_audio);
+        length = 0;
+        for(String[] data : datas){
+            length = data.length + length;
+        }
+        initView();
+    }
+
+    private void initView(){
+        tvNumAudio = findViewById(R.id.tv_num_audio);
+        tvNumAudio.setText("探索 0/" + length);
+        viewPager = findViewById(R.id.view_pager_audio);
+        //把Fragment添加到List集合里面
+        list = new ArrayList<>();
+        for(String[] data : datas){
+            AudioDemandFragment audioDemandFragment = new AudioDemandFragment();
+            Bundle bundle = new Bundle();
+            bundle.putStringArray("data",data);
+            audioDemandFragment.setArguments(bundle);
+            list.add(audioDemandFragment);
+        }
+        adapter = new AudioDemandAdapter(getSupportFragmentManager(), list);
+//        viewPager.setAdapter(new VideoDemandAdapter(this, datas));
+        viewPager.setAdapter(adapter);
+        viewPager.setOffscreenPageLimit(datas.length);
+        viewPager.setCurrentItem(0);
+
+        // 上一个
+        ImageView ivAudioPrevious = findViewById(R.id.iv_audio_previous);
+        ivAudioPrevious.setOnClickListener(v -> {
+            int current = viewPager.getCurrentItem();
+            if(current > 0){
+                viewPager.setCurrentItem(current - 1);
+            }
+        });
+
+        // 下一个
+        ImageView ivAudioNext = findViewById(R.id.iv_audio_next);
+        ivAudioNext.setOnClickListener(v -> {
+            int current = viewPager.getCurrentItem();
+            if(current < datas.length - 1){
+                viewPager.setCurrentItem(current + 1);
+            }
+        });
+    }
+
+    public void addSelectedNum() {
+
+        selectedNum = selectedNum + 1;
+        if(selectedNum == length){
+            tvNumAudio.setText("完成");
+        }else{
+            tvNumAudio.setText("探索 "+selectedNum+"/" + length);
+        }
+    }
+}

+ 7 - 3
app/src/main/java/com/xunao/effectdemo/activity/MapChallengeActivity.java

@@ -38,14 +38,18 @@ public class MapChallengeActivity extends Activity {
     void initView(){
         btnMap1 = findViewById(R.id.btn_map_1);
         btnMap2 = findViewById(R.id.btn_map_2);
-        btnMap3 = findViewById(R.id.btn_map_3);
-        btnMap3.setOnClickListener(new View.OnClickListener() {
+        btnMap2.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                intent = new Intent(MapChallengeActivity.this, VideoDemandActivity.class);
+                intent = new Intent(MapChallengeActivity.this, AudioActivity.class);
                 startActivity(intent);
             }
         });
+        btnMap3 = findViewById(R.id.btn_map_3);
+        btnMap3.setOnClickListener(v -> {
+            intent = new Intent(MapChallengeActivity.this, VideoDemandActivity.class);
+            startActivity(intent);
+        });
         btnMap4 = findViewById(R.id.btn_map_4);
         btnMap5 = findViewById(R.id.btn_map_5);
         btnMap6 = findViewById(R.id.btn_map_6);

+ 69 - 3
app/src/main/java/com/xunao/effectdemo/activity/VideoDemandActivity.java

@@ -1,20 +1,86 @@
 package com.xunao.effectdemo.activity;
 
-import androidx.appcompat.app.AppCompatActivity;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
+import androidx.viewpager.widget.ViewPager;
 
-import android.app.Activity;
 import android.os.Bundle;
+import android.widget.ImageView;
+import android.widget.TextView;
 
 import com.xunao.effectdemo.R;
+import com.xunao.effectdemo.adapter.VideoDemandAdapter;
+import com.xunao.effectdemo.fragment.VideoDemandFragment;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * 视频点播
  */
-public class VideoDemandActivity extends Activity {
+public class VideoDemandActivity extends FragmentActivity {
+
+    private ViewPager viewPager;
+    private String[] datas = {"a", "b", "c", "d", "e", "f"};
+
+    private List<Fragment> list;
+    private VideoDemandAdapter adapter;
+
+    private int selectedNum = 0;
+    private TextView tvNum;
+
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_video_demand);
+        initView();
+    }
+
+    private void initView(){
+        tvNum = findViewById(R.id.tv_num);
+        tvNum.setText("探索 0/"+datas.length);
+        viewPager = findViewById(R.id.view_pager);
+        //把Fragment添加到List集合里面
+        list = new ArrayList<>();
+        for(String data : datas){
+            VideoDemandFragment videoDemandFragment = new VideoDemandFragment();
+            Bundle bundle = new Bundle();
+            bundle.putString("data",data);
+            videoDemandFragment.setArguments(bundle);
+            list.add(videoDemandFragment);
+        }
+        adapter = new VideoDemandAdapter(getSupportFragmentManager(), list);
+//        viewPager.setAdapter(new VideoDemandAdapter(this, datas));
+        viewPager.setAdapter(adapter);
+        viewPager.setOffscreenPageLimit(datas.length);
+        viewPager.setCurrentItem(0);
+
+        // 上一个
+        ImageView tvPrevious = findViewById(R.id.tv_previous);
+        tvPrevious.setOnClickListener(v -> {
+            int current = viewPager.getCurrentItem();
+            if(current > 0){
+                viewPager.setCurrentItem(current - 1);
+            }
+        });
+
+        // 下一个
+        ImageView tvNext = findViewById(R.id.tv_next);
+        tvNext.setOnClickListener(v -> {
+            int current = viewPager.getCurrentItem();
+            if(current < datas.length - 1){
+                viewPager.setCurrentItem(current + 1);
+            }
+        });
+    }
+
+    public void addSelectedNum() {
+        selectedNum = selectedNum + 1;
+        if(selectedNum == datas.length){
+            tvNum.setText("完成");
+        }else{
+            tvNum.setText("探索 "+selectedNum+"/"+datas.length);
+        }
     }
 }

+ 187 - 0
app/src/main/java/com/xunao/effectdemo/adapter/AudioAdapter.java

@@ -0,0 +1,187 @@
+package com.xunao.effectdemo.adapter;
+
+import static android.view.View.GONE;
+
+import static com.mobile.auth.gatewayauth.utils.ReflectionUtils.getActivity;
+
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.content.Context;
+import android.media.MediaPlayer;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.xunao.effectdemo.R;
+import com.xunao.effectdemo.activity.AudioActivity;
+import com.xunao.effectdemo.activity.VideoDemandActivity;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class AudioAdapter extends RecyclerView.Adapter<AudioAdapter.ViewHolder> {
+    private final String TAG = "AudioAdapter";
+
+    private AnimatorSet mRightOutSet; // 右出动画
+    private AnimatorSet mLeftInSet; // 左入动画
+    private List<String> wordList;
+    private final Context context;
+    private String url = "http://www.mobvcasting.com/android/audio/goodmorningandroid.mp3";
+
+    private MediaPlayer mediaPlayer;
+    private List<Integer> selectList = new ArrayList<>();
+
+    public AudioAdapter(String[] wordList, Context context) {
+        this.wordList = Arrays.asList(wordList);
+        this.context = context;
+    }
+
+    @NonNull
+    @Override
+    public AudioAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
+        View view = LayoutInflater.from(viewGroup.getContext())
+                .inflate(R.layout.item_audio_demand,viewGroup,false);
+        ViewHolder holder = new ViewHolder(view);
+        return holder;
+    }
+
+    @Override
+    public void onBindViewHolder(@NonNull AudioAdapter.ViewHolder viewHolder, int i) {
+
+        if(selectList.contains(i)){
+//            viewHolder.tvBack.setVisibility(GONE);
+            Log.i(TAG, "点击后" + selectList.toString());
+        }
+
+        setAnimators(viewHolder, i);
+        setCameraDistance(viewHolder);
+
+        mediaPlayer = new MediaPlayer();
+        mediaPlayer.setOnPreparedListener(mp -> Log.i(TAG,"onPrepared:准备完成"));
+        mediaPlayer.setOnCompletionListener(mp -> Log.i(TAG,"OnCompletion:播放完成"));
+        try {
+            mediaPlayer.setDataSource(url);
+            mediaPlayer.prepareAsync();// 开始在后台缓冲音频文件并返回
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        viewHolder.tvBack.setOnClickListener(v -> {
+            Log.i(TAG, "点击前1" + selectList.toString() + "---" + i);
+            if(!selectList.contains(i)){
+                selectList.add(i);
+                notifyItemChanged(i);
+                flipCard(viewHolder);
+
+                AudioActivity audioActivity = (AudioActivity) getActivity();
+                assert audioActivity != null;
+                audioActivity.addSelectedNum();
+
+                Log.i(TAG, "点击前2" + selectList.toString() + "---" + i);
+            }else {
+                // 重播
+//                mediaPlayer.stop();
+                if(mediaPlayer.isPlaying()){
+                    mediaPlayer.seekTo(0);
+                }else{
+                    mediaPlayer.start();
+                }
+                Log.i(TAG, "重新播放音频");
+            }
+        });
+
+    }
+
+
+
+    @Override
+    public int getItemCount() {
+        Log.i(TAG, "getItemCount" + wordList.size());
+        return wordList.isEmpty() ? 0 : wordList.size();
+    }
+
+    // 设置动画
+    private void setAnimators(AudioAdapter.ViewHolder viewHolder, int pos) {
+        mRightOutSet = (AnimatorSet) AnimatorInflater.loadAnimator(context, R.animator.anim_out);
+        mLeftInSet = (AnimatorSet) AnimatorInflater.loadAnimator(context, R.animator.anim_in);
+
+        // 设置点击事件
+        mRightOutSet.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                super.onAnimationStart(animation);
+                viewHolder.tvBack.setClickable(false);
+            }
+        });
+        mLeftInSet.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                super.onAnimationEnd(animation);
+                viewHolder.tvBack.setClickable(true);
+
+                if(mediaPlayer != null){
+                    mediaPlayer.start();
+                }
+                Log.i(TAG, "播放音频");
+            }
+        });
+    }
+
+    // 改变视角距离, 贴近屏幕
+    private void setCameraDistance(AudioAdapter.ViewHolder viewHolder) {
+        int distance = 1000000;
+        float scale = context.getResources().getDisplayMetrics().density * distance;
+        viewHolder.tvFront.setCameraDistance(scale);
+        viewHolder.tvBack.setCameraDistance(scale);
+        Log.i(TAG, "setCameraDistance:改变视角距离" + scale);
+    }
+
+    // 翻转卡片
+    public void flipCard(AudioAdapter.ViewHolder viewHolder) {
+        // 正面朝上
+//        if (!mIsShowBack) {
+//            mRightOutSet.setTarget(tvFront);
+//            mLeftInSet.setTarget(tvBack);
+//            mRightOutSet.start();
+//            mLeftInSet.start();
+//            mIsShowBack = true;
+//            Log.i(TAG, "flipCard:正面朝上");
+//        } else { // 背面朝上
+            mRightOutSet.setTarget(viewHolder.tvBack);
+            mLeftInSet.setTarget(viewHolder.tvFront);
+            mRightOutSet.start();
+            mLeftInSet.start();
+//            mIsShowBack = false;
+            Log.i(TAG, "flipCard:背面朝上");
+//        }
+    }
+
+    public void release(){
+        mediaPlayer.release();
+        mediaPlayer = null;
+        Log.i(TAG, "release");
+    }
+
+    public static class ViewHolder extends RecyclerView.ViewHolder {
+
+        private TextView tvFront;
+        private TextView tvBack;
+
+        public ViewHolder(@NonNull View itemView) {
+            super(itemView);
+            tvFront = itemView.findViewById(R.id.tv_previous_audio);
+            tvBack = itemView.findViewById(R.id.tv_back_audio);
+        }
+    }
+}

+ 27 - 0
app/src/main/java/com/xunao/effectdemo/adapter/AudioDemandAdapter.java

@@ -0,0 +1,27 @@
+package com.xunao.effectdemo.adapter;
+
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentPagerAdapter;
+
+import java.util.List;
+
+public class AudioDemandAdapter extends FragmentPagerAdapter {
+
+    private List<Fragment> mlist;
+
+    public AudioDemandAdapter(FragmentManager fm, List<Fragment> list) {
+        super(fm);
+        this.mlist = list;
+    }
+    //显示第几个页面
+    @Override
+    public Fragment getItem(int position) {
+        return mlist.get(position);
+    }
+    //一共有几个页面,注意,使用Fragment特有的构造器时,和ViewPager的原生构造器的方法不同
+    @Override
+    public int getCount() {
+        return mlist.size();
+    }
+}

+ 35 - 0
app/src/main/java/com/xunao/effectdemo/adapter/VideoDemandAdapter.java

@@ -0,0 +1,35 @@
+package com.xunao.effectdemo.adapter;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentPagerAdapter;
+import androidx.viewpager.widget.PagerAdapter;
+
+import com.xunao.effectdemo.R;
+
+import java.util.List;
+
+public class VideoDemandAdapter extends FragmentPagerAdapter {
+
+    private List<Fragment> mlist;
+
+    public VideoDemandAdapter(FragmentManager fm, List<Fragment> list) {
+        super(fm);
+        this.mlist = list;
+    }
+    //显示第几个页面
+    @Override
+    public Fragment getItem(int position) {
+        return mlist.get(position);
+    }
+    //一共有几个页面,注意,使用Fragment特有的构造器时,和ViewPager的原生构造器的方法不同
+    @Override
+    public int getCount() {
+        return mlist.size();
+    }
+}

+ 81 - 0
app/src/main/java/com/xunao/effectdemo/fragment/AudioDemandFragment.java

@@ -0,0 +1,81 @@
+package com.xunao.effectdemo.fragment;
+
+import static android.view.View.GONE;
+
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.media.MediaPlayer;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import androidx.fragment.app.Fragment;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.SimpleItemAnimator;
+
+import com.shuyu.gsyvideoplayer.GSYVideoManager;
+import com.xunao.effectdemo.R;
+import com.xunao.effectdemo.activity.AudioActivity;
+import com.xunao.effectdemo.adapter.AudioAdapter;
+import com.xunao.effectdemo.adapter.WordCutAdapter;
+
+import java.io.IOException;
+import java.util.Objects;
+
+public class AudioDemandFragment extends Fragment {
+    private final String TAG = "AudioDemandFragment";
+
+    private AudioActivity activity = (AudioActivity) getActivity();
+
+    private String[] data;
+
+    private RecyclerView rvAudio;
+    private AudioAdapter audioAdapter;
+
+    private MediaPlayer mediaPlayer;
+    private String url = "http://www.mobvcasting.com/android/audio/goodmorningandroid.mp3";
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        View view = inflater.inflate(R.layout.fragment_audio_demand, container, false);
+
+        assert getArguments() != null;
+        data = getArguments().getStringArray("data");
+
+        rvAudio = view.findViewById(R.id.rv_audio);
+        ((SimpleItemAnimator) Objects.requireNonNull(rvAudio.getItemAnimator())).setSupportsChangeAnimations(false);
+        // 设置横向布局
+        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false){
+            @Override
+            public boolean canScrollHorizontally() {
+                return false;
+            }
+        };
+        rvAudio.setLayoutManager(linearLayoutManager);
+        audioAdapter = new AudioAdapter(data, getContext());
+        rvAudio.setAdapter(audioAdapter);
+
+        return view;
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        audioAdapter.release();
+    }
+
+    // 当前fragment 可见->不可见 或 不可见->可见时 会调用这个方法
+    @Override
+    public void setUserVisibleHint(boolean isVisibleToUser) {
+        super.setUserVisibleHint(isVisibleToUser);
+        Log.i(TAG, "setUserVisibleHint: " + isVisibleToUser + "--" + data);
+
+    }
+}

+ 168 - 0
app/src/main/java/com/xunao/effectdemo/fragment/VideoDemandFragment.java

@@ -0,0 +1,168 @@
+package com.xunao.effectdemo.fragment;
+
+import static android.view.View.GONE;
+
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import androidx.fragment.app.Fragment;
+
+import com.shuyu.gsyvideoplayer.GSYVideoManager;
+import com.shuyu.gsyvideoplayer.listener.GSYVideoProgressListener;
+import com.xunao.effectdemo.R;
+import com.xunao.effectdemo.activity.VideoDemandActivity;
+import com.xunao.effectdemo.view.VideoPreviewPlay;
+
+public class VideoDemandFragment extends Fragment {
+    private final String TAG = "VideoDemandFragment";
+
+    private AnimatorSet mRightOutSet; // 右出动画
+    private AnimatorSet mLeftInSet; // 左入动画
+    private RelativeLayout rlContainer;
+    private VideoPreviewPlay videoFront;
+    private TextView tvBack;
+    private boolean mIsShowBack = true;
+    private String url = "http://v3.cztv.com/cztv/vod/2018/06/28/7c45987529ea410dad7c088ba3b53dac/h264_1500k_mp4.mp4";
+//    private String url = "https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4";
+    private String data;
+
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        View view = inflater.inflate(R.layout.fragment_video_demand, container, false);
+        videoFront = view.findViewById(R.id.video_front);
+        videoFront.setUp(url, true, "null");
+        videoFront.getTitleTextView().setVisibility(View.GONE);
+        videoFront.getFullscreenButton().setVisibility(View.GONE);
+        videoFront.getBackButton().setVisibility(GONE);
+        videoFront.setGSYVideoProgressListener(new GSYVideoProgressListener() {
+            @Override
+            public void onProgress(int progress, int secProgress, int currentPosition, int duration) {
+                Log.i(TAG, "onProgress:" +progress + "----" + secProgress + "----" + currentPosition + "---" + duration);
+                if(progress == 100){
+                    // 翻转到缩略图并且记录改项已完成
+                }
+            }
+        });
+//        videoFront.startPlayLogic();
+        tvBack = view.findViewById(R.id.tv_back);
+        rlContainer = view.findViewById(R.id.rl_container);
+        tvBack.setOnClickListener(v -> {
+            flipCard();
+
+            VideoDemandActivity videoDemandActivity = (VideoDemandActivity) getActivity();
+            assert videoDemandActivity != null;
+            videoDemandActivity.addSelectedNum();
+
+            videoFront.setUp(url, true, "null");
+            videoFront.startPlayLogic();
+        });
+        setAnimators(); // 设置动画
+        setCameraDistance(); // 设置镜头距离
+
+        assert getArguments() != null;
+        data = getArguments().getString("data");
+        tvBack.setText("背面" + data);
+        return view;
+    }
+
+    // 设置动画
+    private void setAnimators() {
+        mRightOutSet = (AnimatorSet) AnimatorInflater.loadAnimator(getContext(), R.animator.anim_out);
+        mLeftInSet = (AnimatorSet) AnimatorInflater.loadAnimator(getContext(), R.animator.anim_in);
+
+        // 设置点击事件
+        mRightOutSet.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                super.onAnimationStart(animation);
+                tvBack.setClickable(false);
+            }
+        });
+        mLeftInSet.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                super.onAnimationEnd(animation);
+                tvBack.setClickable(true);
+                tvBack.setVisibility(GONE);
+            }
+        });
+    }
+
+    // 改变视角距离, 贴近屏幕
+    private void setCameraDistance() {
+        int distance = 1000000;
+        float scale = getContext().getResources().getDisplayMetrics().density * distance;
+        videoFront.setCameraDistance(scale);
+        tvBack.setCameraDistance(scale);
+        Log.i(TAG, "setCameraDistance:改变视角距离" + scale);
+    }
+
+    // 翻转卡片
+    public void flipCard() {
+        // 正面朝上
+        if (!mIsShowBack) {
+            mRightOutSet.setTarget(videoFront);
+            mLeftInSet.setTarget(tvBack);
+            mRightOutSet.start();
+            mLeftInSet.start();
+            mIsShowBack = true;
+            Log.i(TAG, "flipCard:正面朝上");
+        } else { // 背面朝上
+            mRightOutSet.setTarget(tvBack);
+            mLeftInSet.setTarget(videoFront);
+            mRightOutSet.start();
+            mLeftInSet.start();
+            mIsShowBack = false;
+            Log.i(TAG, "flipCard:背面朝上");
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        videoFront.onVideoResume();
+        Log.i(TAG, "onResume");
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        videoFront.onVideoPause();
+        Log.i(TAG, "onPause");
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        Log.i(TAG, "onStop");
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        GSYVideoManager.releaseAllVideos();
+        Log.i(TAG, "onDestroy");
+    }
+
+
+    // 当前fragment 可见->不可见 或 不可见->可见时 会调用这个方法
+    @Override
+    public void setUserVisibleHint(boolean isVisibleToUser) {
+        super.setUserVisibleHint(isVisibleToUser);
+        Log.i(TAG, "setUserVisibleHint: " + isVisibleToUser + "--" + data);
+        // 不可见时暂停视频
+        if(!isVisibleToUser && videoFront != null){
+            videoFront.onVideoPause();
+        }
+    }
+}

+ 25 - 0
app/src/main/res/animator/anim_in.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <!--消失-->
+    <objectAnimator
+        android:duration="0"
+        android:propertyName="alpha"
+        android:valueFrom="1.0"
+        android:valueTo="0.0" />
+
+    <!--旋转-->
+    <objectAnimator
+        android:duration="@integer/anim_length"
+        android:propertyName="rotationY"
+        android:valueFrom="-180"
+        android:valueTo="0" />
+
+    <!--出现-->
+    <objectAnimator
+        android:duration="0"
+        android:propertyName="alpha"
+        android:startOffset="@integer/anim_half_length"
+        android:valueFrom="0.0"
+        android:valueTo="1.0" />
+</set>

+ 17 - 0
app/src/main/res/animator/anim_out.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <!--旋转-->
+    <objectAnimator
+        android:duration="@integer/anim_length"
+        android:propertyName="rotationY"
+        android:valueFrom="0"
+        android:valueTo="180" />
+
+    <!--消失-->
+    <objectAnimator
+        android:duration="0"
+        android:propertyName="alpha"
+        android:startOffset="@integer/anim_half_length"
+        android:valueFrom="1.0"
+        android:valueTo="0.0" />
+</set>

BIN
app/src/main/res/drawable/next_icon.png


BIN
app/src/main/res/drawable/previous_icon.png


+ 37 - 0
app/src/main/res/layout/activity_audio.xml

@@ -0,0 +1,37 @@
+<?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:gravity="center"
+    android:orientation="vertical"
+    tools:context=".activity.VideoDemandActivity">
+  <LinearLayout
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content"
+      android:gravity="center">
+    <ImageView
+        android:id="@+id/iv_audio_previous"
+        android:layout_width="64dp"
+        android:layout_height="64dp"
+        android:src="@drawable/previous_icon"/>
+    <androidx.viewpager.widget.ViewPager
+        android:id="@+id/view_pager_audio"
+        android:layout_width="0dp"
+        android:layout_height="300dp"
+        android:layout_weight="1"/>
+    <ImageView
+        android:id="@+id/iv_audio_next"
+        android:layout_width="64dp"
+        android:layout_height="64dp"
+        android:src="@drawable/next_icon"/>
+  </LinearLayout>
+
+  <TextView
+      android:id="@+id/tv_num_audio"
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content"
+      android:textSize="30sp"
+      android:layout_marginTop="40dp"/>
+</LinearLayout>

+ 28 - 3
app/src/main/res/layout/activity_video_demand.xml

@@ -1,9 +1,34 @@
 <?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<RelativeLayout 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"
     tools:context=".activity.VideoDemandActivity">
-
-</androidx.constraintlayout.widget.ConstraintLayout>
+    <ImageView
+        android:id="@+id/tv_previous"
+        android:layout_width="64dp"
+        android:layout_height="64dp"
+        android:src="@drawable/previous_icon"
+        android:layout_centerVertical="true"/>
+    <androidx.viewpager.widget.ViewPager
+        android:id="@+id/view_pager"
+        android:layout_width="400dp"
+        android:layout_height="300dp"
+        android:layout_centerInParent="true"/>
+    <ImageView
+        android:id="@+id/tv_next"
+        android:layout_width="64dp"
+        android:layout_height="64dp"
+        android:src="@drawable/next_icon"
+        android:layout_centerVertical="true"
+        android:layout_alignParentRight="true"/>
+    <TextView
+        android:id="@+id/tv_num"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:layout_centerHorizontal="true"
+        android:layout_marginBottom="20dp"
+        android:textSize="30sp"/>
+</RelativeLayout>

+ 5 - 0
app/src/main/res/layout/fragment_audio_demand.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/rv_audio"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"/>

+ 19 - 0
app/src/main/res/layout/fragment_video_demand.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/rl_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <com.xunao.effectdemo.view.VideoPreviewPlay
+        android:id="@+id/video_front"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+    <TextView
+        android:id="@+id/tv_back"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@color/colorGrayDark"
+        android:gravity="center"
+        android:textSize="28sp"
+        android:textColor="@color/exo_white"
+        android:text="背面"/>
+</RelativeLayout>

+ 25 - 0
app/src/main/res/layout/item_audio_demand.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/rl_container"
+    android:layout_width="230dp"
+    android:layout_height="300dp"
+    android:layout_marginHorizontal="22dp">
+    <TextView
+        android:id="@+id/tv_previous_audio"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@color/colorGrayDark"
+        android:gravity="center"
+        android:textSize="28sp"
+        android:textColor="@color/exo_white"
+        android:text="正面"/>
+    <TextView
+        android:id="@+id/tv_back_audio"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@color/colorGrayDark"
+        android:gravity="center"
+        android:textSize="28sp"
+        android:textColor="@color/exo_white"
+        android:text="背面"/>
+</RelativeLayout>

+ 5 - 0
app/src/main/res/values/Integers.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <integer name="anim_length">3000</integer>
+    <integer name="anim_half_length">1500</integer>
+</resources>