Skip to content

Commit b3fbfb3

Browse files
committed
improved shared element transition for videos
video view bugs fixed
1 parent a6b299d commit b3fbfb3

File tree

9 files changed

+223
-85
lines changed

9 files changed

+223
-85
lines changed

SmartFileBrowser/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ android {
3434
}
3535
}
3636
group = 'ir.smartdevelopers'
37-
version = '2.0.4'
37+
version = '2.0.5'
3838

3939
dependencies {
4040

SmartFileBrowser/src/main/java/ir/smartdevelopers/smartfilebrowser/acitivties/FileBrowserMainActivity.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import android.graphics.RenderEffect;
4545
import android.graphics.Shader;
4646
import android.graphics.drawable.ColorDrawable;
47+
import android.graphics.drawable.Drawable;
4748
import android.net.Uri;
4849
import android.os.Build;
4950
import android.os.Bundle;
@@ -252,6 +253,7 @@ public boolean accept(File pathname) {
252253
protected void onCreate(Bundle savedInstanceState) {
253254
setTheme(R.style.sfb_MainAppTheme_sfb_AppTheme);
254255
Window window = getWindow();
256+
// window.setSharedElementsUseOverlay(false);
255257
WindowCompat.enableEdgeToEdge(window);
256258
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
257259
window.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
@@ -738,11 +740,11 @@ public void onItemClicked(GalleryModel model, View view, int position) {
738740
}
739741
};
740742
}
741-
742743
private void openVideoActivity(GalleryModel model, View view, int position) {
743744
Uri uri = FileProvider.getUriForFile(this, getPackageName() + ".sfb_provider", model.getCurrentFile());
744745
Intent videoActivityIntent = new Intent(this, VideoViewActivity.class);
745746
videoActivityIntent.setData(uri);
747+
746748
Bundle options = null;
747749
if (view != null) {
748750
String sharedName = ViewCompat.getTransitionName(view);
@@ -752,7 +754,8 @@ private void openVideoActivity(GalleryModel model, View view, int position) {
752754
options = ActivityOptionsCompat.makeSceneTransitionAnimation(this, view, sharedName).toBundle();
753755
videoActivityIntent.putExtra(VideoViewActivity.KEY_TRANSITION_NAME, sharedName);
754756
}
755-
ActivityCompat.startActivity(this, videoActivityIntent, options);
757+
ActivityCompat.startActivityForResult(this,videoActivityIntent,696987, options);
758+
// ContextCompat.startActivity(this,videoActivityIntent, options);
756759
}
757760

758761
private void openImageEditor(GalleryModel model, View view, int position) {
@@ -764,11 +767,13 @@ private void openImageEditor(GalleryModel model, View view, int position) {
764767
Intent editorIntent = new Intent(this, PhotoEditorActivity.class);
765768
editorIntent.setData(uri);
766769
if (view instanceof ImageView){
767-
Rect rect = Utils.calculateBitmapBound(getResources(),model);
768-
Bitmap preview = DrawableKt.toBitmap(((ImageView) view).getDrawable(),rect.width(),rect.height(), Bitmap.Config.ARGB_8888);
769-
770-
PhotoEditorActivity.Preview = preview;
770+
Drawable d = ((ImageView) view).getDrawable();
771+
if (d != null){
772+
Rect rect = Utils.calculateBitmapBound(getResources(),model);
773+
PhotoEditorActivity.Preview = DrawableKt.toBitmap(d,rect.width(),rect.height(), Bitmap.Config.ARGB_8888);
774+
}
771775
}
776+
772777
editorIntent.putExtra(PhotoEditorActivity.KEY_SAVE_PATH, mEditedImagePath);
773778
Bundle options = null;
774779
if (view != null) {

SmartFileBrowser/src/main/java/ir/smartdevelopers/smartfilebrowser/acitivties/VideoViewActivity.java

Lines changed: 159 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import static ir.smartdevelopers.smartfilebrowser.customClasses.Utils.formatTime;
44

5+
import androidx.activity.OnBackPressedCallback;
56
import androidx.annotation.NonNull;
67
import androidx.annotation.Nullable;
78
import androidx.appcompat.app.AppCompatActivity;
@@ -11,11 +12,16 @@
1112
import androidx.core.app.ActivityCompat;
1213
import androidx.core.app.SharedElementCallback;
1314
import androidx.core.view.ViewCompat;
15+
import androidx.core.view.WindowCompat;
16+
import androidx.core.view.WindowInsetsControllerCompat;
1417

18+
import android.animation.ValueAnimator;
1519
import android.annotation.SuppressLint;
1620
import android.content.res.Configuration;
21+
import android.content.res.Resources;
1722
import android.graphics.Bitmap;
1823
import android.graphics.Color;
24+
import android.graphics.drawable.ColorDrawable;
1925
import android.graphics.drawable.Drawable;
2026
import android.media.MediaMetadataRetriever;
2127
import android.media.MediaPlayer;
@@ -29,25 +35,37 @@
2935
import android.provider.MediaStore;
3036
import android.transition.Transition;
3137
import android.transition.TransitionInflater;
38+
import android.util.DisplayMetrics;
3239
import android.util.Log;
3340
import android.view.MotionEvent;
41+
import android.view.SurfaceHolder;
3442
import android.view.View;
43+
import android.view.ViewTreeObserver;
3544
import android.view.Window;
45+
import android.view.WindowManager;
3646
import android.widget.ImageView;
3747
import android.widget.MediaController;
3848
import android.widget.TextView;
3949
import android.widget.VideoView;
50+
51+
import com.bumptech.glide.Glide;
4052
import com.google.android.material.slider.LabelFormatter;
4153
import com.google.android.material.slider.Slider;
4254

4355
import java.io.IOException;
56+
import java.util.List;
4457
import java.util.Locale;
58+
import java.util.concurrent.ExecutorService;
59+
import java.util.concurrent.Executors;
60+
4561
import ir.smartdevelopers.smartfilebrowser.R;
4662
import ir.smartdevelopers.smartfilebrowser.customClasses.MyVideoView;
4763

4864
public class VideoViewActivity extends AppCompatActivity {
4965

5066
public static final String KEY_TRANSITION_NAME="transition_name";
67+
private final long animationDuration = 500;
68+
5169
private Uri mVideoUri;
5270
private ImageView imgThumbnailHolder;
5371

@@ -59,36 +77,73 @@ public class VideoViewActivity extends AppCompatActivity {
5977
private Handler mTimerHandler;
6078
private boolean isPlaying;
6179
private Slider mSlider;
80+
private boolean mVideoPrapered = false;
81+
private boolean mTransitionEnds = false;
6282
@SuppressLint("ClickableViewAccessibility")
6383
@Override
6484
protected void onCreate(Bundle savedInstanceState) {
65-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
66-
getWindow().requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
67-
Transition transition= TransitionInflater.from(this).inflateTransition(R.transition.iten_transition_in);
68-
getWindow().setSharedElementEnterTransition(transition);
69-
getWindow().setSharedElementReturnTransition(transition);
85+
Window window = getWindow();
86+
String transitionName=getIntent().getStringExtra(KEY_TRANSITION_NAME);
87+
window.requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS);
88+
// window.setSharedElementsUseOverlay(false);
89+
Transition transition= TransitionInflater.from(this).inflateTransition(R.transition.iten_transition_in);
90+
//transition.addTarget(R.id.sfb_activity_videoView_imagePlaceHolder);
91+
window.setSharedElementEnterTransition(transition);
92+
window.setSharedElementReturnTransition(transition);
93+
94+
transition.addListener(new Transition.TransitionListener() {
95+
@Override
96+
public void onTransitionCancel(Transition transition) {
97+
98+
}
99+
100+
@Override
101+
public void onTransitionEnd(Transition transition) {
102+
if (!isExiting){
103+
mTransitionEnds = true;
104+
mVideoView.setVideoURI(mVideoUri);
105+
hideThumbNaile(true);
106+
}
107+
}
108+
109+
@Override
110+
public void onTransitionPause(Transition transition) {
111+
112+
}
113+
114+
@Override
115+
public void onTransitionResume(Transition transition) {
116+
117+
}
70118

119+
@Override
120+
public void onTransitionStart(Transition transition) {
71121

122+
}
123+
});
124+
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
125+
window.setBackgroundDrawable(new ColorDrawable(Color.BLACK));
126+
WindowCompat.enableEdgeToEdge(window);
127+
WindowInsetsControllerCompat controllerCompat = WindowCompat.getInsetsController(window,window.getDecorView());
128+
if (controllerCompat != null){
129+
controllerCompat.setAppearanceLightStatusBars(false);
72130
}
73131
super.onCreate(savedInstanceState);
74132
setContentView(R.layout.activity_video_view);
133+
supportPostponeEnterTransition();
75134

76135
mVideoUri=getIntent().getData();
77-
String transitionName=getIntent().getStringExtra(KEY_TRANSITION_NAME);
136+
78137

79138
findViews();
80-
initTimer();
81139
ViewCompat.setTransitionName(imgThumbnailHolder,transitionName);
140+
initTimer();
82141

83142
btnPlay.setOnClickListener(v->{
84143
btnPlay.setVisibility(View.GONE);
85-
mVideoView.setVisibility(View.VISIBLE);
86144
playVideo();
87-
if (imgThumbnailHolder.getVisibility()==View.VISIBLE){
88-
new Handler().postDelayed(()->{
89-
imgThumbnailHolder.setVisibility(View.INVISIBLE);
90-
},900);
91-
}
145+
hideThumbNaile(false);
146+
92147

93148
});
94149

@@ -104,8 +159,22 @@ public boolean onTouch(View v, MotionEvent event) {
104159
return false;
105160
}
106161
});
162+
mVideoView.setOnInfoListener(new MediaPlayer.OnInfoListener() {
163+
@Override
164+
public boolean onInfo(MediaPlayer mp, int what, int extra) {
165+
Log.d("VideoVieAcivity","Player info = "+what);
166+
return false;
167+
}
168+
});
107169

108-
170+
mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
171+
@Override
172+
public void onPrepared(MediaPlayer mp) {
173+
mVideoPrapered = true;
174+
mVideoView.seekTo(1);
175+
hideThumbNaile(true);
176+
}
177+
});
109178
mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
110179
@Override
111180
public void onCompletion(MediaPlayer mp) {
@@ -118,13 +187,54 @@ public void onCompletion(MediaPlayer mp) {
118187
}
119188
});
120189

121-
mVideoView.setVideoURI(mVideoUri);
122-
mVideoView.seekTo(1);
190+
//mVideoView.setZOrderOnTop(false);
191+
192+
// mVideoView.resume();
193+
// mVideoView.pause();
123194

124195

125-
ActivityCompat.postponeEnterTransition(this);
196+
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
197+
@Override
198+
public void handleOnBackPressed() {
199+
if (mVideoView !=null ){
200+
mVideoView.pause();
201+
}
202+
203+
isPlaying=false;
204+
showThumbnail(false);
205+
isExiting=true;
206+
remove();
207+
ActivityCompat.finishAfterTransition(VideoViewActivity.this);
208+
209+
}
210+
});
211+
126212
loadVideoThumbnail();
213+
// new Handler().postDelayed(()->loadVideoThumbnail(),2000);
214+
215+
127216

217+
}
218+
private void showThumbnail(boolean animate) {
219+
if (animate){
220+
imgThumbnailHolder.animate().setDuration(animationDuration)
221+
.alpha(1)
222+
.start();
223+
}else{
224+
imgThumbnailHolder.setAlpha(1f);
225+
mVideoView.setVisibility(View.GONE);
226+
}
227+
}
228+
229+
230+
private void hideThumbNaile(boolean animate) {
231+
if (mVideoPrapered && mTransitionEnds){
232+
if (animate){
233+
imgThumbnailHolder.animate().setDuration(animationDuration).alpha(0);
234+
}else{
235+
imgThumbnailHolder.setAlpha(0f);
236+
}
237+
}
128238
}
129239

130240
private void initTimer() {
@@ -193,7 +303,7 @@ public String getFormattedValue(float value) {
193303
@Override
194304
public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) {
195305
if (fromUser){
196-
mVideoView.seekTo((int) slider.getValue());
306+
mVideoView.seekTo((int) value);
197307
}
198308
}
199309
});
@@ -221,25 +331,38 @@ public void onStopTrackingTouch(@NonNull Slider slider) {
221331
}
222332

223333
private void loadVideoThumbnail() {
224-
MediaMetadataRetriever retriever=new MediaMetadataRetriever();
225-
retriever.setDataSource(this,mVideoUri);
226-
Bitmap bitmap=retriever.getFrameAtTime();
227-
imgThumbnailHolder.setImageBitmap(bitmap);
228-
229-
String durationSt=retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
230-
if (durationSt!=null){
231-
long duration=Long.parseLong(durationSt);
232-
setTime(duration,txtVideoLength);
233-
mSlider.setValueTo(duration);
234-
}
334+
imgThumbnailHolder.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
335+
@Override
336+
public boolean onPreDraw() {
337+
imgThumbnailHolder.getViewTreeObserver().removeOnPreDrawListener(this);
338+
int h = imgThumbnailHolder.getMeasuredHeight();
339+
int w = imgThumbnailHolder.getMeasuredWidth();
340+
supportStartPostponedEnterTransition();
341+
return true;
342+
}
343+
});
344+
345+
try (MediaMetadataRetriever retriever=new MediaMetadataRetriever()){
346+
retriever.setDataSource(this,mVideoUri);
347+
DisplayMetrics metrics = getResources().getDisplayMetrics();
348+
Bitmap bitmap=retriever.getFrameAtTime();
349+
Glide.with(imgThumbnailHolder).load(bitmap).dontTransform()
350+
.override(metrics.widthPixels,metrics.heightPixels)
351+
.into(imgThumbnailHolder);
352+
353+
String durationSt=retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
354+
if (durationSt!=null){
355+
long duration=Long.parseLong(durationSt);
356+
setTime(duration,txtVideoLength);
357+
mSlider.setValueTo(duration);
358+
}
359+
setTime(0,txtCurrentTime);
360+
361+
} catch (IOException e) {
362+
Log.e(getPackageName(),e.getMessage(),e);
363+
}
364+
235365

236-
setTime(0,txtCurrentTime);
237-
ActivityCompat.startPostponedEnterTransition(VideoViewActivity.this);
238-
try {
239-
retriever.release();
240-
} catch (IOException e) {
241-
Log.e(getPackageName(),e.getMessage(),e);
242-
}
243366
}
244367

245368

@@ -269,18 +392,5 @@ protected void onDestroy() {
269392
super.onDestroy();
270393
}
271394

272-
@Override
273-
public void onBackPressed() {
274-
if (mVideoView !=null ){
275-
mVideoView.pause();
276-
}
277395

278-
isPlaying=false;
279-
imgThumbnailHolder.setVisibility(View.VISIBLE);
280-
imgThumbnailHolder.post(()->{
281-
mVideoView.setVisibility(View.GONE);
282-
});
283-
isExiting=true;
284-
super.onBackPressed();
285-
}
286396
}

0 commit comments

Comments
 (0)