Recording video in Android changes - android

I have a small problem when recording a video on my phone. I have followed this example to learn and get inspired:
http://examples.javacodegeeks.com/android/core/android-video-capture-example/
Based on that ( btw a good example), it seems that when recording a video, it changes the aspect a little bit but I want to avoid that.
Any advice?
Android code:
public class VideoPreivewFragment extends Fragment implements TextureView.SurfaceTextureListener, OnClickListener {
#InjectView(R.id.preview_movie)
TextureView mTextureView;
#InjectView(R.id.video_play_button)
ImageButton mButtonVideoPlay;
#InjectView(R.id.playMovie_afl)
AspectFrameLayout layout;
private MediaPlayer mMediaPlayer;
float mVideoHeight, mVideoWidth;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View viewRoot = inflater.inflate(R.layout.video_preview_screen, container, false);
ButterKnife.inject(this, viewRoot);
calculateVideoSize();
mTextureView.setSurfaceTextureListener(this);
Backendless.setUrl("https://api.backendless.com");
return viewRoot;
}
private void calculateVideoSize() {
try {
String videopath = ((VideoPreviewActivity) getActivity()).
fragmentArgumentToIntent(getArguments()).getStringExtra(Constants.TEMP_VIDEOPATH);
MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
metaRetriever.setDataSource(videopath);
String height = metaRetriever
.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
String width = metaRetriever
.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
mVideoHeight = Float.parseFloat(height);
mVideoWidth = Float.parseFloat(width);
} catch (Exception e) {
}
}
private void adjustAspectRatio(float videoWidth, float videoHeight) {
int viewWidth = layout.getWidth();
int viewHeight = layout.getHeight();
double aspectRatio = (double) videoHeight / videoWidth;
int newWidth, newHeight;
if (viewHeight > (int) (viewWidth * aspectRatio)) {
// limited by narrow width; restrict height
newWidth = viewWidth;
newHeight = (int) (viewWidth * aspectRatio);
} else {
// limited by short height; restrict width
newWidth = (int) (viewHeight / aspectRatio);
newHeight = viewHeight;
}
int xoff = (viewWidth - newWidth) / 2;
int yoff = (viewHeight - newHeight) / 2;
Matrix txform = new Matrix();
mTextureView.getTransform(txform);
txform.setScale((float) newWidth / viewWidth, (float) newHeight / viewHeight);
//txform.postRotate(10); // just for fun
txform.postTranslate(xoff, yoff);
mTextureView.setTransform(txform);
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onResume() {
super.onResume();
}
#Override
public void onPause() {
ButterKnife.reset(this);
super.onPause();
}
#Override
public void onStop() {
ButterKnife.reset(this);
super.onStop();
}
#Override
public void onDestroy() {
ButterKnife.reset(this);
if (mMediaPlayer != null) {
// Make sure we stop video and release resources when activity is destroyed.
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
}
super.onDestroy();
}
#Override
public void onDetach() {
super.onDetach();
}
#Override
#OnClick({R.id.preview_movie, R.id.video_play_button})
public void onClick(View view) {
if (view.getId() == R.id.video_play_button) {
} else if (view.getId() == R.id.preview_movie) {
if(mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
}
else {
mMediaPlayer.start();
}
}
}
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
Surface surface = new Surface(surfaceTexture);
try {
String videopath = ((VideoPreviewActivity) getActivity()).
fragmentArgumentToIntent(getArguments()).getStringExtra(Constants.TEMP_VIDEOPATH);
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDataSource(videopath);
mMediaPlayer.setSurface(surface);
// don't forget to call MediaPlayer.prepareAsync() method when you use constructor for
// creating MediaPlayer
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
int videoWidth = mMediaPlayer.getVideoWidth();
int videoHeight = mMediaPlayer.getVideoHeight();
DisplayMetrics displayMetrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int screenWidth = displayMetrics.widthPixels;
int screenHeight = displayMetrics.heightPixels;
float videoProportion = (float) videoWidth / (float) videoHeight;
float screenProportion = (float) screenWidth / (float) screenHeight;
ViewGroup.LayoutParams lp = layout.getLayoutParams();
if (videoProportion > screenProportion) {
lp.width = screenWidth;
lp.height = (int) (videoProportion * (float) screenHeight);
lp.height = screenHeight;
}
layout.setLayoutParams(lp);
mediaPlayer.start();
}
});
mTextureView.setFitsSystemWindows(true);
} catch (IllegalArgumentException | IllegalStateException | SecurityException | IOException e) {
}
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
}
}
layout file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.awesome.kkh.theelevator.layout.AspectFrameLayout
android:id="#+id/playMovie_afl"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/control"
android:layout_centerInParent="true" >
<TextureView
android:id="#+id/preview_movie"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal"
android:layout_gravity="center"
/>
</com.awesome.kkh.theelevator.layout.AspectFrameLayout>
<FrameLayout
android:id="#+id/control"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:background="#color/color_darker_background">
<ImageButton
android:id="#+id/video_play_button"
android:layout_width="55dp"
android:layout_height="55dp"
android:layout_gravity="center"
android:background="#drawable/circlebutton"
android:src="#drawable/ic_fa_play" />
</FrameLayout>
</RelativeLayout>

Related

Auto moving TextView across the screen

I am trying to make TextView which moves across the screen in all directions randomly using translateAnimation. I need text moving like in screen saver for example going round and round until it is clicked.But have some problems:
1. text moves just from top to bottom
2.it doesn't stop in screen borders , it is going off the screen then coming back again :
public class aktivityStarted extends AppCompatActivity {
TextView textMovin;
/* int loc[]=new int[2];
int x=loc[0];
int y=loc[1];*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_aktivity_started);
textMovin=findViewById(R.id.movingText);
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
final int width = displaymetrics.widthPixels-textMovin.getWidth();
final int height = displaymetrics.heightPixels-textMovin.getHeight();
final Random r = new Random();
final int translationX = r.nextInt(width);
final int translationY = r.nextInt(height);
final int randomx=r.nextInt(50)+1;
final int randomy=r.nextInt(50)+1;
final TranslateAnimation anim = new TranslateAnimation(-translationX,translationX ,-translationY,translationY ); //Use current view position instead of `currentX` and `currentY`
anim.setDuration(2500);
anim.setRepeatCount(-1);
anim.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
anim.reset();
anim.setRepeatMode(Animation.REVERSE);
anim.setFillAfter(true);
}
#Override
public void onAnimationRepeat(Animation animation) {
textMovin.setY(r.nextInt(height));
textMovin.setX(r.nextInt(width));
anim.start();
}
});
textMovin.startAnimation(anim);
}
}
try this code:
public class MainActivity extends AppCompatActivity {
private View parent;
private TextView textMovin;
private float speedX;
private float speedY;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textMovin = findViewById(R.id.textV);
parent = findViewById(R.id.parent);
final Random r = new Random();
speedX = r.nextFloat() * 200;
speedY = r.nextFloat() * 200;
parent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
final int width = parent.getWidth() - textMovin.getWidth();
final int height = parent.getHeight() - textMovin.getHeight();
final int period = 50;
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
textMovin.post(new TimerTask() {
#Override
public void run() {
textMovin.setX(speedX * period / 1000.0f + textMovin.getX());
textMovin.setY(speedY * period / 1000.0f + textMovin.getY());
if (textMovin.getY() <= 0 || textMovin.getY() >= height)
speedY *= -1;
if (textMovin.getX() <= 0 || textMovin.getX() >= width)
speedX *= -1;
}
});
}
}, 50, period);
}
});
findViewById(R.id.random).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Random r = new Random();
speedX = r.nextFloat() * 200;
speedY = r.nextFloat() * 200;
}
});
}
}
and the layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="#+id/textV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Hello World!" />
<Button
android:id="#+id/random"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="10dp"
android:text="Random" />
</RelativeLayout>
Hope it works for you.
public class OnDragTouchListener implements View.OnTouchListener {
/**
* Callback used to indicate when the drag is finished
*/
public interface OnDragActionListener {
/**
* Called when drag event is started
*
* #param view The view dragged
*/
void onDragStart(View view);
/**
* Called when drag event is completed
*
* #param view The view dragged
*/
void onDragEnd(View view);
}
private View mView;
private View mParent;
private boolean isDragging;
private boolean isInitialized = false;
private int width;
private float xWhenAttached;
private float maxLeft;
private float maxRight;
private float dX;
private int height;
private float yWhenAttached;
private float maxTop;
private float maxBottom;
private float dY;
private OnDragActionListener mOnDragActionListener;
public OnDragTouchListener(View view) {
this(view, (View) view.getParent(), null);
}
public OnDragTouchListener(View view, View parent) {
this(view, parent, null);
}
public OnDragTouchListener(View view, OnDragActionListener onDragActionListener) {
this(view, (View) view.getParent(), onDragActionListener);
}
public OnDragTouchListener(View view, View parent, OnDragActionListener onDragActionListener) {
initListener(view, parent);
setOnDragActionListener(onDragActionListener);
}
public void setOnDragActionListener(OnDragActionListener onDragActionListener) {
mOnDragActionListener = onDragActionListener;
}
public void initListener(View view, View parent) {
mView = view;
mParent = parent;
isDragging = false;
isInitialized = false;
}
public void updateBounds() {
updateViewBounds();
updateParentBounds();
isInitialized = true;
}
public void updateViewBounds() {
width = mView.getWidth();
xWhenAttached = mView.getX();
dX = 0;
height = mView.getHeight();
yWhenAttached = mView.getY();
dY = 0;
}
public void updateParentBounds() {
maxLeft = 0;
maxRight = maxLeft + mParent.getWidth();
maxTop = 0;
maxBottom = maxTop + mParent.getHeight();
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if (isDragging) {
float[] bounds = new float[4];
// LEFT
bounds[0] = event.getRawX() + dX;
if (bounds[0] < maxLeft) {
bounds[0] = maxLeft;
}
// RIGHT
bounds[2] = bounds[0] + width;
if (bounds[2] > maxRight) {
bounds[2] = maxRight;
bounds[0] = bounds[2] - width;
}
// TOP
bounds[1] = event.getRawY() + dY;
if (bounds[1] < maxTop) {
bounds[1] = maxTop;
}
// BOTTOM
bounds[3] = bounds[1] + height;
if (bounds[3] > maxBottom) {
bounds[3] = maxBottom;
bounds[1] = bounds[3] - height;
}
switch (event.getAction()) {
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
onDragFinish();
break;
case MotionEvent.ACTION_MOVE:
mView.animate().x(bounds[0]).y(bounds[1]).setDuration(0).start();
break;
}
return true;
} else {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isDragging = true;
if (!isInitialized) {
updateBounds();
}
dX = v.getX() - event.getRawX();
dY = v.getY() - event.getRawY();
if (mOnDragActionListener != null) {
mOnDragActionListener.onDragStart(mView);
}
return true;
}
}
return false;
}
private void onDragFinish() {
if (mOnDragActionListener != null) {
mOnDragActionListener.onDragEnd(mView);
}
dX = 0;
dY = 0;
isDragging = false;
}
}
And you can set it using:
myView.setOnTouchListener(new OnDragTouchListener(myView));
Or by adding this directly in init method of your Custom View:
setOnTouchListener(new OnDragTouchListener(this));

How to add media controller on VLC android programatically

I want to to add the media controller on VLC player android integration but i didn't find any option to do that i am sharing the code -
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.otherformat);
load = (ProgressBar) this.findViewById(R.id.load);
intent = getIntent();
load.setVisibility(View.VISIBLE);
handler = new Handler();
mFilePath ="http://mm2.pcslab.com/mm/7h800.mp4";
Log.e(TAG, "Playing: " + mFilePath);
mSurface = (SurfaceView) findViewById(R.id.surface);
holder = mSurface.getHolder();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setSize(mVideoWidth, mVideoHeight);
}
#Override
protected void onResume() {
super.onResume();
createPlayer(mFilePath);
}
#Override
protected void onPause() {
super.onPause();
releasePlayer();
}
#Override
protected void onDestroy() {
super.onDestroy();
releasePlayer();
}
/**
* Used to set size for SurfaceView
*
* #param width
* #param height
*/
private void setSize(int width, int height) {
mVideoWidth = width;
mVideoHeight = height;
if (mVideoWidth * mVideoHeight <= 1)
return;
if (holder == null || mSurface == null)
return;
int w = getWindow().getDecorView().getWidth();
int h = getWindow().getDecorView().getHeight();
boolean isPortrait = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
if (w > h && isPortrait || w < h && !isPortrait) {
int i = w;
w = h;
h = i;
}
float videoAR = (float) mVideoWidth / (float) mVideoHeight;
float screenAR = (float) w / (float) h;
if (screenAR < videoAR)
h = (int) (w / videoAR);
else
w = (int) (h * videoAR);
holder.setFixedSize(mVideoWidth, mVideoHeight);
ViewGroup.LayoutParams lp = mSurface.getLayoutParams();
lp.width = w;
lp.height = h;
mSurface.setLayoutParams(lp);
mSurface.invalidate();
}
/**
* Creates MediaPlayer and plays video
*
* #param media
*/
private void createPlayer(String media) {
releasePlayer();
try {
if (media.length() > 0) {
Toast toast = Toast.makeText(this, media, Toast.LENGTH_LONG);
toast.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0,
0);
//toast.show();
}
// Create LibVLC
// TODO: make this more robust, and sync with audio demo
ArrayList<String> options = new ArrayList<String>();
//options.add("--subsdec-encoding <encoding>");
options.add("--aout=opensles");
options.add("--audio-time-stretch"); // time stretching
options.add("-vvv"); // verbosity
libvlc = new LibVLC(this, options);
holder.setKeepScreenOn(true);
// Creating media player
mMediaPlayer = new MediaPlayer(libvlc);
mMediaPlayer.setEventListener(mPlayerListener);
mMediaPlayer.setVideoTrackEnabled(true);
// Seting up video output
final IVLCVout vout = mMediaPlayer.getVLCVout();
vout.setVideoView(mSurface);
//vout.setSubtitlesView(mSurfaceSubtitles);
vout.addCallback(this);
vout.attachViews();
Media m = new Media(libvlc, Uri.parse(media));
mMediaPlayer.setMedia(m);
mMediaPlayer.play();
////////////////////////////////////////////////
/* //mController = new MediaController(this);
mController = (MediaController)findViewById(R.id.mediaController);
mController.setVisibility(View.VISIBLE);
mController.setAnchorView(mSurface);
mController.show(0);*/
/*mController = new MediaController(this);
mController.setAnchorView(mSurface);
handler.post(new Runnable() {
public void run() {
mController.show();
}
});*/
} catch (Exception e) {
Log.e("Err", e.getMessage()+"");
Toast.makeText(this, "Error in creating player!"+e.getMessage(), Toast
.LENGTH_LONG).show();
}
}
private void releasePlayer() {
if (libvlc == null)
return;
mMediaPlayer.stop();
final IVLCVout vout = mMediaPlayer.getVLCVout();
vout.removeCallback(this);
vout.detachViews();
holder = null;
libvlc.release();
libvlc = null;
mVideoWidth = 0;
mVideoHeight = 0;
}
/**
* Registering callbacks
*/
private MediaPlayer.EventListener mPlayerListener = new MyPlayerListener(this);
#Override
public void onNewLayout(IVLCVout vout, int width, int height, int visibleWidth, int visibleHeight, int sarNum, int sarDen) {
if (width * height == 0)
return;
// store video size
mVideoWidth = width;
mVideoHeight = height;
setSize(mVideoWidth, mVideoHeight);
}
#Override
public void onSurfacesCreated(IVLCVout vout) {
}
#Override
public void onSurfacesDestroyed(IVLCVout vout) {
}
#Override
public void onHardwareAccelerationError(IVLCVout vlcVout) {
Log.e(TAG, "Error with hardware acceleration");
this.releasePlayer();
Toast.makeText(this, "Error with hardware acceleration", Toast.LENGTH_LONG).show();
}
private static class MyPlayerListener implements MediaPlayer.EventListener {
private WeakReference<OtherFormat> mOwner;
public MyPlayerListener(OtherFormat owner) {
mOwner = new WeakReference<OtherFormat>(owner);
}
#Override
public void onEvent(MediaPlayer.Event event) {
OtherFormat player = mOwner.get();
switch (event.type) {
case MediaPlayer.Event.EndReached:
Log.d(TAG, "MediaPlayerEndReached");
player.releasePlayer();
break;
case MediaPlayer.Event.Playing:
load.setVisibility(View.GONE);
break;
case MediaPlayer.Event.Paused:
case MediaPlayer.Event.Buffering:
float percent = event.getBuffering(); /* from 0.0f to 100f */
Log.e("Percent><><",""+percent);
break;
case MediaPlayer.Event.Stopped:
default:
break;
}
}
}}
XML for this activity -
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<SurfaceView
android:id="#+id/surface"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center" />
<ProgressBar
android:id="#+id/load"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:visibility="visible"
android:layout_gravity="center"
/>
<MediaController
android:id="#+id/mediaController"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" >
</MediaController>
</FrameLayout>
By this code mediacontrollers not showing please help me how to show media controllers for pause, play and seekbar for video position in surfaceview of vlc media player.
I had the same issue and have found a solution.
Sure, it's too late for answer, but maybe I will save some time to someone.
To add default media control you need to implement it in following way
remove MediaController from layout and add some container for media control to to your activity (it will be added programmatically).
<FrameLayout
android:id="#+id/video_surface_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:foregroundGravity="clip_horizontal|clip_vertical"
tools:ignore="true">
<SurfaceView
android:id="#+id/surface"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center" />
</FrameLayout>
add controller init to onStart activity or to onCreate
import android.widget.MediaController;
private MediaController controller;
#Override
protected void onStart() {
super.onStart();
....
controller = new MediaController(this);
controller.setMediaPlayer(findViewByid(R.id.video_surface_frame));
controller.setAnchorView(mVideoSurfaceFrame);
mVideoSurfaceFrame.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
controller.show(10000);
}
});
}
to define playerInterface, you need to implement the MediaController.MediaPlayerControl interface like this
private MediaController.MediaPlayerControl playerInterface = new MediaController.MediaPlayerControl() {
public int getBufferPercentage() {
return 0;
}
public int getCurrentPosition() {
float pos = mLibVlc.getPosition();
return (int)(pos * getDuration());
}
public int getDuration() {
return (int)mLibVlc.getLength();
}
public boolean isPlaying() {
return mLibVlc.isPlaying();
}
public void pause() {
mLibVlc.pause();
}
public void seekTo(int pos) {
mLibVlc.setPosition((float)pos / getDuration());
}
public void start() {
mLibVlc.play();
}
public boolean canPause() {
return true;
}
public boolean canSeekBackward() {
return true;
}
public boolean canSeekForward() {
return true;
}
#Override
public int getAudioSessionId() {
return 0;
}
};
launch your app and tap on video. You will see default media control and it will hide in 10 sec
Good luck!
Link to VideoLan sample on github:
https://code.videolan.org/videolan/vlc-android/blob/f3db2e4a33bf96c03056874322fb5b9304f92259/vlc-android/src/vlc/android/VLC.java
public class Show_Array extends AppCompatActivity implements IVLCVout.Callback {
private TextView container_extension;
private String stream_typee,stream_idd,container_extensionn ;
private String SAMPLE_URL = "";
public int mHeight;
public int mWidth;
private SurfaceView mVideoSurface = null;
private FrameLayout sdk;
private IVLCVout vlcVout;
private LibVLC mLibVlc = null;
private MediaPlayer mMediaPlayer = null;
private int flag = 0;
private ImageButton Resize;
private Media media;
private ArrayList<String> args;
private SurfaceHolder mSurfaceHolderVideo;
private MediaController controller;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.show__array);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
//Referances
Resize = findViewById(R.id.Resize);
mVideoSurface = findViewById(R.id.video_surface);
stream_typee = getIntent().getExtras().getString("stream_type");
stream_idd = getIntent().getExtras().getString("stream_id");
container_extensionn = getIntent().getExtras().getString("container_extension");
args = new ArrayList<>();
args.add("-vvv");
mLibVlc = new LibVLC(this, args);
mMediaPlayer = new MediaPlayer(mLibVlc);
vlcVout = mMediaPlayer.getVLCVout();
sdk = findViewById(R.id.sdk);
Resize_video();
setup_url();
controller = new MediaController(this);
controller.setMediaPlayer(playerInterface);
controller.setAnchorView(mVideoSurface);
mVideoSurface.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
controller.show(10000);
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
mMediaPlayer.release();
mLibVlc.release();
}
void Resize_video()
{
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
mHeight = displayMetrics.heightPixels;
mWidth = displayMetrics.widthPixels;
Resize.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
flag+=1;
int width = 1000;
int height = 560;
if(flag%2!=0) {
LinearLayout.LayoutParams myImageLayout = new LinearLayout.LayoutParams(width, height);
myImageLayout.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL;
sdk.setLayoutParams(myImageLayout);
vlcVout.setWindowSize(width,height);
}
else
{
LinearLayout.LayoutParams myImageLayout = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
myImageLayout.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL;
sdk.setLayoutParams(myImageLayout);
vlcVout.setWindowSize(mWidth,mHeight);
}
}
});
}
void setup_url()
{
//TextView
container_extension = findViewById(R.id.URL);
if (stream_typee.equals("live"))
{
SAMPLE_URL = "http://uautv.ru:2095/"+stream_typee+"/webserver/6tE#BzW73#sX/"+stream_idd+".ts";
container_extension.setText( SAMPLE_URL);
}else
{
SAMPLE_URL = "http://uautv.ru:2095/"+stream_typee+"/webserver/6tE#BzW73#sX/"+stream_idd+"."+container_extensionn;
container_extension.setText( SAMPLE_URL);
}
}
#Override
protected void onStart() {
super.onStart();
vlcVout.setWindowSize(mWidth,mHeight);
vlcVout.setVideoView(mVideoSurface);
vlcVout.attachViews();
mMediaPlayer.getVLCVout().addCallback(this);
if(!SAMPLE_URL.isEmpty()) {
media = new Media(mLibVlc, Uri.parse(SAMPLE_URL));
mMediaPlayer.setMedia(media);
media.release();
mMediaPlayer.play();
}else
{
Toast.makeText(getApplicationContext(),"URL EMPTY",Toast.LENGTH_LONG).show();
}
}
#Override
protected void onStop() {
super.onStop();
mMediaPlayer.stop();
mMediaPlayer.getVLCVout().detachViews();
mMediaPlayer.getVLCVout().removeCallback(this);
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
#Override
public void onNewLayout(IVLCVout vlcVout, int width, int height, int visibleWidth, int visibleHeight, int sarNum, int sarDen)
{ }
#Override
public void onSurfacesCreated(IVLCVout vlcVout) {
}
#Override
public void onSurfacesDestroyed(IVLCVout vlcVout) {
}
private MediaController.MediaPlayerControl playerInterface = new MediaController.MediaPlayerControl() {
public int getBufferPercentage() {
return 0;
}
public int getCurrentPosition() {
float pos = mMediaPlayer.getPosition();
return (int)(pos * getDuration());
}
public int getDuration() {
return (int)mMediaPlayer.getLength();
}
public boolean isPlaying() {
return mMediaPlayer.isPlaying();
}
public void pause() {
mMediaPlayer.pause();
}
public void seekTo(int pos) {
mMediaPlayer.setPosition((float)pos / getDuration());
}
public void start() {
mMediaPlayer.play();
}
public boolean canPause() {
return true;
}
public boolean canSeekBackward() {
return true;
}
public boolean canSeekForward() {
return true;
}
#Override
public int getAudioSessionId() {
return 0;
}
};
}

Media Controller in fragments

I'm trying to make a media controller in Android studio but using a fragment instead of an activity, I'm using the code below, but it gives me the following error :
public class Tab1Helloworld extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.tab1helloworld, container, false);
return rootView;
VideoView video = (VideoView)rootView.findViewById(R.id.videoView);
video.requestFocus();
String videopath = "android.resource://com.r.teamkape.kiddiecodiel/" + R.raw.helloworldvid;
video.setVideoURI(Uri.parse(videopath));
video.setMediaController(new MediaController(this)); //error in (this)[enter image description here][1]
video.requestFocus();
video.start();
}
}
public class Tab1Helloworld extends Fragment
{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{ View rootView = inflater.inflate(R.layout.tab1helloworld,container, false);
VideoView video = (VideoView)rootView.findViewById(R.id.videoView);
video.requestFocus();
String videopath = "android.resource://com.r.teamkape.kiddiecodiel/" + R.raw.helloworldvid;
video.setVideoURI(Uri.parse(videopath));
video.setMediaController(new MediaController(getActivity())); //error in (this)[enter image description here][1]
video.requestFocus();
video.start();
return rootView;
}
}
#xhen, Use below code this works perfect,
in xml layout add this
<sg.xyz.test.util.CustomVideoView
android:id="#+id/videoview"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
/>
in your Fragment class call these medthods
private MediaController mediaController;
private Uri uri;
public void setupVideo(){
if (mediaController == null) {
mediaController = new
MediaController(mContext);
mediaController.setAnchorView(mBinding.videoview);
mBinding.videoview.setMediaController(mediaController);
}
try {
uri = Util.buildURiPath(resourceID);
mBinding.videoview.setVideoURI(uri);
} catch (Exception e) {
Logger.debug("Error: " + e.getMessage());
e.printStackTrace();
}
mBinding.videoview.requestFocus();
mBinding.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mBinding.videoview.start();
mBinding.imageView.setVisibility(View.INVISIBLE);
}
});
mBinding.videoview.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
#Override
public void onVideoSizeChanged(MediaPlayer mediaPlayer, int width, int height) {
mediaController.setAnchorView(mBinding.videoview);
}
});
Logger.debug("Duration = " +
mBinding.videoview.getDuration());
}
});
mBinding.videoview.setOnErrorListener(new MediaPlayer.OnErrorListener() {
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
AlertDialogFactory.buildAlertDialog(mContext, 0, R.string.video_playing_error).show();
return false;
}
});
}
public static Uri buildURiPath(int resourceID)
{
String uriPath = String.valueOf(Uri.parse("android.resource://" + LoginActivity.PACKAGE_NAME + "/"
+resourceID));
Uri uri = Uri.parse(uriPath);
return uri;
}
Replace this mBinding.videoview with your video object that's it.
Now, Create CustomVideoView class
public class CustomVideoView extends VideoView {
private int width;
private int height;
private Context context;
private VideoSizeChangeListener listener;
private boolean isFullscreen;
public CustomVideoView(Context context) {
super(context);
init(context);
}
public CustomVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
/**
* get video screen width and height for calculate size
*
* #param context Context
*/
private void init(Context context) {
this.context = context;
setScreenSize();
}
/**
* calculate real screen size
*/
private void setScreenSize() {
Display display = ((Activity) context).getWindowManager().getDefaultDisplay();
if (Build.VERSION.SDK_INT >= 17) {
//new pleasant way to get real metrics
DisplayMetrics realMetrics = new DisplayMetrics();
display.getRealMetrics(realMetrics);
width = realMetrics.widthPixels;
height = realMetrics.heightPixels;
} else if (Build.VERSION.SDK_INT >= 14) {
//reflection for this weird in-between time
try {
Method mGetRawH = Display.class.getMethod("getRawHeight");
Method mGetRawW = Display.class.getMethod("getRawWidth");
width = (Integer) mGetRawW.invoke(display);
height = (Integer) mGetRawH.invoke(display);
} catch (Exception e) {
//this may not be 100% accurate, but it's all we've got
width = display.getWidth();
height = display.getHeight();
}
} else {
//This should be close, as lower API devices should not have window navigation bars
width = display.getWidth();
height = display.getHeight();
}
// when landscape w > h, swap it
if (width > height) {
int temp = width;
width = height;
height = temp;
}
}
/**
* set video size change listener
*
*/
public void setVideoSizeChangeListener(VideoSizeChangeListener listener) {
this.listener = listener;
}
public interface VideoSizeChangeListener {
/**
* when landscape
*/
void onFullScreen();
/**
* when portrait
*/
void onNormalSize();
}
#Override
public void setVideoURI(Uri uri) {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(this.getContext(), uri);
width = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
height = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
super.setVideoURI(uri);
super.setVideoURI(uri);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
// full screen when landscape
setSize(height, width);
if (listener != null) listener.onFullScreen();
isFullscreen = true;
} else {
// height = width * 9/16
setSize(width, width * 9 / 16);
if (listener != null) listener.onNormalSize();
isFullscreen = false;
}
}
/**
* #return true: fullscreen
*/
public boolean isFullscreen() {
return isFullscreen;
}
/**
* set video sie
*
* #param w Width
* #param h Height
*/
private void setSize(int w, int h) {
setMeasuredDimension(w, h);
getHolder().setFixedSize(w, h);
}
}
the issue from the error you added
flag Error:(33, 54) error: incompatible types: Tab1Helloworld cannot be converted to Context
is in this line
replace
video.setMediaController(new MediaController(this));
with
video.setMediaController(new MediaController(getActivity()));
also move
return rootView;
to the end of the method after starting the video

Viewpager shows entire next slide over Fragment when bringing a slide with a VideoView

Hi Stackoverflow.
I've been trying to handle this issue for two days now.
We have a UnswipableViewPager, which is a custom implementation of ViewPager to intercept touch events and stop 'em (and nothing else), and right by it's right side we have a FrameLayout that we want to replace (through a FragmentTransaction) with our fragment. Nothing out of ordinary here if it wasn't for the fact our ViewPager has to shrink to fit the new Fragment. We have a custom implementation of RelativeLayout called ResizableLayout which we use to do that. It works ok with images, mind you, it's when we're loading a slide with a video, through a VideoView, that the issues pop.
This is how it looks from a design perspective. First we have it unshrunk, then we have it shrunk correctly, and last we have what happens whenever I try to load a slide with a VideoView inside it.
The snippet from the XML layout file:
<RelativeLayout
android:id="#+id/content_relative_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clipChildren="false"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true">
<br.com.i9algo.taxiadv.v2.views.widgets.ResizableLayout
android:id="#+id/slideshow_frame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:clickable="true"
android:clipChildren="false"
android:orientation="horizontal"
android:scaleType="fitXY"
layout="#layout/slideshow_item_fragment">
<mypackage.widgets.UnswipableViewPager
android:id="#+id/playlist_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
layout="#layout/slideshow_item_fragment"
android:clipChildren="false"
android:clickable="true"
android:scaleType="fitXY"
/>
</mypackage.widgets.ResizableLayout>
<FrameLayout
android:id="#+id/sidebar_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:clipChildren="false"
android:layout_toEndOf="#+id/slideshow_frame"
android:scaleType="fitXY" />
</RelativeLayout>
Our ResizableLayout class:
public class ResizableLayout extends RelativeLayout {
private int originalHeight = 0;
private int originalWidth = 0;
private int minWidth = 0;
private static final float SLIDE_TOP = 0f;
private static final float SLIDE_BOTTOM = 1f;
private boolean mMinimized = false;
public ResizableLayout(Context context) {
this(context, null, 0);
}
public ResizableLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ResizableLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
if (!isInEditMode()) {
minWidth = getContext().getResources().getDimensionPixelSize(R.dimen.playlist_min_width);
}
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
}
public boolean smoothSlideTo(#NonNull float slideOffset) {
final int topBound = getPaddingTop();
int x = (int) (slideOffset * (getWidth() - getOriginalWidth()));
int y = (int) (topBound + slideOffset * getVerticalDragRange());
ViewCompat.postInvalidateOnAnimation(this);
return true;
}
public void minimize() {
if (isMinimized())
return;
mMinimized = true;
try {
ResizeAnimation resizeAnimation = new ResizeAnimation(this, minWidth, getOriginalHeight(), false);
resizeAnimation.setDuration(500);
resizeAnimation.setTopMargin(20);
setAnimation(resizeAnimation);
smoothSlideTo(SLIDE_BOTTOM);
requestLayout();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void maximize() {
if (isMaximized())
return;
mMinimized = false;
try {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) getLayoutParams();
params.width = getOriginalWidth();
params.topMargin = 0;
setLayoutParams(params);
measure(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
smoothSlideTo(SLIDE_TOP);
requestLayout();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public int getOriginalHeight() {
if (originalHeight == 0) {
originalHeight = getMeasuredHeight();
}
return originalHeight;
}
public int getOriginalWidth() {
if (originalWidth == 0) {
originalWidth = getMeasuredWidth();
}
return originalWidth;
}
public boolean isMinimized() {
return mMinimized;
}
public boolean isMaximized() {
return !mMinimized;
}
private float getVerticalDragRange() {
return getHeight() - getOriginalHeight();
}
This is ResizeAnimation in case anybody is wondering
public class ResizeAnimation extends Animation {
private final int mOriginalWidth;
private final int mOriginalHeight;
private final int mTargetWidth;
private final int mTargetHeight;
private int topMargin, leftMargin, bottomMargin, rightMargin;
private boolean mDown;
private View mView;
public ResizeAnimation(View view, int targetWidth, int targetHeight, boolean down) {
this.mView = view;
this.mTargetWidth = targetWidth;
this.mTargetHeight = targetHeight;
mOriginalWidth = view.getWidth();
mOriginalHeight = view.getHeight();
this.mDown = down;
}
public void setTopMargin(int value) {
this.topMargin = value;
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
int newWidth = (int) (mOriginalWidth + (mTargetWidth - mOriginalWidth) * interpolatedTime);
int newHeight = (int) (mOriginalHeight + (mTargetHeight - mOriginalHeight) * interpolatedTime);
if (mDown) {
newWidth = mTargetWidth;
newHeight = mTargetHeight;
}
mView.getLayoutParams().width = newWidth;
mView.getLayoutParams().height = newHeight;
try {
((RelativeLayout.LayoutParams) mView.getLayoutParams()).topMargin = topMargin;
((RelativeLayout.LayoutParams) mView.getLayoutParams()).leftMargin = leftMargin;
((RelativeLayout.LayoutParams) mView.getLayoutParams()).bottomMargin = bottomMargin;
((RelativeLayout.LayoutParams) mView.getLayoutParams()).rightMargin = rightMargin;
} catch (Exception e) {
e.printStackTrace();
}
mView.requestLayout();
//mView.invalidate();
}
#Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
}
#Override
public boolean willChangeBounds() {
return true;
}
}
And this is the method that handles the FragmentTransaction.
#Override
public void showSidebarFragment() {
resizableLayout.minimize();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.sidebar_frame, sidebarFragment, "sidebarFragment");
ft.commit();
mContentRelativeLayout.requestLayout();
sidebarframe.requestLayout();
}
Mind you that Sidebarframe is injected through Butterknife and sidebarFragment is injected through Dagger2 - we use the same instance of the fragment for everything.
I have no clue what's going on. I've tried several ways of bringing the Fragment to front but nothing seems to work. I'd love if anyone could give me a hand either on how to fix the issue or how to achieve the same effect through other means - whatever works.

Is it possible to set an animated gif file as live wallpaper in android?

I'm new to Android platform. I wish to develop a live wallpaper application. When i was searched regarding this in search Engine's, many of them created a live wallpaper as their code (using SurfaceView and Canvas), I'm not much aware in this. Here my doubt is, any possible to set a .gif images as a live wallpaper.
This is the basic wallpaper service (as supplied in the Live Wallpaper Tutorial) hacked to display an animated gif.
First - create a project & set up your manifest as a Live wallpaper.
Then - download a gif, like this one
Save that gif in res/raw/nyan.gif in your project.
Create a live wallpaper service, like shown in this example.
public class NyanNyanService extends WallpaperService {
static final String TAG = "NYAN";
static final Handler mNyanHandler = new Handler();
/**
* #see android.service.wallpaper.WallpaperService#onCreate()
*/
#Override
public void onCreate() {
super.onCreate();
}
/**
* #see android.service.wallpaper.WallpaperService#onCreateEngine()
*/
#Override
public Engine onCreateEngine() {
try {
return new NyanEngine();
} catch (IOException e) {
Log.w(TAG, "Error creating NyanEngine", e);
stopSelf();
return null;
}
}
class NyanEngine extends Engine {
private final Movie mNyan;
private final int mNyanDuration;
private final Runnable mNyanNyan;
float mScaleX;
float mScaleY;
int mWhen;
long mStart;
NyanEngine() throws IOException {
InputStream is = getResources().openRawResource(R.raw.nyan);
if (is != null) {
try {
mNyan = Movie.decodeStream(is);
mNyanDuration = mNyan.duration();
} finally {
is.close();
}
} else {
throw new IOException("Unable to open R.raw.nyan");
}
mWhen = -1;
mNyanNyan = new Runnable() {
public void run() {
nyan();
}
};
}
#Override
public void onDestroy() {
super.onDestroy();
mNyanHandler.removeCallbacks(mNyanNyan);
}
#Override
public void onVisibilityChanged(boolean visible) {
super.onVisibilityChanged(visible);
if (visible) {
nyan();
} else {
mNyanHandler.removeCallbacks(mNyanNyan);
}
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
mScaleX = width / (1f * mNyan.width());
mScaleY = height / (1f * mNyan.height());
nyan();
}
#Override
public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep,
float yOffsetStep, int xPixelOffset, int yPixelOffset) {
super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep, xPixelOffset, yPixelOffset);
nyan();
}
void nyan() {
tick();
SurfaceHolder surfaceHolder = getSurfaceHolder();
Canvas canvas = null;
try {
canvas = surfaceHolder.lockCanvas();
if (canvas != null) {
nyanNyan(canvas);
}
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
mNyanHandler.removeCallbacks(mNyanNyan);
if (isVisible()) {
mNyanHandler.postDelayed(mNyanNyan, 1000L/25L);
}
}
void tick() {
if (mWhen == -1L) {
mWhen = 0;
mStart = SystemClock.uptimeMillis();
} else {
long mDiff = SystemClock.uptimeMillis() - mStart;
mWhen = (int) (mDiff % mNyanDuration);
}
}
void nyanNyan(Canvas canvas) {
canvas.save();
canvas.scale(mScaleX, mScaleY);
mNyan.setTime(mWhen);
mNyan.draw(canvas, 0, 0);
canvas.restore();
}
}
}
This will basically scale the nyan-nyan cat to fit the screen and animate it perpetually.
A Live wallpaper manifest looks sort-of-like this (this example does not contain a configuration activity):
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="your.nyan.nyan.package"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="10" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/application_nyan" >
<service
android:label="#string/wallpaper_nyan"
android:name=".NyanNyanService"
android:permission="android.permission.BIND_WALLPAPER">
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
</intent-filter>
<meta-data android:name="android.service.wallpaper" android:resource="#xml/nyan" />
</service>
</application>
</manifest>
The AndroidManifest.xml has a reference to a file in res/xml, in this case named "nyan.xml":
<?xml version="1.0" encoding="utf-8"?>
<wallpaper xmlns:android="http://schemas.android.com/apk/res/android" />
See this article: How to set gif as android live wallpaper - techprpr - Medium
Jens answer use "Movie" class, but Movie class is deprecated in android api 28
so when api >= 28, I use AnimatedImageDrawable instead
Setup live wallpaper like Jens answer, and I change wallpaper service code:
wallpaper service: AnimWallpaper
public class AnimWallpaper extends WallpaperService {
#Override
public Engine onCreateEngine() {
return new CustomEngine();
}
class CustomEngine extends Engine {
UseAnim useAnim;
public CustomEngine() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
useAnim = new UseAnim(getApplicationContext(), getSurfaceHolder(), R.raw.gif2);
}
}
#Override
public void onVisibilityChanged(boolean visible) {
super.onVisibilityChanged(visible);
if (visible) {
useAnim.restart();
} else {
useAnim.stop();
}
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
useAnim.updateScaleAndPadding2(width, height);
useAnim.restart();
}
#Override
public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, float yOffsetStep, int xPixelOffset, int yPixelOffset) {
super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep, xPixelOffset, yPixelOffset);
useAnim.restart();
}
#Override
public void onDestroy() {
super.onDestroy();
useAnim.stop();
}
}
}
UseAnim
class UseAnim {
SurfaceHolder holder;
Runnable startRunnable;
AnimatedImageDrawable gif;
float fps = 60;
Handler handler = new Handler();
#RequiresApi(api = Build.VERSION_CODES.P)
public UseAnim(Context ctx, SurfaceHolder holder, int gifResId) {
this.holder = holder;
final ImageDecoder.Source src = ImageDecoder.createSource(ctx.getResources(), gifResId);
startRunnable = new Runnable() {
#Override
public void run() {
start();
}
};
new Handler().post(new Runnable() {
#Override
public void run() {
try {
UseAnim.this.gif = (AnimatedImageDrawable) ImageDecoder.decodeDrawable(src);
} catch (IOException e) {
throw new RuntimeException(e);
}
UseAnim.this.gif.start();
}
});
}
public void restart() {
stop();
start();
}
float scale = -1;
public void start() {
// since get gif with AnimatedImageDrawable must be in handler.post, so gif maybe null
if (gif != null) {
Canvas canvas = null;
try {
if (scale == -1) {
updateScaleAndPadding();
}
canvas = holder.lockCanvas();
if (canvas != null) {
canvas.translate(horiPadding, vertiPadding);
canvas.scale(scale, scale);
gif.draw(canvas);
}
} finally {
if (canvas != null) {
holder.unlockCanvasAndPost(canvas);
}
}
}
handler.removeCallbacks(startRunnable);
handler.postDelayed(startRunnable, (long) (1000L / fps));
}
public void stop() {
handler.removeCallbacks(startRunnable);
}
int horiPadding;
int vertiPadding;
private void updateScaleAndPadding() {
Canvas canvas = null;
try {
canvas = holder.lockCanvas();
int cw = canvas.getWidth();
int ch = canvas.getHeight();
updateScaleAndPadding2(cw, ch);
} finally {
if (canvas != null) {
holder.unlockCanvasAndPost(canvas);
}
}
}
public void updateScaleAndPadding2(int cw, int ch) {
if (gif != null) {
int gifW = gif.getIntrinsicWidth();
int gifH = gif.getIntrinsicHeight();
if (gifW * 1f / gifH > cw * 1f / ch) {
scale = ch * 1f / gifH;
} else {
scale = cw * 1f / gifW;
}
horiPadding = (int) ((cw - gifW * scale) / 2);
vertiPadding = (int) ((ch - gifH * scale) / 2);
}
}
}

Categories

Resources