Rotated View's onTouch wrong coordinates - android

I must get upside down view w/o moving the System menu. So I do:
getWindow().getDecorView().getRootView().setRotation(180);
But all child buttons get onTouch event not when they being touched, but when I touch the areas where they would be without rotation.
How can I fix the problem?

Got solution without translation matrix and such... Just create a new Layout class like this:
public class RotatableView extends FrameLayout {
public RotatableView(Context context) {
this(context, null);
}
public RotatableView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
setUpsideDown();
}
private void setUpsideDown() {
this.setRotation(180);
}
}
and use it for your layouts

Related

Android TabHost Auto Scroll vertically in side ScrollView on TabChange?

I am using TabHost inside ScrollView in my Activity but when ever I select tab it automatically scrolls my view vertically to end.
In this case child view getting focus due to that it get scrolled upward.
for resolve this you need to create custom ScrollView that extend ScrollView.
code snipt will look like this.
public class MyScrollView extends ScrollView {
public MyScrollView(Context context) {
super(context);
}
public MyScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public void requestChildFocus(View child, View focused) {
// if (focused instanceof TabHost) // here
return;
//super.requestChildFocus(child, focused);
// here you need to return instead of **super.requestChildFocus(child, focused);**
}
and xml looks like this
<com.views.widget.MyScrollView
android:focusable="false"
android:focusableInTouchMode="false"
android:id="#+id/root_scroll_view"
android:layout_width="match_parent"
android:fillViewport="true"
android:layout_height="wrap_content">
</com.views.widget.MyScrollView >
Based on Er Pragati Singh's answer I did not override requestChildFocus(View child, View focused) but computeScrollDeltaToGetChildRectOnScreen(Rect rect).
Overriding requestChildFocus will also prevent activating the on screen keyboard when touching an EditText which already has focus, while computeScrollDeltaToGetChildRectOnScreen is only used to calculate the delta scroll inside requestChildFocus to bring the View in sight. So overriding this function keeps all other routines intact.
Java:
public class MyScrollView extends ScrollView {
public MyScrollView(Context context) {
super(context);
}
public MyScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {
// This function calculates the scroll delta to bring the focused view on screen.
// -> To prevent unsolicited scrolling to the focued view we'll just return 0 here.
//
return 0;
}
}
XML:
<YOUR.PAKAGE.NAME.MyScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
</YOUR.PAKAGE.NAME.MyScrollView>

Using onInterceptTouchEvent in a class that extends Fragment

I have Fragment with a View which contains some clickable elements (ToggleButtons and a GridView).
I have set an onTouchListener on the View which I use to detect simple swipe gestures, this works perfectly well as long as the swipe doesn't start on any of the clickable items. I would like the swipe to work regardless of where it starts.
I understand that the ToggleButtons and GridView are probably consuming the touch event and in classes which extend ViewGroup I could override onInterceptTouchEvent or dispatchTouchEvent in subclasses of Activity.
Any ideas how I could deal with this situation when extending Fragment?
The closest I've found here is: Android adding onInterceptTouchEvent to a fragment Unfortunately there have been no replies to this question.
Thanks in anticipation.
Okay, got there in the end.
I create a subclass of RelativeLayout which is the root of my layout and then within this I override onInterceptTouchEvent.
public class RootLayout extends RelativeLayout {
public RootLayout(Context context) {
super(context);
}
public RootLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RootLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev){
return true;
}
}
Then replace the RelativeLayout in my xml with the new subclass.
<com.walker.leigh.dipswitch2.RootLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
Thanks for your help :)

Get notified about layout refresh/change in background thread when the app is actively being used by the user

I am new to android ecosystem. I wanted to know is there a way to get notified when an apps active layout changes for the end user. I am sorry if the question is a repeat, i searched around for what i thought were relevant keywords and could not find an answer. (Note: I dont want to change the UI from a background thread, i just want to get notified when the layout changes according to the user using the app)
You can create a custom layout and basically override its onDraw method of it which will be called when the layout is been refreshed/updated then get notified from there.
sample:
Lets say you have a parent layout using LinearLayout.
public class Sample2 extends LinearLayout {
public Sample2(Context context) {
super(context);
}
public Sample2(Context context, AttributeSet attrs) {
super(context, attrs);
}
public Sample2(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onDraw(Canvas canvas) {
Log.d("UPDATE", "I am REFRESHED"); //will print if this layout is refresh,updated, or invalidated.
super.onDraw(canvas);
}
}
To use that in the xml:
<?xml version="1.0" encoding="utf-8"?>
<com.example.sfdsffsdf.Sample2 xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
</com.example.sfdsffsdf.Sample2>
You can set an OnGlobalLayoutListener on your layout and get notified when the state or visibility of that layout or any of its children get changed:
myLayout.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// Do something
}
};

How can I mirror the whole display?

I want to be able to mirror my app so it can be viewed in the windshield of a vehicle.
My XML has several nested LinearLayouts, TextViews and ImageViews. Currently I'm transforming each one and although it is mirrored, the structure of the elements is not (what was at the top is now at the bottom).
I've been looking for days and so far have tried a couple of approaches that have failed.
An animation that uses a matrix to flip on the X axis kind of works, except that it either reverts back or it stays and doesn't update, which is no good for interacting with the app.
I just tried to create a custom LinearLayout extending the parent one, hoping that I could apply a Matrix in its onDraw() method but that gives me a blank screen (I had to set setWillNotDraw(false); to hit the onDraw()).
Well eventually I found a solution that works well for me (so far it's caused no issues for users).
My solution was to override dispatchDraw to scale the canvas in my custom LinearLayout. Then I just needed to flip the touch events by overriding dispatchTouchEvent:
public class CustomContainer extends LinearLayout {
public CustomContainer(Context context) {
super(context);
this.setWillNotDraw(false);
}
public CustomContainer(Context context, AttributeSet attrs) {
super(context, attrs);
this.setWillNotDraw(false);
}
public CustomContainer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.setWillNotDraw(false);
}
#Override
protected void dispatchDraw(Canvas canvas) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
// Flip the view canvas
if (MyHUDActivity.mHUDMode) canvas.scale(1,-1, getWidth(), getHeight()/2f);
super.dispatchDraw(canvas);
canvas.restore();
}
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
// If in HUD mode then flip the touch zones
if (MyHUDActivity.mHUDMode) event.setLocation(event.getX(), getHeight()-event.getY());
return super.dispatchTouchEvent(event);
}
}
You can use the new Animation api to deal with reverting back after the horizontal flip.

Android RotationAnimation Complete

I am trying to use the RotationAnimation to move an ImageButton. I have extended ImageButton to override onAnimationEnd to avoid the screen flicker at the end of the animation, and would like to update the position of the actual button [since the animation is just a superficial move]. How can I determine the exact coordinates of the button at the end of the animation? Attached is some of my code..
public class HomeNavigationButton extends ImageButton {
public HomeNavigationButton(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
public HomeNavigationButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public HomeNavigationButton(Context context) {
super(context);
}
#Override
protected void onAnimationEnd() {
super.onAnimationEnd();
int l = ?
int t = ?
int r = ?
int b = ?
this.layout(l,t,r,b);
}
The position of the button animation? I would go out on a limb and guess you can't. Animations are interesting. They're not "real". Think of them as a mirage. Try this. Rotate the image VERY slowly. If the image is a rectangle, when the image is about 45 degrees, click where the image used to be, but is no long. You'll actually register a click, because the image isn't actually being rotate in real coordinates.
I would consider actually animating the button like a game sprite, or do some trial and error with the animation and set values manually. If you do the second one, make sure you dynamically convert to DIP coordinates rather than raw ints.

Categories

Resources