Monday, November 16, 2015

Note of the Navigation Darwer

Source code: https://github.com/AndroidAppNotes/AccountsNavigationDrawer

Gmail-like Side Menu

I needed to create a gmail-like side menu. In the Gmail application, if you configured multiple accounts, its side menu will display three accounts in the navigation view. The three accounts are the currently selected account and the most recent two accounts. If you pressed the email text of the current account, the side menu will display a list of the configured emails.
I used the MaterialDrawer library and guess what? It is great. Checkout the library documentation to see its capabilities.

Names of Recent Accounts

Now, the missing part. Both the Gmail application and the MaterialDrawer display the two recent accounts using images without names.
I wrote some code to overcome this issue and I would like to share it with you.
1. Create a copy of the navigation view layout and add two TextViews for the two recent accounts. The original layout can be found in the library at library/src/main/res/layout/material_drawer_header.xml
In my copy I replaced each image with image and text. For example, the first image changed from:
<com.mikepenz.materialdrawer.view.BezelImageView
    android:id="@+id/material_drawer_account_header_small_first"
    android:layout_width="@dimen/material_drawer_account_header_secondary"
    android:layout_height="@dimen/material_drawer_account_header_secondary"
    android:layout_marginRight="@dimen/material_drawer_vertical_padding"
    android:clickable="true"
    android:elevation="2dp"

    android:visibility="gone" />
to a vertical LinearLayout with image and text:
<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginRight="@dimen/material_drawer_vertical_padding"
    android:gravity="center_horizontal"
    android:orientation="vertical">

    <com.mikepenz.materialdrawer.view.BezelImageView
        android:id="@+id/material_drawer_account_header_small_first"
        android:layout_width="@dimen/material_drawer_account_header_secondary"
        android:layout_height="@dimen/material_drawer_account_header_secondary"
        android:clickable="true"
        android:elevation="2dp"
        android:visibility="gone" />

    <TextView
        android:id="@+id/material_drawer_account_header_text_first"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@android:color/white" />

</LinearLayout>
2. Create a subclass of the AccountHeaderBuilder class and override the  method:
public class AccountHeaderBuilderX extends AccountHeaderBuilder {
    protected TextView mProfileFirstText;
    protected TextView mProfileSecondText;

    @Override
    protected void buildProfiles() {
        super.buildProfiles();

        if (mProfileFirstText == null) {
            mProfileFirstText = (TextView) mAccountHeader.findViewById(R.id.material_drawer_account_header_text_first);
        }

        if (mProfileSecondText == null) {
            mProfileSecondText = (TextView) mAccountHeader.findViewById(R.id.material_drawer_account_header_text_second);
        }

        setAccountName(mProfileFirstText, mProfileFirst);
        setAccountName(mProfileSecondText, mProfileSecond);
    }

    private void setAccountName(TextView tv, IProfile profile) {
        if (tv != null) {
            if (profile != null) {
                StringHolder.applyTo(profile.getName(), tv);
            } else {
                tv.setText(null);
            }
        }
    }

}
3. Create the accounts header using the subclass from step 2 and call the withAccountHeader method with the new layout as a parameter:
AccountHeader headerResult = new AccountHeaderBuilderX()
    .withActivity(this)
    .withAccountHeader(R.layout.material_drawer_header_x)
    ...
    .build();
Recent accounts should now display names below their images.

Hope it helps and let me hear from you.

Sunday, September 13, 2015

Note of Color and Font



TextView with Colored Text

There are different ways to change the color of text inside a TextView and I want to share one way of them with you.
In general, we can add styling to strings with HTML markup. I will use the <font> tag to display the word 'Colors' in a TextView. Steps are simple:
1. Store your styled text resource as an HTML-escaped string. Add a new string resource with text 'Colors', surround each character with the <font> tag including color and then replace the angle bracket at start of each <font> tag with &lt;
<string name="colored_message">&lt;font color="#0057e7">C&lt;/font>&lt;font color="#d62d20">o&lt;/font>&lt;font color="#ffa700">l&lt;/font>&lt;font color="#0057e7">o&lt;/font>&lt;font color="#008744">r&lt;/font>&lt;font color="#d62d20">s&lt;/font></string>
More information about string-resource formatting and styling can be found at Formatting and Styling.
2. Get the string from the string-table and convert the HTML text into styled text.
String text = getResources().getString(R.string.colored_message);
CharSequence styledText = Html.fromHtml(text);
3. Change the text of your TextView.
textView.setText(styledText);

App Font

Again, there are different ways to use custom fonts. I will use the Calligraphy library to change the font of my whole app. The library and its documentation can be found at Calligraphy
Here's a sample usage:
1. Add an assets folder to your project if it does not have one.
Adding the assets folder from inside the Android Studio.
And then add a sub-folder to the assets and name it fonts.
2. Get your font and copy it to the fonts folder. I will use the free font, Back To School. I renamed the file to BackToSchool.ttf
3. Add the Calligraphy library to the dependencies of your project.
compile 'uk.co.chrisjenx:calligraphy:2.1.0'
4. Create an application class and override the onCreate method.
public class FontColorsApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
                        .setDefaultFontPath("fonts/BackToSchool.ttf")
                        .setFontAttrId(R.attr.fontPath)
                        .build()
        );
    }
}
5. In your manifest, set the name attribute of your <application> to the new application class.
<application
    android:name=".FontColorsApp"
    ...
6. Override the attachBaseContext() in your activities.
@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
}
Run your app and it should display your text using the font from the assets.
Hope it helps and let me hear from you.