Effective use of touch/hover co-ordinates on a View - android

On Android phone, I get the information of co-ordinates that, user touch on his/her phone screen or device. How do i then, use/pass these X-Y coordinates to run a specific function of mine, and use it in my code

reference from the post you can get the co-ordinates if the user touched the screen on your app. After you implement that on touch listener then in the if statement MotionEvent.ACTION_UP put this there
float myX = event.getX();
float myY = event.getY();
// now you can then pass myX,myY in your method or function as parameters
if you happen to be targeting Api 14+ then you can use onhover with the same approach as to the first one from that post, instead of using setOnTouchListener usegetWindow().getDecorView().setOnHoverListener() that's about it.
A side note is using the firs one is better because onHover can not be trusted to work,actually it doesn't work to me, thats just btw
hope i answered your question.

You can create custom view by extending android view and overriding onTouchEvent method. For example,
public class NotTouchableWebView extends WebView {
private Context context;
public NotTouchableWebView(Context context) {
super(context);
this.context=context;
}
public NotTouchableWebView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context=context;
}
public NotTouchableWebView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context=context;
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public NotTouchableWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
this.context=context;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (some condition){
//your specific function
return false;
}
return super.onTouchEvent(event);
}
}

Related

Custom view animation with invalidate does not trigger sometimes onDraw()

I am writing a custom view where I draw myself to the canvas in the onDraw(Canvas canvas) method.
My idea is to also animate the view as soon as it becomes visible by using an ObjectAnimator and a setter for a particular variable in my view. Class looks as follows:
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, -1);
}
public DrawView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public DrawView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs, defStyleAttr);
}
private void init(final Context context, AttributeSet attrs, int defStyleAttr) {
anim = ObjectAnimator.ofInt(this, PROGRESS, 0, 100);
anim.setDuration(animDuration);
if (getVisibility() == VISIBLE) {
getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
getViewTreeObserver().removeOnPreDrawListener(this);
animate();
return true;
}
});
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Draw something here using progress
}
protected void setProgress(final int pathProgressParam) {
// Re-draw
invalidate();
}
}
When triggering the animation, the "setProgress" method is called properly, and the View gets invalidated to force a re-draw with the new value for my progress field.
The problem comes when sometimes, let's say 30% of the times, the onDraw method is not called even though the View gets marked as "dirty", and only the very last frame is drawn, which kinda defeats the purpose of the animation.
I do not know whether there is any better step in the drawing cycle to trigger the animation, of if I should trigger it from somewhere else as well, but it seems as invalidate() is not enough. I have also looked at how Android guys perform property animations, but unfortunately the methods they used are hidden.
Btw, I have used the same idea as Romain Guy did here: https://github.com/romainguy/road-trip

Customized Scrollable EditText in Scrollview Makes the Scrollview Jumps

I want to have a EditText in a scrollview and this EditText needs to be scrollable. So I made a customized one as follow:
public class myEditText extends EditText {
public myEditText(Context context) {
super(context);
}
public myEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public myEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
this.getParent().requestDisallowInterceptTouchEvent(true);
return super.onTouchEvent(ev);
}
}
This EditText has only one problem, that is when the text gets really long, the Scrollview containing it jumps for some reason. This makes me unable to edit text after a certain length. Is anyone know why that happens?
I think I solved it.
The issue was when there is a cursor in the EditText, the bringPointIntoView(int offset) method will make EditText scroll to the position where the cursor is at, so that the cursor will be in your sight and you can edit the text. Usually that's how it works, but when the EditText is in a ScrollView, instead of scroll the EditText, it makes the ScrollView scrolls as well. That's the reason I saw the ScrollView jumps.
The solution is simply override the bringPointIntoView method.
So if anyone wants to use a scrollable EditText in a ScrollView, I think this may help:
public class myEditText extends EditText {
public myEditText(Context context) {
super(context);
}
public myEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public myEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
this.getParent().requestDisallowInterceptTouchEvent(true);
return super.onTouchEvent(ev);
}
#Override
public boolean bringPointIntoView(int offset) {
return false;
}
}

Implement View.OnTouchListener on custom control

I created a view that extend RelativeLayout, and I what that, this view to be able to handle touch events. So what I thought about was to implement the OnTouchListener in my custom control, like this:
class MyCustomControl extends RelativeLayout implements View.OnTouchListener {
public MyCustomControl (Context context) {
super(context);
}
public MyCustomControl (Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyCustomControl (Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
other_methods;
#Override
public boolean onTouch(View view, MotionEvent event) {
//event handle here.
}
}
It doesn't work but if I do something like this, it does:
MyCustomControl control = (MyCustomControl) LayoutInflater.from(context).inflate(R.layout.my_control, null);
control.setOnTouchListener(control);
What should I do in order to have the touchListener built-in(already defined and activated) in my custom control ?
I know, it's late, but I solved my case by adding
this.setOnTouchListener(this);
to constructor

Android TimePicker (Wheel Style) not responding correctly to flick gestures inside ScrollView

I have a dialog box that contains a Scrollview, which contains a layout with two TimePickers.
The timepickers are the newer style ones, what's in ICS.
The problem is that they seem to fight for focus when you change the time by dragging the wheel, or flicking it. It will change the time just a little, and then the layout will scroll instead.
Any ideas?
Thanks in advance.
I had the same problem when using the Holo theme, and here is where I found the solution: https://groups.google.com/forum/?fromgroups#!topic/android-developers/FkSfJI6dH8w
You must implement your custom DatePicker or TimePicker and override the following method:
#Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN)
{
ViewParent p = getParent();
if (p != null)
p.requestDisallowInterceptTouchEvent(true);
}
return false;
}
Because the link from Klemens Zleptnig is broken, here is a complete example. This fix helps with the scroll of a TabLayout too btw. I excluded the area around the big numbers in the top of the TimePicker because they don't need the scroll event anyway.
xml:
<com.name.app.MyTimePicker
android:id="#+id/timePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
.../>
java:
public class MyTimePicker extends TimePicker {
public MyTimePicker(Context context) {
super(context);
}
//This is the important constructor
public MyTimePicker(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyTimePicker(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public MyTimePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
//Excluding the top of the view
if(ev.getY() < getHeight()/3.3F)
return false;
ViewParent p = getParent();
if (p != null)
p.requestDisallowInterceptTouchEvent(true);
}
return false;
}
}

How can i find out when onDraw has finished?

how can I find out when onDraw of a View has finished?
Thanks!
I don't know what you're ultimately trying to achieve, but if you need to run some logic once drawing has been completed in an Activity, then you can call View.post(Runnable) and put your logic inside there. onDraw would have likely taken place once the code in your Runnable has been reached since it put that Runnable on the message queue.
Place a boolean member in your View class and set it to true when onDraw is called (If you simply want to be able to test that a View has drawn).
Or if you want some sort of post-draw "event" call to execute a new thread- just put it at the end of onDraw.
Another suggestion how it could be done:
public class FVRTraceAbleListView extends ListView {
ListViewListener listener;
public interface ListViewListener {
void onPostDraw();
}
public FVRTraceAbleListView(Context context) {
super(context);
}
public FVRTraceAbleListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FVRTraceAbleListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public FVRTraceAbleListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public void setListener(ListViewListener listener) {
this.listener = listener;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (listener != null) {
listener.onPostDraw();
}
}
}

Categories

Resources