I am trying to fade in a TextureView but for some reason its not animating. It just simply pops in the video, no fade at all and i dont really know why that is because after some research i have found that TextureView can be animated normally.
Here is my code, i hope you guys can give me a pointer in the right direction.
PS, i have left out all irrelevant code that does not concern itself with the textureview and the animation.
public class MainActivity extends AppCompatActivity implements MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener
{
private static final String TAG = MainActivity.class.getSimpleName();
private MediaPlayer mediaPlayer1;
private ArrayList<Uri> videoUris = new ArrayList<>();
private int current_video_index = 0;
private TextureView textureView;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textureView = (TextureView) findViewById(R.id.textureView);
mediaPlayer1 = new MediaPlayer();
mediaPlayer1.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer1.setOnPreparedListener(this);
mediaPlayer1.setOnCompletionListener(this);
initVideoUris();
initNewVideo();
}
private void startVideo(final Uri uri)
{
textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener()
{
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height)
{
try {
mediaPlayer1.setDataSource(MainActivity.this, uri);
mediaPlayer1.setSurface(new Surface(surface));
mediaPlayer1.setOnCompletionListener(MainActivity.this);
mediaPlayer1.setOnPreparedListener(MainActivity.this);
mediaPlayer1.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer1.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height)
{
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface)
{
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surface)
{
}
});
}
#Override
public void onPrepared(MediaPlayer mp)
{
mp.start();
fadeInView(textureView);
}
#Override
public void onCompletion(MediaPlayer mp)
{
if (!moreVideosAvailable())
{
finish();
}
}
private boolean moreVideosAvailable()
{
return current_video_index < videoUris.size();
}
private void fadeInView(View view)
{
view.setAlpha(0f);
view.setVisibility(View.VISIBLE);
view.animate().alpha(1f).setDuration(2000).setListener(null).start();
}
}
I solved it by making a videoPlayerFragment that uses TextureView as the surface for displaying the video. Then simply animate the whole fragment instead of the textureView.
Related
I'm using below activity for Qr code scanning which helps to trun on and off the flash light.
Flash light on and off functionality is working fine.
But after turning off flash 5-10 sec some kind of black screen is visible.
How to resolve that Black screen?
public class CustomScannerActivity extends Activity implements
DecoratedBarcodeView.TorchListener {
private CaptureManager capture;
private DecoratedBarcodeView barcodeScannerView;
private Button switchFlashlightButton;
private ViewfinderView viewfinderView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_scanner);
barcodeScannerView = findViewById(R.id.zxing_barcode_scanner);
barcodeScannerView.setTorchListener(this);
switchFlashlightButton = findViewById(R.id.switch_flashlight);
viewfinderView = findViewById(R.id.zxing_viewfinder_view);
// if the device does not have flashlight in its camera,
// then remove the switch flashlight button...
if (!hasFlash()) {
switchFlashlightButton.setVisibility(View.GONE);
}
capture = new CaptureManager(this, barcodeScannerView);
capture.initializeFromIntent(getIntent(), savedInstanceState);
capture.setShowMissingCameraPermissionDialog(false);
capture.decode();
changeMaskColor(null);
changeLaserVisibility(true);
}
#Override
protected void onResume() {
super.onResume();
capture.onResume();
}
#Override
protected void onPause() {
super.onPause();
capture.onPause();
}
#Override
protected void onDestroy() {
super.onDestroy();
capture.onDestroy();
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
capture.onSaveInstanceState(outState);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return barcodeScannerView.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
}
/**
* Check if the device's camera has a Flashlight.
* #return true if there is Flashlight, otherwise false.
*/
private boolean hasFlash() {
return getApplicationContext().getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
}
public void switchFlashlight(View view) {
if (getString(R.string.turn_on_flashlight).equals(switchFlashlightButton.getText())) {
barcodeScannerView.setTorchOn();
} else {
barcodeScannerView.setTorchOff();
}
}
public void changeMaskColor(View view) {
Random rnd = new Random();
int color = Color.argb(100, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
viewfinderView.setMaskColor(color);
}
public void changeLaserVisibility(boolean visible) {
viewfinderView.setLaserVisibility(visible);
}
#Override
public void onTorchOn() {
switchFlashlightButton.setText(R.string.turn_off_flashlight);
}
#Override
public void onTorchOff() {
switchFlashlightButton.setText(R.string.turn_on_flashlight);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
capture.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
My application requires to post data to a custom view and redraw the view according to sent data from MainActivity.
Here are sample code.
Custom view->
public class custom_view extends View {
private simple_line line;
public custom_view(Context context) {
super(context);
line=new simple_line(0);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
line.draw_line(canvas);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(),getMeasuredHeight());
}
private class simple_line{
private float x_val;
private Paint mpaint;
public simple_line(float val){
x_val=val;
mpaint=new Paint();
mpaint.setColor(Color.RED);
mpaint.setStyle(Paint.Style.STROKE);
mpaint.setStrokeWidth(10);
}
public float getX_val() {
return x_val;
}
public void setX_val(float x_val) {
this.x_val = x_val;
invalidate();
}
public void draw_line(Canvas canvas){
Path mpath=new Path();
mpath.moveTo(getWidth()/2+x_val,0);
mpath.lineTo(getWidth()/2+x_val,getHeight());
mpath.close();
canvas.drawPath(mpath,mpaint);
}
}
public void update_xval(float val){
line.setX_val(val);
}
}
Here is Main activity->
public class MainActivity extends AppCompatActivity{
private Button button;
private custom_view myview;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=(Button)findViewById(R.id.mybutton);
myview=(custom_view)findViewById(R.id.myview);
myview=new custom_view(this);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myview.update_xval(100);
}
});
}
}
I am unable to update x_val when button is pressed.Where am I going wrong.What needs to be done to update x_val?
there is an issue in draw_line(Canvas canvas) function. you are not calling this function in custom_view. you need to invalidate() after draw_line(Canvas canvas)called.
I am working on a 2d game and I'm trying to make the view where I draw and update everything tell the activity that contains it that the game ended and display a pop-up on the screen. The problem is that I don't know how to access the method in the activity from the view because they work on different threads.
The code looks more or less like this and I want to access the method displayFrame() from the view class. The method in the real code does more operations with other textViews etc. that only the activity has access to.
public class MainActivity extends Activity{
private MyView myView;
RelativeLayout finalFrame;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myView = new MyView(this.getApplicationContext());
this.setContentView(myView);
finalFrame = (RelativeLayout) findViewById(R.id.framefinal);
}
private void displayFrame(){
this.finalFrame.setVisibility(View.VISIBLE);
}
}
public class MyView extends SurfaceView implements SurfaceHolder.Callback{
private MyThread myThread;
private boolean finished = false;
public MyView(Context context) {
super(context);
getHolder().addCallback(this);
this.myThread = new MyThread(getHolder(), this);
this.myThread.setRunning(true);
}
public void update() {
this.finished = someMethod();
if(this.finished){
MainActivity.displayFrame();
}
}
public void draw(Canvas canvas){
//draw something
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
public class MyThread extends Thread{
private MyView myView;
private SurfaceHolder surfaceHolder;
private boolean running = false;
private static Canvas canvas;
public MyThread(SurfaceHolder surfaceHolder, MyView myView){
super();
this.surfaceHolder = surfaceHolder;
this.myView = myView;
}
#Override
public void run(){
while(running){
canvas = null;
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
this.myView.update();
this.myView.draw(canvas);
}
} catch (Exception e) {e.printStackTrace();}
finally{
if(canvas!=null)
{
try {
surfaceHolder.unlockCanvasAndPost(canvas);
}
catch(Exception e){e.printStackTrace();}
}
}
}
}
public void setRunning(boolean running){
this.running = running;
}
}
The easiest way to do that is to define a listener interface in your view and make the activity implement it. Then you can notify the activity that your game has ended and execute the appropriate logic.
public class MyView extends SurfaceView implements SurfaceHolder.Callback {
// your other fields
private GameListener mGameListener;
public void setGameListener(GameListener gameListener) {
mGameListener = gameListener;
}
public void update() {
// your logic
if (mGameListener != null) {
// calling onGameEnd on the main thread
post(new Runnable() {
public void run() {
mGameListener.onGameEnd();
}
});
}
}
// rest of your class as it is
public interface GameListener {
void onGameEnded();
}
}
public class MainActivity extends Activity implements GameListener {
// the rest of your class
public void onGameEnded() {
// call the method you need
}
}
public class MyView extends SurfaceView implements SurfaceHolder.Callback{
private MyThread myThread;
private boolean finished = false;
private Context context;
public MyView(Context context) {
super(context);
this.context=context;
getHolder().addCallback(this);
this.myThread = new MyThread(getHolder(), this);
this.myThread.setRunning(true);
}
runOnUiThread(new Runnable(){
#Override
public void run(){
update();
}
});
public void update() {
this.finished = someMethod();
if(this.finished){
MainActivity mainActivity = (MainActivity) context;
mainActivity.displayFrame();
}
}
public void draw(Canvas canvas){
//draw something
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
Can you try this
I'm trying to make an app that draws a circle on a bitmap. Right now, I have a button that produces the circle. Instead, I would like to draw the circle where the user double-taps (instead of pressing a button). How can I do this programmatically? Here is the content of the activity so far:
public static final String KEY_PATH = "img.jpg";
private ZoomInZoomOut touch;
private Bitmap bitmap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_display);
Intent intent = getIntent();
String path = getIntent().getStringExtra(ImageDisplayActivity.KEY_PATH);
try {
java.io.FileInputStream in = this.openFileInput(path);
bitmap = BitmapFactory.decodeStream(in);
bitmap = bitmap.copy(bitmap.getConfig(), true);
touch = (ZoomInZoomOut)findViewById(R.id.IMAGEID);
touch = arrangeImageView(touch);
touch.setImageBitmap(bitmap);
in.close();
Button draw = (Button) findViewById(R.id.draw);
draw.setOnClickListener(new View.OnClickListener(){
public void onClick(View v)
{
Bitmap bmOverlay = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(),
bitmap.getConfig());
Canvas canvas = new Canvas(bmOverlay);
Paint p = new Paint();
p.setAntiAlias(true);
p.setColor(Color.BLUE);
p.setStrokeWidth(2);
p.setStyle(Paint.Style.STROKE);
canvas.drawBitmap(bitmap,new Matrix(),null);
canvas.drawCircle(1000, 1000, 20, p);
touch.setImageBitmap(bmOverlay);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
You have to implement GestureDetector and put your code in single/double click. Here you can replace button with bitmap.
TestActivity.java
iv.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//putyour first activity call.
}
}
iv.setOnTouchListener(new OnTouchListener() {
GestureDetector gestureDetector = new GestureDetector(new MyGestureDetector(context));
#Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
});
Now you have to create GestureDetector.java class.
public class MyGestureDetector extends SimpleOnGestureListener {
public Context context;
public String phno;
public MyGestureDetector(Context con)
{
this.context=con;
}
#Override
public boolean onDown(MotionEvent e) {
return super.onDown(e);
}
public MyGestureDetector(Context con) {
this.context=con;
}
#Override
public boolean onDoubleTap(MotionEvent e) {
System.out.println("in Double tap");
return true;
}
#Override
public boolean onSingleTapUp(MotionEvent e) {
System.out.println("in single tap up");
//put your second activity.
return super.onSingleTapUp(e);
}
}
I have a problem with code. I have two classes: MainActivity where i checking if sensor (in this case light sensor) is available and if yes - i try to get date from sensor from another class LightSensor, but result is always null. I think that i'm doing something wrong with listener but i don't know what.. and i'm sitting on this couple of hours and still nothing.. If you have any idea, please write and help me.
MainActivity class:
`public class MainActivity extends Activity implements EventListener {
SensorManager mSensorManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView wyswietl = (TextView)findViewById(R.id.res);
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
LightSensor mLightSensor = new LightSensor(getBaseContext());
if (mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT) != null){
//mLightSensor.register();
String newLux = mLightSensor.getLux();
wyswietl.setText("Light level: " + newLux);
}
else{
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}`
and in MainActivioty class i don't know it argument in constructor :
LightSensor mLightSensor = new LightSensor(getBaseContext()); is good...
LightSensor class:
`public class LightSensor implements SensorEventListener {
public SensorManager mSensorManagerx;
public Sensor lightManager;
public String lux;
Context context;
public LightSensor(Context context){
//public void onCreateLight(Context context){
this.context = context;
mSensorManagerx = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
lightManager = mSensorManagerx.getDefaultSensor(Sensor.TYPE_LIGHT);
}
public void register(){
mSensorManagerx.registerListener(this, lightManager, SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
lux = Float.toString(event.values[0]);
}
public String getLux(){
return lux;
}
public void unregister(){
mSensorManagerx.unregisterListener(this);
}
}`
You should not use a getter for this purpose, because the value your getting will be initialized after a unknown time. So it could still be null when you're calling the getLux method.
What you should do is use a listener pattern. I have changed your code a bit to give you an example implementation.
LightSensor:
public class LightSensor implements SensorEventListener {
public static interface LightSensorListener {
abstract void onLightSensorChanged(String lux);
}
private LightSensorListener listener;
private SensorManager mSensorManagerx;
private Sensor lightManager;
public LightSensor(Context context) {
mSensorManagerx = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
lightManager = mSensorManagerx.getDefaultSensor(Sensor.TYPE_LIGHT);
}
public void setListener(LightSensorListener listener) {
this.listener = listener;
}
public boolean register() {
return mSensorManagerx.registerListener(this, lightManager, SensorManager.SENSOR_DELAY_UI);
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
#Override
public void onSensorChanged(SensorEvent event) {
if (listener != null) {
listener.onLightSensorChanged(Float.toString(event.values[0]));
}
}
public void unregister() {
mSensorManagerx.unregisterListener(this);
}
}
Activity:
public class ActivityLightSensor extends Activity implements LightSensorListener {
private TextView text;
private LightSensor mLightSensor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView)findViewById(R.id.test);
mLightSensor = new LightSensor(getBaseContext());
mLightSensor.setListener(this);
}
#Override
public void onLightSensorChanged(String lux){
text.setText("Light level: " + lux);
}
#Override
protected void onResume() {
super.onStart();
if(!mLightSensor.register()){
Toast.makeText(this, "Light sensor not supported!", Toast.LENGTH_SHORT).show();
}
}
#Override
protected void onPause() {
super.onStop();
mLightSensor.unregister();
}
}
onSensorChanged event is not called just after you created listener. It is called after something will change sensot value, then it will be called. So you should implement some callback, or, as for me, better would be to implement SensorEventListener in your activity, then just in onSensorChanged event method call
wyswietl.setText("Light level: " + newLux);