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.
Related
I recently started coding my first Android project using Android Studio 3.1.2 and SDK 19.
One of my fragments contains a RecyclerView with a custom RecyclerView.Adapter attached. On the CardView the Adapter gets by its ViewHolder, there can be a button. The target is, if the button is pressed, a method of my fragment should be called, though it's an instance of a custom subclass of Fragment:
From RequestingFragment:
public abstract class RequestingFragment extends Fragment implements RequestCallbacks {
public final static void startRequest(final RequestOperation, String param) {
//this is the guy i want to call
}
//these are the RequestCallbacks, they're all getting called in startRequest()
public void onSuccess(JSONObject json, String parsingkey) { }
public void onError() { }
public void onFinished() { }
Now one of my RequestingFragments contains a RecyclerView, on which a custom ErrorCompactAdapter is attached. Inside the Adapters ViewHolder, where I load the layout for the single CardViews, there's a button, which should call startRequest() onClick from my RequestingFragment
From ErrorCompactAdapter:
public class ErrorCompactAdapter extends RecyclerView.Adapter<ErrorCompactAdapter.ErrorCompactViewHolder> {
private Context context;
private ArrayList<Error> errors;
public ErrorCompactAdapter(Context context, ArrayList<Error> errors) {
this.context = context;
this.errors = errors;
}
public void onBindViewHolder(ErrorCompactViewHolder, int position) {
//...
holder.errorTakeOverButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//here's were i'm stuck
}
});
//...
}
}
My first approach was to change the context attribute of ErrorCompactAdapter to a RequestingFragment, so that I can call startRequest() on this.
private Context context; // private RequestingFragment attacher;
public void onClick(View v) {
attacher.startRequest(/*params*/);
}
But i'm very unsure, if the fragment that contains the RecyclerView will be the one which receives the response of the request, or if a somehow "pseudo-anonymous" Fragment will receive the response and simply does nothing with it then. Can someone enlight me, if this is the correct path? Thanks in advance.
Pass the Fragment in you ErrorCompactAdapter class's constructor. This works for me the way I want. I had the same issue.
RequestingFragment mFragment;
public ErrorCompactAdapter(Context context, ArrayList<Error> errors,
RequestingFragment fragment)
{
this.context = context;
this.errors = errors;
this.mFragment = fragment;
}
// While passing the fragment into your adapter, do it this way.
ErrorCompactAdapter errorCompactAdapter = new ErrorCompactAdapter(
context, errors, RequestingFragment.this);
holder.errorTakeOverButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// use you method of fragment here
mFragment.startRequest();
}
});
is there a way to create a listener that activates an event under a certain condition(boolean)?
i tried reading about creating custom listeners using interfaces but i dont think it's the answer for my question.
right now in my app i write an if statement everywhere so if i could just create a listener for it, it would be much easier.
set_A==B_Listener(????? {//listener takes place if a==b
#Override
public boolean event(View v, MotionEvent e)
{
//do something
}
});
Create a class variable for your statement, than you can attach an OnChangeListener to your statement in the onCreate method of your Activity
public class DummyActivity extends Activity {
interface OnStateChangeListener{
public void onAttach(Activity activity);
public void onStateChange(boolean state);
}
private boolean state;
private OnStateChangeListener listener;
private YourClass stateChangedCallback;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
listener = new OnStateChangeListener() {
private Activity currentActivity;
#Override
public void onAttach(Activity activity) {
currentActivity = activity;
}
#Override
public void onStateChange(boolean state) {
if (((DummyActivity) this.currentActivity).state != state) {
stateChangedCallback.doSomething();
((DummyActivity) this.currentActivity).state = state;
}
}
};
}
private void yourFunction() {
boolean state = true;
listener.onStateChange(state);
}
}
Please help me with this, i never ever understanded how things work inside onClickListener, so:
Got my own class:
public class ItemFrame extends LinearLayout{
int item_id;
public ItemFrame(Context context){
super(context);
}
public int getItem_id() {
return item_id;
}
public void setItem_id(int item_id) {
this.item_id = item_id;
}
}
I initalize one and add an onClickListener:
ItemFrame myItemFrame = new ItemFrame(this);
myItemFrame.setOnClickListener(new OnClickListener(){
public void onClick(View v){
//ERROR HERE:
//Cannot refer to a non-final variable myItemFrame inside an inner class
//defined in a different method
//Quick fix: Change modifier of 'myItemFrame' to final.
myItemFrame.setItemId(100);
}
});
So... My question is:
How can i set a data tag of my class, inside the onClickListener???
If i change it to final as Eclipse says, i cant modify it since it is final.
Does it make any sense ?
The OnClickListener that you created is an anonymous inner class and can only refer to final values.
Simply change:
ItemFrame myItemFrame = new ItemFrame(this);
to be:
final ItemFrame myItemFrame = new ItemFrame(this);
You can still modify the ItemFrame object that you created. You just can't reassign a new one to the myItemFrame variable.
There is another way to implement your code, have a look at it.
public class ItemFrame extends LinearLayout implements OnClickListener
{
int item_id;
public ItemFrame(Context context)
{
super(context);
}
public int getItem_id()
{
return item_id;
}
public void setItem_id(int item_id)
{
this.item_id = item_id;
}
public void onClick(View v)
{
setItemId(100);
}
}
I have an activity which creates an object instance of my class:
file MyActivity.java:
public class MyActivity extends Activity {
TextView myView = (TextView)findViewById(R.id.myView);
...
Points myPoints new Points();
...
}
--------------------------------------------------------------
file Points.java:
private class Points {
...
HOW TO USE myView HERE ???
...
}
--------------------------------------------------------------
How do I use the UI objects in my class (which does not extend an
Activity)? Should I pass some context to my Points class? How do I do, exactly?
see you post, i've edited it , to fix the problem
hope it helps :=)
here is the Edit :
file MyActivity.java:
public class MyActivity extends Activity {
TextView myView ;
protected void onCreate(android.os.Bundle savedInstanceState) {
myView = (TextView)findViewById(R.id.myView);
Points myPoints = new Points(this);
myPoints.displayMsg("Hello World !!!");
}
}
--------------------------------------------------------------
file Points.java:
private class Points {
protected MyActivity context;
//add a constructor with the Context of your activity
public Points(MyActivity _context){
context = _context;
}
public void displayMsg( final String msg){
context.runOnUiThread(new Runnable() {
#Override
public void run() {
context.myView.setText(msg);
}
});
}
}
Your Points can't be a private class without being an inner class. So your code doesn't even compile...
Pass the view as parameter to the constructor of your Points class:
public class MyActivity extends Activity {
TextView myView = (TextView)findViewById(R.id.myView);
Points myPoints new Points(myView);
private class Points {
public Points(TextView view) {
// todo
}
}
}
You should do everything and pass back the value to the activity to handle UI instead of doing any UI related stuff in the point stuff.
You can pass the main Activity's context (using Points(getApplicationContext());) to the class as a constructor parameter. You could also pass the specific UI elements you want to manipulate.
A better way to do it, however, may be to have Points not know about the Activity. Have your Activity call Points methods and take the necessary actions based on the method output.
You could just pass the view to your class.
Points myPoints = new Points(myView);
private class Points
{
private TextView mTextView;
Points(TextView textView)
{
this.mTextView = textView;
}
}
i was in same trouble..
i found the simple way..
make a static variable and function ...
call from other class..
TestActivity.java
public class TestActivity extends Activity {
static EditText edit_text1;
public void onCreate(Bundle savedInstanceState)
{
.....
edit_text1 = (EditText) findViewById(R.id.edit_text1);
.....
}
public static void setMSG(String str)
{
edit_text1.setText(str);
}
}
Test2.java
TestActivity.setMSG("this is text");
Could work using an interface
file MyActivity.java:
public class MyActivity extends Activity implements Points.MyListener {
TextView myView;
... onCreate(...){
myView = (TextView)findViewById(R.id.myView);
Points myPoints = new Points();
//pass in MyActivity's instance of the listener
myPoints.addListener(this);
}
#Override
public void updateTextView(String message){
myView.setMessage(message);
}
}
file Points.java:
public class Points {
public Points(){
}
public interface MyListener{
void updateTextView(String message);
}
MyListener myListener;
public void addListener(MyListener listener){
myListener = listener;
}
public void updatePoints(){
//do some operations in calculatePoints()
String points = calculatePoints();
//update views using MyActivity's implementation of updateTextView()
myListener.updateTextView(points);
}
}
Doing it this way, events can be fired / messages sent, for lack of better terms, from the external class to update the Activity UI. This might be overkill if all sb need is to call a method in the Points class that returns something
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;
}
}
}