How to create a custom drag shadow? - android

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)

Related

How to make touch events through accessibilty service overlay?

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

Set Click to two different triangular images in a single layout

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;
}
});

Add a transparent fragment on top of an existing layout(android0

I am trying to create a sort of a transparent tutorial which appears only
the first time. This is the fragment i have created. How do I add this on top of an existing layout
here's the code for the fragment
import android.app.Fragment;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import in.webblue.nuclity.Activity.Logs.SaveLog;
import in.webblue.nuclity.R;
import static android.content.Context.MODE_PRIVATE;
/**
* Created by Akshay on 15-06-2017.
*/
public class TutorialFragment extends Fragment {
private String Class_Name = "TutorialFragment";
private boolean ranBefore;
View topLevelLayout1;
View topLevelLayout2;
View myView;
String methodName = "onCreateView";
public static TutorialFragment newInstance() {
TutorialFragment f = new TutorialFragment();
return f;
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myView = inflater.inflate(R.layout.tutorial_layout, container,
false);
topLevelLayout1=myView.findViewById(R.id.tutorial1);
topLevelLayout2=myView.findViewById(R.id.tutorial2);
if (!isFirstTime()) {
topLevelLayout1.setVisibility(View.INVISIBLE);
topLevelLayout2.setVisibility(View.INVISIBLE);
}
return myView;
}
private boolean isFirstTime()
{
try {
SharedPreferences preferences =
this.getActivity().getSharedPreferences("RanBefore", MODE_PRIVATE);
boolean ranBefore = preferences.getBoolean("RanBefore", false);
if (!ranBefore) {
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("RanBefore", true);
editor.commit();
topLevelLayout1.setVisibility(View.VISIBLE);
topLevelLayout2.setVisibility(View.INVISIBLE);
topLevelLayout1.setOnTouchListener(new
View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
topLevelLayout1.setVisibility(View.INVISIBLE);
topLevelLayout2.setVisibility(View.VISIBLE);
return false;
}
});
topLevelLayout2.setOnTouchListener(new
View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
topLevelLayout2.setVisibility(View.INVISIBLE);
return false;
}
});
}
}
catch (Exception e){
Log.e(getClass().getName(),"Method Name :"+methodName+ " "+ e.getStackTrace().toString());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
SaveLog.saveLog(getContext(),Class_Name,methodName,e.toString());
}
}
return ranBefore;
}
}
I need to add this on top of an existing layout
I think FrameLayout is the way to go here.
The secret of FrameLayout is how it layouts its children. Although normally designed to contain one item, it will happily stack up other element on top of each other. Thus FrameLayout is essentially a way to manipulate the Z-order of views on the screen
Here a thread about what a FrameLayout can do:
what does FrameLayout do?
So your Layout would look something like this:
<FrameLayout>
<Fragment/>
<LinearLayout>
// here is your normal layout
</LinearLayout>
</>
You could do it the following way.
This is your activity on top of which you need to add the fragment.
<?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"
android:orientation="vertical">
<LinearLayout
android:id="#+id/example_fragment_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
//YOUR LAYOUT
</LinearLayout>
<LinearLayout
android:id="#+id/example_fragment_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:onClick="EndFragment">
/*THE FRAGMENT YOU WANT TO SHOW. THE LOGIC TO SHOW THIS FRAGMENT
ONLY ONCE WILL HAVE TO BE IN THE ACTIVITY ON TOP OF WHICH YOU ARE
SHOWING THIS FRAGMENT*/
<fragment
android:id="#+id/example_fragment"
android:name="com.example.ExampleFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</RelativeLayout>
Now what you should do is show this fragment only once. The onClick method to hide this fragment is as follows:
public void EndFragment(View view) {
example_fragment_parent.setVisibility(View.GONE);
}
You need to find this fragment in the onCreate() of your activity like below:
LinearLayout example_fragment_parent =
(LinearLayout)findViewById(R.id.example_fragment_parent);

How to pass value from a method to another method

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?

Handling touch Events for all layouts in xml

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;
}
});
}
}
}

Categories

Resources