The Settings app in Android has the following source code:
Code
The Settings class derives from the PreferenceActivity. Even with the android source code, I am not able to figure out what code in the class is responsible for displaying the difference options in the settings screen.
My guess is that the right code is in onResume():
public void onResume() {
super.onResume();
ListAdapter listAdapter = getListAdapter();
if (listAdapter instanceof HeaderAdapter) {
((HeaderAdapter) listAdapter).resume();
}
}
Can someone help?
Thanks.
I am not able to figure out what code in the class is responsible for displaying the difference options in the settings screen.
That is mostly in the preference XML, such as this file that declares the preference headers (left column on a tablet's view of Settings). Some preferences are implemented via custom PreferenceFragments, where the UI departs from the preference norms.
Related
In my Android application, I have implemented class SubtitleColorListPreference which extends from ListPreference. I need this, because I need to set my own layout for each item in list. Everything works fine and it looks like this:
The important code is in method onPrepareDialogBuilder(AlertDialog.Builder builder), where I set my own ListAdapter.
#Override
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
// some other code is here ...
ListAdapter listAdapter = new SubtitleColorAdapter(getContext(), R.layout.subtitle_color_preference_item, colorNameHolders, index, this);
builder.setAdapter(listAdapter, this);
}
Now, I need to use PreferenceFragmentCompat instead of PreferenceFragment, so my SubtitleColorListPreference has to extend android.support.v7.preference.ListPreference. And here is the problem - there are no onPrepareDialogBuilder method in this ListPreference. Also, I did not find any similar method. I tried to find some examples how to create custom android.support.v7.preference.ListPreference, but with no success.
Does anybody know how can I solve this?
Google thinks that you don't need a custom view in ListPreference. It seems, the only way is to use the deprecated PreferenceFragment and android.preference.ListPreference or stay with obsolete SDK 27. It's clear that they don't understand what they're doing.
I want to display different preference options in my app depending on the device SDK and screen size, but certain preferences will be displayed on all devices. I could accomplish this by creating a full preferences.xml file for each possible device, like this:
xml/preferences.xml:
<PreferenceScreen>
<!-- Preference 1 (all devices) -->
<!-- Preference 2 (all devices) -->
</PreferenceScreen>
xml-v21/preferences.xml:
<PreferenceScreen>
<!-- Preference 1 (all devices) -->
<!-- Preference 2 (all devices) -->
<!-- Preference 3 (SDK 21 only) -->
</PreferenceScreen>
But this will get unwieldy very quickly given the number of possible combinations of screen sizes and SDKs. What I'd really like to do would be to use the same basic list of preferences on all devices and dynamically mix in additional preferences that are specific to certain screen sizes and SDKs. I've gone through the Android Providing Resources guide, but it seems that using alternative resources in the manner described there would still require me to create a separate resource directory for every screen-size-and-SDK combination and would require a lot of code duplication. Is there a nice, elegant solution to this problem that I'm missing?
Have you read the Settings guide? My app also has a lot of changes dynamically, both in 1) which headers / fragments to show, and 2) which prefs each fragment contains. For both issues you can use different resource versions, as you describe, or you can implement the differences in code.
For issue #1, you can either call loadHeadersFromResource directly, and have different headers resource files, or you can have code that does something similar. For example, my PreferencesActivity uses a separate PreferenceFragment subclass for each prefs section, and makes a decision at run time about which fragments (headers) to show:
#Override
public void onBuildHeaders(List<Header> targets) {
// Build a list of PreferenceFragment class objects to show now
List<Class<? extends PreferenceFragment>> fragmentClasses = ...;
// Create a Header for each fragment to return to Android
for (Class<? extends PreferenceFragment> fragmentClass: fragmentClasses) {
try {
PreferenceFragment fragment = fragmentClass.newInstance();
Header header = new Header();
header.fragment = fragmentClass.getName();
header.titleRes = fragment.getTitleId();
targets.add(header);
this.headers = targets;
} catch (Exception e) {
}
}
}
For issue #2, you can start with preferences from a common resource file, and then add the conditional ones in code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load common prefs from an XML resource
addPreferencesFromResource(R.xml.preferences);
// Add conditional prefs in code
PreferenceScreen prefScreen = getPreferenceScreen();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Preference pref = ...; // create condition pref
prefScreen.addPreference(pref);
}
}
I actually add all prefs in code, common and conditional. However, I didn't see a way to create a PreferenceScreen from scratch, so I actually have an empty XML file that I load from resources, and then add all preferences in code. It works really well.
Hi I want to create preferences in my application but I cannot use resources at all due to some dependency issues.
I am able to do this using the below code:
public class DTMainActivity extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setPreferenceScreen(defaultPref());
setDependencies();
}
// The first time application is launched this should be read
private PreferenceScreen defaultPref() {
PreferenceScreen root = getPreferenceManager().createPreferenceScreen(this);
SwitchPreference dLogTracingEnablePref = new SwitchPreference(this);
dLogTracingEnablePref.setTitle(R_Class.R_String.dLogTracingEnablePrefString);
dLogTracingEnablePref.setDisableDependentsState(false);
dLogTracingEnablePref.setChecked(true);
dLogTracingEnablePref.setKey(R_Class.R_String.dLogTracingEnablePrefKey);
root.addPreference(dLogTracingEnablePref);
}
I would want to do this using the new fragment based approach, without using the deprecated APIs like getPreferenceManager etc.. I can create all the other UI layout elements like linearlayout etc.. without any resources, but when it comes to preferences and PreferenceFragment class, all that is available is addPreferencesFromResource() which would need an XML. Can any one help me here please?
I managed to made it using a PreferenceFragment, without addPreferencesFromResource(),
Instead I just created the PreferenceScreen like you just did and used
try using the bindPreferenceSummaryToValue, consider "p" being a PreferenceScreen with Preferences already added into it, (and also that has been created and configured previously)
PreferenceScreen p = createPreferences();//a method that creates a PreferenceScreen and add some preferences into it
this.setPreferenceScreen(p);
bindPreferenceSummaryToValue(p.findPreference("preference_key"));
I responded to someone with a similar problem here .. perhaps you can check it out
Everything I've read about Intents talks about using them to push data, or to start one Activity from another Activity. I want to pull data from an Activity that's already running.
The Tab Layout tutorial at http://developer.android.com/resources/tutorials/views/hello-tabwidget.html illustrates what I want to do. (My app is doing some engineering calculations instead, but the tutorial code provides a good analogy to my app.) The tutorial creates an app with three tabs, and each tab hosts a separate activity.
To expand on the example in the tutorial, suppose I select an artist in the Artists tab/activity. I want to be able to select the Albums tab/activity and have it display all the albums featuring that artist.
It seems to me that I need to use an Intent to do this. All of the tutorials I've found assume that I would create a "See albums" Button in the Artists tab/activity, and that pressing the Button would execute an Intent that starts the Albums activity and passes artistName.
I DO NOT want to create that Button. Real estate on the Artists layout is precious, and I have a perfectly good Albums tab, AND the HelloTabWidget activity already contains an intent to create the Albums tab.
Besides, a user will want to skip back and forth between Album and Artist in order to change artist selections, and the tabs are a perfectly good way to do this. There's no need to complicate the UI with another button.
So how can I have the Albums activity PULL artistName from the Artists activity when the Albums tab is selected (or the Albums layout is displayed), rather than have the Artists activity START Albums and PUSH the artistName?
Equivalents I can think of from other programming worlds:
Global variables. Discouraged in Android devt, right? And if they do exist, what are they called?
A getter, like artistName = Artists.getArtistName(); . I get the feeling that it's not that easy.
Writing to, and reading from, a file - that is, mass storage or non-volatile memory. I don't need the artistName value to be permanent. It will be reset to null every time the user launches the application.
So how is it done in the Android world? Do I use an Intent - and if so, how?
Global variables were the right answer.
I thought Java discouraged their use, but a couple of links that appeared in the "Related" links on the right margin of this window mentioned them directly. One was "Android: How to declare global variables?" and the other was "how to pass value betweeen two tab in android". Both pointed to the Application Class as the place to define global variables and methods. Armed with this new knowledge, I found an article called "Android Application Class" on the Xoriant blog that expanded on the StackOverflow answers.
It's best to review those three links first. I need to add some tips to what those authors have said.
Your Application class has to be in its own separate file. (That might be a "duh" to some people, but not to everybody.) Here's a good framework for an example called Something.java:
public class Something extends Application {
// Put application wide (global) variables here
// Constants are final, so they don't have to be private
// But other variables should be declared private;
// use getters/setters to access them
public final boolean FEET = false;
public final boolean METERS = true;
private boolean units = FEET;
#Override
public void onCreate() {
super.onCreate();
// Put any application wide (global) initialization here
}
// Put application wide (global) methods here
public boolean getUnits() {
return units;
}
public void setUnits(boolean whichOne) {
units = whichOne;
}
}
I'm using Eclipse with the ADT plug-in, in Windows XP. Eclipse doesn't always behave properly if you edit XML code directly, so it's best to open AndroidManifest.xml, then select the Application tab and enter your application name in the Name field. You don't need to put a dot or period in front of the name. Just type in the name of your class, like "Globals" or "MyApplication" or whatever. (Note that this is the default application in your Manifest. You don't have to create a separate <application></application> tag.
This step may not be necessary on an actual Android device, but it was necessary for the emulator: you need to use the getApplicationContext() command in every onCreate() and every method that will be accessing the global variables and methods. I tried to put it outside of onCreate() with the rest of my activity wide variables, and it didn't work. Putting it inside every method seems wasteful, but both the emulator and the Android device work fine with it that way. Here's a sample showing how I used it:
public void fooBar() {
// Access to global variables and methods
final Something s = (Something)getApplicationContext();
// ...
// This next line demonstrates both a global method and a global variable
if (s.getUnits() == s.FEET) {
// do something with feet
} else {
// do something with meters instead
}
// ...
}
Those were the only hiccups I encountered. The three references that I have listed, taken together, are otherwise pretty complete.
In my Android app, I have two custom view classes - PortraitClass and LandscapeClass. They both do the same thing. On running the app, the view class fetches some pictures from an SDCard and then maniputlates (skew etc) and displays them. The only difference between the two classes is that the layout of pictures is slightly different on the screen.
I have two display.xml files (one under layout folder and the other under layout-land). The one under the layout folder adds Portrait and the other adds the Landscape class.
On orientation change, I would like to send information (picture numbers and few bitmaps) from one class to another so I won't have to fetch all the bitmaps again and also so that I display the ones that were being displayed.
I find the parcelable thing kind of confusing. I tried following this_example, but I noticed that in onRestoreInstance, the Parcelable has null for the "mSuperState" and I get a classCastException # "SavedState ss = (SavedState)state". The integer (picture number) that I am trying to pass is there. I am not sure what I am doing wrong.
You could use a global singleton in the Application class. For example an "AssetManager" is available here:
public class YourApplication extends Application {
public AssetManager assetManager = new AssetManager();
#Override
public void onCreate()
{
super.onCreate();
}
}
You can then call it from another activity:
YourApplication application = ((YourApplication ) this.getApplication());
application.assetManager.someFunction();
Not sure if this is what you are looking for but my stuff always works in orientation change with onCreate(Bundle savedInstanceState). Mine is all text in edit text boxes though so I am not sure how it would work for you.
Also check this out about midway down under "Persisting State Information During Configuration Change"
http://www.devx.com/wireless/Article/40792/1954