I am currently working on an accessibility service, which has two views. A button and a simple colored view. The colored view appears/disappears when i touch the button.
This is the code for the service -
package com.hardik.accessibiltyservicetest;
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.FingerprintGestureController;
import android.graphics.PixelFormat;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import in.championswimmer.sfg.lib.SimpleFingerGestures;
public class Service extends AccessibilityService {
FrameLayout mLayout;
WindowManager.LayoutParams lp;
LayoutInflater inflater;
WindowManager wm;
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
}
#Override
public void onInterrupt() {
}
#Override
protected void onServiceConnected() {
// Create an overlay and display the action bar
wm = (WindowManager) getSystemService(WINDOW_SERVICE);
mLayout = new FrameLayout(this);
lp = new WindowManager.LayoutParams();
lp.type = WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
lp.format = PixelFormat.TRANSLUCENT;
lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.MATCH_PARENT;
lp.gravity = Gravity.CENTER;
inflater = LayoutInflater.from(this);
inflater.inflate(R.layout.action_bar, mLayout);
wm.addView(mLayout, lp);
configurePowerButton();
}
boolean is = true;
private void configurePowerButton() {
SimpleFingerGestures obj = new SimpleFingerGestures();
obj.setDebug(true);
obj.setConsumeTouchEvents(true);
obj.setOnFingerGestureListener(new SimpleFingerGestures.OnFingerGestureListener() {
#Override
public boolean onSwipeUp(int i, long l, double v) {
Log.e("Swipe", "Up "+i);
return false;
}
#Override
public boolean onSwipeDown(int i, long l, double v) {
return false;
}
#Override
public boolean onSwipeLeft(int i, long l, double v) {
return false;
}
#Override
public boolean onSwipeRight(int i, long l, double v) {
return false;
}
#Override
public boolean onPinch(int i, long l, double v) {
return false;
}
#Override
public boolean onUnpinch(int i, long l, double v) {
return false;
}
#Override
public boolean onDoubleTap(int i) {
return false;
}
});
Button powerButton = mLayout.findViewById(R.id.power);
final View img = mLayout.findViewById(R.id.view);
powerButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//performGlobalAction(GLOBAL_ACTION_POWER_DIALOG);
Toast.makeText(getApplicationContext(), "yus", Toast.LENGTH_SHORT).show();
if (is){
is = false;
img.setVisibility(View.GONE);
}
else{
is =true;
img.setVisibility(View.VISIBLE);
}
}
});
img.setOnTouchListener(obj);
}
}
and this is the layout file -
<android.support.constraint.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"
android:orientation="horizontal">
<Button
android:id="#+id/power"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="32dp"
android:background="#80FFFFFF"
android:text="Test"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="#+id/view"
android:layout_width="300dp"
android:layout_height="300dp"
android:background="#000000"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
the touch event and all works fine. but the problem is that with the current windowmanager parameter length and breadth set to match parent, the overlay blocks touch events to android ui itself, in other words no part of the android ui will respond unless the overlay is stopped, since the overlay consumes all the touch input. And the biggest setback is that i want the overlay to be just like i designed in the layout, and by setting any other length and breadth parameter the background touch problem starts, that is it once again starts consuming the touch events.
It isn't consuming all the touch events when i set the parameters to wrap content, but that doesn't give me the required ui of the service.
Also don't mind the use of gesture library, the code is a part of my personal project.
thanks in advance.
i found a fix. just make separate layouts for each element
Related
I tried to set click to the triangular images placed as shown in figure. But the problem is only one image click is working. And I have implemented as follows:
<ImageView
android:id="#+id/twoWheeler" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/front_screen_design_twowheeler"
android:scaleType="fitStart"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/fourWheeler"
android:src="#drawable/front_screen_design_fourwheeler"
android:scaleType="fitEnd" />
two.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i=new Intent(MainActivity.this,BikeActivity.class);
startActivity(i);
}
});
four.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i=new Intent(MainActivity.this,FourActivity.class);
startActivity(i);
}
});
As you have mentioned in your question I have created the same example for your solution.
I have used two images with half transparent area.
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rlParent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/triangle" />
<ImageView
android:id="#+id/imageView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/triangle2" />
</RelativeLayout>
MainActivity.java
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private ImageView imageView, imageView1;
private RelativeLayout rlParent;
private void showToast(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
rlParent = (RelativeLayout) findViewById(R.id.rlParent);
imageView = (ImageView) findViewById(R.id.imageView);
imageView1 = (ImageView) findViewById(R.id.imageView1);
rlParent.setOnTouchListener(new MyTouchListener(rlParent, this));
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.imageView:
showToast("Image 1 Click");
break;
case R.id.imageView1:
showToast("Image 2 Click");
break;
}
}
private class MyTouchListener implements View.OnTouchListener {
private ViewGroup viewGroup;
private View.OnClickListener onClickListener;
public MyTouchListener(ViewGroup viewGroup, View.OnClickListener onClickListener) {
this.viewGroup = viewGroup;
this.onClickListener = onClickListener;
}
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
for (int pos = 0; pos < viewGroup.getChildCount(); pos++) {
View view = viewGroup.getChildAt(pos);
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
int x = (int) event.getX();
int y = (int) event.getY();
if (bitmap.getPixel(x, y) != Color.TRANSPARENT) {
if (onClickListener != null) {
onClickListener.onClick(view);
break;
}
}
}
break;
}
return true;
}
}
}
You can check below screenshots to check particular image click,
Screenshots
I hope it helps you.
The thing with imageview is it takes a rectangular space. So in your case one imageview is placed above another thus only one imageview is clicked. to achieve that you need to create custom class to implement triangular imageview click try this or look for custom imageview...
You can wrap them in a FrameLayout
framelayout.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
//calculate the position by event.getX(),event.getY();
if(point in triOne){
}else{
}
return true;
}
});
I am trying to programmatically create a centered button that would print a word when pressed.
I have used Gravity for this, however I am getting 2 errors:
eglSurfaceAttrib not implemented
Failed to set EGL_SWAP_BEHAVIOR on surface 0xae0ee360, error=EGL_SUCCESS
Below is my code:
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
public class MainActivity extends ActionBarActivity {
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/////////////
#Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_main);
final ViewGroup vg1 = (ViewGroup) findViewById(android.R.id.content);
float w1 = vg1.getWidth();
float h1 = vg1.getHeight();
final Button b1 = new Button(this);
b1.setText("");
float left = (w1 - vg1.getWidth())/2;
float top = (h1 - vg1.getHeight())/2;
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams((int)w1/2, (int)h1/2);
layoutParams.setMargins( (int)left, (int)top, (int)(left+w1/2), (int)(top+h1/2));
layoutParams.gravity = Gravity.CENTER;
b1.setLayoutParams(layoutParams);
vg1.addView(b1, layoutParams);
b1.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
b1.setText("TestTest");
}
});
}
and the xml:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
Please, help me find my mistake.
I just started learning android development, not really experienced in this.
Thank you!
In order to get the height and width of your layout you need to wait for the measure() pass (more information here https://developer.android.com/guide/topics/ui/how-android-draws.html).
You can add a listener on your layout for example:
gv1.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
// execute your code here, after height and width have been calculated
}
}
);
import android.support.v4.app.Fragment;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.*;
import android.widget.NumberPicker.OnValueChangeListener;
public class MainActivity extends Activity implements OnValueChangeListener {
EditText push_ups, sit_ups;
NumberPicker np;
Button calculate;
final Context context = this;
CheckBox checkbox;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
calculate = (Button)findViewById(R.id.calculate);
push_ups = (EditText)findViewById(R.id.pushups);
sit_ups = (EditText)findViewById(R.id.situps);
np = (NumberPicker)findViewById(R.id.np1);
checkbox = (CheckBox)findViewById(R.id.checkbox);
String[] values = {"some array"};
np.setMaxValue(values.length-1);
np.setMinValue(0);
np.setDisplayedValues(values);
np.setWrapSelectorWheel(false);
//calculateButton runs when I click the "calculate" Button
calculateButton();
LinearLayout layout = (LinearLayout)findViewById(R.id.linearLayout1);
layout.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
hideKeyboard();
return false;
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.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();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
return rootView;
}
}
#Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
}
private void hideKeyboard() {
InputMethodManager imm = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(push_ups.getWindowToken(), 0);
}
public int calculatePushups() {
int pushupScore = 0;
int ageGroup = Integer.parseInt(null, np.getValue());
int pushupReps = Integer.parseInt(push_ups.getText().toString());
final int [][] pushupTable = {"some 2D array"};
if (pushupReps<= 60) {
pushupScore = pushupTable[pushupReps][ageGroup];
} else {
pushupScore = 60;
}
return pushupScore;
}
public int calculateSitups() {
final int [][] situpTable = {"some 2D array"};
return 0;
}
private void normalRun() {
}
private void specialRun() {
}
private void calculateRun() {
if (checkbox.isChecked()) {
specialRun();
}
else {
normalRun();
}
}
private void calculateScore() {
calculatePushups();
calculateSitups();
calculateRun();
}
public void calculateButton() {
final TextView pus = (TextView)findViewById(R.id.pushup_score);
calculate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// custom dialog
final Dialog dialog = new Dialog(context);
dialog.setContentView(R.layout.dialog_custom);
dialog.setTitle("Score");
I am trying to set the TextView to display the pushupScore here but it seems I am trying to pass a result from another method to this. I have no idea how to get it around still new with android,
//pus.setText(pushupScore);
pus.setText(String.valueOf(calculatePushups()));
Button dialogButton = (Button) dialog.findViewById(R.id.dialog_ok);
// if button is clicked, close the custom dialog
dialogButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
dialog.show();
}
});
}
}
Here's my dialog XML code:
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lineSpacingExtra="5dp"
android:text="Push-ups: "
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/pushup_score"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="4.97"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lineSpacingExtra="5dp"
android:text="Sit-ups: "
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lineSpacingExtra="5dp"
android:text="2.4km Run: "
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lineSpacingExtra="5dp"
android:text="Award: "
android:textAppearance="?android:attr/textAppearanceLarge" />
<Button
android:id="#+id/dialog_ok"
style="#style/AppTheme"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:lineSpacingExtra="5dp"
android:text="Ok" />
</LinearLayout>
you are returning the pushupScore in calculatePushups so just write:
pus.setText(String.valueOf(calculatePushups()));
And btw this is not a android mechanism, this is simple java return usage:
http://docs.oracle.com/javase/tutorial/java/javaOO/returnvalue.html
You left out quite a bit of your code so I'm not sure where your problem is, but if you could follow these steps and let me know if you're getting any errors etc? Anyway, here is what you need to have:
Make sure your Activity implements OnClickListener:
public class MainActivity extends Activity implements OnClickListener, OnValueChangeListener {
//...
}
Within the activity's overridden onCreate() method, register the activity as the handler:
calculate = (Button)v.findViewById(R.id.dialog_ok);
calculate.setOnClickListener(this);
Within MainActivity, have the handler like so:
public void onClick(View v){
switch(v.getId(){
case R.id.dialog_ok:
push_ups.setText("" + calculatePushups());
break;
}
// ...
}
Perhaps you should change your EditText into a TextView, the EditText isn't necessary and might be causing problems?
Is this what you were after?
What I want to achieve:
I want to create a drag and drop functionality in Android. I'd like to use a specific layout (different from the dragged object itself) as a drag shadow.
What result I'm getting instead:
Neither of my approaches works as expected - I end up with no visible drag shadow at all (although the target does receive the drop).
What I tried:
I tried
inflating the drag_item layout in the activity, then passing it as an argument to the shadow builder's constructor
and
inflating the drag_item layout in the shadow builder's onDrawShadow method, then drawing it on the canvas
Layouts:
My activity layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.app.DragDropTestActivity"
tools:ignore="MergeRootFrame">
<TextView
android:id="#+id/tvReceiver"
android:text="Drop here"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="#+id/btnDragged"
android:layout_height="wrap_content"
android:text="Drag me"
android:layout_width="match_parent"/>
</LinearLayout>
The layout I want to use as a drag shadow:
dragged_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Dragged Item"/>
</LinearLayout>
Source code:
Here's the code with both approaches (represented by 1, BuilderOne and 2, BuilderTwo, respectively):
package com.example.app;
import android.graphics.Canvas;
import android.graphics.Point;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
public class DragDropTestActivity extends ActionBarActivity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drag_drop_test);
Button dragged = (Button) findViewById(R.id.btnDragged);
dragged.setOnTouchListener(
new View.OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
if (event.getAction() != MotionEvent.ACTION_DOWN) {
return false;
}
LayoutInflater inflater = getLayoutInflater();
int approach = 1;
// both approaches fail
switch (approach) {
case 1: {
View draggedItem = inflater.inflate(R.layout.dragged_item, null);
BuilderOne builder = new BuilderOne(draggedItem);
v.startDrag(null, builder, null, 0);
break;
}
case 2: {
BuilderTwo builder = new BuilderTwo(inflater, v);
v.startDrag(null, builder, null, 0);
break;
}
}
return true;
}
});
}
My BuilderOne class:
public static class BuilderOne extends View.DragShadowBuilder
{
public BuilderOne(View view)
{
super(view);
}
#Override
public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint)
{
super.onProvideShadowMetrics(
shadowSize,
shadowTouchPoint);
}
}
And BuilderTwo class:
public static class BuilderTwo extends View.DragShadowBuilder
{
final LayoutInflater inflater;
public BuilderTwo(LayoutInflater inflater, View view)
{
super(view);
this.inflater = inflater;
}
#Override
public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint)
{
super.onProvideShadowMetrics(
shadowSize,
shadowTouchPoint);
}
#Override
public void onDrawShadow(Canvas canvas)
{
final View draggedItem = inflater.inflate(R.layout.dragged_item, null);
if (draggedItem != null) {
draggedItem.draw(canvas);
}
}
}
}
Question:
What do I do wrong?
Update:
Bounty added.
Kurty is correct in that you shouldn't need to subclass DragShadowBuilder in this case. My thought is that the view you're passing to the DragShadowBuilder doesn't actually exist in the layout, and therefore it doesn't render.
Rather than passing null as the second argument to inflater.inflate, try actually adding the inflated View to the hierarchy somewhere, and then passing it to a regular DragShadowBuilder:
View dragView = findViewById(R.id.dragged_item);
mDragShadowBuilder = new DragShadowBuilder(dragView);
v.startDrag(null, mDragShadowBuilder, null, 0);
EDIT
I'm aware that having the dragged_item view being rendered all the time isn't what you want, but if it works then at least we know where the problem is and can look for a solution to that instead!
Simply put it, you only need this:
private final class TouchListener implements View.OnTouchListener {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
v.startDrag(ClipData.newPlainText("", ""), new View.DragShadowBuilder(v), v, 0);
}
return true;
}
}
(You don't necessarily need the BuilderOne and BuilderTwo class)
I have a linear layout which contains 5 linear layouts as its child. I want to handle the touch event for each child linear layouts. My layout looks like this
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container">
<LinearLayout android:id="#+id/item1"
android:layout_width="match_parent"
style="#style/NavLinkItemContainer"
android:layout_height="wrap_content">
<TextView
style="#style/NaviLinkSelected"
android:text="First"/>
</LinearLayout>
<LinearLayout android:id="#+id/item2"
android:layout_width="match_parent"
style="#style/NavLinkItemContainer"
android:layout_height="wrap_content">
<TextView
style="#style/NaviLinks"
android:text="Second"/>
</LinearLayout>
<LinearLayout android:id="#+id/item3"
android:layout_width="match_parent"
style="#style/NavLinkItemContainer"
android:layout_height="wrap_content">
<TextView
style="#style/NaviLinks"
android:text="Third"/>
</LinearLayout>
<LinearLayout android:id="#+id/item4"
android:layout_width="match_parent"
style="#style/NavLinkItemContainer"
android:layout_height="wrap_content">
<TextView
style="#style/NaviLinks"
android:text="Fourth"/>
</LinearLayout>
<LinearLayout android:id="#+id/item5"
android:layout_width="match_parent"
style="#style/NavLinkItemContainer"
android:layout_height="wrap_content">
<TextView
style="#style/NaviLinks"
android:text="Fifth"/>
</LinearLayout>
</LinearLayout>
and My activity using the layout looks like
public class MainActivity extends Activity implements OnTouchListener{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.d("","ON TOUCH VIEW ######## "+v.getId());
return false;
}
}
When touching the child layouts, am not getting id(item1,item2...) in onTouch Event
Please advice.
For each layout you want to add touch listener, set onTouchListener.
for example,
LinearLayout l1 = (LinearLayout) findViewById(R.id.item2);
l1.setOntouchListener(this);
So for each ViewGroup you have to set the listener. The rest of things is already done by your. Int onTouch method you can handle touch or all ViewGroup
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (v.getId()) {
case R.id.item2:
do something
break;
case R.id.item3:
do something
break;
default:
break;
}
// if you want to consume the behavior then return true else retur false
}
Here is a solution to add an OnTouchListener to every element in the constraint, which will hide the keyboard every time you touch something but an object in the exclusion list.
import android.content.Context;
import android.support.constraint.ConstraintLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.app.AppCompatCallback;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
ConstraintLayout constraintLayout = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText editText = findViewById(R.id.editText);
//Get current ViewGroup. Might have to add an id in the layout xml for the constraint.
constraintLayout = findViewById(R.id.constraint);
//List of items that should be excluded
ArrayList<Integer> listOfExclusion = new ArrayList<>();
listOfExclusion.add(editText.getId());
addTouchListeners(listOfExclusion, constraintLayout);
}
/**
* #param excludedResIds ArrayList of list of ids that should be excluded by the addTouchListener
* #param parent ViewGroup containing the elements you want to lose focus off.
*/
void addTouchListeners(ArrayList<Integer> excludedResIds, ViewGroup parent){
parent.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
constraintLayout.requestFocus();
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
return false;
}
});
addTouchListener(excludedResIds,parent);
}
/**
* #param excludedResIds ArrayList of list of ids that should be excluded by the addTouchListener
* #param parent ViewGroup containing the elements you want to lose focus off.
*/
void addTouchListener(ArrayList<Integer> excludedResIds, ViewGroup parent)
{
for(int index = 0; index<parent.getChildCount(); ++index) {
View nextChild = parent.getChildAt(index);
try{
addTouchListener(excludedResIds, (ViewGroup) nextChild);
}catch (Exception e){
}
if(!excludedResIds.contains(nextChild.getId()))
nextChild.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
constraintLayout.requestFocus();
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
return false;
}
});
}
}
}