I'd like to use a Toolbar on my Settings activity, which is using AppCompatPreferenceActivity. There's plenty of stuff online for doing this if you're just using PreferenceScreen, but I haven't found anything that also works with PreferenceHeaders. Here's my current code:
public class SettingsActivity extends AppCompatPreferenceActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.pref_headers, target);
}
}
I also have some unremarkable PreferenceHeaders in an XML file, which have corresponding PreferenceFragments. The activity runs fine, I just can't figure out how to get the toolbar in there.
Most of the stuff I've seen on this usually involves just a single PreferenceScreen, and you create a layout with the toolbar and a placeholder ListView, and load the Preferences into there, but that doesn't work for me.
I also tried getSupportActionBar(), but that returns null.
Anyone know how I can do this? Thanks!
Related
I got some nested PreferenceScreen in my PreferenceActivity, and under them a series of CheckBoxPreference.
Everything is working well but, whenever the device is rotated, the PreferenceActivity returns to the main PreferenceScreen, disregarding what nested preference screen the user was in.
This is exactly like in these previous SO questions, where the solution was to add a key to the PreferenceScreen:
When my PreferenceActivity rotates, it does not remember which
PreferenceScreen was open
How to prevent quitting from inner preference screen when there's a
configuration change
Nested Preference Screen closes on Screenorientation change in
Android
I've added keys to all my PreferenceScreen and the solution works, as long as I use the deprecated way:
public class Settings extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.prefs);
}
}
The problem is I'm using a PreferenceFragment, like in this SO answer (and also here).
The code:
public class Settings extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getFragmentManager().
beginTransaction().
replace(android.R.id.content, new MyPreferenceFragment()).
commit();
}
public static class MyPreferenceFragment extends PreferenceFragment
{
#Override
public void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.prefs);
}
}
}
So, how to keep inner PreferenceScreen open after screen orientation changes, if possible with the current code?
I see that for Preferences Google now recommends AppCompatActivity and PreferenceFragmentCompat, but I would prefer to not use any libraries, not even Google's, specially for only such a small detail.
I'm quite surprised this little problem managed to generate three SO questions while Android was under API 11, and none - that I can find at least - between API 11 and API 28, when PreferenceFragment was deprecated.
Anyways, I found the solution here in SO as well, in an answer to Android- deprecated method warning regarding PreferenceActivity.
The key is to check if (savedInstanceState == null) before adding the PreferenceFragment, like this:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (savedInstanceState == null)
getFragmentManager().
beginTransaction().
replace(android.R.id.content, new MyPreferenceFragment()).
commit();
}
Now the nested PreferenceScreen remains open when screen orientation changes, as long as it has an android:key value set in, of course.
I've placed the following code in onCreate() to set a toolbar I use in each Activity as the ActionBar:
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
This works fine and shows the back arrow and title in each Activity, and is necessary because we add custom content to our ToolBar, but it's messy and annoying to have to do this in each Activity.
What's the best way to achieve this behavior without the duplication? Can it be done in styles?
You should create Base Activity like this :
public class Base extends AppCompatActivity {
TextView icon1;
#Override
public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
super.onCreate(savedInstanceState, persistentState);
initToolbar()
}
public void initToolbar() {
.
.
.
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
if (showIcon1())
icon1.setVisibility(View.VISIBLE);
else
icon1.setVisibility(View.GONE);
}
public boolean showIcon1(){
return true;
}
And other activity :
public class OtherActivity extends Base {
#Override
public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
super.onCreate(savedInstanceState, persistentState);
}
#Override
public boolean showIcon1() {
return false;
}<br>
Hope this Help.
I'm not sure if "best" but if you really want that in all your activities you have two choices:
Inheritance: A very common Android/Java approach is to subclass Activity and then use that as your base. E.g.:
public class BaseActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setupToolbar();
}
private void setupToolbar() {
// do whatever you need to do
}
}
public class YourFancyClass extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Do anything you need to. The toolbar is set by the base class.
}
}
That's one option (very popular)
Plan B would be to use Composition, mostly preferred in the iOS side, yet still very valid (and sometimes more appropriate, a discussion we're not having now) :)
Basically have an object that is capable of setting your toolbar. Create an interface that can represent that behavior. Have an implementation of such behavior (Java usually calls them XxxxxImpl and have that interface and implementation passed onto the activities that need it.
Sounds more complicated, but it's very clean and clear once you got it all together.
Well, I'm trying to make an app that needs to have some sort of ActionBar, which only have to schedule and design once, and then serve me for all my APP activity.
I'm not sure how this works, need a little guidance please.
To give you an idea of what I want, I would like something like this:
A top, that is the general of the APP. And then below as well as a submenu with icons, with different options.
What exactly would have to use it? I've been tinkering with ActionBar but that it me for the top .. But to the other as you would?
Both want them to be static and are always in every activity of my APP, without having to copy and paste the code of each una..Que I guess and this somehow you are ready to embed it anywhere, programming only once.
This question doesn't really have much to do with Android. This is about how you can re-use code multiple places.
You could use inheritance for this purpose.
Say you have 3 different activities, but you want them to have a set of common features - in your case the ActionBar.
In that case you could create an abstract class that implements the ActionBar and make all your activities inherit from this abstract class.
The hierarchy could look something like this:
public abstract class BaseActivity extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.oncreate(savedInstanceState);
// Setup your common ActionBar here.
}
}
Now for this abstract class to do its work, you'll have to make all your activities inherit from this, like so:
public class MyActivityA extends BaseActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.oncreate(savedInstanceState); // It's important to call through to super to have it setup the ActionBar for the current activity.
// Next call setContentView(R.layout.my_activity_layout);
// And what else you need to do.
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_a_menu, menu);
return true;
}
}
And for the next Activity you do the same:
public class MyActivityB extends BaseActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.oncreate(savedInstanceState);
// Next call setContentView(R.layout.my_activity_layout);
// And what else you need to do.
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_b_menu, menu);
return true;
}
}
The onCreateOptionsMenu is implemented in all your activities, as to create different menu items and the same should go for your onOptionsItemSelected.
Now this is a very basic example of how to share basic features for multiple classes and it should be something you'd have to be knowledgable about before you start working with Android, as the above code is common Java.
Also keep in mind, that it's a very broad question you're asking.
I actually just wanted to put this in a comment, but decided it would become too large to fit into the comments.
I am doing an app with preferences but I have used a method that is deprecated and it says :
"This function is not relevant for a modern fragment-based PreferenceActivity". My code is this:
public class Settings extends PreferenceActivity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
How can I update this to not deprecated function. Thank you very much.
The new way is to do the Preferences in an Fragment instead of an Activity. This is espacially true for large screens and tablets. Fragments can be shown separate or next to each other over an Activity according to screen size. Use them like this:
public static class YourPreferenceFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.preferences);
}
}
and instead of calling the PreferenceActivity you make a call to the Fragment in your Activity:
YourPreferenceFragment prefFragment = new YourPreferenceFragment();
prefFragment.show(getFragmentManager(), "someFragmentId");
Try to use PreferenceFragment instead.
Check this: http://developer.android.com/guide/topics/ui/settings.html
PreferenceActivity is depricated, you can use PreferenceFragment instead.
here are some tutorials
Link 1
Link 2
Here is the documenattion for PreferenceFragment
Users can add projects in my app and I have a PreferenceFragment for settings of the projects.
This is my Fragment:
public class SettingsFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.project_settings);
}
}
And my Activity:
public class Settings extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction()
.replace(android.R.id.content, new SettingsFragment())
.commit();
}
}
The availabal settings for each project are identical but the data should be saved per project (e.g. the project name). So how can I save the preferences to my sqlite database?
Putting this here as none of the other questions/answers on this topic were satisfactory, and I just finished precisely this functionality (connect Preferences in a PreferenceFragment to the database).
Basically, you should set android:persistent="false" for each Preference in the XML. You should then load values into the Preferences manually on onCreate(), and use setOnPreferenceChangeListener() to do database value-updating and Preference summary field updating. You may also have to extend some existing Preferences to allow them to be set with values manually, as some of them (e.g. the RingtonePreference) do not have methods to set their values -- they just get them internally from SharedPreferences.
The answer is a Preference.OnPreferenceChangeListener and some magic inside the onPreferenceChange method.