/* * Copyright 2015. Appsi Mobile * * 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.appsimobile.appsii.theme; import android.app.Activity; import android.content.SharedPreferences; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.v7.widget.Toolbar; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import com.android.colorpicker.ColorPickerDialog; import com.android.colorpicker.ColorPickerSwatch; import com.appsimobile.appsii.ActivityUtils; import com.appsimobile.appsii.AppsiiUtils; import com.appsimobile.appsii.DrawableCompat; import com.appsimobile.appsii.R; import com.appsimobile.appsii.ThemingUtils; import com.appsimobile.appsii.dagger.AppInjector; import javax.inject.Inject; /** * An activity that allows the user to set-up a custom theme for Appsii. * <p/> * The trick is that the {@link ThemingUtils} class will simply create multiple * theme wrapper around the base theme; one for each of the themable properties * <p/> * Created by nick on 04/04/15. */ public class CustomThemeActivity extends Activity implements View.OnClickListener, Toolbar.OnMenuItemClickListener { /** * The set of views the user can click to choose the base theme */ View mBaseThemeView; /** * The set of views the user can click to choose the primary color */ View mPrimaryColorView; /** * The set of views the user can click to choose the accent color */ View mAccentColorView; /** * The text-view that displays the name of the current base theme */ TextView mBaseThemeTextView; /** * The text-view that displays the name of the current primary color */ TextView mPrimaryColorTextView; /** * The text-view that displays the name of the current accent color */ TextView mAccentColorTextView; /** * The ImageView that displays a color for the currently selected * base theme */ ImageView mBaseThemeColorPreview; /** * The ImageView that displays a color for the currently selected * primary color */ ImageView mPrimaryColorPreview; /** * The ImageView that displays a color for the currently selected * accent color */ ImageView mAccentColorPreview; @Inject SharedPreferences mPreferences; @Inject AppsiiUtils mAppsiiUtils; /** * The possible values for the base themes. As defined in a string-array */ String[] mBaseThemeValues; /** * The possible titles for the base themes. As defined in a string-array */ String[] mBaseThemeNames; /** * The possible values for the primary color. As defined in a string-array */ String[] mPrimaryColorValues; /** * The possible titles for the primary color. As defined in a string-array */ String[] mPrimaryColorNames; /** * The possible values for the accent color. As defined in a string-array */ String[] mAccentColorValues; /** * The possible titles for the accent color. As defined in a string-array */ String[] mAccentColorNames; /** * The current base theme (value) */ String mBaseTheme; /** * A listener that is called when the base theme is changed */ final ColorPickerSwatch.OnColorSelectedListener mBaseThemeListener = new ColorPickerSwatch.OnColorSelectedListener() { @Override public void onColorSelected(int color) { onBaseThemePicked(color); } }; /** * The current primary color (value) */ String mPrimaryColor; /** * A listener that is called when the primary color is changed */ final ColorPickerSwatch.OnColorSelectedListener mPrimaryColorListener = new ColorPickerSwatch.OnColorSelectedListener() { @Override public void onColorSelected(int color) { onPrimaryColorPicked(color); } }; /** * The current accent color (value) */ String mAccentColor; /** * A listener that is called when the accent color is changed */ final ColorPickerSwatch.OnColorSelectedListener mAccentColorListener = new ColorPickerSwatch.OnColorSelectedListener() { @Override public void onColorSelected(int color) { onAccentColorPicked(color); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); AppInjector.inject(this); ActivityUtils.setContentView(this, R.layout.activity_customize_theme); mBaseThemeView = findViewById(R.id.base_theme); mPrimaryColorView = findViewById(R.id.primary_color); mAccentColorView = findViewById(R.id.accent_color_container); mBaseThemeTextView = (TextView) findViewById(R.id.theme_value); mPrimaryColorTextView = (TextView) findViewById(R.id.primary_color_value); mAccentColorTextView = (TextView) findViewById(R.id.accent_value); mBaseThemeColorPreview = (ImageView) findViewById(R.id.base_theme_preview); mPrimaryColorPreview = (ImageView) findViewById(R.id.primary_color_preview); mAccentColorPreview = (ImageView) findViewById(R.id.accent_color_preview); Resources resources = getResources(); mBaseThemeValues = resources.getStringArray(R.array.base_theme_values); mBaseThemeNames = resources.getStringArray(R.array.base_theme_names); mPrimaryColorValues = resources.getStringArray(R.array.primary_colors_values); mPrimaryColorNames = resources.getStringArray(R.array.primary_color_names); mAccentColorValues = resources.getStringArray(R.array.accent_colors_values); mAccentColorNames = resources.getStringArray(R.array.accent_color_names); mBaseThemeView.setOnClickListener(this); mPrimaryColorView.setOnClickListener(this); mAccentColorView.setOnClickListener(this); Toolbar toolbar = ActivityUtils.getToolbarPlain(this, R.id.toolbar); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onNavigateUp(); } }); MenuInflater menuInflater = new MenuInflater(this); menuInflater.inflate(R.menu.theme_editor, toolbar.getMenu()); toolbar.setOnMenuItemClickListener(this); String baseTheme = mPreferences.getString( ThemingUtils.PREF_APPSII_BASE_THEME, ThemingUtils.DEFAULT_BASE_THEME); String primary = mPreferences.getString( ThemingUtils.PREF_APPSII_COLOR_PRIMARY, ThemingUtils.DEFAULT_COLOR_PRIMARY); String accent = mPreferences.getString( ThemingUtils.PREF_APPSII_COLOR_ACCENT, ThemingUtils.DEFAULT_COLOR_ACCENT); mBaseTheme = baseTheme; mPrimaryColor = primary; mAccentColor = accent; setupBaseTheme(baseTheme); setupPrimaryColor(primary); setupAccentColor(accent); ColorPickerDialog primaryColorPicker = (ColorPickerDialog) getFragmentManager().findFragmentByTag("primary_color_picker"); if (primaryColorPicker != null) { primaryColorPicker.setOnColorSelectedListener(mPrimaryColorListener); } ColorPickerDialog accentColorPicker = (ColorPickerDialog) getFragmentManager().findFragmentByTag("accent_color_picker"); if (accentColorPicker != null) { accentColorPicker.setOnColorSelectedListener(mAccentColorListener); } ColorPickerDialog baseThemePicker = (ColorPickerDialog) getFragmentManager().findFragmentByTag("base_theme_picker"); if (baseThemePicker != null) { baseThemePicker.setOnColorSelectedListener(mBaseThemeListener); } } private void setupBaseTheme(String baseTheme) { int idx = indexOf(mBaseThemeValues, baseTheme); String name = mBaseThemeNames[idx]; mBaseThemeTextView.setText(name); Drawable drawable = mBaseThemeColorPreview.getDrawable(); int color; color = getColorForBaseTheme(baseTheme); DrawableCompat.setTintColorCompat(drawable, color); } private void setupPrimaryColor(String primaryColor) { int idx = indexOf(mPrimaryColorValues, primaryColor); String name = mPrimaryColorNames[idx]; mPrimaryColorTextView.setText(name); Drawable drawable = mPrimaryColorPreview.getDrawable(); int color = ThemingUtils.getPrimaryColorValue(primaryColor); DrawableCompat.setTintColorCompat(drawable, color); } private void setupAccentColor(String accentColor) { int idx = indexOf(mAccentColorValues, accentColor); String name = mAccentColorNames[idx]; mAccentColorTextView.setText(name); Drawable drawable = mAccentColorPreview.getDrawable(); int color = ThemingUtils.getPrimaryColorValue(accentColor); DrawableCompat.setTintColorCompat(drawable, color); } <T> int indexOf(T[] array, T value) { int N = array.length; for (int i = 0; i < N; i++) { if (value.equals(array[i])) return i; } return -1; } private int getColorForBaseTheme(String baseTheme) { int color; switch (baseTheme) { case "theme_dark": color = 0xFF333333; break; case "theme_light": color = 0xFFCCCCCC; break; default: case "theme_dark_light_ab": color = 0xFF666666; break; case "theme_light_dark_ab": color = 0xFF999999; break; } return color; } void onBaseThemePicked(int color) { String baseTheme = getBaseThemeByColor(color); mBaseTheme = baseTheme; setupBaseTheme(baseTheme); mPreferences.edit(). putString(ThemingUtils.PREF_APPSII_THEME, "custom"). putString(ThemingUtils.PREF_APPSII_BASE_THEME, baseTheme). apply(); mAppsiiUtils.restartAppsi(this); } private String getBaseThemeByColor(final int color) { String baseTheme; switch (color) { case 0xFF333333: baseTheme = "theme_dark"; break; case 0xFFCCCCCC: baseTheme = "theme_light"; break; default: case 0xFF666666: baseTheme = "theme_dark_light_ab"; break; case 0xFF999999: baseTheme = "theme_light_dark_ab"; break; } return baseTheme; } void onPrimaryColorPicked(int color) { int[] primaryColors = ThemingUtils.createPrimaryColorArray(mPrimaryColorValues); int idx = indexOf(primaryColors, color); String primaryColorValue = mPrimaryColorValues[idx]; mPrimaryColor = primaryColorValue; setupPrimaryColor(primaryColorValue); mPreferences.edit(). putString(ThemingUtils.PREF_APPSII_THEME, "custom"). putString(ThemingUtils.PREF_APPSII_COLOR_PRIMARY, primaryColorValue). apply(); mAppsiiUtils.restartAppsi(this); } @Override public void onClick(View v) { int id = v.getId(); switch (id) { case R.id.base_theme: showBaseThemePicker(); break; case R.id.primary_color: showPrimaryColorPicker(); break; case R.id.accent_color_container: showAccentColorPicker(); break; } } int indexOf(int[] array, int value) { int N = array.length; for (int i = 0; i < N; i++) { if (value == array[i]) return i; } return -1; } private void showBaseThemePicker() { int[] colors = {0xFFCCCCCC, 0xFF999999, 0xFF666666, 0xFF333333}; int selectedColor = getColorForBaseTheme(mBaseTheme); ColorPickerDialog colorPickerDialog = ColorPickerDialog.newInstance( R.string.base_theme, colors, selectedColor, 4, ColorPickerDialog.SIZE_SMALL); colorPickerDialog.show(getFragmentManager(), "base_theme_picker"); colorPickerDialog.setOnColorSelectedListener(mBaseThemeListener); } void onAccentColorPicked(int color) { int[] accentColors = ThemingUtils.createAccentColorArray(false, mAccentColorValues); int idx = indexOf(accentColors, color); String accentColorValue = mAccentColorValues[idx]; mAccentColor = accentColorValue; setupAccentColor(accentColorValue); mPreferences.edit(). putString(ThemingUtils.PREF_APPSII_THEME, "custom"). putString(ThemingUtils.PREF_APPSII_COLOR_ACCENT, accentColorValue). apply(); mAppsiiUtils.restartAppsi(this); } private void showPrimaryColorPicker() { int[] colors = ThemingUtils.createPrimaryColorArray(mPrimaryColorValues); int selectedColor = ThemingUtils.getPrimaryColorValue(mPrimaryColor); ColorPickerDialog colorPickerDialog = ColorPickerDialog.newInstance( R.string.primary_color, colors, selectedColor, 4, ColorPickerDialog.SIZE_SMALL); colorPickerDialog.show(getFragmentManager(), "primary_color_picker"); colorPickerDialog.setOnColorSelectedListener(mPrimaryColorListener); } @Override public boolean onMenuItemClick(MenuItem menuItem) { int id = menuItem.getItemId(); switch (id) { case R.id.theme_teal: applyPreset("theme_light_dark_ab", "teal", "deep_orange"); return true; case R.id.theme_teal_dark: applyPreset("theme_dark", "teal", "deep_orange"); return true; case R.id.theme_light_green: applyPreset("theme_dark_light_ab", "light_green", "yellow"); return true; case R.id.theme_blue_grey: applyPreset("theme_dark", "blue_grey", "orange"); return true; case R.id.theme_orange: applyPreset("theme_light", "orange", "deep_purple"); return true; } return false; } private void showAccentColorPicker() { int[] colors = ThemingUtils.createAccentColorArray(false, mAccentColorValues); int selectedColor = ThemingUtils.getAccentColorValue(false, mAccentColor); ColorPickerDialog colorPickerDialog = ColorPickerDialog.newInstance( R.string.accent_color, colors, selectedColor, 4, ColorPickerDialog.SIZE_SMALL); colorPickerDialog.show(getFragmentManager(), "accent_color_picker"); colorPickerDialog.setOnColorSelectedListener(mAccentColorListener); } private void applyPreset(String baseTheme, String primaryColor, String accentColor) { mPreferences.edit(). putString(ThemingUtils.PREF_APPSII_THEME, "custom"). putString(ThemingUtils.PREF_APPSII_BASE_THEME, baseTheme). putString(ThemingUtils.PREF_APPSII_COLOR_PRIMARY, primaryColor). putString(ThemingUtils.PREF_APPSII_COLOR_ACCENT, accentColor). apply(); // When the theme has been changed, Appsii needs to be restarted. // This is because it's context needs to be changed. And all of the // views are depending on these values in the theme. mAppsiiUtils.restartAppsi(this); mPrimaryColor = primaryColor; mAccentColor = accentColor; mBaseTheme = baseTheme; setupBaseTheme(baseTheme); setupPrimaryColor(primaryColor); setupAccentColor(accentColor); } }