When showTimeDialog() is called, dialog appears twice. When I click 'ok', there is another dialog waiting.
public void showTimeDialog(){
final TimePicker timePicker = new TimePicker(this);
timePicker.setIs24HourView(true);
timePicker.setCurrentHour(20);
timePicker.setCurrentMinute(15);
timeDialog=new AlertDialog.Builder(this)
.setTitle("Test")
.setPositiveButton(android.R.string.ok, new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Log.d("Picker", timePicker.getCurrentHour() + ":"
+ timePicker.getCurrentMinute());
dialog.dismiss();
}
})
.setNegativeButton(android.R.string.cancel,
new OnClickListener() {
#Override
public void onClick(DialogInterface dialog,
int which) {
Log.d("Picker", "Cancelled!");
dialog.dismiss();
}
}).setView(timePicker).show();
}
In onCreate(), I have:
editText_time.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View arg0, MotionEvent arg1) {
showTimeDialog();
return false;
}
});
This looks like in the code you are calling showTimeDialog() method you expect it to not return unless dialog is dismissed. If it is so (your question is not complete so I am partially guessing), then this is wrong as dialogs are asynchronous.
EDIT
It works fine as your dialog IS fired twice. It's because you are doing this in onTouch() then first dialog is started then you touch the screen (as this triggers touch event ACTION_DOWN) and then you release the finger which triggers ACTION_UP. To avoid this, you may want to add condition to your code, and I'd suggest reacting on ACTION_UP, like this:
public boolean onTouch(View v, MotionEvent event) {
if (event.getActionMasked() == MotionEvent.ACTION_UP) {
showTimeDialog();
}
}
Are you certain it's being called only once? Have you done any log output? My guess is that because you are calling the method in onTouch, the method is being called more times than you think.
onTouch(View, MotionEvent) is not only called when the view is touched. There are a number of times it is called with a single press, and you can check the MotionEvent docs to see all of the possible actions which invoke this method.
Probably what is happening is the showTimeDialog() method is being opened when ACTION_DOWN event occurs, then again when a ACTION_UP or ACTION_CANCEL event occurs because your dialog is now blocking the view. Try changing your onTouch method as follows:
public boolean onTouch(View arg0, MotionEvent arg1) {
if (arg1.getActionMasked() == MotionEvent.ACTION_UP)
showTimeDialog();
return false;
}
Related
I have an editText which is disabled and I want to enable it when I touch it.
Here is what I've done but it doesn't work :
if(textmail.isEnabled() == false){
textmail.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
textmail.setEnabled(true);
return true;
}
});
}
i read your use-case carefully you want to disable your TextView and want to disable it onTouch() (Correct me if i am wrong)
Here's a solution instead of using setEnabled() as if you set it onTouch() is not called so better to do it manually by declaring a global variable(boolean) in your (View/activity/fragment/class) where you are writing the logic.
//this as global variable
private boolean isTextViewDisabled=false;
//place this code on onCreate()
textmail.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN ){
if(isTextViewDisabled){
return false;
}
}
return true;
}
});
Set your isTextViewDisabled to true and false when needed as per your use-case.
But confusion here is condition for enabling and disabling should be something else not the touch event as according to your use case code should be like below:
//place this code on onCreate()
textmail.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN ){
if(isTextViewDisabled){
isTextViewDisabled=false;
}
}
return true;
}
});
The above code doesn't make a lot of sense until you explain why you want to disable the textView
If you disable the Edittext, it will not trigger the events i.e. onTouch/onClick. In order to tackle this issue, you need to avoid using disable and use clickable instead. textmail.setClickable(false); within your onCreate method.
To make the component look like it has been disabled, you can also work with the Alpha value where you are to reduce the opacity of the component to make it look faded away.
textmail.setAlpha(0.5f);
Now it should response to your listener...
textmail.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
textmail.setClickable(true);
textmail.setAlpha(1f);
return false;
}
});
try this i hope this help
textmail.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(textmail.isEnabled() == false){
textmail.setEnabled(true);
}
return true;
}
});
I'm banging my head with this problem which probably is simple but since I'm new to this topic I somehow haven't been able to figure it out yet.
I've successfully implemented dragging a view with onTouch method. I've also successfully implemented onLongClick and onClick methods. But both of these functionalities were implemented separately.
The problem, like the title says is when I want to join these functionalities. I want the onTouch method to be called when a user long clicks a view and I want a new activity to start when a user clicks a view.
Here is the pseudo code:
public class Website extends AppCompatActivity implements View.OnTouchListener{
TextView longpress;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_website);
longpress = (TextView) findViewById(R.id.longpress);
longpress.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view){
//I don't really know how to do this part
onTouch(View view, Motion Event event);
return true;
}
});
longpress.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
//Code for new activity comes here (I know how to do this part)
}
});
}
public boolean onTouch(View view, MotionEvent event) {
switch(event.getAction(){
case MotionEvent.ACTION_DOWN:
//Save initial coordinates of view <-- view.getX(), view.getY()
break;
case MotionEvent.ACTION_MOVE:
//Calculate dX and dY and setX and Y of the view (move view)
break;
case MotionEvent.ACTION_UP:
//If view is certain distance away from initial points do something
break;
}
}
}
Like I said, onTouch works on itself if I don't try to call it from onLongClick method. If I try to call onTouch(View view, MotionEvent event) from onLongClick method the problem occurs because onLongClick only receives one out of two arguments onTouch method should receive (onLongClick only receives view argument but it should also receive event argument).
Maybe I'm trying to do this in a totally wrong way but I have been looking at some documentation e.g. https://developer.android.com/training/gestures/ but still won't get an idea what to do.
(I would like to have a similar functionality to notifications on android phones)
So I've come to a solution which might or might not be a good one but for now it serves my functionality. If someone has a better solution and thinks mine is bad in some way please say so.
Here is the code:
boolean flag;
public boolean onTouch(View view, MotionEvent event){
int action = event.getAction() & MotionEvent.ACTION_MASK;
if(action == MotionEvent.ACTION_DOWN){
//do something on a down press
flag = true;
return true;
}
if(action == MotionEvent.ACTION_UP && flag == true){
//do something if we move finger away from screen we
//didn't move the view first
return true;
}
if(action == MotionEvent.ACTION_UP && flag == false){
//do something if we move finger away from screen and we moved
//the view before we moved the finger away from screen
}
if(action == MotionEvent.ACTION_MOVE){
//do something when moving the view
flag = false;
}
Briefly to say, I have a RecyclerView (a ViewGroup) which should response to TouchEvent, while I also suppose that its item can response individually to TouchEvent.
However, that seems to be impossible for me. For example, if I make both in onTouchEvent() method, then if the item(child view) return a true when ACTION_DOWN, then ViewGroup cannot catch it, whereas if false, the child self cannot response to ACTION_MOVE or ACTION_UP.
I also turned to addOnItemTouchListener() onInterceptTouchEvent(), but none works.
The question is not clear. But based on my understanding, you want to get the click event for entire view and also for each item at the same time.
Get click event for entire view
recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
// this will be called multiple times for single click - for MotionEvent.ACTION_DOWN, MotionEvent.ACTION_UP, and MotionEvent.ACTION_MOVE
// So restricting the call only for ACTION_DOWN,
if(e.getAction() == MotionEvent.ACTION_DOWN) {
Toast.makeText(mContext, "Clicked view", Toast.LENGTH_LONG).show();
}
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
});
and to get the click event for each item, add click listener in onBindViewHolder function
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
holder.item.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(mContext, "Clicked Item", Toast.LENGTH_LONG).show();
}
});
}
Instead of touch listener you can also use click listener on any element of recycler view row...
I was wondering if there is a way to know exactly where a button was tapped, and take different actions based on where the user tapped it. Something like:
fooBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
switch(onClickLocation){
case LEFT:
foo();
break;
case RIGHT:
bar();
break;
case MIDDLE:
baz();
break;
}
}
});
Not using an OnClickListener. OnTouchListener gives you a MotionEvent that you can use to determine where the actual touch event occurred.
For example, here I register both an OnClickListener and an OnTouchListener on the same View (called row):
row.setOnClickListener(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
row.setOnTouchListener(new View.OnTouchListener() {
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public boolean onTouch(View v, MotionEvent event) {
v
.findViewById(R.id.row_content)
.getBackground()
.setHotspot(event.getX(), event.getY());
return(false);
}
});
}
In this case, I don't need to know where the widget was touched for processing the click, but I do need to know where the widget was touched for adjusting the RippleDrawable background, so the ripple appears to emanate from where the user touched. Returning false from onTouch() means I am not consuming the touch event, and so eventually my onClick() method will also be called.
In your case, either:
do the actual work in onTouch(), or
cache the last-seen touch point in onTouch() but do not do the work until onClick()
My gut tells me that the latter should give you better results (e.g., you won't misinterpret a long-click), but I have not tried doing what you are seeking.
I am working on the following code:
private class HandleBackButton implements OnKeyListener
{
#Override
public boolean onKey(View arg0, int arg1, KeyEvent arg2) {
// TODO Auto-generated method stub
if(arg1==KeyEvent.KEYCODE_BACK)
{
showResults(0);
}
return true;
}
}
I am somewhat new to android and my purpose is to operate the above code when the back button is clicked. User can click the back button any time. But, how can I set this listener to the Activity? I can't find something like this.setOnKeyListener().
I am using Android 2.3.3.
For the Activity you should override onBackPressed which is invoked when you press the back button. OnKeyListener dispatches key events to the view. You find setOnKeyListener defined in the View class
Interface definition for a callback to be invoked when a hardware key
event is dispatched to this view. The callback will be invoked before
the key event is given to the view. This is only useful for hardware
keyboards; a software input method has no obligation to trigger this
listener.
Just override the onKeyDown() method of Activity.
You don't have to set a listener then.
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK)
{
showResults(0);
return true;
}
return super.onKeyDown(keyCode, event);
}
Optionally you can also override onBackPressed() if your api level is >= 5.
You can use onBackPressed():
#Override
public void onBackPressed() {
showResults(0);
}