split viewpagerfragment into photo and video

This commit is contained in:
tibbi 2016-06-09 10:22:07 +02:00
parent 1923479591
commit 73575f8839
9 changed files with 381 additions and 326 deletions

View File

@ -2,12 +2,12 @@ package com.simplemobiletools.gallery;
import java.io.Serializable;
public class Media implements Serializable {
public class Medium implements Serializable {
private static final long serialVersionUID = -6543139465975455L;
private final String path;
private final boolean isVideo;
public Media(String path, boolean isVideo) {
public Medium(String path, boolean isVideo) {
this.path = path;
this.isVideo = isVideo;
}

View File

@ -0,0 +1,50 @@
package com.simplemobiletools.gallery;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.davemorrissey.labs.subscaleview.ImageSource;
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
import com.simplemobiletools.gallery.activities.ViewPagerActivity;
public class PhotoFragment extends ViewPagerFragment implements View.OnClickListener {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.pager_photo_item, container, false);
final Medium medium = (Medium) getArguments().getSerializable(Constants.MEDIUM);
if (medium == null)
return view;
final SubsamplingScaleImageView imageView = (SubsamplingScaleImageView) view.findViewById(R.id.photo_view);
imageView.setOrientation(SubsamplingScaleImageView.ORIENTATION_USE_EXIF);
imageView.setImage(ImageSource.uri(medium.getPath()));
imageView.setMaxScale(5f);
imageView.setOnClickListener(this);
return view;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
@Override
public void onClick(View v) {
((ViewPagerActivity) getActivity()).fragmentClicked();
}
@Override
public void itemDragged() {
}
@Override
public void fragmentHidden() {
}
}

View File

@ -0,0 +1,285 @@
package com.simplemobiletools.gallery;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import com.simplemobiletools.gallery.activities.ViewPagerActivity;
import java.io.IOException;
import java.util.Locale;
public class VideoFragment extends ViewPagerFragment
implements View.OnClickListener, SurfaceHolder.Callback, MediaPlayer.OnCompletionListener, MediaPlayer.OnVideoSizeChangedListener,
SeekBar.OnSeekBarChangeListener {
private static final String TAG = VideoFragment.class.getSimpleName();
private static final String MEDIUM = "medium";
private MediaPlayer mediaPlayer;
private SurfaceHolder surfaceHolder;
private ImageView playOutline;
private TextView currTimeView;
private TextView durationView;
private Handler timerHandler;
private SeekBar seekBar;
private Medium medium;
private boolean isPlaying;
private boolean isDragged;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.pager_video_item, container, false);
;
medium = (Medium) getArguments().getSerializable(Constants.MEDIUM);
if (medium == null)
return view;
setupPlayer(view);
view.setOnClickListener(this);
return view;
}
private void setupPlayer(View view) {
if (getActivity() == null)
return;
playOutline = (ImageView) view.findViewById(R.id.video_play_outline);
playOutline.setOnClickListener(this);
final SurfaceView surfaceView = (SurfaceView) view.findViewById(R.id.video_surface);
surfaceView.setOnClickListener(this);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
initTimeHolder(view);
}
public void itemDragged() {
pauseVideo();
}
public void fragmentHidden() {
cleanup();
}
private void initTimeHolder(View view) {
RelativeLayout timeHolder = (RelativeLayout) view.findViewById(R.id.video_time_holder);
final Resources res = getResources();
final int height = Utils.getNavBarHeight(res);
final int left = timeHolder.getPaddingLeft();
final int top = timeHolder.getPaddingTop();
final int right = timeHolder.getPaddingRight();
final int bottom = timeHolder.getPaddingBottom();
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
timeHolder.setPadding(left, top, right, bottom + height);
} else {
timeHolder.setPadding(left, top, right + height, bottom);
}
currTimeView = (TextView) view.findViewById(R.id.video_curr_time);
durationView = (TextView) view.findViewById(R.id.video_duration);
seekBar = (SeekBar) view.findViewById(R.id.video_seekbar);
seekBar.setOnSeekBarChangeListener(this);
}
private void setupTimeHolder() {
final int duration = mediaPlayer.getDuration() / 1000;
seekBar.setMax(duration);
durationView.setText(getTimeString(duration));
timerHandler = new Handler();
setupTimer();
}
private void setupTimer() {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
if (mediaPlayer != null && !isDragged && isPlaying) {
int currPos = mediaPlayer.getCurrentPosition() / 1000;
seekBar.setProgress(currPos);
currTimeView.setText(getTimeString(currPos));
}
timerHandler.postDelayed(this, 1000);
}
});
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable(MEDIUM, medium);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.video_play_outline:
togglePlayPause();
break;
default:
((ViewPagerActivity) getActivity()).fragmentClicked();
}
}
private void pauseVideo() {
if (isPlaying) {
togglePlayPause();
}
}
private void togglePlayPause() {
if (getActivity() == null)
return;
isPlaying = !isPlaying;
if (isPlaying) {
if (mediaPlayer != null) {
mediaPlayer.start();
}
playOutline.setImageDrawable(null);
} else {
if (mediaPlayer != null) {
mediaPlayer.pause();
}
playOutline.setImageDrawable(getResources().getDrawable(R.mipmap.play_outline_big));
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
initMediaPlayer();
}
private void initMediaPlayer() {
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(getContext(), Uri.parse(medium.getPath()));
mediaPlayer.setDisplay(surfaceHolder);
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setOnVideoSizeChangedListener(this);
mediaPlayer.prepare();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
addPreviewImage();
setupTimeHolder();
seekBar.setProgress(0);
currTimeView.setText(getTimeString(0));
} catch (IOException e) {
Log.e(TAG, "init media player " + e.getMessage());
}
}
private void addPreviewImage() {
mediaPlayer.start();
mediaPlayer.pause();
}
@Override
public void onPause() {
super.onPause();
cleanup();
}
private void cleanup() {
pauseVideo();
if (currTimeView != null)
currTimeView.setText(getTimeString(0));
if (mediaPlayer != null) {
mediaPlayer.release();
mediaPlayer = null;
}
if (seekBar != null)
seekBar.setProgress(0);
if (timerHandler != null)
timerHandler.removeCallbacksAndMessages(null);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
@Override
public void onCompletion(MediaPlayer mp) {
pauseVideo();
}
@Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
surfaceHolder.setFixedSize(width, height);
}
private String getTimeString(int duration) {
final StringBuilder sb = new StringBuilder(8);
final int hours = duration / (60 * 60);
final int minutes = (duration % (60 * 60)) / 60;
final int seconds = ((duration % (60 * 60)) % 60);
if (mediaPlayer != null && mediaPlayer.getDuration() > 3600000) {
sb.append(String.format(Locale.getDefault(), "%02d", hours)).append(":");
}
sb.append(String.format(Locale.getDefault(), "%02d", minutes));
sb.append(":").append(String.format(Locale.getDefault(), "%02d", seconds));
return sb.toString();
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (mediaPlayer != null && fromUser) {
mediaPlayer.seekTo(progress * 1000);
seekBar.setProgress(progress);
currTimeView.setText(getTimeString(progress));
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
if (mediaPlayer == null)
initMediaPlayer();
mediaPlayer.pause();
isDragged = true;
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
if (!isPlaying) {
togglePlayPause();
} else {
mediaPlayer.start();
}
isDragged = false;
}
}

View File

@ -1,305 +1,9 @@
package com.simplemobiletools.gallery;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import com.davemorrissey.labs.subscaleview.ImageSource;
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
import com.simplemobiletools.gallery.activities.ViewPagerActivity;
public abstract class ViewPagerFragment extends Fragment {
public abstract void itemDragged();
import java.io.IOException;
import java.util.Locale;
public class ViewPagerFragment extends Fragment
implements View.OnClickListener, SurfaceHolder.Callback, MediaPlayer.OnCompletionListener, MediaPlayer.OnVideoSizeChangedListener,
SeekBar.OnSeekBarChangeListener {
private static final String TAG = ViewPagerFragment.class.getSimpleName();
private static final String MEDIUM = "medium";
private static MediaPlayer mediaPlayer;
private SurfaceHolder surfaceHolder;
private ImageView playOutline;
private TextView currTimeView;
private TextView durationView;
private Handler timerHandler;
private SeekBar seekBar;
private Media medium;
private boolean isPlaying;
private boolean isDragged;
public void setMedium(Media medium) {
this.medium = medium;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view;
if (medium == null && savedInstanceState != null) {
medium = (Media) savedInstanceState.getSerializable(MEDIUM);
}
if (medium != null) {
if (medium.getIsVideo()) {
view = inflater.inflate(R.layout.pager_video_item, container, false);
setupPlayer(view);
} else {
view = inflater.inflate(R.layout.pager_photo_item, container, false);
final SubsamplingScaleImageView imageView = (SubsamplingScaleImageView) view.findViewById(R.id.photo_view);
imageView.setOrientation(SubsamplingScaleImageView.ORIENTATION_USE_EXIF);
imageView.setImage(ImageSource.uri(medium.getPath()));
imageView.setMaxScale(5f);
}
} else {
view = inflater.inflate(R.layout.pager_photo_item, container, false);
}
view.setOnClickListener(this);
return view;
}
private void setupPlayer(View view) {
if (getActivity() == null)
return;
playOutline = (ImageView) view.findViewById(R.id.video_play_outline);
playOutline.setOnClickListener(this);
final SurfaceView surfaceView = (SurfaceView) view.findViewById(R.id.video_surface);
surfaceView.setOnClickListener(this);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
initTimeHolder(view);
}
public void itemDragged() {
pauseVideo();
}
public void fragmentHidden() {
cleanup();
}
private void initTimeHolder(View view) {
RelativeLayout timeHolder = (RelativeLayout) view.findViewById(R.id.video_time_holder);
final Resources res = getResources();
final int height = Utils.getNavBarHeight(res);
final int left = timeHolder.getPaddingLeft();
final int top = timeHolder.getPaddingTop();
final int right = timeHolder.getPaddingRight();
final int bottom = timeHolder.getPaddingBottom();
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
timeHolder.setPadding(left, top, right, bottom + height);
} else {
timeHolder.setPadding(left, top, right + height, bottom);
}
currTimeView = (TextView) view.findViewById(R.id.video_curr_time);
durationView = (TextView) view.findViewById(R.id.video_duration);
seekBar = (SeekBar) view.findViewById(R.id.video_seekbar);
seekBar.setOnSeekBarChangeListener(this);
}
private void setupTimeHolder() {
final int duration = mediaPlayer.getDuration() / 1000;
seekBar.setMax(duration);
durationView.setText(getTimeString(duration));
timerHandler = new Handler();
setupTimer();
}
private void setupTimer() {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
if (mediaPlayer != null && !isDragged && isPlaying) {
int currPos = mediaPlayer.getCurrentPosition() / 1000;
seekBar.setProgress(currPos);
currTimeView.setText(getTimeString(currPos));
}
timerHandler.postDelayed(this, 1000);
}
});
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable(MEDIUM, medium);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.video_play_outline:
togglePlayPause();
break;
default:
((ViewPagerActivity) getActivity()).photoClicked();
}
}
private void pauseVideo() {
if (isPlaying) {
togglePlayPause();
}
}
private void togglePlayPause() {
if (getActivity() == null)
return;
isPlaying = !isPlaying;
if (isPlaying) {
if (mediaPlayer != null) {
mediaPlayer.start();
}
playOutline.setImageDrawable(null);
} else {
if (mediaPlayer != null) {
mediaPlayer.pause();
}
playOutline.setImageDrawable(getResources().getDrawable(R.mipmap.play_outline_big));
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
initMediaPlayer();
}
private void initMediaPlayer() {
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(getContext(), Uri.parse(medium.getPath()));
mediaPlayer.setDisplay(surfaceHolder);
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setOnVideoSizeChangedListener(this);
mediaPlayer.prepare();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
addPreviewImage();
setupTimeHolder();
seekBar.setProgress(0);
currTimeView.setText(getTimeString(0));
} catch (IOException e) {
Log.e(TAG, "init media player " + e.getMessage());
}
}
private void addPreviewImage() {
mediaPlayer.start();
mediaPlayer.pause();
}
@Override
public void onPause() {
super.onPause();
cleanup();
}
private void cleanup() {
pauseVideo();
if (currTimeView != null)
currTimeView.setText(getTimeString(0));
if (mediaPlayer != null) {
mediaPlayer.release();
mediaPlayer = null;
}
if (seekBar != null)
seekBar.setProgress(0);
if (timerHandler != null)
timerHandler.removeCallbacksAndMessages(null);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
@Override
public void onCompletion(MediaPlayer mp) {
pauseVideo();
}
@Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
surfaceHolder.setFixedSize(width, height);
}
private String getTimeString(int duration) {
final StringBuilder sb = new StringBuilder(8);
final int hours = duration / (60 * 60);
final int minutes = (duration % (60 * 60)) / 60;
final int seconds = ((duration % (60 * 60)) % 60);
if (mediaPlayer != null && mediaPlayer.getDuration() > 3600000) {
sb.append(String.format(Locale.getDefault(), "%02d", hours)).append(":");
}
sb.append(String.format(Locale.getDefault(), "%02d", minutes));
sb.append(":").append(String.format(Locale.getDefault(), "%02d", seconds));
return sb.toString();
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (mediaPlayer != null && fromUser) {
mediaPlayer.seekTo(progress * 1000);
seekBar.setProgress(progress);
currTimeView.setText(getTimeString(progress));
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
if (mediaPlayer == null)
initMediaPlayer();
mediaPlayer.pause();
isDragged = true;
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
if (!isPlaying) {
togglePlayPause();
} else {
mediaPlayer.start();
}
isDragged = false;
}
public abstract void fragmentHidden();
}

View File

@ -28,7 +28,7 @@ import android.widget.GridView;
import android.widget.Toast;
import com.simplemobiletools.gallery.Constants;
import com.simplemobiletools.gallery.Media;
import com.simplemobiletools.gallery.Medium;
import com.simplemobiletools.gallery.R;
import com.simplemobiletools.gallery.Utils;
import com.simplemobiletools.gallery.adapters.MediaAdapter;
@ -47,7 +47,7 @@ public class MediaActivity extends AppCompatActivity
@BindView(R.id.media_grid) GridView gridView;
private static final int STORAGE_PERMISSION = 1;
private List<Media> media;
private List<Medium> media;
private int selectedItemsCnt;
private String path;
private Snackbar snackbar;
@ -124,8 +124,8 @@ public class MediaActivity extends AppCompatActivity
}
}
private List<Media> getMedia() {
final List<Media> myMedia = new ArrayList<>();
private List<Medium> getMedia() {
final List<Medium> myMedia = new ArrayList<>();
final List<String> invalidFiles = new ArrayList<>();
for (int i = 0; i < 2; i++) {
Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
@ -146,7 +146,7 @@ public class MediaActivity extends AppCompatActivity
if (curPath.matches(pattern) && !toBeDeleted.contains(curPath)) {
final File file = new File(curPath);
if (file.exists()) {
myMedia.add(new Media(curPath, (i == 1)));
myMedia.add(new Medium(curPath, (i == 1)));
} else {
invalidFiles.add(file.getAbsolutePath());
}

View File

@ -20,7 +20,7 @@ import android.widget.EditText;
import android.widget.RelativeLayout;
import com.simplemobiletools.gallery.Constants;
import com.simplemobiletools.gallery.Media;
import com.simplemobiletools.gallery.Medium;
import com.simplemobiletools.gallery.MyViewPager;
import com.simplemobiletools.gallery.R;
import com.simplemobiletools.gallery.Utils;
@ -44,7 +44,7 @@ public class ViewPagerActivity extends AppCompatActivity
private int pos;
private boolean isFullScreen;
private ActionBar actionbar;
private List<Media> media;
private List<Medium> media;
private String path;
private String directory;
private boolean isUndoShown;
@ -207,7 +207,7 @@ public class ViewPagerActivity extends AppCompatActivity
if (file.renameTo(newFile)) {
final int currItem = pager.getCurrentItem();
media.set(currItem, new Media(newFile.getAbsolutePath(), media.get(currItem).getIsVideo()));
media.set(currItem, new Medium(newFile.getAbsolutePath(), media.get(currItem).getIsVideo()));
final String[] changedFiles = {file.getAbsolutePath(), newFile.getAbsolutePath()};
MediaScannerConnection.scanFile(getApplicationContext(), changedFiles, null, null);
@ -246,8 +246,8 @@ public class ViewPagerActivity extends AppCompatActivity
MediaScannerConnection.scanFile(getApplicationContext(), toBeDeleted, null, null);
}
private List<Media> getMedia() {
final List<Media> myMedia = new ArrayList<>();
private List<Medium> getMedia() {
final List<Medium> myMedia = new ArrayList<>();
int j = 0;
for (int i = 0; i < 2; i++) {
Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
@ -266,7 +266,7 @@ public class ViewPagerActivity extends AppCompatActivity
do {
final String curPath = cursor.getString(pathIndex);
if (curPath.matches(pattern) && !curPath.equals(toBeDeleted) && !curPath.equals(beingDeleted)) {
myMedia.add(new Media(curPath, i == 1));
myMedia.add(new Medium(curPath, i == 1));
if (curPath.equals(path)) {
pos = j;
@ -281,7 +281,7 @@ public class ViewPagerActivity extends AppCompatActivity
return myMedia;
}
public void photoClicked() {
public void fragmentClicked() {
deleteFile();
isFullScreen = !isFullScreen;
if (isFullScreen) {

View File

@ -8,17 +8,17 @@ import android.widget.BaseAdapter;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.simplemobiletools.gallery.Media;
import com.simplemobiletools.gallery.Medium;
import com.simplemobiletools.gallery.R;
import java.util.List;
public class MediaAdapter extends BaseAdapter {
private final Context context;
private final List<Media> media;
private final List<Medium> media;
private final LayoutInflater inflater;
public MediaAdapter(Context context, List<Media> media) {
public MediaAdapter(Context context, List<Medium> media) {
this.context = context;
this.media = media;
this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@ -26,7 +26,7 @@ public class MediaAdapter extends BaseAdapter {
@Override
public View getView(int position, View view, ViewGroup parent) {
final Media medium = media.get(position);
final Medium medium = media.get(position);
ViewHolder holder;
if (view == null) {
int layout = R.layout.photo_item;
@ -61,7 +61,7 @@ public class MediaAdapter extends BaseAdapter {
return 0;
}
public void updateItems(List<Media> newPhotos) {
public void updateItems(List<Medium> newPhotos) {
media.clear();
media.addAll(newPhotos);
notifyDataSetChanged();

View File

@ -1,19 +1,23 @@
package com.simplemobiletools.gallery.adapters;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import com.simplemobiletools.gallery.Media;
import com.simplemobiletools.gallery.Constants;
import com.simplemobiletools.gallery.Medium;
import com.simplemobiletools.gallery.PhotoFragment;
import com.simplemobiletools.gallery.VideoFragment;
import com.simplemobiletools.gallery.ViewPagerFragment;
import java.util.List;
public class MyPagerAdapter extends FragmentStatePagerAdapter {
private List<Media> media;
private List<Medium> media;
private ViewPagerFragment fragment;
public MyPagerAdapter(FragmentManager fm, List<Media> media) {
public MyPagerAdapter(FragmentManager fm, List<Medium> media) {
super(fm);
this.media = media;
}
@ -28,17 +32,28 @@ public class MyPagerAdapter extends FragmentStatePagerAdapter {
if (fragment != null) {
fragment.fragmentHidden();
}
fragment = new ViewPagerFragment();
fragment.setMedium(media.get(position));
final Medium medium = media.get(position);
Bundle bundle = new Bundle();
bundle.putSerializable(Constants.MEDIUM, medium);
if (medium.getIsVideo()) {
fragment = new VideoFragment();
} else {
fragment = new PhotoFragment();
}
fragment.setArguments(bundle);
return fragment;
}
public void itemDragged() {
if (fragment != null)
if (fragment != null) {
fragment.itemDragged();
}
}
public void updateItems(List<Media> newPaths) {
public void updateItems(List<Medium> newPaths) {
media.clear();
media.addAll(newPaths);
notifyDataSetChanged();

View File

@ -2,7 +2,8 @@
<RelativeLayout android:id="@+id/video_holder"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:background="@android:color/black">
<SurfaceView
android:id="@+id/video_surface"