Remixer helps teams use and refine design specs by providing an abstraction for these values that is accessible and configurable from both inside and outside the app itself.
This SDK for Android is currently in development.
New to Remixer? Visit our main repo to get a full description of what it is and how it works.
The project is defined as a gradle project with submodules.
- remixer_core: The core framework code, has no dependencies on the android framework and contains the core logic to run callbacks on changes to a Variable, etc. Most of the base classes are here
- main: The code for the core framework
- tests: JUnit tests for the Remixer code.
- remixer_ui: The code that shows remixes in the UI.
- main
com.google.android.libraries.remixer.ui.view
is the code to display the UI as a BottomSheetFragmentDialogcom.google.android.libraries.remixer.ui.widget
is a family of widgets that can display each individual Remixer item (variable or trigger).com.google.android.libraries.remixer.ui.widget.RemixerItemWidget
is an Interface to implement such widgets. Necessary if you want to provide different widgets.com.google.android.libraries.remixer.ui.RemixerCallbacks
is an implementation ofApplication.ActivityLifecycleCallbacks
that clears up callbacks once the corresponding activity is destroyed so it doesn't leak. It needs to be registered in theApplication.onCreate()
method.
- tests: JUnit/Robolectric tests.
- main
- remixer_annotation: An annotation processor to make it easier to add remixes to your code.
- main: The annotation processing code.
- tests: JUnit tests based on actual classes to compile.
- remixer_example: This is an example app.
- main: the code for the example app
Disclaimer: Remixer still hasn't reached a stage that we consider is stable enough to commit to the current status of the API, it will be evolving quickly and we may commit breaking changes every once in a while. That said, we would love to have you try it out and tell us what you think is missing and what you'd like us to focus on.
Using gradle it's super easy to start using Remixer following these instructions.
In your main build.gradle file make sure you have the following dependencies and repositories set up:
buildscript {
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
allprojects {
repositories {
jcenter()
maven { url "https://jitpack.io" }
}
}
And in your modules, apply the android-apt
plugin and add the remixer dependency:
apply plugin: 'android-apt'
dependencies {
compile 'com.github.material-foundation.material-remixer-android:remixer:0.5.2'
}
Notice the dependency on remixer_annotation
is a provided
clause instead of compile
, this is on purpose as this is not a regular dependency but a compiler plugin.
If you have not subclassed the application class it is recommended you do it since this is a one-time global initialization.
In your application class you need to call the Remixer initialization method. Remember this application class MUST be (declared in your Android Manifest)[https://developer.android.com/guide/topics/manifest/application-element.html#nm].
import android.app.Application;
import com.google.android.libraries.remixer.Remixer;
import com.google.android.libraries.remixer.storage.LocalStorage;
import com.google.android.libraries.remixer.ui.RemixerInitialization;
class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
RemixerInitialization.initRemixer(Remixer.getInstance(), this);
Remixer.getInstance().setSynchronizationMechanism(new LocalStorage(getApplicationContext()));
}
}
The line that calls setSynchronizationMechanism
makes Remixer values persistent using SharedPreferences. If you would not like to persist values remove this line.
Only in the activities where you're using remixer
You need to add a few lines at the end of your Activity.onCreate()
RemixerBinder.bind(this);
creates, initializes and sets up all the Variables and trigger you define in this activity.RemixerFragment remixerFragment = RemixerFragment.newInstance();
creates the fragment that will be shown when remixer is invoked, then you need at least one of the following:
- A variation of
remixerFragment.attachToGesture(this, Direction.UP, 3);
, this example ties showing the Remixer Fragment on a 3-finger swipe up. remixerFragment.attachToButton(this, someButtonObject);
, this makes the OnClickListener for a button open the Remixer fragment.
Your Activity.onCreate
may look like this:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
remixerButton = (Button) findViewById(R.id.button);
RemixerBinder.bind(this);
RemixerFragment remixerFragment = RemixerFragment.newInstance();
remixerFragment.attachToGesture(this, Direction.UP, 3);
remixerFragment.attachToButton(this, remixerButton);
}
In order to define variables you only need to write methods that take one argument of the correct type and annotate them. The methods contain your logic to handle changes to these variables (update the UI accordingly). You can rest assured those methods will run in the main UI thread.
There are a few very simple examples here, but you should look at the example activities and documentation for these annotations for more information.
Once you add your annotated methods and build you should be able to invoke remixer (by doing a 3 finger swipe or clicking a button, depending on how you configured it in the section above), and tweak the variables or trigger the events guarded by the trigger.
Note: for the time being they only support Integers, not floats or doubles.
They support the following properties:
key
the key for this variable, you can use it to share the same value across activities, if not set it assumes the method name.title
the displayable name of the variable, if not set assumeskey
defaultValue
the initial value, if not set assumes 0 orminValue
if 0 is out of range.minValue
the minimum value, if not set assumes 0maxValue
the maximum value, if not set assumes 100increment
the increment between two steps of the range, 1 by default.layoutId
a layoutId to display this, must implement RemixerItemWidget. It assumes a sensible default if unset.
A Range variable that goes from 15 to 70 and starts at 20 by default:
@RangeVariableMethod(
minValue = 15, maxValue = 70, defaultValue = 20)
public void setFontSize(Integer fontSize) {
}
(Notice how integer variables take Integer
and not int
, this is a limitation on the Java type system)
They support the following properties:
key
the key for this variable, you can use it to share the same value across activities, if not set it assumes the method name.title
the displayable name of the variable, if not set assumeskey
defaultValue
the initial value, if not set assumesfalse
layoutId
a layoutId to display this, must implement RemixerItemWidget. It assumes a sensible default if unset.
A Boolean variable that has true as a default value:
@BooleanVariableMethod(defaultValue = true, key = "someRemixerKey")
public void setUseNewDialog(Boolean useNewDialog) {
}
(Notice how boolean variables take Boolean
and not boolean
, this is a limitation on the Java type system)
They support the following properties:
key
the key for this variable, you can use it to share the same value across activities, if not set it assumes the method name.title
the displayable name of the variable, if not set assumeskey
defaultValue
the initial value, if not set assumes the first in thepossibleValues
listpossibleValues
the list of possible values.layoutId
a layoutId to display this, must implement RemixerItemWidget. It assumes a sensible default if unset.
A String List variable that sets fonts from a list and defaults to the first in the list:
@StringListVariableMethod(
title = "Title font",
possibleValues = {"Roboto", "Roboto Mono", "Comic Sans MS"})
public void setTitleFont(String fontName) {
}
key
the key for this variable, you can use it to share the same value across activities, if not set it assumes the method name.title
the displayable name of the variable, if not set assumeskey
defaultValue
the initial value, if not set assumes the empty string.layoutId
a layoutId to display this, must implement RemixerItemWidget. It assumes a sensible default if unset.
A String variable that sets freeform example text:
@StringVariableMethod
public void setExampleText(String exampleText) {
}
key
the key for this variable, you can use it to share the same value across activities, if not set it assumes the method name.title
the displayable name of the variable, if not set assumeskey
defaultValue
the initial value, if not set assumes the first in thepossibleValues
listpossibleValues
the list of possible values.layoutId
a layoutId to display this, must implement RemixerItemWidget. It assumes a sensible default if unset.
A variable that lets you pick colors from a list, this example uses a custom layout id to guarantee that it's treated as a Color:
@IntegerListVariableMethod(
title = "Title Color",
possibleValues = {Color.parseColor("#000000"), Color.parseColor("#DCDCDC")},
layoutId = R.layout.color_list_variable_widget)
public void setTitleColor(Integer color) {
}
key
the key for this trigger, you can use it to share the same value across activities, if not set it assumes the method name.title
the displayable name of the trigger, if not set assumeskey
layoutId
a layoutId to display this, must implement RemixerItemWidget. It assumes a sensible default if unset.
A trigger to simulate an event happening:
@TriggerMethod
public void simulateConnectionFailure() {
}
- Clone the repository
git clone https://github.com/material-foundation/material-remixer-android.git
- You have two options here:
- Open it on Android Studio and build from there.
- run
./gradlew build
on your terminal (gradlew.bat build
on Windows). * This assumes that you have a copy of the android SDK and, * That you have exported aANDROID_HOME
environment variable that points to your SDK install (the directory that contains subdirectories such astools
,platform-tools
, etc.)- If you use Android Studio on a mac that defaults to
/Users/<yourusername>/Library/Android/sdk
- In this case you can put
export ANDROID_HOME=/Users/<yourusername>/Library/Android/sdk
in your~/.profile
or~/.bash_profile
as appropriate.)
- If you use Android Studio on a mac that defaults to
If you're reading this you're probably installing the app from the terminal as opposed to Android Studio.
adb install -r remixer_example/build/outputs/apk/remixer_example-debug.apk
Visit our State of Development wiki for the current roadmap and status of development for each platform.
The main Remixer GitHub repo for documentation, project tracking, and general information:
Platform specific libraries and tools can be found in the following GitHub repos:
- iOS - Remixer for iOS.
- Web - Remixer for Web.
- Web Remote - Remixer web remote controller for all platforms (available soon).
Yes, the material-foundation organization is one of Google's new homes for tools and frameworks related to our Material Design system. Please check out our blog post Design is Never Done for more information regarding Material Design and how Remixer integrates with the system.
We gladly welcome contributions! If you have found a bug, have questions, or wish to contribute, please follow our Contributing Guidelines.
© Google, 2016. Licensed under an Apache-2 license.