I have a messaging app similar to whatsapp where there are messages videos and images in the chat activity. Now I want to implement a double tap like feature on this but the problem is I also have a onclicklistner attached to my image and video frame that opens up a fullscreenactivity showing the image in fullscreen or playing the video in fullscreen. So on double tap instead of liking the picture or video it simply opens the video or image in the fullscreen mode. Since in messages I don't have a onclick listner attached double tap like works fine. Any ideas on how I can make the double tap like work in case of the videos or images. I am fairly new to android development using Java. So any help is appreciated.
HI, I think the approach to take depends on the future of your app, using LongClick is kinda good but what if you want to achieve a zoom like onLongClick?
What I did below is that I created a subclass that extends GestureDetector.SimpleOnGestureListener and then in my GestureTest class, I an ontouchListener and return the gesture instance created before, finally I parse the listener to the button that has to perform the clicks, it can be any View object.
Finally, I used the TextView I created to display/monitor my actions.
GestureDetector like below:
public class GestureTest extends AppCompatActivity{
private Button btn;
private TextView actions;
private GestureDetector mDetector;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gesture_test);
btn = findViewById(R.id.btn);
actions = findViewById(R.id.action);
mDetector = new GestureDetector(this, new SampleGestureListener());
View.OnTouchListener touchListener = new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return mDetector.onTouchEvent(event);
}
};
btn.setOnTouchListener(touchListener);
}
public class SampleGestureListener extends GestureDetector.SimpleOnGestureListener{
#Override
public boolean onDown(MotionEvent event) {
Log.e("EVENT","BUTTON PRESSED DOWN, NOT YET RELEASED WILL TRIGGER ONLONG-PRESS");
// don't return false here or else none of the other
// gestures will work
return true;
}
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
Log.e("EVENT", "SINGLE CLICK EVENT");
actions.setText("THIS CLICK IS FOR IMAGE OR VIDEO TO OPEN ?");
return true;
}
#Override
public void onLongPress(MotionEvent e) {
Log.e("EVENT", "LONG PRESSED");
actions.setText("THIS IS ZOOM LIKE NOT DOUBLE CLICK!!!");
}
#Override
public boolean onDoubleTap(MotionEvent e) {
Log.e("EVENT", "DOUBLE CLICKED HAPPENED");
actions.setText("THIS CLICK IS TO LIKE IMAGE OR VIDEO ?");
return true;
}
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
Log.e("EVENT", "SCROLLING");
actions.setText("YOU\" Scrolling on many images...");
return true;
}
#Override
public boolean onFling(MotionEvent event1, MotionEvent event2,
float velocityX, float velocityY) {
Log.e("EVENT", "FLINGED");
actions.setText("THIS IS TINDER FLING LIKE ?");
return true;
}
}
}
AND BELOW IS MY activity_gesture_test.xml FOR TESTING:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/btn"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="match_parent"
android:layout_height="100dp"/>
<TextView
android:id="#+id/action"
android:textSize="20dp"
android:textColor="#color/black"
app:layout_constraintTop_toBottomOf="#+id/btn"
android:layout_width="match_parent"
android:layout_height="100dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
GoodLuck Coding.
try this for double click:
int i = 0;
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
i++;
Handler handler = new Handler();
Runnable r = new Runnable() {
#Override
public void run() {
i = 0;
}
};
if (i == 1) {
//Single click
handler.postDelayed(r, 250);
} else if (i == 2) {
//Double click
i = 0;
ShowDailog();
}
}
});
and for click listener:
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
It is generally accepted to use long tap instead of double click in android apps. Try this:
yourView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
//do Your stuff here
return true;
}
});
Related
I use a GestureListener on an image to detect a Double Tap.
holder.image.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return holder.myDoubleTapDetector.onTouchEvent(event);
}
});
And I use the library Zoomy to make the images zoomable.
Zoomy.Builder builder = new Zoomy.Builder(mActivity).target(holder.image);
builder.register();
Both work perfectly fine for them alone.
But adding both at the same time does not work! Only the one that was added last works.
How can I have both of them working?
Zoomy provides a solution for that:
Because Zoomy works by attaching a View.OnTouchListener to the registered View, View.OnClickListener can not be set along with Zoomy, so a TapListener, LongPressListener and DoubleTapListener are provided to ensure the View still can listen for gestures. A ZoomListener is also provided if you are interested in zoom events.
In Code:
Zoomy.Builder builder = new Zoomy.Builder(this)
.target(mZoomableView)
.tapListener(new TapListener() {
#Override
public void onTap(View v) {
//View tapped, do stuff
}
})
.longPressListener(new LongPressListener() {
#Override
public void onLongPress(View v) {
//View long pressed, do stuff
}
}).doubleTapListener(new DoubleTapListener() {
#Override
public void onDoubleTap(View v) {
//View double tapped, do stuff
}
})
.zoomListener(new ZoomListener() {
#Override
public void onViewStartedZooming(View view) {
//View started zooming
}
#Override
public void onViewEndedZooming(View view) {
//View ended zooming
}
});
after clicking the button mouse scroll will be activated and scroll up, button value should be increment and when scroll down value decrement. but button outside code working,then button inside code not work.my sample code here.
public class MainActivity extends Activity {
Button button;
int x,f;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=(Button)findViewById(R.id.button1);
button.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
// TODO Auto-generated method stub
// i need implement code here ,how can i do?
return false;
}
});
}
#SuppressLint("NewApi") #Override
public boolean onGenericMotionEvent(MotionEvent event) {
//if (0 != (event.getSource() & InputDevice.SOURCE_CLASS_POINTER)) {
switch (event.getAction()) {
case MotionEvent.ACTION_SCROLL:
if (event.getAxisValue(MotionEvent.AXIS_VSCROLL) < 0.0f)
//selectNext();
{
x=Integer.parseInt(button.getText().toString());
f=x+5;
button.setText(""+f);
}
else
{
x=Integer.parseInt(button.getText().toString());
f=x-5;
button.setText(""+f);
return true;
}
}
return super.onGenericMotionEvent(event);
} }
i need those function inside the touch listener i don't know how can i do,please help me!
I want to have same thing happen when I press a button as I press enter on text edit(s).
Here is implementation of OnEditorActionListener for text edit:
private OnEditorActionListener clickedEnter = (new OnEditorActionListener()
{
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
//implemtation of task1
}
return false;
}
});
And here is implementation for the button:
show.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
//How can I call clickedEnter here?
}
});
The reason is, I want to have less code and easier debugging etc. Thanks in advance.
Edit:
final EditText editText = (EditText) findViewById(R.id.textView);
editText.setOnEditorActionListener(clickedEnter);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
editText.onEditorAction(EditorInfo.IME_ACTION_DONE);
}
});
And here's my xml:
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="200dp "
android:text="Done!"/>
<EditText
android:id="#+id/textView"
android:inputType="text"
android:singleLine="true"
android:imeOptions="actionDone"
android:textSize="30dp"
android:textColor="#333"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:hint="Enter text"/>
Depends on what action you want to invoke within the editor.
You can either create a method and call it in the two functions, or call show.performClick() in the first method.
Solution 1:
private OnEditorActionListener clickedEnter = (new OnEditorActionListener()
{
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
yourMethod();
}
return false;
}
});
show.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
yourMethod();
}
});
private void yourMethod(){
//Instructions
}
Solution 2 :
private Button show;
private OnEditorActionListener clickedEnter = (new OnEditorActionListener()
{
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
show.performClick();
}
return false;
}
});
show.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
//Instructions...
}
});
you can make a different method for your task and call that method in both the listener's events.
I think you want something like this
etOne.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
bSearch.performClick();
closeKeyboard(getActivity(),
etOne.getWindowToken());
return true;
}
return false;
}
});
and
bSearch.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//Do something..
}
});
now the button will //Do something .. and if you want that when user press enter on keyboard and the same thing happens as what the button does.. just call bSearch.performClick(); hope it helps..
Edit : also closeKeyboard(getActivity(),etOne.getWindowToken()); will auto hide the soft keyboard after hitting enter.
I have a onClickListener on a textview and the textview has the flag that it's selectable.
But the onclick event I specified is only called when the textview is clicked a second time.
After the second time it calles the onclick right, but if a other textview that also is selectable with a onclicklistener it also is only called the second time, then it works fine, but then the other one works only the second time again. I can't find the source of these weird events.
telefoonTXT.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {startTelIntent();}}
);
urlTXT.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {startWebIntent();}
});
I faced this issue as well. Whenever text view is touched firstly onTouch, then OnSelection and at last OnClick is called.
If i understand your problem clearly you want to select text in text view when user double taps or long presses like the usual text selection but when user simply clicks it once u want the onClick to function. I think the following might help you.
Add a gestureDetector to your text View.
GestureDetectorCompat mDetector;
mDetector = new GestureDetectorCompat(this, new GestureDetector.SimpleOnGestureListener());
mDetector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() {
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
// This is where u add your OnClick event
startTelIntent();
return false;
}
#Override
public boolean onDoubleTap(MotionEvent e) {
Log.d("dtttt", "double tap");
return false;
}
#Override
public boolean onDoubleTapEvent(MotionEvent e) {
return false;
}
});
telefoonTXT.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
mDetector.onTouchEvent(event);
return false;
}
});
In my case focus change listener works, but be aware for cases when you use it in androidTv that you move with D-pad
textView.setOnFocusChangeListener { v, hasFocus ->
if (hasFocus && textView.measuredHeight > textView.lineHeight * textView.lineCount) {
//your click event
}
}
I check if text can be scrolled then don't take the click event
The accepted answer is good. But I had one additional issue with it: When I have some selection text in textview, I want to tap on textview to only deselecting the text - without perfoming on click listener. And perform on click only with no text selection.
So below is my solution:
#SuppressLint("ClickableViewAccessibility")
public static void setOnClickGestureDetectorListener(TextView textView, Context context, View.OnClickListener onClickListener){
if (textView == null || context == null || onClickListener == null)){
return;
}
final GestureDetectorCompat detector = new GestureDetectorCompat(context, new GestureDetector.SimpleOnGestureListener());
detector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() {
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
onClickListener.onClick(textView);
return false;
}
#Override
public boolean onDoubleTap(MotionEvent e) {
return false;
}
#Override
public boolean onDoubleTapEvent(MotionEvent e) {
return false;
}
});
textView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if ( v instanceof TextView ) {
TextView textView = (TextView)v;
if (textView.getSelectionStart() >= 0 && textView.getSelectionEnd() > textView.getSelectionStart()){
return false;
}
detector.onTouchEvent(event);
}
return false;
}
});
}
And calling example is below:
setOnClickGestureDetectorListener(textView, getContext(), new View.OnClickListener() {
#Override
public void onClick(View v) {
// This is where u add your OnClick event
}
});
set this ...
TextisSelectable = "false"
i think it will be work correctly
My Question: Is there a work-around for using an onTouchEvent in a FragmentActivity?
My Situation: I'm writing a simple flashlight app and I have a FragmentActivity where a user can swipe between colors (the whole screen is just one color. This app is for personal improvement). I want to be able to do a onLongPress event for options, a onDoubleTap event for hiding the navigation bar, and most importantly a touch event to control brightness of the app (I want to let the user scroll up and down for brightness changes, any ideas here are welcome! is the onFling event good for this?)
What I've tried: I have a GestureDetector with my implementation of an SimpleOnGestureListener. I override the onTouchEvent in the FragmentActivity, but I have just found out that this method is never called in a FragmentActivity (I also tested this with a Log.print in the method and it's never called). Is there a work-around? Thanks!
Salient Code:
MainActivity:
public class MainActivity extends FragmentActivity {
private GestureDetector gestureDetector;
private FragmentPagerAdapter mAdapter;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
gestureDetector = new GestureDetector(getApplicationContext(), new MyGestureListener(getWindow()));
mAdapter = new ColorFragmentAdapter(getSupportFragmentManager(), getDefaultColorList());
ViewPager pager = (ViewPager) super.findViewById(R.id.viewpager);
pager.setAdapter(mAdapter);
pager.setCurrentItem(Math.round(mAdapter.getCount() / 2)); //Set current fragment to middle fragment
}
#Override
public boolean onTouchEvent(MotionEvent event) {
print("Sending touch event to gestureDetector.");
//This line is never run.
return gestureDetector.onTouchEvent(event);
}
/**
* Prints the given object to the log with the debug priority with the tag FLASHLIGHT
*
* #param object
*/
public static void print(Object object) {
Log.println(Log.DEBUG, "FLASHLIGHT", object.toString());
}
}
MyGestureListener :
public class MyGestureListener extends SimpleOnGestureListener {
private final Window window;
public MyGestureListener(Window window) {
super();
this.window = window;
}
#Override
public void onLongPress(MotionEvent e) {
//onLongPress code
}
#Override
public boolean onDoubleTap(MotionEvent e) {
//onDoubleTap code
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
//onFling cod
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<android.support.v4.view.ViewPager
android:id="#+android:id/viewpager"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
I don't think you'd need anything else to answer the question, but let me know if you do.
So the solution to this is relatively easy. The problem is that the ViewPager is eating the touch event. So what I did was write my own implementation of a ViewPager and overrided the onTouchEvent(MotionEvent event) method by calling super.onTouchEvent(event) and then passing the event to the gestureDetector within the class.
Relevant Code:
MainActivity
public class MainActivity extends FragmentActivity {
private FragmentPagerAdapter mAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_main);
mAdapter = new FragmentAdapter(getSupportFragmentManager());
MyViewPager pager = (MyViewPager) findViewById(R.id.viewpager);
pager.setGestureDetector(new GestureDetector(this, new MyGestureListener(this)));
pager.setAdapter(mAdapter);
pager.setCurrentItem(Math.round(mAdapter.getCount() / 2));
}
}
MyViewPager
public class MyViewPager extends ViewPager {
private GestureDetector gestureDetector;
public MyViewPager(Context context) {
super(context);
}
public MyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onTouchEvent(MotionEvent e) {
return super.onTouchEvent(e) && gestureDetector.onTouchEvent(e);
}
}
MyGestureListener
public class MyGestureListener extends SimpleOnGestureListener {
private final Activity activity;
public MyGestureListener(Activity activity) {
super();
this.activity = activity;
}
#Override
public boolean onDoubleTap(MotionEvent e) {
//...
}
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
//...
}
//... etc...
}
layout_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<com.kentcdodds.flashlight.MyViewPager
android:id="#+android:id/viewpager"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
try doing this:
gestureDetector = new GestureDetector(this);
and on the TouchEvent this:
#Override
public boolean onTouchEvent(MotionEvent me) {
return gestureDetector.onTouchEvent(me);
}
Source
If you just want to simply detect when a user touches on the fragmentActivity use the following method:
public void onUserInteraction(){
Log.d("FragmentActivity","touched");
}
More info at : http://developer.android.com/reference/android/support/v4/app/FragmentActivity.html