Need to touch screen twice to get onTouchEvent called - android

I am using onTouchEvent to capture clicks on buttons. These buttons are in views, inflated in the main view.
My problem is that I have to click twice time on the screen to get my onTouchEvent triggered.
I found a similar topic telling to call setContentView after inflating but my app contains many other things so I just cannot call setContentView each time I inflate a new view.
activity_main.xml :
<RelativeLayout android:id="#+id/activity_main"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.pixeemedical.kneeplus.MainActivity"
xmlns:app="http://schemas.android.com/apk/res-auto">
... other stuff here
<RelativeLayout
android:id="#+id/rlayout_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true">
</RelativeLayout>
</RelativeLayout>
My ActivityMain.java :
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMainLayout = findViewById(R.id.rlayout_content);
mMainLayout.removeAllViews();
View currentLayoutToAdd = LayoutInflater.from(this).inflate(R.layout.layout_to_inflate, mMainLayout, false);
mMainLayout.addView(currentLayoutToAdd, 0);
Button btn = findViewById(R.id.btn);
btn.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
// called only after second click
}
});
}
}

Related

Simultaneous touch events handling on multiple views in Android

Considering the example from the below image,
I'm looking for a solution to pass the touch events from the canvas View to the Viewpager. This is necessary for applying the same amount of zoom on both views at the same time.
Here's the technical description of what's going on,
(Lets consider the view as A, B & C)
A. Parent View
B. View
C. View Pager
Before the dispatchTouchEvent() is called on the children (B & C), the A.dispatchTouchEvent() will first calls A.onInterceptTouchEvent() to see if the view group is interested in intercepting the event.
So if A.onTouchEvent() returns false, then it goes back up to B.onTouchEvent(). If that returns false then it goes back up to C.onTouchEvent() and the dispatching continues as usual.
And upon returning true,
ACTION_CANCEL will be dispatched to all the children.
All the subsequent gesture events (till ACTION_UP/ACTION_CANCEL) will be consumed by the event listeners (OnTouchListener.onTouch()) if defined, else the event handler A.onTouchEvent() at A’s level.
At this point I can pass the events from the parent to the child views but can't let the 2 child view B. & C handle the events together (applying same amount of zoom on both views).
Is there any way to pass the touch events from the parent view to a child one so that they can process the events simultaneously?
Here's my layout setup,
<RelativeLayout
android:id="#+id/layoutParent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFFFF">
<com.androidapp.NonSwipeableViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="#color/transparent" />
<com.androidapp.DrawingView
android:id="#+id/drawing"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/transparent" />
</RelativeLayout>
If I'm not wrong, you want to process the same touch event both on the top and bottom view. According to Android touch architecture, you can't handle touch events from multiple views at the same time. Either you have to process it inside the onTouchEvent() method or pass to the next view. You also need to wait till the top view finish processing the MotionEvent() and let the child view to handle.
Here's a possible solution using RxAndroid approach,
Inside your canvas view's MotionEvent(),
#Override
public boolean onTouchEvent(MotionEvent event) {
// process all touch events (UP/DOWN/MOVE)
//send events as observable
RxBus.getInstance().sendMotionEvent(event);
return true;
}
This will observe the motion events and notify all observers.
Now, inside your viewpager's onResume() subscribe for the motion events so that whenever a change is made from the canvas It'll immediately pass the events.
Subscription RxBus _rxBus = RxBus.getInstance();
subscription = _rxBus.getMotionEvent()
.subscribe(new Action1<MotionEvent>() {
#Override
public void call(MotionEvent event) {
// call the onTouchEvent of your widget e.g. ImageView and pass the received event
// this will apply the same touch event that was applied in the canvas
// .onTouchEvent(event) is important to override the onTouchEvent() of your widget that will use the touch event
imageView.onTouchEvent(event);
}
});
The RxBus class is given below,
public class RxBus {
private static RxBus instance;
private final PublishSubject<MotionEvent> motion_event = PublishSubject.create();
public static RxBus getInstance() {
if (instance == null) {
instance = new RxBus();
}
return instance;
}
public void sendMotionEvent(MotionEvent motionEvent) {
motion_event.onNext(motionEvent);
}
public Observable<MotionEvent> getMotionEvent() {
return motion_event;
}
}
It is pretty easy to implement by using call back. Just create an Interface with whatever methods, you need and then implement in your Viewpager. Call will be invoked in your View class based on your touch events and responds will come to Viewpager. I have created an example with an ImageView in my MainActivity and called to changed its size from a different fragment and it works. Here is my code below:
public interface ICallBackForResize {
void resizeme();
void actionUp();
void actionDown();
}
MainActivity:
public class MainActivity extends AppCompatActivity implements ICallBackForResize {
ImageView img;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img= (ImageView) findViewById(R.id.image);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void resizeme() {
Toast.makeText(MainActivity.this,"called",Toast.LENGTH_LONG).show();
img.getLayoutParams().height += 20;
img.getLayoutParams().width += 20;
img.requestLayout();
}
#Override
public void actionUp() {
//do whatever
}
#Override
public void actionDown() {
//do whatever
}
}
My Fragment class with a simple button:
public class MyFragmentButton extends Fragment {
View view;
ICallBackForResize callBackForResize;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
callBackForResize= (ICallBackForResize) getActivity();
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view=inflater.inflate(R.layout.mybutton,container,false);
Button btn= (Button) view.findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
callBackForResize.resizeme();
}
});
return view;
}
}
I believe you dont need xml file. I just shared if somebody needs:
activity_main:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_main"/>
</android.support.design.widget.CoordinatorLayout>
content_main:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/activity_main"
tools:context="nanofaroque.com.addlistener.MainActivity">
<ImageView
android:id="#+id/image"
android:text="Hello World!"
android:layout_width="100dp"
android:layout_gravity="center"
android:src="#mipmap/ic_launcher"
android:layout_height="100dp" />
<fragment
android:name="nanofaroque.com.addlistener.MyFragmentButton"
android:id="#+id/headlines_fragment"
android:layout_width="100dp"
android:layout_height="100dp" />
</FrameLayout>
mybutton:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

How to disable area of Gridview before pressed a Button?

I'm trying to make a simple game that select a value from item of Gridview. But i want that value just can clickable after press Play Button.We can't click in anywhere if did not press Play Button. How can i do that?
What you can do is to change the clickable property of your grid view
and then in the button click listener just set the clickable property to true
so your code should look like the following:
let's assume that this is your view:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="50dp" />
<GridView
android:id="#+id/grid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="false" />
</LinearLayout>
your activity should contain the following code:
public class MainActivity extends AppCompatActivity {
private Button mButton;
private GridView mGridView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGridView = (GridView) findViewById(R.id.grid);
mButton = (Button) findViewById(R.id.button);
// if you want to do it with setEnable
mGridView.setEnabled(false);
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mGridView.setClickable(true);
// if you want to toggle then you can use the following code:
// mGridView.setClickable(!mGridView.isClickable());
// you can also change the setEnable property and not the clickable
mGridView.setEnabled(true);
}
});
}
}

How to implement Facebook's new emoting emojis: Love, haha, wow, sad and angry in android?

I need to implement my own Facebook reaction popup in my app. While searching i came across with the below github app https://github.com/chRyNaN/Reactions. I have tried to called the Show method in ReactionView class using below set of codes.
ReactionView reactionView = new ReactionView(MainActivity.this);
final Button mReactionView = (Button)findViewById(R.id.openpopup);
mReactionView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
reactionView.show(event);
return true;
}
});
But Reaction Popup is not visible. I am not sure, what i am missing? Can anybody help me on this?
Note: Github source is missing with layout folder and also Main activity class.
It can be launched like this
public class MainActivity extends AppCompatActivity {
private ReactionView reactionView;
private Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
reactionView = (ReactionView) findViewById(R.id.reaction);
button = (Button) findViewById(R.id.button);
button.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
reactionView.show(motionEvent);
return false;
}
});
}
}
Here is the layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
tools:context="me.superup.reactions.MainActivity">
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/app_name"/>
<me.superup.reactions.reactions.ReactionView
android:id="#+id/reaction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/button"/>
</RelativeLayout>
Add this dependency in build.gradle file...
implementation 'com.github.abbyChandra16:FB-Reaction:1.0'
Add a button in xml file and Inside activity.java file, add this code...
Button btn = findViewById(R.id.btn);
btn.setOnClickListener(view ->
{
Reaction var = new Reaction();
var.react(this,view);
});

How to show/hide grouped views in Android?

I want to create an activity such as mentioned in photo...
as soon as I press the maximize button I want it to become full screen for the activity and part 1 become minimize, and again when I press the restore button I want it to become in a first state: to be able to see part 1 and part 2 ...
I think if we put two layouts it is possible? Isn't it? Please refer me to a resource to help me about this, or show me the code to achieve a solution.
Part one and two should be in their own layout. After, play with the visilibity property of each layout. Specifically to hide any view without it continues to occupy its space, use the value gone for the visibility property.
Ok, here I go. Below you have a complete example of how to hide/show grouped views.
main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="#+id/viewsContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="5dp" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextBox One" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="TextBox Two" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="TextBox Three" />
</LinearLayout>
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="Hide" />
</RelativeLayout>
Activity
public class MyActivity extends Activity implements OnClickListener {
private boolean viewGroupIsVisible = true;
private View mViewGroup;
private Button mButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mViewGroup = findViewById(R.id.viewsContainer);
mButton = findViewById(R.id.button);
mButton.setOnClickListener(this);
}
#Override
public void onClick(View button) {
if (viewGroupIsVisible) {
mViewGroup.setVisibility(View.GONE);
mButton.setText("Show");
} else {
mViewGroup.setVisibility(View.VISIBLE);
mButton.setText("Hide");
}
viewGroupIsVisible = !viewGroupIsVisible;
}
I hope this helps ;)
There is a bit simplified solution, than Diego Palomar produced, without using additional variable. I'll take his code to show:
public class MyActivity extends Activity implements OnClickListener {
private View mViewGroup;
private Button mButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mViewGroup = findViewById(R.id.viewsContainer);
mButton = findViewById(R.id.button);
mButton.setOnClickListener(this);
}
#Override
public void onClick(View button) {
if (mViewGroup.getVisibility() == View.VISIBLE) {
mViewGroup.setVisibility(View.GONE);
mButton.setText("Show");
} else {
mViewGroup.setVisibility(View.VISIBLE);
mButton.setText("Hide");
}
}

How to do something like "Touch anywhere to continue"?

How would you do something like "Touch Anywhere to Continue."
Set an onclick listener for the layout of the entire screen
It's as simple as this.
Give an id to "main" layout
set the listener to the main layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:id="#+id/mainLayout"> //<--- Provide ID
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
/>
</RelativeLayout>
In this case, the main element is RelativeLayout. So add the listener to RelativeLayout to implement Touch anywhere to continue.
public class MainActivity extends AppCompatActivity {
private RelativeLayout layout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layout = (RelativeLayout)findViewById(R.id.mainLayout);
layout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "Clicked", Toast.LENGTH_SHORT).show();
}
});
}
}

Categories

Resources