Java Android, attach guesture listener - java

I wrote Gesture Detector class and no try to add the gesture listener, it works fine when i call it in the onCreate() function for the activity_main view but i can't attach it to the invisible view with i create by button click.. Here is my code,
I receive no errors, it just don't listen, i can also set a onTouchListener() in the invisibleView class..
main
public class MainActivity extends Activity {
String TAG = "myTAG";
SocketClass mySocketClass;
View viewToWatch;
InvisibleView myInvisibleView;
Context myContext;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
savedInstanceState = new Bundle();
myInvisibleView = new InvisibleView();
/*
-----------------------------------------------------
this works, when i add the listener to the main view:
-----------------------------------------------------
viewToWatch= (View) findViewById(R.id.mainViewId);
viewToWatch.setOnTouchListener(new ClassGesturesDetection() {
public void returnSingleTapUp() {
Log.d ("Gesture from main View", "single tab");
}
});
-----------------------------------------------------
*/
}
public void startApp(View activity_main_view){
myInvisibleView.onCreate(this.getApplicationContext());
putOnTochListenerToInvsibleView();
}
public void putOnTochListenerToInvsibleView( ) {
/*
-----------------------------------------------------
there i want to add the listener:
-----------------------------------------------------
*/
setContentView(R.layout.invisibleviewxml);
viewToWatch= (View) findViewById(R.id.invisibleViewId);
viewToWatch.setOnTouchListener(new ClassGesturesDetection() {
public void returnSingleTapUp() {
Log.d ("Gesture from transparent view", "single tab");
}
});
}
}
here the class where i create the system overlay view:
public class InvisibleView extends Service {
View myView;
#Override
public IBinder onBind(Intent intent) {
return null;
}
public void onCreate(Context myContext) {
super.onCreate();
LayoutInflater inflater = (LayoutInflater) myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
myView = new View(myContext);
myView = inflater.inflate(R.layout.invisibleviewxml, null);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
WindowManager wm = (WindowManager) myContext.getSystemService(WINDOW_SERVICE);
wm.addView(myView, params);
/*
-----------------------------------------------------
this also works,the system overlay catches clicks
-----------------------------------------------------
myView.setOnTouchListener( new OnTouchListener() {
#Override
public boolean onTouch(View inviView, MotionEvent event) {
Log.d("Gesture", "simple touch from InvisibleView Class");
return true;
}
});
-----------------------------------------------------
this does not work
-----------------------------------------------------
myView.setOnTouchListener(new ClassGesturesDetection() {
public void returnSingleTapUp() {
Log.d ("Gesture from transparent", "single tab");
}
});
----------------------------------------------------- */
}
#Override
public void onDestroy() {
super.onDestroy();
if(myView != null)
{
((WindowManager) getSystemService(WINDOW_SERVICE)).removeView(myView);
myView = null;
}
}
}
here the my Class of Gesture Dedection:
public class ClassGesturesDetection implements OnTouchListener {
#SuppressWarnings("deprecation")
private final GestureDetector gestureDetector = new GestureDetector(new GestureListener());
public boolean onTouch(final View view, final MotionEvent motionEvent) {
return gestureDetector.onTouchEvent(motionEvent);
}
private final class GestureListener extends SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
#Override
public boolean onDown(MotionEvent e) {
//Log.d("class Gesture", "on Down");
return true;
}
#Override
public void onLongPress(MotionEvent e) {
returnOnLongPress();
}
#Override
public boolean onSingleTapUp(MotionEvent e) {
returnSingleTapUp();
return false;
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
boolean result = false;
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
onSwipeRight();
} else {
onSwipeLeft();
}
}
} else {
if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
onSwipeBottom();
} else {
onSwipeTop();
}
}
}
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
}
public void onSwipeRight() {
}
public void onSwipeLeft() {
}
public void onSwipeTop() {
}
public void onSwipeBottom() {
}
public void returnSingleTapUp() {
}
public void returnOnLongPress() {
}
}

you must add this permission
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
You can follow this
I had answered there for your question

Related

how can I match seekbar to the mediaplayer?

I have a Recyclerview that each item plays media and the media has been set with an seekbar that is connected to media player I mean that each item has a seekbar too, but the problem that I am facing is that when you play the media all seekbar work at the same time as other item and sometimes when I click the first media the seekbar of last item is working not the first item after I pause media player somehow work on seekbar but every time I play a new media the seekbar of other item start working
what can i do to solve this problem ? I would be very grateful if you could do any help
public class VersionAdapter3 extends RecyclerView.Adapter<VersionAdapter3.VersionViewholder> {
Context context;
private final List<Version3> versionsList;
private final MediaPlayer mediaPlayer ;
private Integer currentlyplayingindex=-1;
Runnable run;
Handler seekHandler = new Handler();
public VersionAdapter3(Context context, List<Version3> versionsList) {
this.context = context;
this.versionsList = versionsList;
this.mediaPlayer=new MediaPlayer();
mediaPlayer.setOnCompletionListener(mediaPlayer1 -> {});
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void setupMediaPlayer(){
mediaPlayer.setAudioAttributes(
new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.setUsage(AudioAttributes.USAGE_MEDIA)
.build()
);
}
private void onplaybtntapped(int newIndex){
if (newIndex !=currentlyplayingindex && currentlyplayingindex!=-1){
versionsList.get(currentlyplayingindex).setState(Version3.State.STOPPED);
notifyItemChanged(currentlyplayingindex);
mediaPlayer.stop();
}
if (newIndex == currentlyplayingindex){
if (mediaPlayer.isPlaying()){
versionsList.get(newIndex).setState(Version3.State.PAUSED);
mediaPlayer.pause();
}else {
versionsList.get(newIndex).setState(Version3.State.PLAYING);
mediaPlayer.start();
}
}else {
try {
currentlyplayingindex = newIndex;
Version3 version3 = versionsList.get(newIndex);
String datasource = version3.getSong();
version3.setState(Version3.State.PLAYING);
mediaPlayer.reset();
mediaPlayer.setDataSource(datasource);
mediaPlayer.prepare();
mediaPlayer.start();
}
catch (Exception e) {
e.printStackTrace();
}
}
notifyItemChanged(newIndex);
}
#Override
public void onViewAttachedToWindow(#NonNull VersionViewholder holder) {
super.onViewAttachedToWindow(holder);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
setupMediaPlayer();
}
}
#NonNull
#Override
public VersionViewholder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.raw3,parent,false);
return new VersionViewholder(view);
}
#Override
public void onBindViewHolder(#NonNull VersionViewholder holder, int position) {
Version3 version3 = versionsList.get(position);
holder.codeNameTxt.setText(version3.getCodeName());
holder.versionTxt.setText(version3.getVersion());
holder.descriptiontxt.setText(version3.getDescription());
holder.seekBar.setMax(mediaPlayer.getDuration());
holder.seekBar.setTag(position);
run = new Runnable() {
#Override
public void run() {
holder.seekBar.setProgress(mediaPlayer.getCurrentPosition());
seekHandler.postDelayed(run, 100);
}
};
run.run();
holder.adjustBtnTextByState(version3.getState());
holder.btnplay.setOnClickListener(view -> onplaybtntapped(position));
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
holder.btnplay.setText("play");
}
});
boolean isExpandable = versionsList.get(position).isExpandable();
holder.expandableLayout.setVisibility(isExpandable ? View.VISIBLE : View.GONE);
holder.seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
if (mediaPlayer != null && b) {
//holder.seekBar.setProgress(i);
mediaPlayer.seekTo(i);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
#Override
public int getItemCount() {
return versionsList.size();
}
public class VersionViewholder extends RecyclerView.ViewHolder {
TextView codeNameTxt, versionTxt, descriptiontxt;
LinearLayout linearLayout;
RelativeLayout expandableLayout;
Button btnplay;
SeekBar seekBar;
public VersionViewholder(#NonNull View itemView) {
super(itemView);
seekBar=itemView.findViewById(R.id.seekbar);
codeNameTxt = itemView.findViewById(R.id.codename);
versionTxt = itemView.findViewById(R.id.version);
descriptiontxt = itemView.findViewById(R.id.description);
btnplay = itemView.findViewById(R.id.track_play);
linearLayout = itemView.findViewById(R.id.linear);
expandableLayout = itemView.findViewById(R.id.expandable);
linearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Version3 version3 = versionsList.get(getAdapterPosition());
version3.setExpandable(!version3.isExpandable());
notifyItemChanged(getAdapterPosition());
}
});
}
#SuppressLint("SetTextI18n")
public void adjustBtnTextByState(Version3.State state){
switch (state){
case STOPPED:
btnplay.setText("play");
break;
case PLAYING:
btnplay.setText("playing");
break;
case PAUSED:
btnplay.setText("paused");
break;
}
}
}
}

How can I expand/collapse an EditText when I click on it?

I want to create an animation to expand an EditText when I click on it(to a height set by me), and when it loses focus(I click on something else) it should collapse back to one line. This is what I tried, but it kinda does nothing..
public class CollapseDownAnimation extends Animation {
private EditText mDescription;
private boolean mDown;
public CollapseDownAnimation(EditText description, boolean down) {
this.mDescription=description;
this.mDown=down;
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation transformation) {
int newHeight;
if(mDown) {
newHeight=(int) (300 * interpolatedTime);
} else {
newHeight=(int) (300 * (1-interpolatedTime));
}
mDescription.getLayoutParams().height=newHeight;
mDescription.requestLayout();
}
#Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
}
#Override
public boolean willChangeBounds() {
return true;
}
}
EditText mDescription;
mDescription = view.findViewById(R.id.description);
CollapseDownAnimation anim = new CollapseDownAnimation(mDescription, mDescription.hasFocus());
anim.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
Log.d(TAG, "the focus is "+mDescription.hasFocus());
mDescription.setAnimation(anim);

How to animate TextureView?

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.

android - call method in view from activity

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

Android: Drawing a circle on bitmap

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);
}
}

Categories