Rhythm
Rhythm is a design overlay engine for Android.
With Rhythm you can easily render grids, keylines, other Material Design cues and even custom elements within your app, helping you to build perfect layouts. Define overlay configurations using simple expression language, and Rhythm will convert them into Drawables¹, which you can then set as view backgrounds, foregrounds, draw to bitmaps etc:
Discontinued library
Unfortunately the development of this library is discontinued. Such decision was made based on its usefulness vs maintenance effort. The library had insignificant if not zero downloads; it's only actively used in my own Material Cue app, and it's been getting harder and harder to mantain these two separately. Let us say, it served its purpose well as an interim step to get Material Cue done.
Rhythm code will remain as is. All new features will go directly into Material Cue.
If you're interested in revival of this library, ping me.
Material Cue
Material Cue is a standalone keyline app built on Rhythm. If you need to verify your layout but don’t want the trouble of setting up another library in your project, Material Cue is perfect for you.
Learn more about the differences between Rhythm and Material Cue.
Quick setup
Starting with 0.9.6, Rhythm is packaged as two separate artifacts:
- Rhythm Core — contains core rendering framework for turning human readable config into Drawable objects¹. You then manage those Drawables yourself.
- Rhythm Control — provides a mechanism to assign many overlays to many views and switch them on the go using the Rhythm Control notification.
Tip: Look at the sample app.
Rhythm Core
-
Add Gradle dependency:
compile 'com.actinarium.rhythm:rhythm:0.9.6'
For alternative setup (JAR, Maven) see Bintray page.
-
Create a raw file in your app’s
/src/res/raw
folder, e.g./src/res/raw/overlays
, with content like this:# Standard 8dp grid grid-lines step=8dp from=top grid-lines step=8dp from=left # Typography grid w/keylines grid-lines step=4dp from=top keyline distance=16dp from=left keyline distance=16dp from=right keyline distance=72dp from=left
Overlays are separated by empty newline. Lines starting with
#
are optional overlay titles. There can also be comments and variables.Take a look at the sample config file for a more complex and documented example. For full docs see the wiki.
-
In your code, inflate this file into a list of overlay objects, wrap them with RhythmDrawables, and assign to views as required:
RhythmOverlayInflater inflater = RhythmOverlayInflater.createDefault(context); List<RhythmOverlay> overlays = inflater.inflate(R.raw.overlays); Drawable overlayDrawable = new RhythmDrawable(overlays.get(1)); view.setBackground(overlayDrawable);
-
Later you can replace the overlay in that drawable:
((RhythmDrawable) view.getBackground()).setOverlay(overlays.get(0));
or disable it:
((RhythmDrawable) view.getBackground()).setOverlay(null);
Rhythm Control
This module is discontinued in favor of Material Cue app and will not receive new functionality.
If you want to switch overlays for the views in your app at runtime, you can setup Rhythm Control. This module allows to define groups with many views and overlays attached to them, and then separately control which overlay is displayed over all views in a particular group. This can be done with a Rhythm Control notification², where you can cycle through the groups (1 › 2 › 3 › … › last › 1) and current group’s overlays (1 › 2 › 3 › … › last › no overlay › 1):
-
Set up Rhythm Core: add a dependency and compose a configuration sheet.
-
Add another dependency for Rhythm Control:
compile 'com.actinarium.rhythm:rhythm-control:0.9.6'
For alternative setup (JAR, Maven) see Bintray page.
-
Implement
RhythmControl.Host
in your Application class (create one if it doesn’t exist yet):public class MyApplication extends Application implements RhythmControl.Host { private RhythmControl mRhythmControl; @Override public void onCreate() { super.onCreate(); mRhythmControl = new RhythmControl(this); /* Rest of OnCreate() code */ } @Override public RhythmControl getRhythmControl() { return mRhythmControl; } }
-
In your
Application.onCreate()
method set up Rhythm groups:// Create an inflater and inflate overlays from your configuration sheet RhythmOverlayInflater inflater = RhythmOverlayInflater.createDefault(this); List<RhythmOverlay> overlays = inflater.inflate(R.raw.overlays); // Create the groups. Each group will be given an index starting from 0 RhythmGroup mainGroup = mRhythmControl.makeGroup("A group with index 0"); RhythmGroup secondaryGroup = mRhythmControl.makeGroup("Another group with index 1"); RhythmGroup anotherGroup = mRhythmControl.makeGroup("Group with index 2"); // Assign overlays to groups mainGroup.addOverlay(overlays.get(0)); // add only one secondaryGroup.addOverlays(overlays); // add all anotherGroup.addOverlays(overlays.subList(0, 2)); // add first two // Finally, display the notification with notification ID unique across your app // (to avoid conflicts with other notifications) mRhythmControl.showQuickControl(RHYTHM_NOTIFICATION_ID);
-
Finally, integrate Rhythm groups into your layouts.
There are two ways to do this:-
Decorate existing views programmatically, e.g. in your
Activity.onCreate()
methods:// Retrieve Rhythm Control from application class: RhythmControl rhythmControl = ((RhythmControl.Host) getApplication()).getRhythmControl(); // Decorate backgrounds of given views (draws overlay over existing background but under content) // Works with any views rhythmControl.getGroup(0).decorate(view1, view2, view3 /*, ... */); // Decorate foregrounds of given views - will draw overlay over content // Works with FrameLayouts and its subclasses (e.g. CardView) only rhythmControl.getGroup(1).decorateForeground(card1, frame2, card3 /*, ... */);
-
Wrap pieces of your layouts with
RhythmFrameLayout
connected to appropriate groups:<com.actinarium.rhythm.control.RhythmFrameLayout xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" app:rhythmGroup="0" app:overlayPosition="overContent"> <LinearLayout ... /> </com.actinarium.rhythm.control.RhythmFrameLayout>
-
Protip: you can use RhythmFrameLayout
on its own, without setting up Rhythm control or groups. Omit the app:rhythmGroup
attribute or set it to app:rhythmGroup="noGroup"
, and set overlays to it programmatically:
// By default, RhythmFrameLayout doesn't have a RhythmDrawable object, so inject a new one rhythmFrameLayout.setRhythmDrawable(new RhythmDrawable(rhythmOverlay));
// After that you can change overlays in that drawable rhythmFrameLayout.getRhythmDrawable().setOverlay(anotherOverlay);
Further reading
A personal appeal
If you like what I’m doing, please consider supporting my efforts.
I quit my full-time job so that I could focus on building useful, time-saving libraries and apps. I’ve already made a few, and I have more in mind, including free and open-source apps, an ultimate charting library for Android, tutorials and samples, and more. But as much as I’d love to give it all away for free, I also need to make a living.
Without your support, in a few months I’ll have to return to workforce, meaning I won’t be able to work on my projects anymore.
Here’s what you can do to help:
- Check out Material Cue, a keyline app I built with Rhythm.
- Gift me a game from my wishlist on Steam to cheer me up.
- Spread the word: tell your fellow developers about Rhythm, Material Cue, and my other projects.
- Add me on Google+ and/or Twitter to be the first to know about my upcoming projects and apps.
- If you or your company are interested in sponsoring my development efforts, please contact me directly at [email protected], and we could arrange something.
- Need a hand with making your app more Material? I guess I could allocate some time to freelance work — contact me to discuss the options.
Thank you!
License
The library is licensed under Apache 2.0 License, meaning that you can freely use it in any of your projects.
Copyright (C) 2016 Actinarium Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Android, Google Play and the Google Play logo are trademarks of Google Inc.
¹ — Said so for simplicity. In fact, Rhythm inflates overlay config into RhythmOverlay objects, which then can be injected into one or many RhythmDrawables, which are, yeah, Drawables. Since it's not 1.0 yet, this may also change.
² — Rhythm Control notification is pretty useless on pre-4.1 (API 15 and below) because of lack of notification actions. The groups and RhythmFrameLayouts
can still be controlled programmatically though.