Set toolbar for all Activities [duplicate] - android

This question already has answers here:
Use Toolbar across all activities (Android)
(2 answers)
Closed 2 years ago.
In my app I would like to make a unique toolbar for all activities except for mainActivity.
I have written this code for set Title and logo, but in toolbar I also have username logged.
So I have written in my dashboard activity this code:
Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
setSupportActionBar(myToolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
assert myToolbar != null;
myToolbar.setLogo(R.mipmap.logo_big);
TextView usernameField = (TextView) findViewById(R.id.username);
try {
usernameField.setText(User.getInstance().getUsername());
} catch (JSONException e) {
e.printStackTrace();
}
And I made a layout that can be included in all xml files.
But How can I reuse this code in all my activities without copy and paste?
Is it wrong to make a singleton? or a utility class?
Thanks

You could create a base activity that runs the common code and have all other activities inherit from it:
// the base class
public abstract class BaseActivity extends AppCompatActivity
{
protected final void onCreate(Bundle savedInstanceState, int layoutId)
{
super.onCreate(savedInstanceState);
setContentView(layoutId);
Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
setSupportActionBar(myToolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
assert myToolbar != null;
myToolbar.setLogo(R.mipmap.logo_big);
TextView usernameField = (TextView) findViewById(R.id.username);
try {
usernameField.setText(User.getInstance().getUsername());
} catch (JSONException e) {
e.printStackTrace();
}
}
}
// inheriting activity
public class SomeActivity extends BaseActivity
{
protected final void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState, R.layout.some_layout);
}
}

keep your code in one CustomActivity.
Where every required in your application extends CustomActivity .
Example:
CustomActivity extends Activity{
// your toolbar code
}
In your all activities extends CustomActivity.

Create a new activity called CustomActivity and a corresponding layout called activity_custom.xml :
<android.support.v4.widget.DrawerLayout
android:id="#+id/activity_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:background="#color/background_material_dark"
/>
<FrameLayout
android:id="#+id/activity_content"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<android.support.design.widget.NavigationView
android:id="#+id/navigationView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="#menu/menu_base"/>
Open BaseActivity.java and make sure to remove setContentView(R.layout.activity_base) from the onCreate() method. and override the setContentView() method with your own implementation:
#Override
public void setContentView(int layoutResID) {
DrawerLayout fullView = (DrawerLayout) getLayoutInflater().inflate(R.layout.activity_base, null);
FrameLayout activityContainer = (FrameLayout) fullView.findViewById(R.id.activity_content);
getLayoutInflater().inflate(layoutResID, activityContainer, true);
super.setContentView(fullView);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
setTitle("Activity Title");
}
In your all activities extends CustomActivity.

You can do like this:
class BaseActivity extends AppCompatActivity
{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public void initToolbar(int toolbarId)
{
Toolbar myToolbar = (Toolbar) findViewById(toolbarId);
setSupportActionBar(myToolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
assert myToolbar != null;
myToolbar.setLogo(R.mipmap.logo_big);
}
}
class YourActivity extends BaseActivity
{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(your activity layout);
initToolbar(R.id.yourToolbarId);
}
}

Related

Why this null pointer error is comming? [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
I was making a list of favorite activity in the android which uses arraylist
as a storing place,but when i was triggering the event by the button press,null pointer error is coming. Why is it so...???
Here is the code of my Kinematics activity where the button is being pressed.
public class Kinematics extends AppCompatActivity {
private DrawerLayout drawerLayout;
private NavigationView navigationView;
private ActionBarDrawerToggle phy_law_toggel;
private Toolbar toolbar;
private WebView webView;
private ScrollView scrollview;
private FloatingActionButton fab;
private ImageButton fav;
#Override
protected void onCreate(Bundle savedInstanceState) {
final Favouritepage favr = new Favouritepage();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_kinematics);
Toolbar toolbar = (Toolbar) findViewById(R.id.phy_lawtoolbar);
setSupportActionBar(toolbar);
setTitle(R.string.Kinematics);
drawerLayout = (DrawerLayout) findViewById(R.id.phy_draw);
navigationView = (NavigationView) findViewById(R.id.nav_view_phy);
phy_law_toggel = new ActionBarDrawerToggle(this,drawerLayout,R.string.open, R.string.Close);
drawerLayout.addDrawerListener(phy_law_toggel);
toolbar = (Toolbar) findViewById(R.id.phy_lawtoolbar);
setSupportActionBar(toolbar);
phy_law_toggel.syncState();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
navigationView.setItemIconTintList(null);
webView = (WebView) findViewById(R.id.phy_law_web);
fav = (ImageButton) findViewById(R.id.fav);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setSupportZoom(true);
final String kine = this.getClass().getSimpleName();
webView.getSettings().setDisplayZoomControls(true);
webView.loadUrl("file:///android_asset/mathscribe/Kinematics.html");
fab = (FloatingActionButton) findViewById(R.id.fab);
scrollview = (ScrollView) findViewById(R.id.scroll);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
webView.scrollTo(0, 0);
}
});
fav.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
favr.mfavlist.add(kine);
}
});
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (phy_law_toggel.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}}
Here, i am making an object of my FavoritePage class and trying to store the element in the arrayList of FavoritePage.
Here is my FavoritePage class
public class Favouritepage extends AppCompatActivity {
public ArrayList<String> mfavlist;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_favouritepage);
mfavlist = new ArrayList<String>();
}}
And here is the XML of kinematics,
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/phy_draw"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.example.alpit.formula2.Kinematics">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="#+id/phy_lawtoolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.NoActionBar.PopupOverlay">
</android.support.v7.widget.Toolbar>
<WebView
android:id="#+id/phy_law_web"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentStart="true"
android:layout_below="#+id/phy_lawtoolbar"></WebView>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_alignBottom="#+id/phy_law_web"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_gravity="bottom|end"
android:layout_marginBottom="43dp"
android:layout_marginEnd="30dp"
android:src="#drawable/fabss"
app:backgroundTint="#F57F17">
</android.support.design.widget.FloatingActionButton>
<ImageButton
android:id="#+id/fav"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_above="#+id/phy_law_web"
android:layout_alignParentEnd="true"
android:background="#color/colorPrimary"
android:src="#drawable/fav" />
</RelativeLayout>
<android.support.design.widget.NavigationView
android:id="#+id/nav_view_phy"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#FFAB40"
app:menu="#menu/navigation_menu"
app:theme="#style/NavigationTheme" />
crashlog
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.alpit.formula2, PID: 22744
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.util.ArrayList.add(java.lang.Object)' on a null object reference
at com.example.alpit.formula2.Kinematics$2.onClick(Kinematics.java:64)
at android.view.View.performClick(View.java:4802)
at android.view.View$PerformClick.run(View.java:20102)
at android.os.Handler.handleCallback(Handler.java:810)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:189)
at android.app.ActivityThread.main(ActivityThread.java:5529)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:950)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:745)
Add this line after setContentView in your Kinematic.
ArrayList<String> mfavlist = new ArrayList<String>();
edit this line of your code
fav.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mfavlist.add(kine);
}
});
Here is my FavoritePage class
public class Favouritepage extends AppCompatActivity {
... Meanwhile in your other class...
final Favouritepage favr = new Favouritepage();
Never ever new an Activity class (because onCreate is never called, therefore the list is null)
Basically, I do not think FavouritePage should extend Activity at all.
Learn more about POJO classes
public class Favouritepage {
public ArrayList<String> mfavlist = new ArrayList<String>();
public Favouritepage() {
// Empty constructor
}
}
Or, if it needs does need to be an Activity class, you will have to find a different way to "share" that list between activities.

What should I define in the setContentView in MainActivity.java file?

I want to know what should come in the bolded part below.It shows me two options:
1.toolbar(The xml I created to add the code for the google appbar)
2.activity_main
The both seems to show no errors that why I want to know which one should I add.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.**toolbar**);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
}
hi add like this,
public class YourActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.youractivity);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
TextView mTitle = (TextView) toolbar.findViewById(R.id.toolbar_title);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayUseLogoEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setDisplayShowTitleEnabled(true);
mTitle.setText("Contact Us");
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
}
}
<include
android:id="#+id/toolbar"
layout="#layout/toolbar" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</RelativeLayout>
hope this will help you
As Bansal mentioned correctly, you must use activity_main in setContentView.
Your activity_main.xml will contain the toolbar. Inside the toolbar tag you must call the toolbar layout. It uses your toolbar.xml layout for your toolbar.

Toolbar empty with Navigation Drawer

My BaseDrawerActivity extends BaseActivity and I have a Toolbar in BaseActivity.
The toolbar shows with no issues in classes that extend BaseActivity, but ALL classes that extend BaseDrawerActivity just show a blank toolbar. The nav drawer works fine.
When I had one main activity class (BaseActivity + BaseDrawerActivity) the toolbar showed no problem and the nav drawer worked.
Why is my implementation here not showing the Toolbar? I debugged and getToolbar() is returning the toolbar for sure.
activity_base_drawer.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="#layout/toolbar"/>
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="?android:windowContentOverlay">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<include layout="#layout/call_to_action_banner"/>
</FrameLayout>
<ListView
android:id="#+id/navigation_drawer"
android:layout_width="#dimen/navigation_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
style="#style/NavDrawerListView" />
</android.support.v4.widget.DrawerLayout>
</LinearLayout>
toolbar.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:theme="#style/ToolbarOverlay"
android:popupTheme="#style/ToolbarOverlay"
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white"
android:minHeight="?attr/actionBarSize"
android:elevation="10dp"/>
BaseDrawerActivity
public abstract class BaseDrawerActivity extends BaseActivity {
private static final int LAYOUT_ID = R.layout.activity_base_drawer;
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
private NavDrawerAdapter mNavDrawerAdapter;
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
#Override
public void onBackPressed() {
if (mDrawerLayout.isDrawerOpen(GravityCompat.START)){
mDrawerLayout.closeDrawers();
} else {
super.onBackPressed();
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(LAYOUT_ID);
setupNavDrawer();
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
private void setupNavDrawer() {
final ListView navDrawerListView = (ListView) findViewById(R.id.navigation_drawer);
View header = getLayoutInflater().inflate(R.layout.nav_drawer_header, null, false);
mNavDrawerAvatarImageView = (ImageView) header.findViewById(R.id.avatar);
mNavDrawerUsernameTextView = (CustomTextView) header.findViewById(R.id.username);
navDrawerListView.addHeaderView(header);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerToggle = new ActionBarDrawerToggle(
this,
mDrawerLayout,
getToolbar(),
R.string.navigation_drawer_open,
R.string.navigation_drawer_close) {
/** Called when a drawer has settled in a completely closed state. */
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
updateNavDrawerUserInfo();
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
mNavDrawerAdapter = new NavDrawerAdapter(this);
navDrawerListView.setAdapter(mNavDrawerAdapter);
navDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
mDrawerLayout.closeDrawer(GravityCompat.START);
onNavigationDrawerItemSelected(position);
}
});
updateNavDrawerUserInfo();
}
private void updateNavDrawerUserInfo() {
final DatabaseHelper db = DatabaseHelper.getInstance(this);
if (db.doesUserExist(SharedPrefs.getUserId())) {
final User currentUser = db.getUser(SharedPrefs.getUserId());
if (currentUser != null) {
if (currentUser.getAvatarType() != null) {
try {
mNavDrawerAvatarImageView.setImageDrawable(getResources().getDrawable(
ViewUtil.getAvatarHeadDrawableId(this,
currentUser.getAvatarType())));
} catch (Resources.NotFoundException e) {
e.printStackTrace();
}
}
if (currentUser.getUsername() != null) {
mNavDrawerUsernameTextView.setText(currentUser.getUsername());
}
}
}
}
}
BaseActivity
private void setupToolbar() {
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
if (getSupportActionBar() != null) {
getSupportActionBar().setTitle("");
getSupportActionBar().setSubtitle("");
getSupportActionBar().setLogo(R.drawable.logo_toolbar);
}
mUpdatingSpinner = (ProgressBar) getLayoutInflater().inflate(
R.layout.toolbar_updating_spinner, null, false);
int dpInPixels = (int) getResources().getDimension(R.dimen.toolbar_updating_spinner);
Toolbar.LayoutParams spinnerLp = new Toolbar.LayoutParams(dpInPixels, dpInPixels,
Gravity.END);
mToolbar.addView(mUpdatingSpinner, spinnerLp);
}
I found the answer although I don't fully understand it.
I basically called setupToolbar() again in my BaseDrawerActivity right before I call setupNavDrawer() and for some reason this fixed it.
I think the reference to the Toolbar from BaseActivity wasn't retrieving correctly (even though I debugged and it had a reference to it). Another thing I tried is setSupportActionBar(mToolbar) right before setting up the nav drawer but that didn't work.
If anyone has any ideas as to why I have to setup the toolbar again in order for it to show I'd be glad to hear it!
go to the AndroidManifest.xml file and replace
android:theme="#style/AppTheme"
with
android:theme="#android:style/Theme.Holo.Light.DarkActionBar"
you have to use setSupportActionBar(Toolbar toolbar).
This question should help.

Adding toolbar to PreferenceActivity via AppCompatPreferenceActivity causes overlapping

I had gone through How to add toolbars to AppCompatPreferenceActivity?
I'm using appcompat-v7:23.0.1 and support-v4:23.0.1
Before using AppCompayPreferenceActivity, my PreferenceActivity looks the following without toolbar.
Without Toolbar
public class JStockPreferenceActivity extends PreferenceActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
// Display the fragment as the main content.
JStockPreferenceFragment jStockPreferenceFragment = JStockPreferenceFragment.newInstance();
jStockPreferenceFragment.setArguments(this.getIntent().getExtras());
this.getFragmentManager().beginTransaction().replace(android.R.id.content, jStockPreferenceFragment).commit();
}
}
After using AppCompayPreferenceActivity, with some Toolbar initialization code, the outcome looks as the following
The outcome isn't as expected :-
The Toolbar overlaps with PreferenceFragment
When touching on Toolbar, the event will be consumed by PreferenceFragment. This means, when you touch on toolbar, "Table header" preference will be touched instead.
With Toolbar
public class JStockPreferenceActivity extends AppCompatPreferenceActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
// Display the fragment as the main content.
JStockPreferenceFragment jStockPreferenceFragment = JStockPreferenceFragment.newInstance();
jStockPreferenceFragment.setArguments(this.getIntent().getExtras());
this.getFragmentManager().beginTransaction().replace(android.R.id.content, jStockPreferenceFragment).commit();
}
initToolbar();
}
private void initToolbar() {
Toolbar toolbar;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
ViewGroup root = (ViewGroup) findViewById(android.R.id.list).getParent().getParent().getParent();
toolbar = (Toolbar) LayoutInflater.from(this).inflate(R.layout.toolbar, root, false);
root.addView(toolbar, 0);
} else {
toolbar = null;
}
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
}
My toolbar is
toolbar.xml
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" >
<!-- android:elevation="4dp" is used due to http://www.google.com/design/spec/what-is-material/elevation-shadows.html#elevation-shadows-elevation-android- -->
</android.support.v7.widget.Toolbar>
I was wondering, what I had did wrong, which causes Toolbar overlapped with PreferenceFragment
After some research and getting advice from Ian Lake, I manage to make it work by
Change from AppCompatPreferenceActivity, to AppCompatActivity+PreferenceFragmentCompat
The following solution is workable for API 10 and above.
JStockPreferenceActivity.java
public class JStockPreferenceActivity extends AppCompatActivity {
#SuppressWarnings("deprecation")
#SuppressLint("NewApi")
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.jstock_preference_activity);
initToolbar();
if (savedInstanceState == null) {
// Display the fragment as the main content.
JStockPreferenceFragment jStockPreferenceFragment = JStockPreferenceFragment.newInstance();
jStockPreferenceFragment.setArguments(this.getIntent().getExtras());
this.getSupportFragmentManager().beginTransaction().replace(R.id.content, jStockPreferenceFragment).commit();
}
}
JStockPreferenceFragment.java
public class JStockPreferenceFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener, PreferenceFragmentCompat.OnPreferenceDisplayDialogCallback {
public static JStockPreferenceFragment newInstance() {
return new JStockPreferenceFragment();
}
However, by doing so, there is a shortcoming. Your previous custom DialogPreference no longer work. To solve this, you need to
Replace DialogPreference with PreferenceDialogFragmentCompat.
Replace DialogPreference in XML with ListPreference. (I'm not exactly sure whether ListPreference as replacement is a right way. It works anyway)
Manually show PreferenceDialogFragmentCompat, in PreferenceFragmentCompat's onPreferenceDisplayDialog.
JStockPreferenceFragment.java
public class JStockPreferenceFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener, PreferenceFragmentCompat.OnPreferenceDisplayDialogCallback {
public static JStockPreferenceFragment newInstance() {
return new JStockPreferenceFragment();
}
////////////////////////////////////////////////////////////////////////////////////////////////
// Showing custom dialog preference.
private void showPreferenceDialogFragmentCompat(PreferenceDialogFragmentCompat preferenceDialogFragmentCompat) {
preferenceDialogFragmentCompat.setTargetFragment(this, 0);
preferenceDialogFragmentCompat.show(this.getFragmentManager(), "android.support.v7.preference.PreferenceFragment.DIALOG");
}
private void showCurrencySymbolPreferenceDialogFragmentCompat(Preference preference) {
CurrencySymbolPreferenceDialogFragmentCompat currencySymbolPreferenceDialogFragmentCompat = CurrencySymbolPreferenceDialogFragmentCompat.newInstance(preference.getKey());
showPreferenceDialogFragmentCompat(currencySymbolPreferenceDialogFragmentCompat);
}
// Showing custom dialog preference.
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////
// Callback when we are using custom dialog preference.
#Override
public Fragment getCallbackFragment() {
return this;
}
#Override
public boolean onPreferenceDisplayDialog(PreferenceFragmentCompat preferenceFragmentCompat, Preference preference) {
final String key = preference.getKey();
if (_CURRENCY_SYMBOL_OPTIONS.equals(key)) {
showCurrencySymbolPreferenceDialogFragmentCompat(preference);
return true;
}
return false;
}
// Callback when we are using custom dialog preference.
////////////////////////////////////////////////////////////////////////////////////////////////
CurrencySymbolPreferenceDialogFragmentCompat.java
public class CurrencySymbolPreferenceDialogFragmentCompat extends PreferenceDialogFragmentCompat {
public CurrencySymbolPreferenceDialogFragmentCompat() {
}
public static CurrencySymbolPreferenceDialogFragmentCompat newInstance(String key) {
CurrencySymbolPreferenceDialogFragmentCompat fragment = new CurrencySymbolPreferenceDialogFragmentCompat();
Bundle b = new Bundle(1);
b.putString("key", key);
fragment.setArguments(b);
return fragment;
}
#Override
public void onDialogClosed(boolean positiveResult) {
if (positiveResult) {
...
this.getPreference().setSummary(getSummary());
...
}
}
}
preferences.xml
<android.support.v7.preference.ListPreference
android:title="#string/preference_currency_symbol_title"
android:key="_CURRENCY_SYMBOL_OPTIONS" />
Please note that, you need to add the following item in your theme.
<item name="preferenceTheme">#style/PreferenceThemeOverlay</item>
Some bugs regarding theme
However, the theme-ing isn't perfect yet - PreferenceFragmentCompat requires preferenceTheme to be set
This is a known issues : https://code.google.com/p/android/issues/detail?id=183376
There is proposed workaround https://stackoverflow.com/a/32108439/72437 But, the workaround will only work for v14 and above, not v7 and above.

Calling Toolbar on each Activity

My app has a toolbar that should be present on every view. Currently, I do the following in my onCreate() method for each Activity I have:
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Does this need to be done in every onCreate() method in every Activity or is there a simpler way? Also, as a side question, how can I implement a "back" feature in the toolbar that takes the user back one action if they click it?
Create a Base class for Activity
public abstract class BaseActivity extends AppCompatActivity {
Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutResource());
configureToolbar();
}
protected abstract int getLayoutResource();
private void configureToolbar() {
toolbar = (Toolbar) findViewById(R.id.toolbar);
if (toolbar != null) {
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
FragmentManager fm = getSupportFragmentManager();
if (fm != null && fm.getBackStackEntryCount() > 0) {
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
} else {
finish();
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
And in each Activity extends this BaseActivity to get the ToolBar and implementing the back feature.
At last don't forget to include the ToolBar in each activity layout.
Edit:
Override that method getLayoutResource() in each Activity and pass the layout id.
public class MainActivity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public int getLayoutResource() {
return R.layout.activity_main;
}
This is my implementation. It removes the need of the getLayoutResources() from the accepted answer and brings back the "setContentView()" in all activities as normal
public abstract class BaseActivity extends AppCompatActivity {
Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
protected boolean useToolbar() {
return true;
}
#Override
public void setContentView(int layoutResID) {
View view = getLayoutInflater().inflate(layoutResID, null);
configureToolbar(view);
super.setContentView(view);
}
private void configureToolbar(View view) {
toolbar = (Toolbar) view.findViewById(R.id.toolbar);
if (toolbar != null) {
if (useToolbar()) {
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
} else {
toolbar.setVisibility(View.GONE);
}
}
}
}
From here on you just extend BaseActivity. If you don't want a toolbar you will have to override the useToolbar().
Don't forget to add in activity.xml at the top
<include layout="#layout/toolbar" />
toolbar.xml
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
</merge>
It depends on your implementation but if you want avoid boilerplate code you should use good programming OO.
An Example using Fragment.
public abstract class FragmentBase extends Fragment {
protected void settingsToolbar(View rootView) {
Toolbar toolbar = (Toolbar) rootView.findViewById(R.id.toolbar);
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
final ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
if (actionBar != null) {
// TODO add your code and your requirements
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
}
I hope this can give you an idea.
If you have used Activity then Create BaseActivity that extends AppCompatActivity or ActionBarActivity(Deprecated) and move Toolbar code to BaseActivity.
public class BaseActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
}
If you have used Fragment then Create BaseFragment that extends Fragment and move Toolbar code to BaseFragment.
public class BaseFragment extends Fragment {
View main;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
main = inflater.inflate(R.layout.fragment_about, container, false);
Toolbar toolbar = (Toolbar) main.findViewById(R.id.toolbar);
getActivity().setSupportActionBar(toolbar);
return main;
}
}
In main XML layout you have to add Toolbar xml code.
Now in every view(Activity) extends BaseActivity instead of AppCompatActivity or ActionBarActivity so you can get access Toolbar in every view.
public class YourActivity extends BaseActivity{
//your code
}
EDIT1:
main.xml
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:theme="#style/toolbarTheme"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/green"
android:minHeight="?attr/actionBarSize" />
</RelativeLayout>
EDIT2:
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
add these two lines below setSupportActionBar(toolbar); in BaseActivity.
I hope it helps!
Create a base activity and initialize your tool bar in this class. Now it can be extends to all other child activity.
FirtActivity extends BaseActivity
SecondActivity extends BaseActivity
In base activity toll bar back button click you can check like below mentioned way
if(this instance of FirstActivity){
//do stuff here
}else if(this instance of SecondActivity){
//do stuff here
}

Categories

Resources