diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ab8603..bdca3a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +# 1.0 + +- First supported release, yay! +- FirebaseRemoteControllerSync is now completely functional and documented + - Fixed an issue with FirebaseRemoteControllerSync not persisting settings across restarts. +- Added a sharing options drawer to the Remixer UI where the user can choose to share the Remote controller link or disable sharing altogether +- Styling is done! +- Added a more real-looking demo. +- Added the ability to attach the Remixer Fragment to a FAB + # 0.6.6 - Fix Proguarding issue with bad instructions for onboarding. diff --git a/README.md b/README.md index 6df0559..60beda6 100644 --- a/README.md +++ b/README.md @@ -1,49 +1,40 @@ -![Remixer](https://cdn.rawgit.com/material-foundation/material-remixer/master/docs/assets/lockup_remixer_icon_horizontal_dark_small.svg) +# ![Remixer](docs/small_logo.png) Remixer Android + [![TravisCI Build Status](https://travis-ci.org/material-foundation/material-remixer-android.svg?branch=develop)](https://travis-ci.org/material-foundation/material-remixer-android) [![CircleCI Build Status](https://circleci.com/gh/material-foundation/material-remixer-android.svg?style=svg)](https://circleci.com/gh/material-foundation/material-remixer-android) [![codecov](https://codecov.io/gh/material-foundation/material-remixer-android/branch/develop/graph/badge.svg)](https://codecov.io/gh/material-foundation/material-remixer-android) -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. +Remixer is a framework to iterate quickly on UI changes by allowing you to adjust UI variables without needing to rebuild (or even restart) your app. You can adjust Numbers, Colors, Booleans, and Strings. To see it in action check out the [example app](https://github.com/material-foundation/material-remixer-android/tree/develop/remixer_example). -This SDK for Android is currently in development. +If you are interested in using Remixer in another platform, you may want to check out the [iOS](https://github.com/material-foundation/material-remixer-ios) and [Javascript](https://github.com/material-foundation/material-remixer-js) repos. With any of the three platforms you can use the [Remote Controller](https://github.com/material-foundation/material-remixer-remote-web). -**New to Remixer?** Visit our [main repo](https://github.com/material-foundation/material-remixer) to get a full description of what it is and how it works. +## Using Remixer in your app -- - - +The following docs explain how to get Remixer up and running in your app, and details on what Variable types are currently supported. -1. [Getting started](GETTING_STARTED.md) -2. [Configure the UI](CONFIGURE_UI.md) -3. [Project structure](PROJECT_STRUCTURE.md) -4. [Supported Data Types](SUPPORTED_DATA_TYPES.md) -5. [Extending Remixer](EXTENDING_REMIXER.md) (TODO) -6. API Reference (_notice this includes internal APIs_): - - [Current Version 0.6.6](https://jitpack.io/com/github/material-foundation/material-remixer-android/remixer/0.6.6/javadoc/index.html) - - [Develop Snapshot](https://jitpack.io/com/github/material-foundation/material-remixer-android/remixer/develop-SNAPSHOT/javadoc/index.html) +- [Using Remixer](docs/USING_REMIXER.md) +- [Configure the UI](docs/CONFIGURE_UI.md) +- [Supported Data Types](docs/SUPPORTED_DATA_TYPES.md) +- (Optionally) [Configure the Firebase Remote Controller](docs/CONFIGURE_FIREBASE.md) -- - - +## Contributing to Remixer -## State of development +We're excited you want to contribute to the project! Please read these docs so we can get your contributions submitted quickly. -Visit our [State of Development](https://github.com/material-foundation/material-remixer/wiki/State-of-Development) wiki for the current roadmap and status of development for each platform. +- [Contribution policy and guidelines](docs/CONTRIBUTING.md) +- [Project structure](docs/PROJECT_STRUCTURE.md) +- [Extending Remixer](docs/EXTENDING_REMIXER.md) -## Repositories +## API Reference -The main Remixer GitHub repo for documentation, project tracking, and general information: -- [Remixer docs](https://github.com/material-foundation/material-remixer) +_Notice this includes internal APIs_: -Platform specific libraries and tools can be found in the following GitHub repos: - -- [iOS](https://github.com/material-foundation/material-remixer-ios) - Remixer for iOS. -- [Web](https://github.com/material-foundation/material-remixer-web) - Remixer for Web. -- [Web Remote](https://github.com/material-foundation/material-remixer-remote-web) - Remixer web remote controller for all platforms. +- [Current Version 1.0](https://jitpack.io/com/github/material-foundation/material-remixer-android/remixer/1.0/javadoc/index.html) +- [Develop Snapshot](https://jitpack.io/com/github/material-foundation/material-remixer-android/remixer/develop-SNAPSHOT/javadoc/index.html) ## Is material-foundation affiliated with Google? Yes, the [material-foundation](https://github.com/material-foundation) organization is one of Google's new homes for tools and frameworks related to our [Material Design](https://material.io) system. Please check out our blog post [Design is Never Done](https://design.google.com/articles/design-is-never-done/) for more information regarding Material Design and how Remixer integrates with the system. -## Contributing - -We gladly welcome contributions! If you have found a bug, have questions, or wish to contribute, please follow our [Contributing Guidelines](CONTRIBUTING.md) and read the [High-level Project Structure](PROJECT_STRUCTURE.md). - ## License © Google, 2016. Licensed under an [Apache-2](https://github.com/material-foundation/material-remixer-android/blob/develop/LICENSE) license. diff --git a/build.gradle b/build.gradle index 4224ee7..1e7014e 100644 --- a/build.gradle +++ b/build.gradle @@ -79,7 +79,7 @@ ext { // Force release proguard when running on a Continuous Integration environment (like TravisCI). forceReleaseProguard = System.getenv("CI").equals("true"); // Sdk and tools - minSdkVersion = 15 + minSdkVersion = 16 targetSdkVersion = 25 compileSdkVersion = 25 buildToolsVersion = '25.0.0' diff --git a/docs/CONFIGURE_FIREBASE.md b/docs/CONFIGURE_FIREBASE.md new file mode 100644 index 0000000..20b23a6 --- /dev/null +++ b/docs/CONFIGURE_FIREBASE.md @@ -0,0 +1,50 @@ +# Configuring the Firebase Remote Controller + +There are three steps to being able to use the Firebase Remote Controller with Remixer for Android: + +1. Install the Firebase Remote Controller on a Firebase Instance. +2. Get your Firebase credentials +3. Set up Remixer synchronization to use the Firebase Remote. + +## Step 1: Install Remote Controller on Firebase + +This is out of the scope of this document, as it is properly documented [in the remote's repo](https://www.github.com/material-foundation/material-remixer-remote-web). + +## Step 2: Get your Firebase credentials + +- Go to your [Firebase console](https://console.firebase.google.com) and click on the Firebase App where you have uploaded the Remixer Remote Controller. +- Click _Add another app_ and follow the instructions (you can reuse an already registered app if that is appropriate). +- At the end you'll download a `google-services.json` file. Put that next to your application module's `build.gradle` + +More detail can be found in [the Firebase documentation](https://firebase.google.com/docs/android/setup#manually_add_firebase). + +## Step 3: Set up Remixer synchronization + +Remixer relies on implementations of `SynchronizationMechanism` to store and sync values. This is set on your Application class's `onCreate()` method. + +In order to use the Remote you only need to use the correct SynchronizationMechanism, `FirebaseRemoteControllerSyncer`, and optionally force it to start sharing variable status immediately + +```java +import android.app.Application; +import com.google.android.libraries.remixer.Remixer; +import com.google.android.libraries.remixer.storage.FirebaseRemoteControllerSyncer; +import com.google.android.libraries.remixer.ui.RemixerInitialization; + +class MyApplication extends Application { + @Override + public void onCreate() { + super.onCreate(); + RemixerInitialization.initRemixer(this); + FirebaseRemoteControllerSyncer syncer = new FirebaseRemoteControllerSyncer(this); + Remixer.getInstance().setSynchronizationMechanism(syncer); + // Optionally you can start sharing your variables to the Remote automatically. + syncer.startSharing(); + } +} +``` + +Since all the Variable Adjustment UI is completely available in the Firebase Remote Controller, if you start sharing in the Application class you may not want/need to use the `RemixerFragment` at all. In that case you can use `FirebaseRemoteControllerSyncer#getShareLinkIntent()` or `FirebaseRemoteControllerSyncer#getRemoteUrl()` to direct users to the remote on your own terms. + +Otherwise, the `RemixerFragment` will automatically show options to share variables with the remote controller and share the link, see below: + +![Sharing UI](sharing_ui.png) diff --git a/CONFIGURE_UI.md b/docs/CONFIGURE_UI.md similarity index 81% rename from CONFIGURE_UI.md rename to docs/CONFIGURE_UI.md index 540d4ab..54eba04 100644 --- a/CONFIGURE_UI.md +++ b/docs/CONFIGURE_UI.md @@ -1,5 +1,3 @@ -![Remixer](https://cdn.rawgit.com/material-foundation/material-remixer/master/docs/assets/lockup_remixer_icon_horizontal_dark_small.svg) - # Display the Remixer Fragment You can configure the `RemixerFragment` in the `Activity`'s `onCreate(Bundle)` method, after the call to `RemixerBinder.bind(this)`. You have 3 (not mutually-exclusive) options. You can see examples of how to do it below. @@ -22,6 +20,22 @@ protected void onCreate(Bundle savedInstanceState) { } ``` +## Attach the Remixer Fragment to a FAB +You need to call `RemixerFragment#attachToFab(FragmentActivity, FloatingActionButton)` + +Your `Activity.onCreate` may look like this: + +```java +@Override +protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + //... + remixerFab = (FloatingActionButton) findViewById(R.id.fab); + RemixerBinder.bind(this); + RemixerFragment.newInstance().attachToFab(this, remixerFab); +} +``` + ## Attach the Remixer Fragment to a multi-touch gesture You need to call `RemixerFragment#attachToGesture(FragmentActivity, Direction, int)` @@ -34,7 +48,7 @@ protected void onCreate(Bundle savedInstanceState) { //... RemixerBinder.bind(this); RemixerFragment.newInstance().attachToGesture( - this, + this, Direction.UP, 3 /* numberOfFingers */); } @@ -75,11 +89,13 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... remixerButton = (Button) findViewById(R.id.button); + remixerFab = (FloatingActionButton) findViewById(R.id.fab); RemixerBinder.bind(this); remixerFragment = RemixerFragment.newInstance(); remixerFragment.attachToGesture(this, Direction.UP, 3); remixerFragment.attachToButton(this, remixerButton); + remixerFragment.attachToFab(this, remixerFab); } @Override diff --git a/CONTRIBUTING.md b/docs/CONTRIBUTING.md similarity index 94% rename from CONTRIBUTING.md rename to docs/CONTRIBUTING.md index 9c5abf7..efbc801 100644 --- a/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -1,5 +1,9 @@ +# Contributing + Want to contribute? Great! First, read this page (including the small print at the end). +You will also be interested in the general [Project structure](PROJECT_STRUCTURE.md) and [How-to extend Remixer](EXTENDING_REMIXER.md) + ## Pull requests Pull requests can be hard to review if they try to tackle too many things diff --git a/EXTENDING_REMIXER.md b/docs/EXTENDING_REMIXER.md similarity index 100% rename from EXTENDING_REMIXER.md rename to docs/EXTENDING_REMIXER.md diff --git a/PROJECT_STRUCTURE.md b/docs/PROJECT_STRUCTURE.md similarity index 98% rename from PROJECT_STRUCTURE.md rename to docs/PROJECT_STRUCTURE.md index e292d48..4f0d8d1 100644 --- a/PROJECT_STRUCTURE.md +++ b/docs/PROJECT_STRUCTURE.md @@ -1,5 +1,3 @@ -![Remixer](https://cdn.rawgit.com/material-foundation/material-remixer/master/docs/assets/lockup_remixer_icon_horizontal_dark_small.svg) - # Project structure Remixer is built as a gradle project with several submodules. If you are interested in contributing you should know the roles of each submodule to be able to put things in the right place. diff --git a/SUPPORTED_DATA_TYPES.md b/docs/SUPPORTED_DATA_TYPES.md similarity index 60% rename from SUPPORTED_DATA_TYPES.md rename to docs/SUPPORTED_DATA_TYPES.md index 83e3ff7..a7312c8 100644 --- a/SUPPORTED_DATA_TYPES.md +++ b/docs/SUPPORTED_DATA_TYPES.md @@ -1,3 +1,17 @@ + +Table of Contents +================= +* [API Flavors](#api-flavors) +* [Constraints](#constraints) + * [Unconstrained variables](#unconstrained-variables) + * [Item-list variables](#item-list-variables) + * [Range variables](#range-variables) +* [Data Types](#data-types) + * [Boolean](#boolean) + * [Color](#color) + * [Number](#number) + * [String](#string) + # Variables in Remixer Variables are the cornerstone of Remixer, a change on a variable's _value_ (by the Remixer UI, remote controller or any other means) triggers the _callback_ (your code). Variables have a _data type_ and (optionally) a _constraint_ (which on Android are represented by subclasses of `com.google.android.libraries.remixer`). @@ -8,13 +22,13 @@ Remixer guarantees that your callbacks are always called on the Main UI Thread f ## API Flavors -First of all you need to know that there are two ways to use variables, either directly through a explicit API in the form of Builders (all in package `com.google.android.libraries.remixer`) or through a convenient set of annotations found in `com.google.android.libraries.remixer.annotations`. +First of all you need to know that there are two ways to use variables, either directly through an explicit API in the form of Builders (all in package `com.google.android.libraries.remixer`) or through a convenient set of annotations found in `com.google.android.libraries.remixer.annotations`. **It is recommended you consistently use annotations unless you are extending Remixer**. In the explicit API you need to implement the `com.google.android.libraries.remixer.Callback` interface to implement your callback and specify the DataType in the builder calls. In the annotation-based API you need to apply the annotation to a public method with one argument of the correct type and at the end of the activity's `onCreate` method you call `RemixerBinder.bind(this)`. -There are a few very simple examples here of how to use both in the following sections, but you should look at the [example](https://github.com/material-foundation/material-remixer-android/blob/develop/remixer_example/src/main/java/com/google/android/apps/remixer/MainActivity.java) [activities](https://github.com/material-foundation/material-remixer-android/blob/develop/remixer_example/src/main/java/com/google/android/apps/remixer/BoxActivity.java) and documentation for [the explicit API](https://github.com/material-foundation/material-remixer-android/tree/develop/remixer_core/src/main/java/com/google/android/libraries/remixer) and [these annotations](https://github.com/material-foundation/material-remixer-android/tree/develop/remixer_core/src/main/java/com/google/android/libraries/remixer/annotation) for more information. +There are a few very simple examples here of how to use both in the following sections, but you should look at the [example activities](https://github.com/material-foundation/material-remixer-android/blob/develop/remixer_example/src/main/java/com/google/android/apps/remixer/TransactionListActivity.java) and documentation for [the explicit API](https://github.com/material-foundation/material-remixer-android/tree/develop/remixer_core/src/main/java/com/google/android/libraries/remixer) and [these annotations](https://github.com/material-foundation/material-remixer-android/tree/develop/remixer_core/src/main/java/com/google/android/libraries/remixer/annotation) for more information. ## Constraints @@ -26,18 +40,22 @@ This is the base variable, it takes any possible value for the data type. #### 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 assumes `key` -- `context` an activity where the variable is defined. Used to avoid memory leaks. -- `initialValue` the initial value. -- `callback` is the method to call once the variable value changes. -- `layoutId` a layoutId to display this, must implement RemixerWidget. It can remain unset and it will use a sensible default in each **supported** case. +| Name | Description | +| ---- | ----------- | +| `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 assumes `key` | +| `context` | An activity where the variable is defined. Used to avoid memory leaks. | +| `initialValue` | The initial value. | +| `callback` | The method to call once the variable value changes. | +| `layoutId` | A layoutId to display this, must implement RemixerWidget. It can remain unset and it will use a sensible default in each **supported** case. | #### Builder classes -- `com.google.android.libraries.remixer.BaseVariableBuilder` can be used theoretically with any type. -- `com.google.android.libraries.remixer.BooleanVariableBuilder` convenience Variable builder that assumes false to be the initial value if unset. -- `com.google.android.libraries.remixer.StringVariableBuilder` convenience Variable builder that assumes the empty string to be the initial value if unset. +| Class | Description | +| ----- | ----------- | +| `com.google.android.libraries.remixer.BaseVariableBuilder` | Can be used theoretically with any type. | +| `com.google.android.libraries.remixer.BooleanVariableBuilder` | Convenience Variable builder that assumes false to be the initial value if unset. | +| `com.google.android.libraries.remixer.StringVariableBuilder` | Convenience Variable builder that assumes the empty string to be the initial value if unset. | #### Annotations @@ -54,11 +72,15 @@ These variables will throw an exception if the value is set to anything that isn This variable constraint has all of the properties of unconstrained variables in addition to: -- `limitedToValues` the list of values this variable is limited to take. +| Name | Description | +| ---- | ----------- | +| `limitedToValues` | The list of values this variable is limited to take. | #### Builder classes -- `com.google.android.libraries.remixer.ItemListVariable.Builder` assumes the first value in the `limitedToValues` list to be the `initialValue` if it is unset. +| Class | Description | +| ----- | ----------- | +| `com.google.android.libraries.remixer.ItemListVariable.Builder` | Assumes the first value in the `limitedToValues` list to be the `initialValue` if it is unset. | #### Annotations @@ -76,13 +98,17 @@ These variables are designed to work with Numbers only, and will throw an except This variable constraint has all of the properties of unconstrained variables in addition to: -- `minValue` the minimum value -- `maxValue` the maximum value -- `increment` the increment between two steps of the range, 1 by default. +| Name | Description | +| ---- | ----------- | +| `minValue` | The minimum value | +| `maxValue` | The maximum value | +| `increment` | The increment between two steps of the range, 1 by default. | #### Builder classes -- `com.google.android.libraries.remixer.RangeVariable.Builder` +| Class | Description | +| ----- | ----------- | +| `com.google.android.libraries.remixer.RangeVariable.Builder` | No Description | #### Annotations @@ -98,10 +124,12 @@ Furthermore, in order to display a Variable, there must be an appropriate widget The boolean data type is pretty self explanatory. Because the boolean data type has only two possible values, `true` and `false`, no constraints are supported. -- Runtime type: `java.lang.Boolean` -- Serializable type: `java.lang.Boolean` -- Converter: `com.google.android.libraries.remixer.serialization.converters.BooleanValueConverter` -- Supported constraints: Unconstrained variables (via `com.google.android.libraries.remixer.ui.widget.BooleanVariableWidget`) +| Name | Value | +| ---- | ----- | +| Runtime type | `java.lang.Boolean` | +| Serializable type | `java.lang.Boolean` | +| Converter | `com.google.android.libraries.remixer.serialization.converters.BooleanValueConverter` | +| Supported constraints | Unconstrained variables (via `com.google.android.libraries.remixer.ui.widget.BooleanVariableWidget`) | #### Explicit API Boolean Variable @@ -131,12 +159,12 @@ public void setUseNewDialog(Boolean useNewDialog) { ### Color The Color data type lets you manipulate colors in the UI. -- Runtime type: `java.lang.Integer` It uses integer as its runtime type as that is the android-native way to represent colors. -- Serializable type: `com.google.android.libraries.remixer.serialization.SerializedColor` it uses an intermediate type to serialize to be cross-platform friendly. -- Converter: `com.google.android.libraries.remixer.serialization.converters.ColorValueConverter` -- Supported constraints: Item List Variables (via `com.google.android.libraries.remixer.ui.widget.ColorListVariableWidget`) - - Theoretically we could support unconstrained variables, but we haven't built a good color picker. You're welcome to [contribute one](CONTRIBUTING.md). - +| Name | Value | +| ---- | ----- | +| Runtime type | `java.lang.Integer` It uses integer as its runtime type as that is the android-native way to represent colors. | +| Serializable type | `com.google.android.libraries.remixer.serialization.SerializedColor` it uses an intermediate type to serialize to be cross-platform friendly. | +| Converter | `com.google.android.libraries.remixer.serialization.converters.ColorValueConverter` | +| Supported constraint | Item List Variables (via `com.google.android.libraries.remixer.ui.widget.ColorListVariableWidget`)

Theoretically we could support unconstrained variables, but we haven't built a good color picker. You're welcome to [contribute one](CONTRIBUTING.md).| #### Explicit API Color List Variable @@ -169,13 +197,15 @@ public void setTitleColor(Integer color) { Remixer only supports `Float` numbers. These should work for most cases anyway. -- Runtime type: `java.lang.Float` -- Serializable type: `java.lang.Float` -- Converter: `com.google.android.libraries.remixer.serialization.converters.NumberValueConverter` -- Supported constraints: - - Item List Variables (via `com.google.android.libraries.remixer.ui.widget.ItemListVariableWidget`) - - Range Variables (via `com.google.android.libraries.remixer.ui.widget.SeekBarRangeVariableWidget`) - - Theoretically we could support Unconstrained Variables if we write a **usable** control that handles non-number values correctly. You're welcome to [contribute an implementation](CONTRIBUTING.md). +| Name | Value | +| ---- | ----- | +| Runtime type | `java.lang.Float` | +| Serializable type | `java.lang.Float` | +| Converter | `com.google.android.libraries.remixer.serialization.converters.NumberValueConverter` | +| Supported constraint | Item List Variables (via `com.google.android.libraries.remixer.ui.widget.ItemListVariableWidget`) | +| Supported constraint | Range Variables (via `com.google.android.libraries.remixer.ui.widget.SeekBarRangeVariableWidget`) | + +Theoretically we could support Unconstrained Variables if we write a **usable** control that handles non-number values correctly. You're welcome to [contribute an implementation](CONTRIBUTING.md). | #### Explicit API Number List Variable @@ -235,12 +265,13 @@ public void setFontSize(Integer fontSize) { The Color data type lets you manipulate colors in the UI. -- Runtime type: `java.lang.String` -- Serializable type: `java.lang.String` -- Converter: `com.google.android.libraries.remixer.serialization.converters.StringValueConverter` -- Supported constraints: - - Item List Variables (via `com.google.android.libraries.remixer.ui.widget.ItemListVariableWidget`) - - Unconstrained Variables (via `com.google.android.libraries.remixer.ui.widget.StringVariableWidget`) +| Name | Value | +| ---- | ----- | +| Runtime type | `java.lang.String` | +| Serializable type | `java.lang.String` | +| Converter | `com.google.android.libraries.remixer.serialization.converters.StringValueConverter` | +| Supported constraints | Item List Variables (via `com.google.android.libraries.remixer.ui.widget.ItemListVariableWidget`) | +| Supported constraints | Unconstrained Variables (via `com.google.android.libraries.remixer.ui.widget.StringVariableWidget`) | #### Explicit API String List Variable diff --git a/GETTING_STARTED.md b/docs/USING_REMIXER.md similarity index 66% rename from GETTING_STARTED.md rename to docs/USING_REMIXER.md index 20049d5..9271b8f 100644 --- a/GETTING_STARTED.md +++ b/docs/USING_REMIXER.md @@ -1,12 +1,10 @@ -![Remixer](https://cdn.rawgit.com/material-foundation/material-remixer/master/docs/assets/lockup_remixer_icon_horizontal_dark_small.svg) +# Using Remixer -# Getting started - -__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 being 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. +This page explains what you need to do to get Remixer running on your app. However, if you're the kind of person who learns by example, you may want to look at our [example app](https://github.com/material-foundation/material-remixer-android/tree/develop/remixer_example). You can read our [javadoc for the current release (0.6.6)](https://jitpack.io/com/github/material-foundation/material-remixer-android/remixer/0.6.6/javadoc/index.html) and the [javadoc for HEAD](https://jitpack.io/com/github/material-foundation/material-remixer-android/remixer/develop-SNAPSHOT/javadoc/index.html) generated by jitpack. -## Set up dependencies +## Dependencies and other requirements Using gradle it's super easy to start using Remixer following these instructions. @@ -39,7 +37,7 @@ dependencies { 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. -Once you start depending on Remixer, your build will fail if no `google-services.json` exists on your app module. This is because Remixer has the option of using firebase to store and sync values, and whether you use it or not the build system looks for that file. It can be an empty file or the one we provide in `remixer_example/src/main/google-services.json`. +**Important:** Once you start depending on Remixer, your build will fail if no `google-services.json` exists on your app module. This is because Remixer has the option of using firebase to store and sync values, and whether you use it or not the build system looks for that file. It can be an empty file or the one we provide in `remixer_example/src/main/google-services.json`. ## Initialize remixer @@ -48,8 +46,8 @@ Once you start depending on Remixer, your build will fail if no `google-services 3. Call the `RemixerInitialization#initRemixer(Application)` method. 4. Set a synchronization mechanism for Remixer (you have a few options): - `com.google.android.libraries.remixer.sync.LocalValueSyncing`, this is the default (you don't need to set it if this is what you want), it doesn't persist any values but makes sure values sync across different contexts (Activities). - - `com.google.android.libraries.remixer.storage.LocalStorage`, this stores values locally in a SharedPreferences file. - - `com.google.android.libraries.remixer.storage.FirebaseRemoteControllerSyncer`, this syncs values to and from a firebase instance to use it as a remote controller. **This functionality is not complete yet** + - Recommended: `com.google.android.libraries.remixer.storage.LocalStorage`, this stores values locally in a SharedPreferences file. + - `com.google.android.libraries.remixer.storage.FirebaseRemoteControllerSyncer`, this syncs values to and from a firebase instance to use it as a remote controller. Take a look at the [Firebase Remote Controller Set-up](CONFIGURE_FIREBASE.md) document for more information. For example: @@ -71,11 +69,11 @@ class MyApplication extends Application { ## Define Variables -You can define variables in an activty by writing 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 define variables in an activity by writing 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](https://github.com/material-foundation/material-remixer-android/blob/develop/remixer_example/src/main/java/com/google/android/apps/remixer/MainActivity.java) [activities](https://github.com/material-foundation/material-remixer-android/blob/develop/remixer_example/src/main/java/com/google/android/apps/remixer/BoxActivity.java) and [documentation for these annotations](https://github.com/material-foundation/material-remixer-android/tree/develop/remixer_core/src/main/java/com/google/android/libraries/remixer/annotation) for more information. +There are a few very simple examples here, but you should look at the [example activity](https://github.com/material-foundation/material-remixer-android/blob/develop/remixer_example/src/main/java/com/google/android/apps/remixer/TransactionListActivity.java) and [documentation for these annotations](https://github.com/material-foundation/material-remixer-android/tree/develop/remixer_core/src/main/java/com/google/android/libraries/remixer/annotation) for more information. For example: @@ -102,10 +100,11 @@ protected void onCreate(Bundle savedInstanceState) { You can configure the `RemixerFragment` in the `Activity`'s `onCreate(Bundle)` method, after the call to `RemixerBinder.bind(this)`. You have 3 (not mutually-exclusive) options: 1. [Attach the RemixerFragment to a button click](CONFIGURE_UI.md#attach-the-remixer-fragment-to-a-button), `RemixerFragment#attachToButton(FragmentActivity, Button)` -2. [Attach the RemixerFragment to a multi-touch gesture](CONFIGURE_UI.md#attach-the-remixer-fragment-to-a-multi-touch-gesture), `RemixerFragment#attachToButton(FragmentActivity, Button)` -3. [Attach the RemixerFragment to a ShakeListener](CONFIGURE_UI.md#attach-the-remixer-fragment-to-a-shake), `RemixerFragment#attachToShake(FragmentActivity, double)`. *In order to conserve battery, you must call `attachToShake` from `onResume` and call `detachFromShake` from `onPause`* +2. [Attach the RemixerFragment to a FAB](CONFIGURE_UI.md#attach-the-remixer-fragment-to-a-fab), `RemixerFragment#attachToFab(FragmentActivity, FloatingActionButton)` +3. [Attach the RemixerFragment to a multi-touch gesture](CONFIGURE_UI.md#attach-the-remixer-fragment-to-a-multi-touch-gesture), `RemixerFragment#attachToButton(FragmentActivity, Button)` +4. [Attach the RemixerFragment to a ShakeListener](CONFIGURE_UI.md#attach-the-remixer-fragment-to-a-shake), `RemixerFragment#attachToShake(FragmentActivity, double)`. *In order to conserve battery, you must call `attachToShake` from `onResume` and call `detachFromShake` from `onPause`* Detailed examples can be found on the [Configure the UI](CONFIGURE_UI.md) page. -_You may not want to use the `RemixerFragment` in case you only want to use a FirebaseRemoteController. Adding a RemixerFragment does affect the UI you may be playing with, so it may be desirable not to use it and tweak remotely instead._ +_You may not want to use the `RemixerFragment` in case you only want to use a FirebaseRemoteController. Adding a RemixerFragment does affect the UI you may be playing with, so it may be desirable not to use it and adjust values remotely instead._ diff --git a/docs/remixer_screenshot.png b/docs/remixer_screenshot.png new file mode 100644 index 0000000..1e3727f Binary files /dev/null and b/docs/remixer_screenshot.png differ diff --git a/docs/sharing_ui.png b/docs/sharing_ui.png new file mode 100644 index 0000000..71a1916 Binary files /dev/null and b/docs/sharing_ui.png differ diff --git a/docs/small_logo.png b/docs/small_logo.png new file mode 100755 index 0000000..077cf04 Binary files /dev/null and b/docs/small_logo.png differ diff --git a/remixer_annotation/src/main/java/com/google/android/libraries/remixer/annotation/processor/ItemListVariableMethodAnnotation.java b/remixer_annotation/src/main/java/com/google/android/libraries/remixer/annotation/processor/ItemListVariableMethodAnnotation.java index 5624f04..628a07a 100644 --- a/remixer_annotation/src/main/java/com/google/android/libraries/remixer/annotation/processor/ItemListVariableMethodAnnotation.java +++ b/remixer_annotation/src/main/java/com/google/android/libraries/remixer/annotation/processor/ItemListVariableMethodAnnotation.java @@ -50,15 +50,15 @@ class ItemListVariableMethodAnnotation extends MethodAnnotation { */ private static final String SET_INITIAL_VALUE_FORMAT = "$L.setInitialValue(%s)"; /** - * Javapoet format escaping for float values + * Javapoet format escaping for float values. */ private static final String FLOAT_JAVAPOET_ESCAPING = "$Lf"; /** - * Javapoet format escaping for integer values + * Javapoet format escaping for integer values. */ private static final String INTEGER_JAVAPOET_ESCAPING = "$L"; /** - * Javapoet format escaping for string values + * Javapoet format escaping for string values. */ private static final String STRING_JAVAPOET_ESCAPING = "$S"; /** @@ -209,10 +209,11 @@ public void addSpecificSetupStatements(MethodSpec.Builder methodBuilder) { } private String getJavaPoetEscaping() { - if (dataType.getName().equals(DataType.STRING.getName())) + if (dataType.getName().equals(DataType.STRING.getName())) { return STRING_JAVAPOET_ESCAPING; - if (dataType.getName().equals(DataType.COLOR.getName())) + } else if (dataType.getName().equals(DataType.COLOR.getName())) { return INTEGER_JAVAPOET_ESCAPING; + } // If it is an item list it can only be either String, Color or a number, since it's neither // color nor number at this point, just assume that it's a number so return // FLOAT_JAVAPOET_ESCAPING. diff --git a/remixer_core/src/main/java/com/google/android/libraries/remixer/DataType.java b/remixer_core/src/main/java/com/google/android/libraries/remixer/DataType.java index b97afe4..ff20cbb 100644 --- a/remixer_core/src/main/java/com/google/android/libraries/remixer/DataType.java +++ b/remixer_core/src/main/java/com/google/android/libraries/remixer/DataType.java @@ -1,3 +1,19 @@ +/* + * Copyright 2017 Google Inc. + * + * 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. + */ + package com.google.android.libraries.remixer; import com.google.android.libraries.remixer.serialization.SerializedColor; @@ -14,10 +30,10 @@ * The data type for each RemixerItem. The data type is used to determine default layoutIDs and to * help serialization. * - * @param The type to use during runtime to represent variables of this DataType - * @param The type to use to serialize variables of this type. + * @param The type to use during runtime to represent variables of this DataType + * @param The type to use to serialize variables of this type. */ -public class DataType { +public class DataType { /** * The serializable, unique name for this data type. @@ -27,17 +43,17 @@ public class DataType { /** * The runtime class of the values contained by this variable. */ - private final Class runtimeType; + private final Class runtimeType; /** * The serializable class of the values contained by this variable. */ - private final Class serializableType; + private final Class serializableType; /** * The value converter that aids in the serialization process. */ - private final ValueConverter converter; + private final ValueConverter converter; /** * Map of default layout ids for this datatype when used with a specific RemixerItem class. @@ -49,17 +65,17 @@ public class DataType { new HashMap<>(); /** - * Constructs a datatype with the given {@code name}, that takes values of type {@code runtimeType} - * and uses {@code converter} to serialize. + * Constructs a datatype with the given {@code name}, that takes values of type + * {@code runtimeType} and uses {@code converter} to serialize. * *

Note {@code converter} has a {@link ValueConverter#dataType} field that must be initialized * to the same as {@code name}. */ public DataType( String name, - Class runtimeType, - Class serializableType, - ValueConverter converter) { + Class runtimeType, + Class serializableType, + ValueConverter converter) { this.name = name; this.runtimeType = runtimeType; this.serializableType = serializableType; @@ -107,15 +123,15 @@ public String getName() { return name; } - public Class getRuntimeType() { + public Class getRuntimeType() { return runtimeType; } - public Class getSerializableType() { + public Class getSerializableType() { return serializableType; } - public ValueConverter getConverter() { + public ValueConverter getConverter() { return converter; } diff --git a/remixer_core/src/main/java/com/google/android/libraries/remixer/ItemListVariable.java b/remixer_core/src/main/java/com/google/android/libraries/remixer/ItemListVariable.java index fbb97a8..a1ca61b 100644 --- a/remixer_core/src/main/java/com/google/android/libraries/remixer/ItemListVariable.java +++ b/remixer_core/src/main/java/com/google/android/libraries/remixer/ItemListVariable.java @@ -106,8 +106,8 @@ public Builder setLimitedToValues(T[] limitedToValues) { * Returns a new ItemListVariable created with the configuration stored in this builder * instance. * - * @throws IllegalArgumentException If key or limitedToValues are missing or if the configuration - * is invalid for ItemListVariable. + * @throws IllegalArgumentException If key or limitedToValues are missing or if the + * configuration is invalid for ItemListVariable. */ @Override public ItemListVariable build() { diff --git a/remixer_core/src/main/java/com/google/android/libraries/remixer/serialization/SerializedColor.java b/remixer_core/src/main/java/com/google/android/libraries/remixer/serialization/SerializedColor.java index 10bead6..e83c8c2 100644 --- a/remixer_core/src/main/java/com/google/android/libraries/remixer/serialization/SerializedColor.java +++ b/remixer_core/src/main/java/com/google/android/libraries/remixer/serialization/SerializedColor.java @@ -22,7 +22,7 @@ *

This is the agreed-upon representation of colors in Remixer. Sadly there is no uniform color * representation across platforms. */ - +@SuppressWarnings("checkstyle:membername") public class SerializedColor { /** @@ -66,6 +66,7 @@ public int getA() { return a; } + @SuppressWarnings("checkstyle:parametername") public void setA(int a) { this.a = a; } @@ -74,6 +75,7 @@ public int getR() { return r; } + @SuppressWarnings("checkstyle:parametername") public void setR(int r) { this.r = r; } @@ -82,6 +84,7 @@ public int getG() { return g; } + @SuppressWarnings("checkstyle:parametername") public void setG(int g) { this.g = g; } @@ -90,6 +93,7 @@ public int getB() { return b; } + @SuppressWarnings("checkstyle:parametername") public void setB(int b) { this.b = b; } diff --git a/remixer_core/src/main/java/com/google/android/libraries/remixer/serialization/converters/BooleanValueConverter.java b/remixer_core/src/main/java/com/google/android/libraries/remixer/serialization/converters/BooleanValueConverter.java index 9d0bff1..85fbbb0 100644 --- a/remixer_core/src/main/java/com/google/android/libraries/remixer/serialization/converters/BooleanValueConverter.java +++ b/remixer_core/src/main/java/com/google/android/libraries/remixer/serialization/converters/BooleanValueConverter.java @@ -1,3 +1,19 @@ +/* + * Copyright 2017 Google Inc. + * + * 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. + */ + package com.google.android.libraries.remixer.serialization.converters; import com.google.android.libraries.remixer.Variable; diff --git a/remixer_core/src/main/java/com/google/android/libraries/remixer/serialization/converters/ColorValueConverter.java b/remixer_core/src/main/java/com/google/android/libraries/remixer/serialization/converters/ColorValueConverter.java index 448dc57..1517cfa 100644 --- a/remixer_core/src/main/java/com/google/android/libraries/remixer/serialization/converters/ColorValueConverter.java +++ b/remixer_core/src/main/java/com/google/android/libraries/remixer/serialization/converters/ColorValueConverter.java @@ -1,3 +1,19 @@ +/* + * Copyright 2017 Google Inc. + * + * 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. + */ + package com.google.android.libraries.remixer.serialization.converters; import com.google.android.libraries.remixer.serialization.GsonProvider; diff --git a/remixer_core/src/main/java/com/google/android/libraries/remixer/serialization/converters/FloatValueConverter.java b/remixer_core/src/main/java/com/google/android/libraries/remixer/serialization/converters/FloatValueConverter.java index ed62018..b3b2cfb 100644 --- a/remixer_core/src/main/java/com/google/android/libraries/remixer/serialization/converters/FloatValueConverter.java +++ b/remixer_core/src/main/java/com/google/android/libraries/remixer/serialization/converters/FloatValueConverter.java @@ -1,3 +1,19 @@ +/* + * Copyright 2017 Google Inc. + * + * 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. + */ + package com.google.android.libraries.remixer.serialization.converters; import com.google.android.libraries.remixer.ItemListVariable; diff --git a/remixer_core/src/main/java/com/google/android/libraries/remixer/serialization/converters/StringValueConverter.java b/remixer_core/src/main/java/com/google/android/libraries/remixer/serialization/converters/StringValueConverter.java index 30d56d6..84cca66 100644 --- a/remixer_core/src/main/java/com/google/android/libraries/remixer/serialization/converters/StringValueConverter.java +++ b/remixer_core/src/main/java/com/google/android/libraries/remixer/serialization/converters/StringValueConverter.java @@ -1,3 +1,19 @@ +/* + * Copyright 2017 Google Inc. + * + * 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. + */ + package com.google.android.libraries.remixer.serialization.converters; import com.google.android.libraries.remixer.ItemListVariable; diff --git a/remixer_example/src/main/AndroidManifest.xml b/remixer_example/src/main/AndroidManifest.xml index 554efa1..362d75f 100644 --- a/remixer_example/src/main/AndroidManifest.xml +++ b/remixer_example/src/main/AndroidManifest.xml @@ -19,13 +19,12 @@ xmlns:tools="http://schemas.android.com/tools" package="com.google.android.apps.remixer" tools:ignore="GoogleAppIndexingWarning"> - @@ -37,31 +36,16 @@ android:supportsRtl="true" android:theme="@style/AppTheme" tools:replace="android:theme"> + + android:name=".TransactionListActivity" + android:label="@string/title_activity_transaction_list"> - - - - - - diff --git a/remixer_example/src/main/java/com/google/android/apps/remixer/BoxActivity.java b/remixer_example/src/main/java/com/google/android/apps/remixer/BoxActivity.java deleted file mode 100644 index e1c01e7..0000000 --- a/remixer_example/src/main/java/com/google/android/apps/remixer/BoxActivity.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.google.android.apps.remixer; - -import android.graphics.Color; -import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; -import android.util.TypedValue; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; -import com.google.android.libraries.remixer.annotation.BooleanVariableMethod; -import com.google.android.libraries.remixer.annotation.ColorListVariableMethod; -import com.google.android.libraries.remixer.annotation.RangeVariableMethod; -import com.google.android.libraries.remixer.annotation.RemixerBinder; -import com.google.android.libraries.remixer.ui.gesture.Direction; -import com.google.android.libraries.remixer.ui.view.RemixerFragment; - -/** - * This activity reuses one of the values from variables in MainActivity. - */ -public class BoxActivity extends AppCompatActivity { - - // A title text whose text size is set by a variable. - private TextView titleText; - // An ImageView that does nothing but draw a box with its background color. - private ImageView box; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_box); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - // Find all UI widgets - titleText = (TextView) findViewById(R.id.titleText); - box = (ImageView) findViewById(R.id.box); - // Initialize the remixer instance - RemixerBinder.bind(this); - RemixerFragment remixerFragment = RemixerFragment.newInstance(); - remixerFragment.attachToGesture(this, Direction.UP, 3); - } - - @RangeVariableMethod( - key = "titleTextSize", title = "(Shared) title text size", - minValue = 16, maxValue = 72, increment = 4 - ) - public void setTitleTextSize(Float size) { - titleText.setTextSize(TypedValue.COMPLEX_UNIT_SP, size); - } - - @BooleanVariableMethod(key = "showBox", title = "Show box") - void showBox(Boolean show) { - box.setVisibility(show ? View.VISIBLE : View.GONE); - } - - @ColorListVariableMethod( - key = "boxColor", title = "Box color", - limitedToValues = {Color.DKGRAY, Color.LTGRAY, Color.MAGENTA, Color.CYAN}, - layoutId = R.layout.color_list_variable_widget - ) - void setBoxColor(Integer color) { - box.setBackgroundColor(color); - } -} - diff --git a/remixer_example/src/main/java/com/google/android/apps/remixer/MainActivity.java b/remixer_example/src/main/java/com/google/android/apps/remixer/MainActivity.java deleted file mode 100644 index 182c134..0000000 --- a/remixer_example/src/main/java/com/google/android/apps/remixer/MainActivity.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2016 Google Inc. - * - * 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. - */ -package com.google.android.apps.remixer; - -import android.hardware.SensorManager; -import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; -import android.util.TypedValue; -import android.widget.Button; -import android.widget.TextView; - -import com.google.android.libraries.remixer.annotation.RangeVariableMethod; -import com.google.android.libraries.remixer.annotation.RemixerBinder; -import com.google.android.libraries.remixer.annotation.StringListVariableMethod; -import com.google.android.libraries.remixer.annotation.StringVariableMethod; -import com.google.android.libraries.remixer.ui.gesture.Direction; -import com.google.android.libraries.remixer.ui.view.RemixerFragment; - -/** - * Example activity where remixer is used to control text size and text values. - */ -public class MainActivity extends AppCompatActivity { - - private TextView titleText; - private TextView freeformText; - private Button remixerButton; - private RemixerFragment remixerFragment; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - titleText = (TextView) findViewById(R.id.titleText); - freeformText = (TextView) findViewById(R.id.freeformText); - remixerButton = (Button) findViewById(R.id.button); - RemixerBinder.bind(this); - - remixerFragment = RemixerFragment.newInstance(); - remixerFragment.attachToGesture(this, Direction.UP, 3); - remixerFragment.attachToButton(this, remixerButton); - } - - @Override - protected void onResume() { - super.onResume(); - remixerFragment.attachToShake(this, 20.0); - } - - @Override - protected void onPause() { - super.onPause(); - remixerFragment.detachFromShake(); - } - - @RangeVariableMethod( - key = "titleTextSize", - minValue = 16, maxValue = 72, increment = 4, title = "(Shared) Title font size") - void setTitleTextSize(Float size) { - titleText.setTextSize(TypedValue.COMPLEX_UNIT_SP, size); - } - - @StringListVariableMethod( - title = "Title text", - limitedToValues = {"Hello World", "Alohomora", "Foo", "Bar", "May the force be with you"}) - void setTitleText(String text) { - titleText.setText(text); - } - - @StringVariableMethod(initialValue = "Change me!") - void setFreeformText(String text) { - freeformText.setText(text); - } -} diff --git a/remixer_example/src/main/java/com/google/android/apps/remixer/MenuActivity.java b/remixer_example/src/main/java/com/google/android/apps/remixer/MenuActivity.java deleted file mode 100644 index 6d6373b..0000000 --- a/remixer_example/src/main/java/com/google/android/apps/remixer/MenuActivity.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2016 Google Inc. - * - * 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. - */ - -package com.google.android.apps.remixer; - -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.StringRes; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.RecyclerView; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -public class MenuActivity extends AppCompatActivity { - - private RecyclerView list; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_menu); - list = (RecyclerView) findViewById(R.id.exampleList); - list.setAdapter(new RecyclerView.Adapter() { - @Override - public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - return new ViewHolder( - LayoutInflater.from(MenuActivity.this).inflate(R.layout.list_text, null)); - } - - @Override - public void onBindViewHolder(ViewHolder holder, int position) { - int textId = position == 0 ? R.string.mainDemoName : R.string.boxDemoName; - Class activityClass = position == 0 ? MainActivity.class : BoxActivity.class; - holder.setContent(textId, activityClass); - } - - @Override - public int getItemCount() { - return 2; - } - }); - } - - class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { - - Class activityClass; - - ViewHolder(View itemView) { - super(itemView); - itemView.setOnClickListener(this); - } - - void setContent(@StringRes int string, Class activityClass) { - ((TextView) itemView).setText(string); - this.activityClass = activityClass; - } - - @Override - public void onClick(View view) { - Intent intent = new Intent(); - intent.setClass(MenuActivity.this, activityClass); - startActivity(intent); - } - } -} diff --git a/remixer_example/src/main/java/com/google/android/apps/remixer/RemixerApplication.java b/remixer_example/src/main/java/com/google/android/apps/remixer/RemixerApplication.java index 252d9d7..cbb6f86 100644 --- a/remixer_example/src/main/java/com/google/android/apps/remixer/RemixerApplication.java +++ b/remixer_example/src/main/java/com/google/android/apps/remixer/RemixerApplication.java @@ -41,10 +41,8 @@ public void onCreate() { super.onCreate(); RemixerInitialization.initRemixer(this); if (USE_FIREBASE_REMOTE_CONTROLLER) { - FirebaseRemoteControllerSyncer syncer = - new FirebaseRemoteControllerSyncer(this); + FirebaseRemoteControllerSyncer syncer = new FirebaseRemoteControllerSyncer(this); Remixer.getInstance().setSynchronizationMechanism(syncer); - syncer.startSyncing(); } else { Remixer.getInstance().setSynchronizationMechanism(new LocalStorage(this)); } diff --git a/remixer_example/src/main/java/com/google/android/apps/remixer/TransactionAdapter.java b/remixer_example/src/main/java/com/google/android/apps/remixer/TransactionAdapter.java new file mode 100644 index 0000000..02dc54b --- /dev/null +++ b/remixer_example/src/main/java/com/google/android/apps/remixer/TransactionAdapter.java @@ -0,0 +1,92 @@ +/* + * Copyright 2017 Google Inc. + * + * 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.Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * + */ + +package com.google.android.apps.remixer; + +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.ViewGroup; +import java.util.Calendar; +import java.util.Date; + +public class TransactionAdapter extends RecyclerView.Adapter { + + private final TransactionItem[] items = TransactionItem.generateTransactions(30); + private boolean iconsVisible = true; + + @Override + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + TransactionItemView view = + (TransactionItemView) LayoutInflater.from(parent.getContext()) + .inflate(R.layout.transaction_item, parent, false); + return new ViewHolder(view); + } + + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + holder.setData(items[position]); + } + + @Override + public int getItemCount() { + return items.length; + } + + public void setIconsVisible(boolean iconsVisible) { + this.iconsVisible = iconsVisible; + } + class ViewHolder extends RecyclerView.ViewHolder { + + TransactionItemView itemView; + + public ViewHolder(TransactionItemView itemView) { + super(itemView); + this.itemView = itemView; + } + + void setData(TransactionItem item) { + itemView.setData(item, iconsVisible); + } + } + + public float getTotalSince(Date date) { + float total = 0; + for (TransactionItem transaction : items) { + if (transaction.getDate().after(date)) { + total += transaction.getAmount(); + } + } + return total; + } + + public float getThisMonthTotal() { + Calendar calendar = Calendar.getInstance(); + calendar.set(Calendar.DAY_OF_MONTH, 1); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); + return getTotalSince(calendar.getTime()); + } + + public float getLastMonthTotal() { + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.MONTH, -1); + return getTotalSince(calendar.getTime()); + } + +} diff --git a/remixer_example/src/main/java/com/google/android/apps/remixer/TransactionItem.java b/remixer_example/src/main/java/com/google/android/apps/remixer/TransactionItem.java new file mode 100644 index 0000000..0e63fb8 --- /dev/null +++ b/remixer_example/src/main/java/com/google/android/apps/remixer/TransactionItem.java @@ -0,0 +1,110 @@ +/* + * Copyright 2017 Google Inc. + * + * 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.Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * + */ + +package com.google.android.apps.remixer; + +import android.support.annotation.DrawableRes; +import java.util.Calendar; +import java.util.Date; +import java.util.Random; + + +public class TransactionItem { + + private final Business business; + private final Date date; + // I know floats are terrible for currency, but this is a simple demo app. + private final float amount; + + public TransactionItem(Business business, Date date, float amount) { + this.business = business; + this.date = date; + this.amount = amount; + } + + public enum Business { + BARCADE(R.drawable.ic_bar, "Barcade"), + BATHTUB_GIN(R.drawable.ic_bar, "Bathtub Gin"), + PDT(R.drawable.ic_bar, "Please don't tell"), + LYFT(R.drawable.ic_taxi, "Lyft"), + NYC_TAXI(R.drawable.ic_taxi, "NYC Taxi"), + APPLE_STORE(R.drawable.ic_shopping, "Apple Store"), + NINTENDO_STORE(R.drawable.ic_shopping, "Nintendo Store"), + AMAZON(R.drawable.ic_shopping, "Amazon"), + IN_N_OUT(R.drawable.ic_fastfood, "In-N-Out"), + FIVE_GUYS(R.drawable.ic_fastfood, "Five Guys"), + STUMPTOWN(R.drawable.ic_cafe, "Stumptown Coffee Roasters"), + BLUE_BOTTLE(R.drawable.ic_fastfood, "Blue Bottle Coffee"); + + @DrawableRes final int iconResource; + final String name; + + Business(@DrawableRes int iconResource, String name) { + this.iconResource = iconResource; + this.name = name; + } + } + + public String getBusinessName() { + return business.name; + } + + public Date getDate() { + return date; + } + + public float getAmount() { + return amount; + } + + @DrawableRes + public int getBusinessTypeIconResource(){ + return this.business.iconResource; + } + + // These members below aid in generating a random list of transactions. + + private static final Random RANDOM = new Random(); + private static final Business[] BUSINESSES = Business.values(); + + private static Business getRandomBusiness() { + return BUSINESSES[RANDOM.nextInt(BUSINESSES.length)]; + } + + private static float getRandomAmount() { + // Only return values up to 99.99f + return RANDOM.nextInt(9999) / 100f; + } + + private static Date getDateInLast3Days(Date today) { + int daysBefore = RANDOM.nextInt(4); + Calendar calendar = Calendar.getInstance(); + calendar.setTime(today); + calendar.add(Calendar.DATE, -daysBefore); + return calendar.getTime(); + } + + public static TransactionItem[] generateTransactions(int amount) { + Date today = new Date(); + TransactionItem[] transactions = new TransactionItem[amount]; + for (int i = 0; i < amount; i++) { + today = getDateInLast3Days(today); + transactions[i] = new TransactionItem(getRandomBusiness(), today, getRandomAmount()); + } + return transactions; + } +} diff --git a/remixer_example/src/main/java/com/google/android/apps/remixer/TransactionItemView.java b/remixer_example/src/main/java/com/google/android/apps/remixer/TransactionItemView.java new file mode 100644 index 0000000..4de8138 --- /dev/null +++ b/remixer_example/src/main/java/com/google/android/apps/remixer/TransactionItemView.java @@ -0,0 +1,66 @@ +/* + * Copyright 2017 Google Inc. + * + * 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.Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * + */ + +package com.google.android.apps.remixer; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; +import java.text.DateFormat; +import java.text.NumberFormat; + +public class TransactionItemView extends RelativeLayout { + + private TextView amount; + private ImageView businessTypeIcon; + private TextView businessName; + private TextView date; + + public TransactionItemView(Context context) { + super(context); + } + + public TransactionItemView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public TransactionItemView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + businessTypeIcon = (ImageView) findViewById(R.id.businessTypeIcon); + businessName = (TextView) findViewById(R.id.businessName); + date = (TextView) findViewById(R.id.date); + amount = (TextView) findViewById(R.id.amount); + } + + public void setData(TransactionItem data, boolean iconVisible) { + businessTypeIcon.setImageResource(data.getBusinessTypeIconResource()); + businessTypeIcon.setVisibility(iconVisible ? View.VISIBLE : View.GONE); + businessName.setText(data.getBusinessName()); + DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(getContext()); + date.setText(dateFormat.format(data.getDate())); + NumberFormat numberFormat = NumberFormat.getCurrencyInstance(); + amount.setText(numberFormat.format(data.getAmount())); + } +} diff --git a/remixer_example/src/main/java/com/google/android/apps/remixer/TransactionListActivity.java b/remixer_example/src/main/java/com/google/android/apps/remixer/TransactionListActivity.java new file mode 100644 index 0000000..d0bf32f --- /dev/null +++ b/remixer_example/src/main/java/com/google/android/apps/remixer/TransactionListActivity.java @@ -0,0 +1,112 @@ +/* + * Copyright 2017 Google Inc. + * + * 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.Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * + */ + +package com.google.android.apps.remixer; + +import android.os.Build; +import android.os.Bundle; +import android.support.design.widget.CollapsingToolbarLayout; +import android.support.design.widget.FloatingActionButton; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.Toolbar; +import android.util.TypedValue; +import android.widget.TextView; +import com.google.android.libraries.remixer.annotation.BooleanVariableMethod; +import com.google.android.libraries.remixer.annotation.ColorListVariableMethod; +import com.google.android.libraries.remixer.annotation.RangeVariableMethod; +import com.google.android.libraries.remixer.annotation.RemixerBinder; +import com.google.android.libraries.remixer.annotation.StringListVariableMethod; +import com.google.android.libraries.remixer.ui.view.RemixerFragment; +import java.text.NumberFormat; + +public class TransactionListActivity extends AppCompatActivity { + + private static final String SPENT_LAST_MONTH = "Spent in the last month"; + private static final String SPENT_THIS_MONTH = "Spent this month"; + private Toolbar toolbar; + private TransactionAdapter adapter; + private RecyclerView list; + private RemixerFragment remixerFragment; + private CollapsingToolbarLayout collapsingToolbarLayout; + private TextView total; + private TextView timePeriodText; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_transaction_list); + toolbar = (Toolbar) findViewById(R.id.toolbar); + list = (RecyclerView) findViewById(R.id.transactionList); + adapter = new TransactionAdapter(); + list.setAdapter(adapter); + collapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsingToolbarLayout); + total = (TextView) findViewById(R.id.totalTransactions); + timePeriodText = (TextView) findViewById(R.id.timePeriod); + total.setText(NumberFormat.getCurrencyInstance().format(adapter.getThisMonthTotal())); + setSupportActionBar(toolbar); + RemixerBinder.bind(this); + FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); + remixerFragment = RemixerFragment.newInstance(); + remixerFragment.attachToFab(this, fab); + } + + @ColorListVariableMethod( + limitedToValues = {0xFF216EB3, 0xFF191919} + ) + void setHeaderBackgroundColor(Integer color) { + toolbar.setBackgroundColor(color); + collapsingToolbarLayout.setContentScrimColor(color); + collapsingToolbarLayout.setBackgroundColor(color); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + getWindow().setStatusBarColor(color); + collapsingToolbarLayout.setStatusBarScrimColor(color); + } + } + + @BooleanVariableMethod(initialValue = true) + void showIcons(Boolean showIcons) { + adapter.setIconsVisible(showIcons); + LinearLayoutManager layoutManager = (LinearLayoutManager) list.getLayoutManager(); + int first = layoutManager.findFirstVisibleItemPosition(); + int last = layoutManager.findLastVisibleItemPosition(); + adapter.notifyItemRangeChanged(first, last - first + 1); + } + + @StringListVariableMethod( + limitedToValues = {SPENT_THIS_MONTH, SPENT_LAST_MONTH} + ) + void setTimePeriod(String calculation) { + timePeriodText.setText(calculation); + float spent = + calculation.equals(SPENT_LAST_MONTH) + ? adapter.getLastMonthTotal() + : adapter.getThisMonthTotal(); + total.setText(NumberFormat.getCurrencyInstance().format(spent)); + } + + @RangeVariableMethod( + minValue = 14, + maxValue = 80, + increment = 0.5f, + initialValue = 48 + ) + void setTotalTextSize(Float size) { + total.setTextSize(TypedValue.COMPLEX_UNIT_SP, size); + } +} diff --git a/remixer_example/src/main/res/drawable-hdpi/ic_bar.png b/remixer_example/src/main/res/drawable-hdpi/ic_bar.png new file mode 100755 index 0000000..1ff1c83 Binary files /dev/null and b/remixer_example/src/main/res/drawable-hdpi/ic_bar.png differ diff --git a/remixer_example/src/main/res/drawable-hdpi/ic_cafe.png b/remixer_example/src/main/res/drawable-hdpi/ic_cafe.png new file mode 100755 index 0000000..6aa2420 Binary files /dev/null and b/remixer_example/src/main/res/drawable-hdpi/ic_cafe.png differ diff --git a/remixer_example/src/main/res/drawable-hdpi/ic_fastfood.png b/remixer_example/src/main/res/drawable-hdpi/ic_fastfood.png new file mode 100755 index 0000000..c7f4aa6 Binary files /dev/null and b/remixer_example/src/main/res/drawable-hdpi/ic_fastfood.png differ diff --git a/remixer_example/src/main/res/drawable-hdpi/ic_shopping.png b/remixer_example/src/main/res/drawable-hdpi/ic_shopping.png new file mode 100755 index 0000000..ba6e82d Binary files /dev/null and b/remixer_example/src/main/res/drawable-hdpi/ic_shopping.png differ diff --git a/remixer_example/src/main/res/drawable-hdpi/ic_taxi.png b/remixer_example/src/main/res/drawable-hdpi/ic_taxi.png new file mode 100755 index 0000000..978ab13 Binary files /dev/null and b/remixer_example/src/main/res/drawable-hdpi/ic_taxi.png differ diff --git a/remixer_example/src/main/res/drawable-mdpi/ic_bar.png b/remixer_example/src/main/res/drawable-mdpi/ic_bar.png new file mode 100755 index 0000000..2803673 Binary files /dev/null and b/remixer_example/src/main/res/drawable-mdpi/ic_bar.png differ diff --git a/remixer_example/src/main/res/drawable-mdpi/ic_cafe.png b/remixer_example/src/main/res/drawable-mdpi/ic_cafe.png new file mode 100755 index 0000000..e2f731c Binary files /dev/null and b/remixer_example/src/main/res/drawable-mdpi/ic_cafe.png differ diff --git a/remixer_example/src/main/res/drawable-mdpi/ic_fastfood.png b/remixer_example/src/main/res/drawable-mdpi/ic_fastfood.png new file mode 100755 index 0000000..8f406d2 Binary files /dev/null and b/remixer_example/src/main/res/drawable-mdpi/ic_fastfood.png differ diff --git a/remixer_example/src/main/res/drawable-mdpi/ic_shopping.png b/remixer_example/src/main/res/drawable-mdpi/ic_shopping.png new file mode 100755 index 0000000..b7b6893 Binary files /dev/null and b/remixer_example/src/main/res/drawable-mdpi/ic_shopping.png differ diff --git a/remixer_example/src/main/res/drawable-mdpi/ic_taxi.png b/remixer_example/src/main/res/drawable-mdpi/ic_taxi.png new file mode 100755 index 0000000..06ef027 Binary files /dev/null and b/remixer_example/src/main/res/drawable-mdpi/ic_taxi.png differ diff --git a/remixer_example/src/main/res/drawable-xhdpi/ic_bar.png b/remixer_example/src/main/res/drawable-xhdpi/ic_bar.png new file mode 100755 index 0000000..9aac23c Binary files /dev/null and b/remixer_example/src/main/res/drawable-xhdpi/ic_bar.png differ diff --git a/remixer_example/src/main/res/drawable-xhdpi/ic_cafe.png b/remixer_example/src/main/res/drawable-xhdpi/ic_cafe.png new file mode 100755 index 0000000..27cf7f3 Binary files /dev/null and b/remixer_example/src/main/res/drawable-xhdpi/ic_cafe.png differ diff --git a/remixer_example/src/main/res/drawable-xhdpi/ic_fastfood.png b/remixer_example/src/main/res/drawable-xhdpi/ic_fastfood.png new file mode 100755 index 0000000..94fda3c Binary files /dev/null and b/remixer_example/src/main/res/drawable-xhdpi/ic_fastfood.png differ diff --git a/remixer_example/src/main/res/drawable-xhdpi/ic_shopping.png b/remixer_example/src/main/res/drawable-xhdpi/ic_shopping.png new file mode 100755 index 0000000..4598407 Binary files /dev/null and b/remixer_example/src/main/res/drawable-xhdpi/ic_shopping.png differ diff --git a/remixer_example/src/main/res/drawable-xhdpi/ic_taxi.png b/remixer_example/src/main/res/drawable-xhdpi/ic_taxi.png new file mode 100755 index 0000000..df8eaa5 Binary files /dev/null and b/remixer_example/src/main/res/drawable-xhdpi/ic_taxi.png differ diff --git a/remixer_example/src/main/res/drawable-xxhdpi/ic_bar.png b/remixer_example/src/main/res/drawable-xxhdpi/ic_bar.png new file mode 100755 index 0000000..40a9345 Binary files /dev/null and b/remixer_example/src/main/res/drawable-xxhdpi/ic_bar.png differ diff --git a/remixer_example/src/main/res/drawable-xxhdpi/ic_cafe.png b/remixer_example/src/main/res/drawable-xxhdpi/ic_cafe.png new file mode 100755 index 0000000..f105098 Binary files /dev/null and b/remixer_example/src/main/res/drawable-xxhdpi/ic_cafe.png differ diff --git a/remixer_example/src/main/res/drawable-xxhdpi/ic_fastfood.png b/remixer_example/src/main/res/drawable-xxhdpi/ic_fastfood.png new file mode 100755 index 0000000..436675a Binary files /dev/null and b/remixer_example/src/main/res/drawable-xxhdpi/ic_fastfood.png differ diff --git a/remixer_example/src/main/res/drawable-xxhdpi/ic_shopping.png b/remixer_example/src/main/res/drawable-xxhdpi/ic_shopping.png new file mode 100755 index 0000000..1010015 Binary files /dev/null and b/remixer_example/src/main/res/drawable-xxhdpi/ic_shopping.png differ diff --git a/remixer_example/src/main/res/drawable-xxhdpi/ic_taxi.png b/remixer_example/src/main/res/drawable-xxhdpi/ic_taxi.png new file mode 100755 index 0000000..8acaf86 Binary files /dev/null and b/remixer_example/src/main/res/drawable-xxhdpi/ic_taxi.png differ diff --git a/remixer_example/src/main/res/drawable-xxxhdpi/ic_bar.png b/remixer_example/src/main/res/drawable-xxxhdpi/ic_bar.png new file mode 100755 index 0000000..4fc56b2 Binary files /dev/null and b/remixer_example/src/main/res/drawable-xxxhdpi/ic_bar.png differ diff --git a/remixer_example/src/main/res/drawable-xxxhdpi/ic_cafe.png b/remixer_example/src/main/res/drawable-xxxhdpi/ic_cafe.png new file mode 100755 index 0000000..80450c7 Binary files /dev/null and b/remixer_example/src/main/res/drawable-xxxhdpi/ic_cafe.png differ diff --git a/remixer_example/src/main/res/drawable-xxxhdpi/ic_fastfood.png b/remixer_example/src/main/res/drawable-xxxhdpi/ic_fastfood.png new file mode 100755 index 0000000..6df8f3e Binary files /dev/null and b/remixer_example/src/main/res/drawable-xxxhdpi/ic_fastfood.png differ diff --git a/remixer_example/src/main/res/drawable-xxxhdpi/ic_shopping.png b/remixer_example/src/main/res/drawable-xxxhdpi/ic_shopping.png new file mode 100755 index 0000000..656c3f9 Binary files /dev/null and b/remixer_example/src/main/res/drawable-xxxhdpi/ic_shopping.png differ diff --git a/remixer_example/src/main/res/drawable-xxxhdpi/ic_taxi.png b/remixer_example/src/main/res/drawable-xxxhdpi/ic_taxi.png new file mode 100755 index 0000000..a40bbee Binary files /dev/null and b/remixer_example/src/main/res/drawable-xxxhdpi/ic_taxi.png differ diff --git a/remixer_example/src/main/res/layout/activity_box.xml b/remixer_example/src/main/res/layout/activity_box.xml deleted file mode 100644 index 0bc41ee..0000000 --- a/remixer_example/src/main/res/layout/activity_box.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - diff --git a/remixer_example/src/main/res/layout/activity_main.xml b/remixer_example/src/main/res/layout/activity_main.xml deleted file mode 100644 index 7514b83..0000000 --- a/remixer_example/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - -