Implementing my own OnTouchListener - android

I would like to create my own OnTouchListener. Then I would like to encapsulate it to a .jar file for making it reusable.
This is my specific OnTouchListener:
public class TouchableView extends View implements OnTouchListener{
myTouch t=null;
public TouchableView(Context context) {
super(context);
// Set KeyListener to ourself
this.setOnTouchListener(this);
}
public TouchableView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// Set KeyListener to ourself
this.setOnTouchListener(this);
}
public TouchableView(Context context, AttributeSet attrs) {
super(context, attrs);
// Set KeyListener to ourself
this.setOnTouchListener(this);
}
public void setmyTouch(myTouch listener) {
t = listener;
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN){
t.downTouch();
return true;
}
return false;
}
public interface myTouch{
public abstract boolean downTouch();
}
}
This is how I'm trying to use it:
public class MyTouchImplement extends Activity implements myTouch{
/** Called when the activity is first created. */
TextView tv;
int i=0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv=(TextView) findViewById(R.id.tv);
TouchableView view = (TouchableView) findViewById(R.id.view);
view.setmyTouch(this);
}
#Override
public boolean downTouch() {
i++;
tv.setText(i+"");
return true;
}
}
I would like to make it work for every component that the OnTouchListener works with.

The following works for me. Please check and see if this helps. Please feel free to modify the constructor to suit your needs. For this test I used a linear layout with two TextView (txtX, txtY) fields and one GridLayout control.
MineSweeperOnTouch.java
public class MineSweeperOnTouch implements View.OnTouchListener {
private View gridLayout = null;
private TextView txtX = null;
private TextView txtY = null;
public MineSweeperOnTouch(View aGridLayout, TextView aTxtX, TextView aTxtY) {
this.gridLayout = aGridLayout;
this.txtX = aTxtX;
this.txtY = aTxtY;
}
public boolean onTouch(View v, MotionEvent event) {
txtTimeX.setText("X: " + String.valueOf(event.getX()));
txtY.setText("Y: " + String.valueOf(event.getY()));
return true;
}
}
MainActivity.java (code snippet only)
-------------------------------------
public class MainActivity extends Activity {
private MineSweeperOnTouch gridLayoutListener = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//custom code starts here
final View gridLayout = findViewById(R.id.gridLayout);
final TextView txtX = (TextView) findViewById(R.id.txtX);
final TextView txtY = (TextView) findViewById(R.id.txtY);
gridLayoutListener = new MineSweeperOnTouch(gridLayout, txtX, txtY);
gridLayout.setOnTouchListener(gridLayoutListener);
}
#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;
}
}

You've created an awfully complicated web of dependencies that you should simplify. For example you shouldn't be passing around the activity object like that.
Also you when creating an Activity class you do not need to redefine the constructors. Using the super constructors is fine. What you do need to define are the onCreate onStart onPause onStop onDestroy methods. I highly suggest you read the Activity Documentation
A simpler implementation than what you have above, would be to get rid of your myTouch interface. Remove the implements OnTouchListener from the TouchableView class and create a OnTouchListener class inside your activity class.
It would look something like this:
public class MyTouchActivity extends Activity{
TouchableView tv;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tv = new TouchableView();
tv.setOnTouchListener(new MyOwnTouchListener());
}
class MyOnTouchListener implements OnTouchListener{
public boolean onTouchEvent(View v, MotionEvent e){
switch(e.getAction){
case (MotionEvent.TOUCH_DOWN)
MyTouchActivity.this.touchDown();
break;
}
}
}
public boolean touchDown(){
//touch down happened
}
}

Related

How to distinguish for EditText's between pasting into or setting per setText()?

I have an EditText what I populate via
editText.setText(content)
The reason this is an EditText and not a TextView is because I also want to paste stuff (later when user is operating the app) in it or manually type in it, if applicable.
But I have to
reset a flag if editText set via setText()
and nothing if pasted by user
How can I distinguish how a EditText was populated? addTextChangedListener()'s callbacks are triggered in each case.
You can set Listener Class:
public interface GoEditTextListener {
void onUpdate();
}
Custom Edittext
public class GoEditText extends EditText
{
ArrayList<GoEditTextListener> listeners;
public GoEditText(Context context)
{
super(context);
listeners = new ArrayList<>();
}
public GoEditText(Context context, AttributeSet attrs)
{
super(context, attrs);
listeners = new ArrayList<>();
}
public GoEditText(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
listeners = new ArrayList<>();
}
public void addListener(GoEditTextListener listener) {
try {
listeners.add(listener);
} catch (NullPointerException e) {
e.printStackTrace();
}
}
/**
* Here you can catch paste, copy and cut events
*/
#Override
public boolean onTextContextMenuItem(int id) {
boolean consumed = super.onTextContextMenuItem(id);
switch (id){
case android.R.id.cut:
onTextCut();
break;
case android.R.id.paste:
onTextPaste();
break;
case android.R.id.copy:
onTextCopy();
}
return consumed;
}
public void onTextCut(){
}
public void onTextCopy(){
}
/**
* adding listener for Paste for example
*/
public void onTextPaste(){
for (GoEditTextListener listener : listeners) {
listener.onUpdate();
}
}
}
xml
<com.yourname.project.GoEditText
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/editText1"/>
Code
private GoEditText editText1;
editText1 = (GoEditText) findViewById(R.id.editText1);
editText1.addListener(new GoEditTextListener() {
#Override
public void onUpdate() {
//here do what you want when text Pasted
}
});
Simply extend EditText, include the flag, and override setText:
public class MyEditText extends EditText {
boolean fromSetText;
#Override
public void setText(String text) {
super.setText(text);
fromSetText = true;
}
}
You can define your own setters/getters and constructors based on your requirements.

Callback with extended EditText

I'm trying to create a custom EditText that provides an onLostFocus event. However, I can't get my head around how I tell the custom class what method to run when the focus is lost.
This is my extended EditText:
public class smtyEditText extends EditText {
public smtyEditText(Context context) {
super(context);
}
public smtyEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public smtyEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setFocusChangeListener() {
this.setOnFocusChangeListener(new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
// notify the relevant activity, probably passing it some parameters like what instance of smtyEditText triggered the event.
}
}
});
}
}
The intention of the setFocusChangeListener function was that from any given activity I could do something like:
public class AddMeal extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_meal);
EditText etMealName = (EditText) findViewById(R.id.txtmealName);
etMealName.setFocusChangeListener(this.fieldLostFocus)
}
// then
public void fieldLostFocus(eventSource) {
// run some kind of validation on the field text.
}
}
Clearly I'm "code paraphrasing" here. I also get that Interfaces, and some other "EventNotifier" class might be needed. These are the resources I've tried to decipher so far:
http://www.javaworld.com/article/2077462/learn-java/java-tip-10--implement-callback-routines-in-java.html
How to Define Callbacks in Android?
http://www.justinmccandless.com/blog/Setting+Up+a+Callback+Function+in+Android
But for whatever reason I can't crystallize what is needed. Do you have any suggestions on how I can achieve this?
You don't need the inheritance... it only adds an unnecessary layer of indirection. Just add the focus change handler in your activity.
public class AddMeal extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_meal);
EditText etMealName = (EditText) findViewById(R.id.txtmealName);
etMealName.setFocusChangeListener(new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
// call method to handle loss of focus
}
}
});
}
// then
public void fieldLostFocus(eventSource) {
// run some kind of validation on the field text.
}
}

dispatchTouchEvent in Fragment in Android

I am trying to get swipe up and swipe down gestures working in Fragment.
The same is working fine with activity. In Fragment, I have an issue with dispatchTouchEvent. How do I use dispatchTouchEvent in Fragment? Is there an equivalent way to achieve this?
#Override
public boolean dispatchTouchEvent(MotionEvent me)
{
this.detector.onTouchEvent(me);
return super.dispatchTouchEvent(me);
}
Fragments are attached to activity, not replacing activity. So you can still override dispatchTouchEvent in your fragment parent activity and pass any actions from there.
For example:
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
MyFragment myFragment = (MyFragment) getFragmentManager().findFragmentByTag("MY_FRAGMENT_TAG");
myFragment.doSomething();
return super.dispatchTouchEvent(ev);
}
If your goal is to detect/handle swipe, add touch event listener on the fragment's view after creating the view.
You must dispatchTouchEvent in your parent activity like that
Add this code to parent activity:
private List<MyOnTouchListener> onTouchListeners;
#Override
protected void onCreate(Bundle savedInstanceState) {
if(onTouchListeners==null)
{
onTouchListeners=new ArrayList<>();
}
}
public void registerMyOnTouchListener(MyOnTouchListener listener){
onTouchListeners.add(listener);
}
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
for(MyOnTouchListener listener:onTouchListeners)
listener.onTouch(ev);
return super.dispatchTouchEvent(ev);
}
public interface MyOnTouchListener {
public void onTouch(MotionEvent ev);
}
OnSwipeTouchListener:
public class OnSwipeTouchListener{
private final GestureDetector gestureDetector;
public OnSwipeTouchListener (Context ctx){
gestureDetector = new GestureDetector(ctx, new GestureListener());
}
private final class GestureListener extends SimpleOnGestureListener {
//override touch methode like ondown ...
//and call the impelinfragment()
}
public void impelinfragment(){
//this method impelment in fragment
}
//by calling this mehod pass touch to detector
public void onTouch( MotionEvent event) {
gestureDetector.onTouchEvent(event);
}
And add this code to fragment you like to dispach touch in it:
//ontouch listenr
MainActivity.MyOnTouchListener onTouchListener;
private OnSwipeTouchListener touchListener=new OnSwipeTouchListener(getActivity()) {
public void impelinfragment(){
//do what you want:D
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setting for on touch listener
((MainActivity)getActivity()).registerMyOnTouchListener(new MainActivity.MyOnTouchListener() {
#Override
public void onTouch(MotionEvent ev) {
LocalUtil.showToast("i got it ");
touchListener.onTouch(ev);
}
});
}
I use this method to get all swipe to right or left event in fragment without conflicting with other elem in page .unlike rax answer

implementing interface in android linear layout class android

I am developing small android application in which i created one class abc which extends LinearLayout and one activity xyz. Inside my class abc i define one interface in following manner
public class abc extends LinearLayout {
private OnclickxitemListener listener1;
public interface OnclickxitemListener
{
public String nil = "nilkash";
public void onclickxtitem();
}
public void setOnxitemSelectedListener(OnclickxitemListener listener)
{
this.listener1 = listener;
Log.i("#######################################", "inside set listener "+listener1);
}
public abc(Context context)
{
super(context);
}
#SuppressWarnings("deprecation")
public void initialiseImages()
{
create custome linear view here
ImageView image_View = (ImageView) parentLayout.findViewById(0);
image_View.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
String n = listener1.nil;
Log.i("#################################", "inside click"+n);
listener1.onclickxitem();
}
});
}
}
Now I tred to use this interface from my activity in following manner.
public class xyz extends Activity implements abc.OnclickxitemListener{
CustomviewActivity cubes;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
abc widget = new abc(this);
widget.setOnxitemSelectedListener(this);
cubes.initialiseImages();
}
#Override
public void onclickxitem() {
}
}
Now problem is that when I excuted image click listener in my class I am able to access variable value ("string nilkash") but I am not able to access method listener1.onclickxitem();. when i tried to acees that it gives me null pointer exception.
Whether I am doing anything wrong. How to solve this problem.
need help...
Thank you...
Ok I am really a little confused with your code. I would do something like this. If abc is my custom view in package com.test in my activity layout file xyz.xml
<com.test.abc
android:id="#+id/myview"
<!-- You can modify the values below the way you want -->
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_gravity="center"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"/>
In my abc class i would write something like this
public class abc extends ImageView{
private OnclickxitemListener listener;
public interface OnclickxitemListener
{
public String nil = "nilkash";
public void onclickxtitem();
}
public void setOnxitemSelectedListener(OnclickxitemListener l )
{
listener = l;
}
public abc(Context context, AttributeSet attrs)
{
super(context, attrs);
initialize();
}
public void initialize()
{
this.setImageResource(R.drawable.*name of the image saved in drawable*);
setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View arg0)
{
// TODO Auto-generated method stub
notifyListener();
}
});
}
private void notifyListener()
{
if (null!=listener)
listener.onclickxtitem();
}
}
Finally in your activity xyz
public class xyz extends Activity {
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.xyz);
abc myview = (abc)findViewById(R.id.myview);
myview.setOnxitemSelectedListener(new abc.OnclickxitemListener()
{
#Override
public void onclickxtitem()
{
}
});
}
}
Based on the code you pasted in, your activity needs to implement OnclickxitemListener for your abc class to callback on. Remove the onclickxitem from your activity, implement the OnclickxitemListener and let your IDE implement the unimplemented onclickxitem method from the interface.
Calling cubes.initialiseImages(); will also give you a null pointer as cubes has not been initialised. Surely you want to be calling widget.initialiseImages()?
You are able to access the listener1.nil String as this has been declared and given a value.

How to create our own Listener interface in android?

Could someone help me to create user defined listener interface with some code snippets?
Create a new file:
MyListener.java:
public interface MyListener {
// you can define any parameter as per your requirement
public void callback(View view, String result);
}
In your activity, implement the interface:
MyActivity.java:
public class MyActivity extends Activity implements MyListener {
#override
public void onCreate(){
MyButton m = new MyButton(this);
}
// method is invoked when MyButton is clicked
#override
public void callback(View view, String result) {
// do your stuff here
}
}
In your custom class, invoke the interface when needed:
MyButton.java:
public class MyButton {
MyListener ml;
// constructor
MyButton(MyListener ml) {
//Setting the listener
this.ml = ml;
}
public void MyLogicToIntimateOthers() {
//Invoke the interface
ml.callback(this, "success");
}
}
please do read observer pattern
listener interface
public interface OnEventListener {
void onEvent(EventResult er);
// or void onEvent(); as per your need
}
then in your class say Event class
public class Event {
private OnEventListener mOnEventListener;
public void setOnEventListener(OnEventListener listener) {
mOnEventListener = listener;
}
public void doEvent() {
/*
* code code code
*/
// and in the end
if (mOnEventListener != null)
mOnEventListener.onEvent(eventResult); // event result object :)
}
}
in your driver class MyTestDriver
public class MyTestDriver {
public static void main(String[] args) {
Event e = new Event();
e.setOnEventListener(new OnEventListener() {
public void onEvent(EventResult er) {
// do your work.
}
});
e.doEvent();
}
}
I have created a Generic AsyncTask Listener which get result from AsycTask seperate class and give it to CallingActivity using Interface Callback.
new GenericAsyncTask(context,new AsyncTaskCompleteListener()
{
public void onTaskComplete(String response)
{
// do your work.
}
}).execute();
Interface
interface AsyncTaskCompleteListener<T> {
public void onTaskComplete(T result);
}
GenericAsyncTask
class GenericAsyncTask extends AsyncTask<String, Void, String>
{
private AsyncTaskCompleteListener<String> callback;
public A(Context context, AsyncTaskCompleteListener<String> cb) {
this.context = context;
this.callback = cb;
}
protected void onPostExecute(String result) {
finalResult = result;
callback.onTaskComplete(result);
}
}
Have a look at this , this question for more details.
There are 4 steps:
1.create interface class (listener)
2.use interface in view 1 (define variable)
3.implements interface to view 2 (view 1 used in view 2)
4.pass interface in view 1 to view 2
Example:
Step 1: you need create interface and definde function
public interface onAddTextViewCustomListener {
void onAddText(String text);
}
Step 2: use this interface in view
public class CTextView extends TextView {
onAddTextViewCustomListener onAddTextViewCustomListener; //listener custom
public CTextView(Context context, onAddTextViewCustomListener onAddTextViewCustomListener) {
super(context);
this.onAddTextViewCustomListener = onAddTextViewCustomListener;
init(context, null);
}
public CTextView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public CTextView(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public CTextView(Context context, #Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
public void init(Context context, #Nullable AttributeSet attrs) {
if (isInEditMode())
return;
//call listener
onAddTextViewCustomListener.onAddText("this TextView added");
}
}
Step 3,4: implements to activity
public class MainActivity extends AppCompatActivity implements onAddTextViewCustomListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//get main view from layout
RelativeLayout mainView = (RelativeLayout)findViewById(R.id.mainView);
//create new CTextView and set listener
CTextView cTextView = new CTextView(getApplicationContext(), this);
//add cTextView to mainView
mainView.addView(cTextView);
}
#Override
public void onAddText(String text) {
Log.i("Message ", text);
}
}
Create listener interface.
public interface YourCustomListener
{
public void onCustomClick(View view);
// pass view as argument or whatever you want.
}
And create method setOnCustomClick in another activity(or fragment) , where you want to apply your custom listener......
public void setCustomClickListener(YourCustomListener yourCustomListener)
{
this.yourCustomListener= yourCustomListener;
}
Call this method from your First activity, and pass the listener interface...
In the year of 2018, there's no need for listeners interfaces. You've got Android LiveData to take care of passing the desired result back to the UI components.
If I'll take Rupesh's answer and adjust it to use LiveData, it will like so:
public class Event {
public LiveData<EventResult> doEvent() {
/*
* code code code
*/
// and in the end
LiveData<EventResult> result = new MutableLiveData<>();
result.setValue(eventResult);
return result;
}
}
and now in your driver class MyTestDriver:
public class MyTestDriver {
public static void main(String[] args) {
Event e = new Event();
e.doEvent().observe(this, new Observer<EventResult>() {
#Override
public void onChanged(final EventResult er) {
// do your work.
}
});
}
}
For more information along with code samples you can read my post about it, as well as the offical docs:
When and why to use LiveData
Official docs
In Android,you can create an interface such as Listener,and your Activity implements it,but i don't think it is a good idea.
if we have many components to listen the changes of their state,we can create a BaseListener implements interface Listener,and use type code to handle them.
we can bind the method when we create XML file,for example:
<Button
android:id="#+id/button4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button4"
android:onClick="Btn4OnClick" />
and the source code:
public void Btn4OnClick(View view) {
String strTmp = "点击Button04";
tv.setText(strTmp);
}
but i don't think it is a good idea...
I have done it something like below for sending my model class from the Second Activity to First Activity. I used LiveData to achieve this, with the help of answers from Rupesh and TheCodeFather.
Second Activity
public static MutableLiveData<AudioListModel> getLiveSong() {
MutableLiveData<AudioListModel> result = new MutableLiveData<>();
result.setValue(liveSong);
return result;
}
"liveSong" is AudioListModel declared globally
Call this method in the First Activity
PlayerActivity.getLiveSong().observe(this, new Observer<AudioListModel>() {
#Override
public void onChanged(AudioListModel audioListModel) {
if (PlayerActivity.mediaPlayer != null && PlayerActivity.mediaPlayer.isPlaying()) {
Log.d("LiveSong--->Changes-->", audioListModel.getSongName());
}
}
});
May this help for new explorers like me.
Simple method to do this approach. Firstly implements the OnClickListeners in your Activity class.
Code:
class MainActivity extends Activity implements OnClickListeners{
protected void OnCreate(Bundle bundle)
{
super.onCreate(bundle);
setContentView(R.layout.activity_main.xml);
Button b1=(Button)findViewById(R.id.sipsi);
Button b2=(Button)findViewById(R.id.pipsi);
b1.SetOnClickListener(this);
b2.SetOnClickListener(this);
}
public void OnClick(View V)
{
int i=v.getId();
switch(i)
{
case R.id.sipsi:
{
//you can do anything from this button
break;
}
case R.id.pipsi:
{
//you can do anything from this button
break;
}
}
}

Categories

Resources