Aesthetic


Source link: https://github.com/afollestad/aesthetic

Aesthetic

Aesthetic is an easy to use, fast, Rx-powered theme engine for Android applications.

You can download an APK of the sample project.


Table of Contents

  1. Gradle Dependency
  2. Integration
  3. Basics
    1. Basic Theme Colors
    2. Retrieving Current Values
    3. Status Bar
    4. Navigation Bar
    5. Text Colors
    6. Icon and Title Colors
    7. Activity Styles
    8. Window Background
  4. View Backgrounds
  5. Ignoring Views
  6. Snackbars
  7. Tab Layouts
  8. Drawer Layouts
  9. Bottom Navigation
  10. Collapsible Toolbar Layouts
  11. Custom View Subclasses
  12. Activity Keys

Gradle Dependency

The Gradle dependency is available via jCenter. jCenter is the default Maven repository used by Android Studio.

Add this to your module's build.gradle file:

dependencies {

  // ... other dependencies
  compile 'com.afollestad:aesthetic:0.4.6' 
}

Integration

The easiest way to integrate the library is to have your Activities extend AestheticActivity. This allows the library to handle lifecycle changes for you:

public class MainActivity extends AestheticActivity {

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {

  super.onCreate(savedInstanceState);

  // setContentView(...), etc.

 // If we haven't set any defaults, do that now
  if (Aesthetic.isFirstTime()) {

Aesthetic.get()

 ...

 .apply();

  
}

}
 
}

If you don't want to extend AestheticActivity, there are a few methods you need to call:

public class AestheticActivity extends AppCompatActivity {

 @Override
protected void onCreate(@Nullable Bundle savedInstanceState) {

  Aesthetic.attach(this);
 // MUST come before super.onCreate(...)
  super.onCreate(savedInstanceState);

}

 @Override
protected void onResume() {

  super.onResume();

  Aesthetic.resume(this);

}

 @Override
protected void onPause() {

  Aesthetic.pause(this);

  super.onPause();

}
 
}
 

Basics

Basic Theme Colors

The primary color and accent color are the two base theme colors used by apps. Generally, you see the primary color on things such as Toolbar's, and the accent color on widgets such as EditText's, CheckBox's, RadioButton's, Switch's, SeekBar's, ProgressBar's, etc.

Aesthetic.get()
  .colorPrimaryRes(R.color.md_indigo)
  .colorPrimaryDarkRes(R.color.md_indigo_dark)
  .colorAccentRes(R.color.md_yellow)
  .apply();

You use Aesthetic.get() to retrieve the current attached Aesthetic instance, set theme properties, and apply() theme. This will trigger color changes in the visible Activity WITHOUT recreating it. The set theme properties will also be persisted automatically.

The methods above end with Res, indicating they take a color resource. If you remove the Res suffix, you can pass a literal color integer.


Retrieving Current Values

All the setter methods also have equivalent getters. For an example, you can get the current primary theme color:

Aesthetic.get()
  .colorPrimary()
  .take(1)
  .subscribe(color -> {

 // Use color (an integer)
  
}
);

colorPrimary() returns an RxJava Observable<Integer>. take(1) here retrieves the latest value, and automatically unsubscribes so you don't continue to receive updates when the primary color changes.

If you were to leave take(1) out, you need to manage the subscription. You will continue to receive updates every time the primary color is changed, until you unsubscribe.

Disposable subscription =
 Aesthetic.get()

 .colorPrimary()

 .subscribe(color -> {

// Use color (an integer)

 
}
);

  // Later, you should unsubscribe, e.g. when your Activity pauses subscription.dispose();

Status Bar

The status bar is the bar on the top of your screen that shows notifications, the time, etc. (I'm sure you're aware of that). Per the Material Design guidelines, the status bar color should be a slightly darker version of the primary color. You can manually set the color:

Aesthetic.get()
  .colorStatusBar(R.color.md_indigo_dark)
  .apply();

Or you can have it automatically generated from the primary color ( you need to set the primary color first):

Aesthetic.get()
  .colorStatusBarAuto()
  .apply();

Aesthetic will automatically use light status bar mode (on Android Marshmallow and above) if your status bar color is light. You can modify this behavior:

// AUTO is the default. ON forces light status bar mode, OFF forces it to stay disabled. Aesthetic.get()
  .lightStatusBarMode(AutoSwitchMode.AUTO)
  .apply();

Navigation Bar

By default, the navigation bar on the bottom of your screen is black. You can set it to any color you wish, although generally it should be the same as your primary color if not black or transparent:

Aesthetic.get()
  .colorNavigationBarRes(R.color.md_indigo)
  .apply();

You can automatically set it to the primary color, also ( you need to set the primary color first):

Aesthetic.get()
  .colorNavigationBarAuto()
  .apply();

Text Colors

You can customize text colors which are used on TextView's, EditText's, etc.

Aesthetic.get()
  .textColorPrimaryRes(android.R.color.black)
  .textColorPrimaryInverseRes(android.R.color.white)
  .textColorSecondaryRes(R.color.dark_gray)
  .textColorSecondaryInverseRes(R.color.lesser_white)
  .apply();

Take this layout:

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
 <TextView
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:text="Hello, world!"
  android:textColor="?android:textColorPrimary"
  android:textSize="24sp"/>
 <TextView
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:text="My name is Aidan."
  android:textColor="?android:textColorSecondary"
  android:textSize="16sp"/>  </LinearLayout>

The first TextView uses the stock Android framework attribute ?android:textColorPrimary, this library will see that and automatically swap it out with whatever value you set to textColorPrimary. The second TextView also uses a stock framework attribute, ?android:textColorSecondary. It will be swapped out with whatever you set to textColorSecondary in this library. If you do not specify a textColor attribute at all, TextView's will use the secondary text color as a default.

You can set the text color and hint text color on EditText's too. By default, the text color will match your primary text color, and the hint text color will match your secondary text color.

In addition to the two stock attributes above, these are some other attributes that are auto swappable: ?colorPrimary, ?colorPrimaryDark, ?colorAccent, ?android:windowBackground, ?android:textColorPrimaryInverse, ?android:textColorSecondaryInverse.


Icon and Title Colors

You can modify the "icon and title" colors which are used in various places. A main example is on toolbars. The color of the toolbar title and the menu icons are taken from this theme value. By default, the Material Design guideline colors are used, when isDark() is true and when it's false.

Aesthetic.get()
  .colorIconTitleActiveRes(R.color.md_black)
  .colorIconTitleInactiveRes(R.color.md_dark_gray)
  .apply();

The getter for these methods are combined into one: Observable<ActiveInactiveColors> colorIconTitle(Observable<Integer>).

Another example of where this is used is the text color for Tab Layout tabs. There are others that you will see if you change these values and observe differences.


Activity Styles

Aesthetic allows you to change the actual styles.xml theme applied to Activities:

// Apply an overall light theme Aesthetic.get()
  .activityTheme(R.style.Theme_AppCompat_Light_NoActionBar)
  .isDark(false)
  .apply();
  // Apply an overall dark theme Aesthetic.get()
  .activityTheme(R.style.Theme_AppCompat_NoActionBar)
  .isDark(false)
  .apply();

isDark is important, it's used as a hint by this library for various things. For an example, with a Switch widget, the unchecked state is either light gray or dark gray based on whether it's being used with a dark theme or light theme.

When the activityTheme property is changed, apply() WILL recreate the visible Activity. This is the ONLY property which requires a recreate.


Window Background

Aside from changing the entire base theme of an Activity, you can also change just the window background:

Aesthetic.get()
  .colorWindowBackgroundRes(R.color.window_background_gray)
  .apply();

View Backgrounds

When you set stock or AppCompat attributes to the background of certain views, Aesthetic will swap out the attribute with your dynamic theme colors at inflation time:

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="196dp"
android:background="?colorAccent"
android:orientation="vertical" />

Above, ?colorAccent is an attribute provided by AppCompat. Aesthetic will automatically set the background to whatever accentColor you have set.

You could also use: ?colorPrimary, ?colorPrimaryDark, ?android:windowBackground, ?android:textColorPrimary, ?android:textColorPrimaryInverse, ?android:textColorSecondary, ?android:textColorSecondaryInverse.


Ignoring Views

You can make this library ignore views from being themed by setting the view's tag to :aesthetic_ignore.


Snackbars

Snackbar theming is pretty simple. You can change the color of the message text and the color of the (optional) action button.

Aesthetic.get()
  .snackbarTextColorRes(R.color.white)
  .snackbarActionTextColorRes(R.color.md_blue)
  .apply();

By default, the text color will match textColorPrimary when isDark() is true, or textColorPrimaryInverse when isDark() is false. By default, the action text color will match colorAccent().


Tab Layouts

Tab Layouts from the Design Support library are automatically themed. The main screen in the sample project is an example of this, you see the two tabs under the toolbar at the top.

You can customize background theming behavior:

// The background of the tab layout will match your primary theme color. This is the default. Aesthetic.get()
  .tabLayoutBackgroundMode(

TabLayoutBgMode.PRIMARY)
  .apply();
  // The background of the tab layout will match your accent theme color. Aesthetic.get()
  .tabLayoutBackgroundMode(

TabLayoutBgMode.ACCENT)
  .apply();

And indicator (underline) theming behavior:

// The selected tab underline will match your primary theme color. Aesthetic.get()
  .tabLayoutIndicatorMode(

TabLayoutIndicatorMode.PRIMARY)
  .apply();
  // The selected tab underline will match your accent theme color. This is the default. Aesthetic.get()
  .tabLayoutIndicatorMode(

TabLayoutIndicatorMode.ACCENT)
  .apply();

The color of icons and text in your tab layout will automatically be white or black, depending on what is more visible over the set background color.


Drawer Layouts

When your Activity has a DrawerLayout at its root, your status bar color will get set to the DrawerLayout instead of the Activity, and the Activity's status bar color will be made transparent per the Material Design guidelines (so that the drawer goes behind the status bar).

If you use NavigationView, it will be themed automatically, also.

You can customize behavior:

// Checked nav drawer item will use your set primary color Aesthetic.get()
  .navigationViewMode(

NavigationViewMode.SELECTED_PRIMARY)
  .apply();
  // Checked nav drawer item will use your set accent color Aesthetic.get()
  .navigationViewMode(

NavigationViewMode.SELECTED_ACCENT)
  .apply();

In addition, unselected nav drawer items will be shades of white or black based on the set isDark value.


Bottom Navigation

Bottom Navigation Views from the Design Support library are automatically themed.

You can customize background theming behavior:

// The background of the bottom tabs will match your primary theme color. Aesthetic.get()
  .bottomNavigationBackgroundMode(

BottomNavBgMode.PRIMARY)
  .apply();
  // The background of the bottom tabs will match your status bar theme color. Aesthetic.get()
  .bottomNavigationBackgroundMode(

BottomNavBgMode.PRIMARY_DARK)
  .apply();
  // The background of the bottom tabs will match your accent theme color. Aesthetic.get()
  .bottomNavigationBackgroundMode(

BottomNavBgMode.ACCENT)
  .apply();
  // The background of the bottom tabs will be dark gray or white depending on the isDark() property. // This is the default. Aesthetic.get()
  .bottomNavigationBackgroundMode(

BottomNavBgMode.BLACK_WHITE_AUTO)
  .apply();

You can also customize icon/text theming behavior:

// The selected tab icon/text color will match your primary theme color. Aesthetic.get()
  .bottomNavigationIconTextMode(

BottomNavIconTextMode.SELECTED_PRIMARY)
  .apply();
  // The selected tab icon/text color will match your accent theme color. This is the default. Aesthetic.get()
  .bottomNavigationIconTextMode(

BottomNavIconTextMode.SELECTED_ACCENT)
  .apply();
  // The selected tab icon/text color will be black or white depending on which is more visible  // over the background of the bottom tabs. Aesthetic.get()
  .bottomNavigationIconTextMode(

BottomNavIconTextMode.BLACK_WHITE_AUTO)
  .apply();

Collapsible Toolbar Layouts

Collapsible Toolbar Layouts are automatically themed, as seen in the sample project.

In the sample layout, we automatically set the accent color to the expanded view. The collapsed toolbar color will match whatever color your toolbar uses, which is the primary theme color by default. You'll also notice that the icons and title color are updated to be most visible over the background color.


Custom View Subclasses

If you have custom view subclasses in your app, such as:

public class MyCustomTextView extends TextView {

... 
}

You may want your view to be themable. You can do so by swapping out TextView with AestheticTextView, or any of Aesthetic's other view classes beginning with "Aesthetic". These views handle subscribing and unsubscribing from theme property updates automatically; they also handle pulling out attributes such as android:textColor. Note that all views support background color theming, you don't need to extend any special views for background color support.

public class MyCustomTextView extends AestheticTextView {

... 
}

Otherwise, you can subscribe to theme properties (as seen in Retrieving Current Values) such as Aesthetic.get().primaryColor() and manually update your custom view (text color or whatever else).


Activity Keys

AestheticActivity has an optional override named key():

public class MyActivity extends AestheticActivity {

...

 @Nullable
  @Override
  public String key() {

 return "my_activity";
  
}
 
}

You can return whatever you wish. If this key is specified, this specific Activity will save its own version of the activityTheme(), colorStatusBar(), and colorNavigationBar() theme properties.

An example of where this can be useful: You have an Activity which displays a list of videos, this main activity has a colored status bar and navigation bar. When you tap a video, it brings you to a player Activity. This player Activity needs a different theme so that the status bar and nav bar are transparent and hidden. You can use a separate key for this player Activity so that it doesn't adopt the same window theme properties as the main activity.

If you do not use AestheticActivity, your custom Activity can implement the AestheticKeyProvider interface.

Proguard

In case you are using views from the support library (e.g. TextInputLayout & TextInputEditText), you will need to add the following to your proguard:

-keep class android.support.design.widget.** {
 *; 
}
 

Resources

osmdroid is a (almost) full/free replacement for Android's MapView (v1 API) class. It also includes a modular tile provider system with support for numerous online and offline tile sources and overlay support with built-in overlays for plotting icons, tracking location, and drawing shapes.

A carefully crafted Android framework that includes: DI, ORM, EventBus, JSON (de)serialization feature, improved AsyncTask & IntentService, Logger, RESTClient, ImageFetcher, and a lot of utils.

Android common lib, include ImageCache, HttpCache, DropDownListView, DownloadManager, Utils and so on.

An HTTP & SPDY client for Android and Java applications.

Autobahn|Android is a subproject of the Autobahn project and provides an open-source implementation of WebSocket Protocol and Web Application Messaging Protocol (WAMP).

Android ListView with drag and drop reordering.

Topics


2D Engines   3D Engines   9-Patch   Action Bars   Activities   ADB   Advertisements   Analytics   Animations   ANR   AOP   API   APK   APT   Architecture   Audio   Autocomplete   Background Processing   Backward Compatibility   Badges   Bar Codes   Benchmarking   Bitmaps   Bluetooth   Blur Effects   Bread Crumbs   BRMS   Browser Extensions   Build Systems   Bundles   Buttons   Caching   Camera   Canvas   Cards   Carousels   Changelog   Checkboxes   Cloud Storages   Color Analysis   Color Pickers   Colors   Comet/Push   Compass Sensors   Conferences   Content Providers   Continuous Integration   Crash Reports   Credit Cards   Credits   CSV   Curl/Flip   Data Binding   Data Generators   Data Structures   Database   Database Browsers   Date &   Debugging   Decompilers   Deep Links   Dependency Injections   Design   Design Patterns   Dex   Dialogs   Distributed Computing   Distribution Platforms   Download Managers   Drawables   Emoji   Emulators   EPUB   Equalizers &   Event Buses   Exception Handling   Face Recognition   Feedback &   File System   File/Directory   Fingerprint   Floating Action   Fonts   Forms   Fragments   FRP   FSM   Functional Programming   Gamepads   Games   Geocaching   Gestures   GIF   Glow Pad   Gradle Plugins   Graphics   Grid Views   Highlighting   HTML   HTTP Mocking   Icons   IDE   IDE Plugins   Image Croppers   Image Loaders   Image Pickers   Image Processing   Image Views   Instrumentation   Intents   Job Schedulers   JSON   Keyboard   Kotlin   Layouts   Library Demos   List View   List Views   Localization   Location   Lock Patterns   Logcat   Logging   Mails   Maps   Markdown   Mathematics   Maven Plugins   MBaaS   Media   Menus   Messaging   MIME   Mobile Web   Native Image   Navigation   NDK   Networking   NFC   NoSQL   Number Pickers   OAuth   Object Mocking   OCR Engines   OpenGL   ORM   Other Pickers   Parallax List   Parcelables   Particle Systems   Password Inputs   PDF   Permissions   Physics Engines   Platforms   Plugin Frameworks   Preferences   Progress Indicators   ProGuard   Properties   Protocol Buffer   Pull To   Purchases   Push/Pull   QR Codes   Quick Return   Radio Buttons   Range Bars   Ratings   Recycler Views   Resources   REST   Ripple Effects   RSS   Screenshots   Scripting   Scroll Views   SDK   Search Inputs   Security   Sensors   Services   Showcase Views   Signatures   Sliding Panels   Snackbars   SOAP   Social Networks   Spannable   Spinners   Splash Screens   SSH   Static Analysis   Status Bars   Styling   SVG   System   Tags   Task Managers   TDD &   Template Engines   Testing   Testing Tools   Text Formatting   Text Views   Text Watchers   Text-to   Toasts   Toolkits For   Tools   Tooltips   Trainings   TV   Twitter   Updaters   USB   User Stories   Utils   Validation   Video   View Adapters   View Pagers   Views   Watch Face   Wearable Data   Wearables   Weather   Web Tools   Web Views   WebRTC   WebSockets   Wheel Widgets   Wi-Fi   Widgets   Windows   Wizards   XML   XMPP   YAML   ZIP Codes