I am pretty new at android/java development and I am trying to process onClick events in an array of view from a "library" class but I can't figure out how it should work.
What I have so far is :
For the library :
public class WordArea {
private ImageView[] imageViewArray;
public boolean createWordTemplate(Activity myActivity, int layoutId, int numberOfLetters, int[] imageArray) {
imageViewArray = new ImageView[10];
// .....
for (int i = 0; i < 10; i++) {
// ...
imageViewArray[i].setClickable(true);
layout.addView(imageViewArray[i], params);
imageViewArray[i].setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
thisIsWhereIwouldLikeTheCallbackToWork( v );
}
});
Then in my activity class I am defining objects like this :
private WordArea myWordArea = new WordArea();
And I would like to define in the activity class the method to be called by the setOnClickListener
Can anyone please help me with the code I should put in the library and in the activity class to make it work ?
Related
I have two inner classes named CalculatorClass and UpdatePayment in MainActivity class.
In UpdatePayment class there is a for loop and I have a array of Buttons.
I want to add listener to each button in loop. Those buttons will initialize the CalculatorClass and get value of calculations.
Demo code is:
public static class MainActivity{
private interface UpdateEditText{
void onCallback(String s);
}
private class CalculatorClass extends Dialog{
UpdateEditText updateEditText;
public CalculatorInterface(#NonNull Context context, UpdateEditText updateEditText) {
super(context);
this.updateEditText = updateEditText;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.calculator);
initialize();
}
initialize(){
.......................
s = "Some texts";
updateEditText.onCallback(s);
}
}
private class UpdatePayment extends Dialog{
private Button[] button = new Button[100];
private EditText[] editText = new EditText[100];
public CalculatorInterface(#NonNull Context context) {
super(context);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.update);
initialize();
}
initialize(){
.......................
for(int i = 0; i < MAXSize; i++){
button[i] = new Button(MainActivity.this);
editText[i] = new EditText(MainActivity.this);
//add buttons to view to layout
button[i].setOnclickListener(new View.OnClickListener(){
public void onClick(View v) {
CalculatorClass calculator = new
CalculatorClass(MainActivity.this,
new UpdateEditText() {
#Override
public void onCallback(String s) {
editText[i - 1].setText(s);
}
});
calculator.show();
}
);
}
}
}
}
Problem is the line editText[i].setText(s) work for the last editText what ever button I click, i.e, any button I click, it fills the editText[MaxSize -1]
What should I do?
How can I perform this action for all i?
Please help me, I tried a lot searching in internet, still I didn't get any solution.
Anonymous classes are very much treated like static variables in java.It's happenning because your i value after your activity is initialized is equal to 1 less than the length of the edit text array.
editText[indicies_of_button_clicke].setText(s)
How you will get the indicies of button clicked is by :
se the tag to button below this line "editText[i] = new EditText(MainActivity.this);", like this :
button[i].setTag(i)
to retreive the index of your actual button clicked inside button clicklisteners,
v.getTag()// this will give you an integer value which will be the indices of actual button clicked
//use this value to set your edit text value.
Solution:
After a whole night, I got answer, now I feel awwww, this was easy go!
I never came in this thought.
button[i].setId(i);
then call:
CalculatorClass calculator = new CalculatorClass(MainActivity.this, v.getId(),
new UpdateEditText() {
#Override
public void onUpdate(String s, int ID) {
Log.i("test", ID + "");
editText[ID].setText(s);
}
});
At the same time, #Rishabh Ritweek answered correctly.
Thanks to him.
I have the following code for the recyclerview adapter for an android app that I'm working on right now:
#Override
public void onBindViewHolder(final FeedViewHolder contactViewHolder, final int i) {
final FeedInfo ci = feedInfoList.get(i);
//Set the text of the feed with your data
contactViewHolder.feedText.setText(ci.getFeed());
contactViewHolder.surNameText.setText(ci.getSurName());
contactViewHolder.nameText.setText(ci.getFirstName());
contactViewHolder.feedDate.setText(ci.getDate());
contactViewHolder.numberOfGoingText.setText(ci.getNumber_of_going());
contactViewHolder.numberOfInterestedText.setText(ci.getNumber_of_interested());
//seteaza fotografia de profil in postare
new ProfilePictureDownloadImage(contactViewHolder.profilePicture).execute(ci.getProfileImageURL());
ImageButton interestedButton = contactViewHolder.interestedButton;
interestedButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = i;
FeedInfo fi = feedInfoList.get(position);
int displayedNumberOfInterested = Integer.parseInt(ci.getNumber_of_interested()) + 1;
contactViewHolder.numberOfInterestedText.setText(Integer.toString(displayedNumberOfInterested));
System.out.println("emilutzy interested from within" + fi.getPostID());
contactViewHolder.surNameText.setText("kk");
}
});
}
The problem is the click listener. In theory the button I press should increment the number right next to it. However, since I have to declare onBindViewHolder's arguments as final, only the first click works, the rest of the clicks do not change the value of the number. I am new to Android, so could you please help me find a better solution?
There's a nice method called getAdapterPosition() that you can use in your RecyclerView's ViewHolder.
Instead of setting the click listener in onBindViewHolder, set it in the constructor of your ViewHolder like so:
public class FeedViewHolder extends RecyclerView.ViewHolder {
private TextView feedText;
private TextView surNameText;
private Button interestedButton;
// ... the rest of your viewholder elements
public FeedViewHolder(View itemView) {
super(itemView);
feedtext = itemView.findViewById(R.id.feedtext);
// ... find your other views
interestedButton.setOnClickListener(new View.OnClickListener() {
final FeedInfo fi = feedInfoList.get(getAdapterPosition());
int numInterested = Integer.parseInt(ci.getNumber_of_interested()) + 1;
// setting the views here might work,
// but you will find that they reset themselves
// after you scroll up and down (views get recycled).
// find a way to update feedInfoList,
// I like to use EventBus to send an event to the
// host activity/fragment like so:
EventBus.getDefault().post(
new UpdateFeedInfoListEvent(getAdapterPosition(), numInterested));
// in your host activity/fragment,
// update the list and call
// notifyDatasetChanged/notifyDataUpdated()
//on this RecyclerView adapter accordingly
});
}
}
Don't set your position in onBindViewHolder to final (Android Studio will warn you why).
I'm not sure how the object FeedInfo looks like but you could also at a method called for example increaseNumberOfInterested() which would increase the value of Number_of_interested by one and would persist in the object when the recyclerview recycle the cell. it would like kind of like below
#Override
public void onBindViewHolder(final FeedViewHolder contactViewHolder, final int i) {
final FeedInfo ci = feedInfoList.get(i);
//Set the text of the feed with your data
contactViewHolder.numberOfInterestedText.setText(ci.getNumber_of_interested());
contactViewHolder.interestedButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Increase the number of interested in the object, so it can be persisted when cell is reclycled
ci.setNumberOfInterested(ci.getNumber_of_interested()) + 1);
//Get new value and display
contactViewHolder.numberOfInterestedText.setText(Integer.toString(ci.getNumber_of_interested()));
}
Sorry if this question might be stupid for you, but I'm new to Android programming and I can't wrap my head around Java syntax.
Can you explain what is happening with this line of code step by step?
View.OnClickListener ourOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View v){
ourMessage.setText(“The button got tapped”);
}
};
There is an interface declared inside View class, and it's OnClickListener, it looks like this in View.java source:
/**
* Interface definition for a callback to be invoked when a view is clicked.
*/
public interface OnClickListener {
/**
* Called when a view has been clicked.
*
* #param v The view that was clicked.
*/
void onClick(View v);
}
Normally you would create a class, and have it implement this interface:
public void MyClass implements View.OnClickListener {
#Override
public void onClick(View view) {
// do stuff
}
}
But sometimes you don't need this class in a separate file. Instead, you can create anonymous inner class, it's like creating new class, which only methods are the one from the interface specified:
new View.OnClickListener() {
#Override
public void onClick(View v){
ourMessage.setText(“The button got tapped”);
}
}
You can then use instance of this class everywhere the View.OnClickListener interface is needed.
What's also worth mentioning is that anonymous inner class will hold a reference to the class in which you're creating it. So this will be legal and valid:
public class MyClass {
private int clicksCount = 0;
private View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View view) {
clicksCount += 1;
}
}
}
Here you can access clicksCount field, which is field of MyClass even from the inner class that implements OnClickListener. Side note - if you want to access a variable, you need to add final modifier to it:
public void testMethod(final int canAccess, int cantAccess) {
final String test = otherView.getText().toString();
myView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Cannot access cantAccess, because it's not final
if (test.length == 0) { // can access
// do something
}
}
}
I am quite a beginner and trying to access the instance variable of an object array in the child class but all I get is the initialized values instead of updated values. It is a little more complex but making it simple, the code can be put this way.
Seed.java
public class Seed {
int weight = 0;
}
Apple.java
public class Apple {
public Seed[] seed = new Seed[10];
}
MainActivity.java
Main Activity {
public static Apple[] apple = new Apple[2];
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
apple[0] = new Apple();
for (int i = 0; i < 10; i++)
apple[0].seed[i] = new seed();
assign();
//and here new activity childActivity starts
}
public void assign() {
for(int i =0; i < 10; i++)
apple[0].seed[i].weight = 10;
}
}
ChildActivity.java
ChildActivity extends mainActivity {
//display a layout with a button
//upon button click
display();
public void display() {
//output to textview
String.valueOf(apple[0].seed[0].weight);
}
gives me output of 0 instead of 10. I am not able to figure out whats wrong. I checked the values are being assigned properly in the mainActivity. I get no errors or crashes. Thanks for the help!
I'm trying to pass something from one class to my MainActivity, but it doesn't seem to work, I don't understand why.
I have my GPS Tracker on another class (not the MainActivity) in order to reuse it.
When the location changes, I want my other class to call a method from within the MainActivity to update my UI.
I summarized my code like that :
My MAIN ACTIVITY :
public class MainActivity extends Activity implements OnClickListener {
TextView tv;
EditText et;
Button btun;
int arg0;
int stuff;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
et = (EditText) findViewById(R.id.et);
btun = (Button) findViewById(R.id.btun);
btun.setOnClickListener(this);
}
private void setter(int stuff) {
tv.setText(stuff);
}
public void setText(int _stuff) {
_stuff = stuff;
setter(_stuff);
}
#Override
public void onClick(View v) {
Getter get = new Getter();
get.getInfo(Integer.parseInt(et.getText().toString()));
}
The other Class :
public class Getter {
int _getString;
MainActivity main = new MainActivity();
public void getInfo(int getString) {
_getString = getString * 8;
main.setText(_getString);
}
}
I end up having a NullPointerException in my LogCat
at :
- tv.setText(stuff);
- setter(_stuff);
- main.setText(_getString);
- get.getInfo(Integer.parseInt(et.getText().toString()));
and I don't really know why, and above all, how to fix it.
I'll appreciate any help !
(PS : My GPS tracker thingy is working fine, it's just about invoking my setter() method.
Instantiaing an Object of MainActivity doesn't automatically call onCreate method but this method is called when you start an activity using Intent; And using the same intent you can pass extra values. For example:
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra("key", value);
context.startActivity(intent);
and then in your main activity onCreate method:
String value = getIntent.getStringExtra("key");
Edit:
In your case why don't you change your void getInfo(int getString) to return a String value i.e.
public class Getter {
...
...
public String getInfo(int getString) {
_getString = getString * 8;
return Integer.toString(_getString);
}
}
and then in onClick event of MainActivity bind this returned text to TextView
It's maybe because the MainActivity's onCreate()-Method hasn't been called. Therefore the tv is still null causing the NullPointerException
One problem is here. main is an Activity, but it should be the MainActivity calling this object.
public class Getter {
int _getString;
MainActivity main = new MainActivity();
public void getInfo(int getString) {
_getString = getString * 8;
main.setText(_getString);
}
}
I cannot really make out what you are trying to achieve in the Getter class, but either:
1: Pass the Activity instance to the object
public class Getter {
int _getString;
MainActivity _main = null;
public Getter(MainActivity main) {
_main = main;
}
public void getInfo(int getString) {
_getString = getString * 8;
_main.setText(_getString);
}
}
#Override
public void onClick(View v) {
Getter get = new Getter(this);
get.getInfo(Integer.parseInt(et.getText().toString()));
}
or
2: set the text in the Activity and only get the value from the Getter (My choice)
public class Getter {
int _getString;
MainActivity main = new MainActivity();
public void getInfo(int getString) {
return getString * 8;
}
}
#Override
public void onClick(View v) {
Getter get = new Getter();
int info = get.getInfo(Integer.parseInt(et.getText().toString()));
setText(Integer.toString(info));
}
Use Application Class or create a separate Class and declare a static variable in it. Use getter & setter methods to get the value. To update the Textview in mainacivity from other class pass the texview reference variable from main activity and put null check condition in other class if textview is not null then update the value.