How to setText to a TextView in a different Activity [duplicate] - android

This question already has answers here:
What's the best way to share data between activities?
(14 answers)
Closed 4 years ago.
So what I am trying to make happen is when you check this checkBoxA, some text will appear in a different TextView in a different Activity that the user will reach later on. The app is kind of like a quiz app so this off the text being displaid like the final score or something.
At first I tried this:
if (checkBoxA.isChecked()){
systemView.setText("Business");
}
But then I got a nullPointerException cause the "systemView" is not in the same activity. The activity is extended to the other activity that the "systemView" is located. So I am not really sure whats wrong anyone know what I should do?

Your issue is that even though you can get the ID of the systemView TextView by using R.id.systemView when you try to find that view using findViewById(R.id.systemView) the view cannot be found as it is not in the current activity's list of ViewGroup. As such null is returned.
Note systemView as the id given to the TextView has been assumed.
That is, You can only successfully use findViewById to find views within the current ViewGroup (e.g. for this.FindyViewById the layout as set by setContentView).
Instead you need to make the value available to the other activity and then retrieve the value in the other activity.
There are various ways that you can make the value available, some options are :-
To pass it to the activity via the Intent that starts the other activity as an intent extra, you could store the value in shared preferences and then retrieve it in the other activity or you could store the value in a database, e.g. SQLite and retrieve it.
Using an IntentExtra is ideal if you are directly starting the other activity with a limited number of values.
using chained Intent Extras is also feasible (that is passing to one activity, then to another and so on).
Shared preferences could suit a situation where there are a limited number of values to be passed and the other activity isn't directly started from the activity.
A database would suit a situation where there is a fair amount of structured data and/or related data (or if you are using a database for other aspects).
An example of using an Intent could be :-
In the Activity that is passing the value
Intent i = new Intent(this, yourOtherActivity.class);
i.putExtra("YOURINTENTEXTRAKEY","Business"); //<<<< 1st parameter is a Key for identification, the 2nd parameter is the value to be passed
startActivity(i);
In the other Activity's onCreate (after you've set the contentView)
TextView mSystemView = this.find(R.id.systemView);
if (this.getIntent().getStringExtra("YOURINTENTEXTRAKEY") != null) {
mSystemView.setText(this.getItent().getStringExtra("YOURINTENTEXTRAKEY"));
} else {
mSystemView.setText("NO VALUE PASSED");
}
You set pass and return multiple IntentExtras see Intent for various options and types of values that can be passed/retrieved.
Simple Working Example
The following is code for a working example. The first activity (MainActivity) has a CheckBox and a Button.
The Button can be clicked or longClicked. If the latter then nothing is passed to the second activity. If the former then depedning upon whether or not the CheckBox is ticked will either pass "Not Checked" or "Business".
The second activity, if passed a value (either "Not Checked" or "Business") will display the passed value, if nothing is passed then it will display "NOTHING PASSED". The button on the second activity will return to the first activity (alternately using the back button will return to the first activity).
MainActivity.java
public class MainActivity extends AppCompatActivity {
public static final String INTENTKEY_CHECKBOXA = "checkboxa";
CheckBox checkBoxA;
Button nextActivity;
String valueToPass = "Not Checked";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkBoxA = this.findViewById(R.id.checkBoxA);
checkBoxA.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (checkBoxA.isChecked()) {
valueToPass = "Business";
} else {
valueToPass = "Not Checked";
}
}
});
nextActivity = this.findViewById(R.id.nextActivity);
//Set onlick listener (pass value via intent)
nextActivity.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
callNextActivity(true);
}
});
// Set onlongclick listener (doesn't pass value via intent)
nextActivity.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
callNextActivity(false);
return true;
}
});
}
private void callNextActivity(boolean passvalue) {
Intent i = new Intent(this,NextActivity.class);
if (passvalue) {
i.putExtra(INTENTKEY_CHECKBOXA, valueToPass);
}
startActivity(i);
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<Button
android:id="#+id/nextActivity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="NEXT ACTIVITY"/>
<CheckBox
android:id="#+id/checkBoxA"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
NextActivity.java
public class NextActivity extends AppCompatActivity {
Button doneButton;
TextView systemView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_next);
systemView = this.findViewById(R.id.sysstemView);
doneButton = this.findViewById(R.id.done);
if (this.getIntent().getStringExtra(MainActivity.INTENTKEY_CHECKBOXA) != null) {
systemView.setText(this.getIntent().getStringExtra(MainActivity.INTENTKEY_CHECKBOXA));
} else {
systemView.setText("NOTHING PASSED");
}
doneButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
doneWithActivity();
}
});
}
// Return from this activity
private void doneWithActivity() {
this.finish();
}
}
activity_next.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".NextActivity">
<Button
android:id="#+id/done"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="DONE"/>
<TextView
android:id="#+id/sysstemView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>

you can pass your text in the intents of navigations between the activities .. otherwise if you want to save your text to recover it later, even if you close and restart your application, you can save it in a shared preferences file, to retrieve it from this file when you want to display it later.. but you can not set a text to a textview of an activity that is not in foreground.

There are many ways to do this depending on your exact use case one may be better suited than the others.
You can wrap the data in a bundle and pass it to your other activity through an intent if you are opening a second activity
Or you could store the values (in shared prefs or sqlite) and then retrieve them in the next activity.
You could use RxJava to create a stream via a subject (bevahior subject most likely in this case) and write to the stream in the first activity, then subscribe on the stream in the next to get the values.

If you are using an intent to go to the next activity you could put the value in a string and pass the string as an extra to the intent. Take the value in the next activity and set the text view.
//First Activty
String valueToPass = "";
if (checkBoxA.isChecked()){
valueToPass = "Business";
}
startActivity(new Intent(CurrentActivity.this, NextActivity.class).putExtra("value", valueToPass));
//Second Activity
if(getIntent().getString("value") != null)){
systemView.setText(getIntent().getString("value"));
}

Just use SharedPreferences to save the TextView value and then when go to the Activity that contain the TextView get the saved value and set it to the TextView in the onCreate method

Related

android - replace only content in the same activity

I have a MainActivity, which contains ImageView, TextView and 3 clickable Buttons.
After clicking the button, I want to change something in SQlite dtb and according that load different data, but show it again in the same activity.
public void ClickBtn(View v)
{
//insertData(String...
Intent intent = new Intent(MainActivity.this, MainActivity.class);
startActivity(intent);
}
So generally - in Main Activity.js I am getting the data from ID, which was clicked before and show that data. The MainActivity should be used infinity times to show different data.
The layout will be always the same - ImageView, TextView and 3 clickable Buttons, just the text will be different.
The question is, how can I only change content inside the same Activity?
I don't think Intent intent = new Intent(MainActivity.this, MainActivity.class); from the current activity can open the same activity...
You really need to study the basics.
When you are working in android, XML layout files are merely blueprints which ultimately are parsed into a reflection-created anonymous view instance, which contains as children each of the members of the XML layout, with the valid XML tag parameters applied to them. Therefore, you aren't dealing with 'Layouts', but with java/kotlin objects, which can be:
Referenced
Mutated
Replaced
So, if you want to change the contents, the first steps is to keep a reference to each object: ImageView, TextView and Buttons, and move the code in charge of filling them to a new method, so you can call it either when loading the activity (onCreate), or when clicking the button. That way the same activity can perform the same action over and over.
Finally, constant recreation of an activity is a TERRIBLE idea. For every object you generate (and an activity IS an object, like everything else), you need X+Y memory, where X is the sum of all the members of the object's class, and Y is the sum of all the operations necessary for instantiation, so by recreating the activity constantly, you waste the device resources, with the added problem of generating a huge backstack of identical activities.
Take a look at a java book, then a kotlin one. It will make your life easier.
This is how I solved it. Just replacing text without refreshing activity. Tested it hundred times also via Memory monitoring and absolutely no impact on device memory.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//get from dtb
int room = 1; int a1 = 2; int a2 = 3; int a3 =4;
TextView views = findViewById(R.id.text1);
views.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//get from dtb - img, text where room = a1;
TextView vv = findViewById(R.id.textof);
vv.setText("text from dtb");
}
});
TextView view2 = findViewById(R.id.text2);
view2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//get from dtb - img, text where room = a2;
TextView vv = findViewById(R.id.textof);
vv.setText("another text from dtb");
}
});
}

Is it possible to bind onClick to specific activity?

I'm trying to build a single window app.
I have one layout (one xml file) and two activities. A button on the first activity starts the second activity, which is an infinite quiz. Then the second activity modifies some of the views (displays series of questions).
The button purpose is to finish the second activity if it's up, then start it again.
The problem is when I click the button the second time, the app crashes. Per my understanding, it's because it can't find the onClick method in the second activity code. This is the error message:
java.lang.IllegalStateException: Could not find method startQuiz(View) in a parent or ancestor Context for android:onClick attribute defined on view class android.support.v7.widget.AppCompatButton with id 'buttonStart'
I am looking for a way to bind the onClick of that button to only the main activity.
Is it possible? I Would appreciate any help.
My button xml:
<Button
android:id="#+id/buttonStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginTop="32dp"
android:background="#android:color/holo_orange_dark"
android:onClick="startQuiz"
android:text="#string/start"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/arithMul" />
My main activity:
/** Called when the user taps the Start button */
public void startQuiz(View view) {
finishActivity();
initQuiz();
}
public void initQuiz() {
Intent intent = new Intent(this, QuizActivity.class);
startActivity(intent);
}
public void finishActivity() {
Intent intent = new Intent("finish.quiz");
sendBroadcast(intent);
}
My second activity (QuizActivity):
public class QuizActivity extends AppCompatActivity {
TextView textQuestion = null;
EditText textAnswer = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// register to finish broadcast message
IntentFilter filter = new IntentFilter();
filter.addAction("finish.quiz");
registerReceiver(broadcast_reciever, filter);
// access main activity layout
setContentView(R.layout.activity_main);
// main layout text views
ConstraintLayout layoutChoose = findViewById(R.id.constraintLayoutQuiz);
layoutChoose.setVisibility(View.VISIBLE);
textQuestion = (TextView) findViewById(R.id.textViewQuestion);
textAnswer = (EditText) findViewById(R.id.editTextAnswer);
// start the quiz
startQuizSequence();
}
// register for broadcast to finish this activity
BroadcastReceiver broadcast_reciever = new BroadcastReceiver() {
#Override
public void onReceive(Context arg0, Intent intent) {
//finish the activity
finish();
}
};
private void startQuizSequence() {
...
}
}
you could use findByViewId in both activities to find the button and explicitly set onClickListeners in each activity.
The problem is when I click the button the second time, the app crashes. Per my understanding, it's because it can't find the onClick method in the second activity code.
You're correct. When you're using Button with android:onClick attribute like the following:
<Button
android:id="#+id/buttonStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="startQuiz"
...
/>
You're expected to create a method similar with the attribute value like this:
public void startQuiz(View v) {
}
You need to add the same method to another activity using the XML layout.
But, It becomes a problem when you're trying to rename the Button View and rename the android:onClick value to reflect the change. But then you forgot to rename the method in the Activity.
So, you need to decouple the layout from the code. Instead using a android:onClick attribute, you need to set the Button click listener. Update your Button view to something like this:
<!-- I usually use a more readable id for the button -->
<Button
android:id="#+id/start_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
...
/>
Then, set the click listener:
Button button = (Button) findViewById(R.id.start_btn);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// do something here.
}
});

Change TextView String Resource in multiple activities

I have a bunch of TextViews within different activities in my app that show some string.
I wanted to add an option somewhere, where if you check it (or press it, whatever) those textviews will use some other string.
I though I could do it with having a second res value strings, and the app will switch between the two. But I see those are for localizing and do not use any user input.
Your requirement seems like you need DataBinding. You can create a Model call lets say StringManager
public class StringManager {
private final String str;
private final String str2;
private final String str3;
public StringManager(String str1,String str2, String str3){
//Initialize all class variables here
}
//Create getter methods for all
}
In your main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="stringManager " type="com.example.StringManager "/>
</data>
<LinearLayout
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="#{stringManager.str1}"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{stringManager.str2}"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{stringManager.str3}"/>
<Button
android:id="#+id/btnClickMe"
android:text="Click me"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="clicked"/>
</LinearLayout>
</layout>
In your MainActivity.java
public class MainActivity extends AppCompatActivity{
private MainActivityBinding binding;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.main_activity);
StringManager stringManager = new StringManager("strA", "StrB", "StrC");
binding.setStringManager(stringManager);
}
public void clicked(View v){
StringManager stringManager = new StringManager("strD", "StrE", "StrF");
binding.setStringManager(stringManager);
}
}
You can find the official tutorial here.
Due to there is no specific piece of code in the answer I will just sketch out my solution as pseudo code.
This solution is based on the onResume callback which is getting called as soon as an activity is getting active and the SharedPreferences class. As well it is important to know that only one activity will be active at once.
Initialize a variable as SharedPreference with the default string resource
User input changes that exact variable which is stored as
SharedPreference instead of the TextView's text itself. The nature of a SharedPreference will make it so that every button in every activity references the same variable. The second string resource can be used as source here.
The TextView's text is getting updated by using the SharedReference variable only.
In case of a new activity becoming active onCreate can be used to update the TextView's text by using the SharedReference variable.
In case of an other already initialized activity becoming active onResume can be used to update the TextView's text by using the SharedPreference variable

android- Appending textView objects to a LinearLayout by clicking on a button from a different page (multiple times)

I have two Activities. Activity 1 is designed to take in user input (EditText), and has a button that (if clicked) will go to activity 2. In activity 2, there is a LinearLayout and a button that will take you back to activity 1. I can currently add one textView (containing the user input from activity 1) to the LinearLayout in activity 2, but I would like to add several textView objects to the LinearLayout. When I try to add user input any time after the first, it simply replaces the textView object that held the information from the user input that was entered the first time.
From Activity 1 (AddExercise):
public class AddExercise extends AppCompatActivity {
private EditText name;
private EditText weight;
private EditText sets;
private EditText reps;
private String deets;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_exercise);
Button button = (Button) findViewById(R.id.button5);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
goToAddWorkout();
}
});
}
private void goToAddWorkout() {
Intent intent = new Intent(this, AddWorkout.class);
name = (EditText) findViewById(R.id.name);
weight = (EditText) findViewById(R.id.weight);
sets = (EditText) findViewById(R.id.sets);
reps = (EditText) findViewById(R.id.reps);
deets = name.getText().toString() + "\n\t\tWeight: " + weight.getText().toString() + "\n\t\tSets: " + sets.getText().toString() + "\n\t\tReps: " + reps.getText().toString();
intent.putExtra("details", deets);
startActivity(intent);
}
}
From Activity 2 (AddWorkout):
public class AddWorkout extends AppCompactActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_workout);
LinearLayout vBox = (LinearLayout) findViewById(R.id.vBox);
Bundle extras = getIntent().getExtras();
if (extras != null) {
TextView tv = new TextView(this);
tv.setText(extras.getString("details").toString());
vBox.addView(tv);
}
Button button = (Button) findViewById(R.id.button3);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
goToAddExercise();
}
});
}
}
You can try a public static List of String each time you can add your text to list and then On your second activity create text-view as per your list count. And add to your linear-layout.
For more click here....
So you want to be able to add multiple entries in your second activity, for every time you add one in the first. I would recommend a different and easier approach.
In your second activity, use a listview/recyclerview, instead of adding new textview. This has the added advantage that once you have added enough entries, scrolling won't be an issue.
Maintain a global list of entries, which you add the entries to. And populate the listview using this list.
you should try something like that as said by roshan-
((ArrayAdapter)listView.getAdapter()).insert(data_object, index);
((ArrayAdapter)listView.getAdapter()).notifyDataSetChanged();
use a shared preference for index... every time you come to second activity increment the index... on exit of app just clear the shared pref index variable.
Also you can add textview in your each list view item
There can be several ways to do it according to me, pick the one that suits your relevant application.
have a single activity and host two fragments. So you can share the data between the fragments using single activity. (Recommended way, I guess Fragments will ease the job for you.). Also you can store a local variable in Activity so that each time you start your application you can start it afresh, if its intended!
If not, you can use SharedPreferences. For each button click, add a string to the preference. When you add one more click, append the new data with a separator like ("|", "||").. So in Activity one write to the preference, in activity 2 read from the preference and display it as list view of dynamically create the linear layout and append it to the root layout.
Declare a static ArrayList in your Activity 1 and access it in activity 2. (Really bad way)

images from button press,images enlarged

new to android development and run into a hurdle,im making an app that will have a lot of pictures, what i want to achieve is after i have pressed a button in the main activity to take me to another activity, i would like a page full of buttons on this new activity that once pressed each button will show a image and have some text i would like to add, i would like to do this without having to create a new activity for each photo so i am hoping somebody could kindly help me with this! think of it like a sounbank app that plays a sound when the buttons from each row is pressed! in my case it will show an image for each button, could this be done with just the main activity and an extra activity or will i end up with an activity open in project explorer for each picture.
your help is greatly appreaciated thank you.
Ok lets assume you are using drawables from your resource folder.
In that way you deal with integer ids that represent the images.
These id can be transmitted per Intent to a second activity, that
retrieves the intent, parses the id and loads / shows the image.
In your Activity A, where you have all your buttons, I assume further that
you've added OnClicklisteners to the button like:
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//something
}
});
In your click listener you replace //something with:
Intent i = new Intent(getApplicationContext, ActivityToShowImage.class);
i.putExtra(ActivityToShowImage.IMAGE_KEY_SOME_STRING, R.drawable.oneOfYourImages);
startActivity(i);
The first argument is the key to retrieve the id later and the second is the id.
The R.drawable.oneOfYourImages depends on which button got clicked and shoud
be different for every button.
You can do this for every button, or you create a method that returns an
OnClickListener with the id as parameter.
private View.OnClickListener showImageFor(final int resIdOfImage) {
return new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(getApplicationContext, ActivityToShowImage.class);
i.putExtra(ActivityToShowImage.IMAGE_KEY_SOME_STRING, resIdOfImage);
startActivity(i);
}
};
}
Now, in Your ActivityToShowImage, you override the onCreate like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.yourLayout);
int imageId = 0;
Bundle extras = getIntent().getExtras();
if(extras != null){
imageId = extras.getInt(IMAGE_KEY_SOME_STRING, 0);
}
if(imageId == 0){
//some log message or exception and don't forget to finish in onResume()
}else{
loadImage(imageId);
}
}
And in your loadImage method you load the image via the id into an ImageView.
I hope that is the answer to your question and sorry for the late response.

Categories

Resources