In my PreferenceActivity I have some Preferences.
One I inflate from layout:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.layout.settings);
...
}
protected void onResume() {
super.onResume();
Preference registrationStatus = (Preference) findPreference("registrationStatusPref");
if (!TextUtils.isEmpty(somestring){
registrationStatus.setLayoutResource(R.layout.push_reg_status);
TextView push_reg_status_txt = (TextView)findViewById(R.id.pushRegTxtPref);
}
....
}
push_reg_status_txt is a TextView from push_reg_status layout, and push_reg_status_txt is always null.
push_reg_status layout:
....
<TextView
android:id="#+id/pushRegTxtPref"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:layout_marginBottom="4dp"
android:text="Registration Succesful"
android:textColor="#99ff33"
android:gravity="center_horizontal"
android:layout_gravity="center_horizontal"/>
.....
Why?
Preference.setLayoutResource() only updates the internal reference that preference has to a layout ID, it does not actually update the layout to redisplay. Therefore the TextView you are looking for with findViewById() is not inflated for your use. The only place Preferences inflate their layouts is when created.
You'll either need to have that custom layout set at the start (before addPreferencesFromResource() inflates everything), or adjust the title/summary properties of the existing preference instead to set your "Registration Successful" string. Also, if you are using a custom preference layout, make sure you're following the rules set forth in the SDK Documentation.
Hope that Helps!
Maybe because you calls findViewById of your Activity instead of calling same method of registrationStatus object.
Related
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
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
I'm using a PreferenceFragment and want the version of my app to appear below the List that holds all the settings. I know for a normal ListView I could just do addFooterView(theTextView), but the PreferenceFragment doesn't provide access to doing this (no access to the ListView that is populated from preferences xml). Anyone have a slick way of doing this?
George's answer (Option 1) was on the right track, but I found it better to take it one step further than simply adding a preference. I created a custom preference by using the layout in the accepted answer here, and then was able to totally customize what I wanted to show by centering text, and even making the preference only appear under certain circumstances (for example, if the user has the most recent version, don't show the preference, etc.).
I used the Android docs on Settings to create a class that extends Preference to do the dynamic work needed.
You can add an empty preference item in the end of xml, then give it an custom layout.
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- other preferences -->
<Preference app:layout="#layout/place_holder" />
</PreferenceScreen>
In your PreferencesFragment, just new a custom PreferenceCategory, then add it to PreferenceScreen. you can do your things in the onCreateView part of the custom PreferenceCategory.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
initPrefs();
PreferenceCategory preferenceCategory = new PreferenceCategory(getActivity()) {
#Override
protected View onCreateView(ViewGroup parent) {
super.onCreateView(parent);
View view =
getActivity().getLayoutInflater().inflate(R.layout.layout_infos, null);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getActivity(), "thanks", Toast.LENGTH_SHORT).show();
}
});
return view;
}
};
getPreferenceScreen().addPreference(preferenceCategory);
}
I have two activities, activity one has buttons that refer to activity two and methods in it. I'm trying to use TextView.SetText to put something on the screen but keep getting NullPointerException.
Activity 2:
public class SomeActivity extends Activity {
TextView textview ;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.some_activity);
textview = (TextView) findViewById( R.id.textview );
spill("Some text");
}
public void spill(String s){
textview.setText(s);
}
public void methodCalledFromActivityOne(){
System.out.println("Works");
spill("Why Doesn't this work?");
}
XML has this:
<TextView
android:id="#+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
tools:context=".SomeActivity" />
I'm new to Android and will REALLY appreciate all/any help.
EDIT: The name of the XML is fine, the error only occurs when I press button 1 in activity 1 which calls methodCalledFromActivityOne().
This is what I get from LogCat:
Caused by: java.lang.NullPointerException at android.app.Activity.findViewById at data.storage.SomeActivity.spill at data.storage.SomeActivity.methodCalledFromActivityOne
at data.storage.ActivityOne.button1clicked
textview in activity 2 will be initialized only when onCreate() is called. And onCreate() of activity 2 will be called only when this activity comes into the phone view. You cannot set the values of views of another activity from your current activity. It is a bad idea.
If you want the values to get to activity 2, then send those in an intent.
If you're calling methodCalledFromActivityOne() method from another activity make sure you've created TextView property at that activity also. Otherwise it'll not work.
Good morning folks,
I'm working on an Android app and I've run into a bit of a problem. I have created a new class that extends View. I have overridden the appropriate methods (the Constructor, onDraw, onMeasure) and am instantiating the View through the applications layout XML (which is called main.xml).
Within the source code of my app I have the following code:
public class CustomViewTest extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* I *think* I need to setContentView before I actually can use any of the widgets on the form. */
setContentView(R.layout.main);
Button b = (Button)findViewById(R.id.button);
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
// my new widget
newWidget s = (newWidget)findViewById(R.id.testWidget);
s.setRequestedViewSize(300);
}
});
}
}
the problem here, is that s.setRequestedViewSize(300) throws a NullPointerException. Has anyone run into this before or can lend me some advice?
[EDIT]
The main.XML looks like this:
It returning null, but the XML looks like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<com.testing.CustomViewTest02.newWidget
android:id="#+id/testWidget"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<Button android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
></Button>
</LinearLayout>
Thanks you!
Sam
The problem was in my widget, I had the correct constructor (Context context AttributeSet attr); HOWEVER - super(context) was being called - not super(context, attr). Once I fixed that, life was better.
Thanks for the info everyone!
You have no view with the R.id.testWidget ID: it's not about nonstatic methods. Since findViewById() returns null, the next line throws an exception.
Do you reference your custom view inside your main.xml? #Pontus is right. There is no View being returned from the findViewById() method.
It would probably be better to get your reference to it in the onCreate method (call the constructor there if necessary) and then set it visible or add it to another view (whatever you are trying to do with it) once the button is clicked.
EDIT: Based on your XML above. Does your custom class implement a constructor that takes a Context and an AttributeSet? The constructor with the AttributeSet is the constructor that Android will call to create your class from the XML layout.