I have created the customAdapter of ListView. when I click the Button in the ListView,I want to control the TextView outside the ListView from different layout. Notice ! There are not in the same Java code.
here is what I want to do:
viewHolder.plus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
TextView tx=(TextView) txt.findViewById(R.id.moneytext);
//find the textview outside listview (now In the same java code and xml)
totalmoney= (Integer.parseInt(tx.getText().toString()))+(Integer.parseInt(price[position]));
//get the textview integer and add to my present number
tx.setText(""+totalmoney);
//post on the textview
}
});
There is couple ways to do that I remember 3 of :
1) Add TextView to your ListView adapter constructor's parameters
2) Add your Activity to constructor
3) Use Event based solution like EventBus [This can be used even your TextView and ListView in different Activity and you don't need parameters]
There is example of 1 and 2:
public class YourListAdapter{
TextView strangerTextView;
YourActivity yourActivity;
public YourListAdapter(TextView strangerTextView,Activity yourActivity){
//using one of them is enough
this.strangerTextView=strangerTextView;
this.yourActivity=yourActivity;
}
//when changing text use like
strangerTextView.setText("Class Board");
//or (make sure you have global public textview attribute in your YourActivity class)
yourActivity.textview.setText("Class Board");
}
For EventBus :
1) Create a class that holds event information :
public class TextChangeEvent{
public String newtext;
public TextChangeEvent(String newtext){
this.newtext=newtext;
}
}
2) Then in your relevant Activity :
#Override
protected void onStart() {
super.onStart();
if(!EventBus.getDefault().isRegistered(this))EventBus.getDefault().register(this);
}
#Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
#Subscribe
public void onEvent(TextChangeEvent event) {
this.textView.setText(event.newtext)
}
3) Post events like that, anywhere you want :
EventBus.getDefault().post(new TextChangeEvent("newtext"));
Are your TextView in the same activity? If yes, then you should put
tx = (TextView) findViewById(R.id.moneytext);
in onCreate() method and then access it from listener you have:
tx.setText("" + totalmoney);
If it is not in the same activity, you can make something like this:
public class ClassA extends Activity
{
public TextView textView;
public void onCreate()
{
super.onCreate();
textView = (TextView) findViewById(R.id.moneytext);
}
}
public class ClassB extends Activity
{
...
viewHolder.plus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//classA is a global variable that you get for example from contructor
tx = classA.textView;
totalmoney= (Integer.parseInt(tx.getText().toString()))+(Integer.parseInt(price[position]));
//get the textview integer and add to my present number
tx.setText(""+totalmoney);
//post on the textview
}
});
...
}
Related
I'm playing around with Firebase and Android and I'm storing my data online in Firebase. I have an activity with 3 EditTexts and a button and I want it to essentially check that the 3 values in the textboxes are in the database and if so, move onto the next activity.
These values are static and so I'm using the .addListenerForSingleValueEvent method and using it as an anonymous function. I want this to work even if the device is offline but if any of the values come back as null then I want it to reject moving to the next activity.
Is there any way to detect when Firebase has either retrieved a value from the database or retrieved null from the database? This way I could check each value consecutively and if any return null then reject changing activities.
The only other thing I could think to do is to nest the anonymous functions for each listener but that sounds like it would be a bad idea.
Any advice would be much appreciated. Thanks!
Well, i understand you want to check for values in your database before moving to the next activity. My advice is that
1) create an ArrayList of DatabaseReference that point to the data locations in firebase in your activity.
Arraylist<DatabaseReference> list = new ArrayList<>();
list.add(FirebaseDatabase.getInstance().getReference().child("my_child_node_1"):
list.add(FirebaseDatabase.getInstance().getReference().child("my_child_node_2"):
list.add(FirebaseDatabase.getInstance().getReference().child("my_child_node_3"):
2) create an interface and a call back method.
public static interface DataCallback {
static void onDataAdded(String string); //Use the necessary data type
}
3) use the interface to create a constructor for your Event listener.
public static class DataListener implements ValueEventListener {
private DataCallback dataCallback;
public DataListener(DataCallback dataCallback) {
this.dataCallback = dataCallback;
}
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String data = snapshot.getValue(String.class);
//This is step 4
if(dataCallback!=null) {
dataCallback.onContactAdded(data);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
}
4) Pass the value from the listener to your activity as follows inside onDataChange() method of the Listener
if(dataCallback!=null) {
dataCallback.onContactAdded(data);
}
5) implement the interface in your activity and override its callback method
public class MyActivity extends AppCompatActivity implements DataCallback{
private EditText edittext1;
private EditText edittext2;
private EditText edittext3;
private ArrayList<String> my_list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//do stuff...
}
#Override
public void onDataAdded(String data) {
}
}
6) Instantiate and add the listener in your activity's onResume() method
#Override
public void onResume(){
super.onResume();
DataListener listener = new DataListener(this);
list[0].addListenerForSingleValueEvent(listener);
list[1].addListenerForSingleValueEvent(listener);
list[2].addListenerForSingleValueEvent(listener);
}
7) get the values from firebase in your activity inside the Callback method as follows
#Override
public void onDataAdded(String data){
my_list.add(data);
}
8) you can check if the values gotten from firebase match the values gotten from the EditText inside the OnClicklistener for you button.
if (button != null) {
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(my_list.contains(edittext1.getText().toString)){
if(my_list.contains(edittext.getText().toString)){
if(my_list.contains(edittext.getText().toString)){
startActivity(new intent(MyActivity.this, NextActivity.class))
}
}
}
}
});
}
9) remove the listeners inside the onPause() method.
#Override
public void onPause(){
super.onPause();
list[0].removeEventListener(listener);
list[1].removeEventListener(listener);
list[2].removeEventListener(listener);
}
I have 7 buttons in all my 6 activities. All 6 buttons have the same functionality in all activities. How can I perform a common click event lisnter for these 6 buttons.
You can create a new class that implements View.OnClickListener like this:
public class MyClickListener implements View.OnClickListener {
#Override
public void onClick(View view) {
// TODO handle the click
}
}
In all your activities you can then set the click listener like this:
button.setOnClickListener(new MyClickListener());
You could even save the context in the class for displaying Toasts etc.
public class MyClickListener implements View.OnClickListener {
private Context context;
public MyClickListener(Context context) {
this.context = context;
}
#Override
public void onClick(View view) {
Button button = (Button) view;
Toast.makeText(this.context, button.getText().toString(), Toast.LENGTH_SHORT).show();
}
}
Have a class like this:
public class OnClickMaker{
public static View.OnClickListener getOnClick(){
return new View.OnClickListener(){
public void on click(View v){
//do stuff
}
};
}
}
And then in your other class, do this
button.setOnClickListener(OnClickMaker.getOnClick());
Putting more words in Sagar's answer given above.
Assumption:
As you have said you have 7 buttons in your 6 activities, I assume all the 7 buttons have same functionality/code.
Solution:
Step 1: Include android:click="btnFirstClick" in <Button> inside your XML layouts.
Step 2: Define abstract BaseActivity class by extending Activity and include methods with the same name you have given in android:onClick attribute.
abstract public class BaseActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public void btnFirstClick(View v) {
}
public void btnSecondClick(View v) {
}
.....
.....
// same for other buttons
}
Step 3: Now extends this BaseActivity to all your 6 activities.
For example:
public class FirstActivity extends BaseActivity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_first);
}
}
Make a Function in a Class and put that class in the same package where all other classes are there. Simply just call that function in 6 onclicklisteners .
You can do this,
Put the click events in the XML files android:click="clickMe"
Create this function in a Activity say
public void clickMe(View view) {
...//You handling code
}
and extend this Activity by all your activities.
You can do like following
create a base activity
class BaseActivity extends Activity{
public void onSpecificEvent(View v){
// do your tasks
}
}
now extends your activities from this one
class Activity1 extends BaseActivity
class Activity2 extends BaseActivity
In which buttons you need to implement the onClick use following in xml
android:onClick="onSpecificEvent"
If you are in the same situation like me, I have a linear layout with undetermined number of buttons in it (generated dynamically) and you want a common listener for all of the button (log out their text for example), you can do like this
for (int i = 0; i < linearLayout.getChildCount(); i++)
{
final Button b = (Button) linearLayout.getChildAt(i);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Commons.log(b.getText().toString());
//your other code here
}
});
}
Now all the children (buttons) of the linear layout have same click listener
TestaActivity.java
public class TestaActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tvText=(TextView)findViewById(R.id.textView1);
tvText.setText("Sample");
}
}
Print.java
public class Print {
public Print(Context tempContext) {
//I want to assign the value to the tvText from here
}
}
In the above example, as you can see I have set the text in tvText to "Sample". In the same way, I need to assign the textView1 ID with some value inside Print class, once it is created.
Please help me to figure out the way to do it.
If your class Print is instantiated when TestaActivity is on the screen, then you can get tvText reference, passing to Print in some way a TestaActivity reference.
Maybe you could pass it via constructor:
From TestaActivity you do:
Print print = new Print(this);
where this represents the instance of TestaActivity.
And then in your Print code you can do:
TextView tvText = (TextView)((TestaActivity)context.findViewById(R.id.textView1));
tvText.setText("Sample");
Another solution is provide an interface from TestaActivity, transparent for the outside, which manage your changes on the textview (or whatever).
Something like that:
private TextView tvText;
public void setTvText(String str){
tvText.setText( str );
}
And then in your Print class:
((TestaActivity)context).setTvText( "Sample" );
try as:
public class Print {
protected TestaActivity context;
public Print(Context tempContext) {
context = tempContext;
}
public void changetextViewtext(final String msg){
context.runOnUiThread(new Runnable() {
#Override
public void run() {
//assign the value to the tvText from here
context.tvText.setText("Hello Test");
}
});
}
}
and call changetextViewtext from Activity for Changeing TextView Text from Print Class
public class TestaActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tvText=(TextView)findViewById(R.id.textView1);
tvText.setText("Sample");
Print myPrint = new Print(this);
myPrint.changetextViewtext("Hello World !!!");
}
}
as your need!!!!:)
#imran - the solution is correct except that you would want to pass the TextView as an argument in the constructor or the method.
Harcoding TextView in a method is bad because you cannot be reuse it.
Hi guys I can't figure out why I cant get it to work, to check the CheckBox of an activity from within another class.
In the onCreate method of the activity I'm passing a reference of itself to another class
public MainActivity()
...
dbi = new DBPrefsInterface(this);
...
}
public DBPrefsInterface(Context ctx)
{
MainActivity pma = (MainActivity)ctx;
this.ma = pma;
}
Now I try to Check a checkbox which is placed on the activity
this.ma.cbx.setChecked(true);
but it isn't working.
It seems I didn't pass a reference, only a Copy of MainActivity.
Thanks in adcance
Try passing a handler and a reference to the checkbox in the constructor of the other class
and make the handler send a message to the checkbox's original context
hanlder.post(new Runnable() {
#override
void run {
checkbox.setChecked(true);
}
});
Why don't you pass in the CheckBox itself? So your constructor becomes public DBPrefsInterface(CheckBox cbx) and you manipulate that reference.
Here is an example of a simple activity to demonstrate:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.checkbox);
CheckBox cbx = (CheckBox) findViewById(R.id.box);
Button button = (Button) findViewById(R.id.button);
final DBPrefsInterface iface = new DBPrefsInterface(cbx);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
iface.toggle();
}
});
}
private class DBPrefsInterface {
CheckBox cbx = null;
public DBPrefsInterface(CheckBox cbx) {
this.cbx = cbx;
}
public void toggle() {
cbx.setChecked(cbx.isChecked());
}
}
I don't see why you would want to do this, but I think using the following constructor would do the work:
private MainActivity ma;
public DBPrefsInterface(MainActivity a){
ma = a;
}
Then to set the checkbox (but checkbox needs to be public in order to work):
ma.cbx.setChecked(true);
I have made a custom component like Mybutton.java
and I have set an onclick listener in Mybutton.java.
Now, in my new activity, I have to call a Mybutton
and add content in onclick listener.
However, if I use OnClickListener mClickListener = new OnClickListener(){......
it will replace the old content.
I hope it can do the old and new listener together.
I have searched for some information, found out i can implement this method.
After many attempts, I'm still getting errors.
Can anyone give me a simple example
that i can learn to modify it?
I don't think there's an API in the Android API that allows multiple onClick listeners. You'd need some custom class that handles a single onClick() and pass in handlers for it to call. Something like this:
private class CompositeOnClickListener implements View.OnClickListener{
List<View.OnClickListener> listeners;
public CompositeOnClickListener(){
listeners = new ArrayList<View.OnClickListener>();
}
public void addOnClickListener(View.OnClickListener listener){
listeners.add(listener);
}
#Override
public void onClick(View v){
for(View.OnClickListener listener : listeners){
listener.onClick(v);
}
}
}
When your setting your buttons, do:
CompositeOnClickListener groupListener = new CompositeOnClickListener();
myButton.setOnClickListener(groupListener);
Then, whenever you want to add another listener, just call
groupListener.addOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
**** Custom implementation ****
}
});
You could create your custom Button class something like this :
public class MyButton extends Button {
private CustomOnClickListener mCustomOnClickListener;
public interface CustomOnClickListener {
void onClick(View v);
}
public MyButton(Context context) {
super(context);
// Set your own onClickListener
View.OnClickListener ocl = new View.OnClickListener() {
#Override
public void onClick(View v) {
// Do whatever you want to do
// Invoke the other added onclick listener
if(mCustomOnClickListener != null) {
mCustomOnClickListener.onClick(v);
}
}
};
setOnClickListener(ocl);
}
// use this function to set the other onclick listener
public void setCustomOnClickListener(CustomOnClickListener cl) {
mCustomOnClickListener = cl;
}
}
and, use it like this :
// create your button
MyButton button = new MyButton(context);
// add your custom onClickListener
button.setCustomOnClickListener(new MyButton.CustomOnClickListener() {
#Override
public void onClick(View v) {
// Do whatever you intend to do after the actual onClickListener
// from MyButton class has been invoked.
}
});
If you want to execute some internal logic in your custom view's onClick and want to execute the externally set up OnClickListener's logic, I think a simple way is overriding setOnClickListener as below.
In Kotlin:
override fun setOnClickListener(externalOnClickListener: View.OnClickListener?) {
val internalOnClickListener = View.OnClickListener { view ->
//Your awesome internal logic
externalOnClickListener?.onClick(view)
}
super.setOnClickListener(internalOnClickListener)
}
Same in Java:
#Override
public void setOnClickListener(#Nullable final View.OnClickListener externalOnClickListener) {
View.OnClickListener internalOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View view) {
//Your awesome internal logic
if (externalOnClickListener != null) {
externalOnClickListener.onClick(view);
}
}
};
super.setOnClickListener(internalOnClickListener);
}