diff --git a/chameleon/.gitignore b/chameleon/.gitignore
new file mode 100644
index 000000000..796b96d1c
--- /dev/null
+++ b/chameleon/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/chameleon/build.gradle b/chameleon/build.gradle
new file mode 100644
index 000000000..ff0911dfb
--- /dev/null
+++ b/chameleon/build.gradle
@@ -0,0 +1,34 @@
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion 25
+ buildToolsVersion "25.0.2"
+
+ defaultConfig {
+ minSdkVersion 14
+ targetSdkVersion 25
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ compile 'com.android.support:appcompat-v7:25.1.0'
+ compile 'com.android.support:design:25.1.0'
+
+ testCompile 'junit:junit:4.12'
+
+ androidTestCompile "com.android.support:support-annotations:$android_support_lib_version"
+ androidTestCompile 'com.android.support.test:runner:0.5'
+ androidTestCompile 'com.android.support.test:rules:0.5'
+}
diff --git a/chameleon/proguard-rules.pro b/chameleon/proguard-rules.pro
new file mode 100644
index 000000000..a3abb5fc4
--- /dev/null
+++ b/chameleon/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/mariotaku/Library/Android/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/chameleon/src/androidTest/java/org/mariotaku/chameleon/ExampleInstrumentedTest.java b/chameleon/src/androidTest/java/org/mariotaku/chameleon/ExampleInstrumentedTest.java
new file mode 100644
index 000000000..e26a2eb37
--- /dev/null
+++ b/chameleon/src/androidTest/java/org/mariotaku/chameleon/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package org.mariotaku.chameleon;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumentation test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() throws Exception {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getTargetContext();
+
+ assertEquals("org.mariotaku.chameleon.test", appContext.getPackageName());
+ }
+}
diff --git a/chameleon/src/main/AndroidManifest.xml b/chameleon/src/main/AndroidManifest.xml
new file mode 100644
index 000000000..bb57eb4fc
--- /dev/null
+++ b/chameleon/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/chameleon/src/main/java/org/mariotaku/chameleon/Chameleon.java b/chameleon/src/main/java/org/mariotaku/chameleon/Chameleon.java
new file mode 100644
index 000000000..01176ca53
--- /dev/null
+++ b/chameleon/src/main/java/org/mariotaku/chameleon/Chameleon.java
@@ -0,0 +1,205 @@
+package org.mariotaku.chameleon;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.util.ArrayMap;
+import android.support.v4.view.LayoutInflaterCompat;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.app.AppCompatDelegate;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import org.mariotaku.chameleon.internal.ChameleonInflationFactory;
+
+/**
+ * Created by mariotaku on 2016/12/18.
+ */
+
+public class Chameleon {
+
+ private final Activity activity;
+ private final Theme theme;
+ private final ArrayMap postApplyViews;
+
+ private Chameleon(Activity activity) {
+ this.activity = activity;
+ this.theme = getOverrideTheme(activity, activity);
+ this.postApplyViews = new ArrayMap<>();
+ }
+
+ public static Chameleon getInstance(Activity activity) {
+ return new Chameleon(activity);
+ }
+
+ public void preApply() {
+
+ final LayoutInflater inflater = activity.getLayoutInflater();
+ AppCompatDelegate delegate = null;
+ if (activity instanceof AppCompatActivity) {
+ delegate = ((AppCompatActivity) activity).getDelegate();
+ }
+ final ChameleonInflationFactory factory = new ChameleonInflationFactory(inflater, activity,
+ delegate, theme, postApplyViews);
+ LayoutInflaterCompat.setFactory(inflater, factory);
+ }
+
+ public void postApply() {
+ for (int i = 0, j = postApplyViews.size(); i < j; i++) {
+ postApplyViews.keyAt(i).applyAppearance(postApplyViews.valueAt(i));
+ }
+ postApplyViews.clear();
+
+ boolean statusBarColorHandled = false;
+ final View rootView = getRootView();
+ if (rootView instanceof ChameleonView.StatusBarThemeable) {
+ if (((ChameleonView.StatusBarThemeable) rootView).isStatusBarColorHandled()) {
+ statusBarColorHandled = true;
+ }
+ }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !statusBarColorHandled) {
+ activity.getWindow().setStatusBarColor(theme.getStatusBarColor());
+ }
+ }
+
+ private View getRootView() {
+ return ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
+ }
+
+ public void invalidateActivity() {
+
+ }
+
+ public void cleanUp() {
+ postApplyViews.clear();
+ }
+
+ public void themeOverflow() {
+
+ }
+
+ @NonNull
+ public static Theme getOverrideTheme(Context context, Object obj) {
+ if (obj instanceof Themeable) {
+ final Theme theme = ((Themeable) obj).getOverrideTheme();
+ if (theme != null) {
+ return theme;
+ }
+ }
+ return Theme.from(context);
+ }
+
+ /**
+ * Created by mariotaku on 2016/12/18.
+ */
+
+ public static class Theme {
+ private int colorPrimary;
+ private int colorAccent;
+ private int colorToolbar;
+ private int colorBackground;
+ private int colorForeground;
+ private boolean toolbarColored;
+ private int textColorPrimary;
+ private int statusBarColor;
+
+ Theme() {
+
+ }
+
+ public int getColorAccent() {
+ return colorAccent;
+ }
+
+ public void setColorAccent(int colorAccent) {
+ this.colorAccent = colorAccent;
+ }
+
+ public int getColorPrimary() {
+ return colorPrimary;
+ }
+
+ public void setColorPrimary(int colorPrimary) {
+ this.colorPrimary = colorPrimary;
+ }
+
+ public int getColorToolbar() {
+ if (colorToolbar == 0) return colorPrimary;
+ return colorToolbar;
+ }
+
+ public void setColorToolbar(int colorToolbar) {
+ this.colorToolbar = colorToolbar;
+ }
+
+ public boolean isToolbarColored() {
+ return toolbarColored;
+ }
+
+ public void setToolbarColored(boolean toolbarColored) {
+ this.toolbarColored = toolbarColored;
+ }
+
+ public int getTextColorPrimary() {
+ return textColorPrimary;
+ }
+
+ public void setTextColorPrimary(int textColorPrimary) {
+ this.textColorPrimary = textColorPrimary;
+ }
+
+ public int getColorBackground() {
+ return colorBackground;
+ }
+
+ public void setColorBackground(int colorBackground) {
+ this.colorBackground = colorBackground;
+ }
+
+ public int getColorForeground() {
+ return colorForeground;
+ }
+
+ public void setColorForeground(int colorForeground) {
+ this.colorForeground = colorForeground;
+ }
+
+ @NonNull
+ public static Theme from(Context context) {
+ Theme theme = new Theme();
+ TypedArray a = context.obtainStyledAttributes(R.styleable.ChameleonTheme);
+ theme.setColorPrimary(a.getColor(R.styleable.ChameleonTheme_colorPrimary, 0));
+ theme.setColorAccent(a.getColor(R.styleable.ChameleonTheme_colorAccent, 0));
+ theme.setColorToolbar(a.getColor(R.styleable.ChameleonTheme_colorToolbar, theme.getColorPrimary()));
+ theme.setColorBackground(a.getColor(R.styleable.ChameleonTheme_android_colorBackground, 0));
+ theme.setColorForeground(a.getColor(R.styleable.ChameleonTheme_android_colorForeground, 0));
+ theme.setToolbarColored(a.getBoolean(R.styleable.ChameleonTheme_isToolbarColored, true));
+ a.recycle();
+ return theme;
+ }
+
+ public int getStatusBarColor() {
+ if (statusBarColor == 0) {
+ return ChameleonUtils.darkenColor(getColorToolbar());
+ }
+ return statusBarColor;
+ }
+
+ public void setStatusBarColor(int statusBarColor) {
+ this.statusBarColor = statusBarColor;
+ }
+ }
+
+ /**
+ * Created by mariotaku on 2016/12/18.
+ */
+
+ public interface Themeable {
+ @Nullable
+ Theme getOverrideTheme();
+ }
+}
diff --git a/twidere/src/main/kotlin/org/mariotaku/chameleon/ChameleonActivity.java b/chameleon/src/main/java/org/mariotaku/chameleon/ChameleonActivity.java
similarity index 100%
rename from twidere/src/main/kotlin/org/mariotaku/chameleon/ChameleonActivity.java
rename to chameleon/src/main/java/org/mariotaku/chameleon/ChameleonActivity.java
diff --git a/chameleon/src/main/java/org/mariotaku/chameleon/ChameleonTypedArray.java b/chameleon/src/main/java/org/mariotaku/chameleon/ChameleonTypedArray.java
new file mode 100644
index 000000000..dc8ffc8e8
--- /dev/null
+++ b/chameleon/src/main/java/org/mariotaku/chameleon/ChameleonTypedArray.java
@@ -0,0 +1,77 @@
+package org.mariotaku.chameleon;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+
+/**
+ * Created by mariotaku on 2016/12/18.
+ */
+
+public class ChameleonTypedArray {
+ private final TypedArray wrapped;
+ private final boolean[] hasAttributeStates;
+ private final int[] attributeReferences;
+ private final Chameleon.Theme theme;
+
+ private ChameleonTypedArray(TypedArray wrapped, boolean[] hasAttributeStates, int[] attributeReferences, Chameleon.Theme theme) {
+ this.wrapped = wrapped;
+ this.hasAttributeStates = hasAttributeStates;
+ this.attributeReferences = attributeReferences;
+ this.theme = theme;
+ }
+
+ public void recycle() {
+ wrapped.recycle();
+ }
+
+ public static ChameleonTypedArray obtain(Context context, AttributeSet set, int[] attrs, Chameleon.Theme theme) {
+ @SuppressLint("Recycle") TypedArray array = context.obtainStyledAttributes(set, attrs);
+ boolean[] hasAttribute = new boolean[attrs.length];
+ int[] attributeReferences = new int[attrs.length];
+ for (int i = 0; i < attrs.length; i++) {
+ final int index = ChameleonUtils.findAttributeIndex(set, attrs[i]);
+ if (index != -1) {
+ hasAttribute[i] = true;
+ String value = set.getAttributeValue(index);
+ if (value != null && value.startsWith("?")) {
+ attributeReferences[i] = Integer.parseInt(value.substring(1));
+ }
+ }
+ }
+ return new ChameleonTypedArray(array, hasAttribute, attributeReferences, theme);
+ }
+
+ public int getColor(int index) {
+ return wrapped.getColor(index, 0);
+ }
+
+ public int getColor(int index, int defValue) {
+ final int ref = attributeReferences[index];
+ if (ref == android.support.design.R.attr.colorPrimary) {
+ return theme.getColorPrimary();
+ } else if (ref == android.support.design.R.attr.colorAccent) {
+ return theme.getColorAccent();
+ } else if (ref == R.attr.colorToolbar) {
+ return theme.getColorToolbar();
+ }
+ if (!hasAttributeStates[index]) return defValue;
+ return wrapped.getColor(index, defValue);
+ }
+
+ public Drawable getDrawable(int index) {
+ final int ref = attributeReferences[index];
+ if (ref == android.support.design.R.attr.colorPrimary) {
+ return new ColorDrawable(theme.getColorPrimary());
+ } else if (ref == android.support.design.R.attr.colorAccent) {
+ return new ColorDrawable(theme.getColorAccent());
+ } else if (ref == R.attr.colorToolbar) {
+ return new ColorDrawable(theme.getColorToolbar());
+ }
+ if (!hasAttributeStates[index]) return null;
+ return wrapped.getDrawable(index);
+ }
+}
diff --git a/chameleon/src/main/java/org/mariotaku/chameleon/ChameleonUtils.java b/chameleon/src/main/java/org/mariotaku/chameleon/ChameleonUtils.java
new file mode 100644
index 000000000..9d4ed3a91
--- /dev/null
+++ b/chameleon/src/main/java/org/mariotaku/chameleon/ChameleonUtils.java
@@ -0,0 +1,51 @@
+package org.mariotaku.chameleon;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.graphics.Color;
+import android.support.annotation.ColorInt;
+import android.support.annotation.FloatRange;
+import android.util.AttributeSet;
+
+/**
+ * Created by mariotaku on 2016/12/18.
+ */
+
+public class ChameleonUtils {
+ public static int findAttributeIndex(AttributeSet attributeSet, int attributeNameResource) {
+ for (int i = 0, j = attributeSet.getAttributeCount(); i < j; i++) {
+ if (attributeSet.getAttributeNameResource(i) == attributeNameResource) return i;
+ }
+ return -1;
+ }
+
+ public static boolean isColorLight(@ColorInt int color) {
+ if (color == Color.BLACK) return false;
+ else if (color == Color.WHITE || color == Color.TRANSPARENT) return true;
+ final double darkness = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255;
+ return darkness < 0.4;
+ }
+
+ @ColorInt
+ public static int shiftColor(@ColorInt int color, @FloatRange(from = 0.0f, to = 2.0f) float by) {
+ if (by == 1f) return color;
+ float[] hsv = new float[3];
+ Color.colorToHSV(color, hsv);
+ hsv[2] *= by; // value component
+ return Color.HSVToColor(hsv);
+ }
+
+ @ColorInt
+ public static int darkenColor(@ColorInt int color) {
+ return shiftColor(color, 0.9f);
+ }
+
+ public static Activity getActivity(Context context) {
+ if (context instanceof Activity) return (Activity) context;
+ if (context instanceof ContextWrapper) {
+ return getActivity(((ContextWrapper) context).getBaseContext());
+ }
+ return null;
+ }
+}
diff --git a/chameleon/src/main/java/org/mariotaku/chameleon/ChameleonView.java b/chameleon/src/main/java/org/mariotaku/chameleon/ChameleonView.java
new file mode 100644
index 000000000..6ff8fc2b8
--- /dev/null
+++ b/chameleon/src/main/java/org/mariotaku/chameleon/ChameleonView.java
@@ -0,0 +1,28 @@
+package org.mariotaku.chameleon;
+
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+
+/**
+ * Created by mariotaku on 2016/12/18.
+ */
+
+public interface ChameleonView {
+
+ boolean isPostApplyTheme();
+
+ @Nullable
+ Appearance createAppearance(Context context, AttributeSet attributeSet, Chameleon.Theme theme);
+
+ void applyAppearance(@NonNull Appearance appearance);
+
+ interface Appearance {
+
+ }
+
+ interface StatusBarThemeable {
+ boolean isStatusBarColorHandled();
+ }
+}
diff --git a/chameleon/src/main/java/org/mariotaku/chameleon/internal/ChameleonInflationFactory.java b/chameleon/src/main/java/org/mariotaku/chameleon/internal/ChameleonInflationFactory.java
new file mode 100644
index 000000000..3d1cbe030
--- /dev/null
+++ b/chameleon/src/main/java/org/mariotaku/chameleon/internal/ChameleonInflationFactory.java
@@ -0,0 +1,176 @@
+package org.mariotaku.chameleon.internal;
+
+import android.app.Activity;
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.util.ArrayMap;
+import android.support.v4.view.LayoutInflaterFactory;
+import android.support.v7.app.AppCompatDelegate;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import org.mariotaku.chameleon.Chameleon;
+import org.mariotaku.chameleon.ChameleonView;
+import org.mariotaku.chameleon.view.ChameleonAutoCompleteTextView;
+import org.mariotaku.chameleon.view.ChameleonEditText;
+import org.mariotaku.chameleon.view.ChameleonFloatingActionButton;
+import org.mariotaku.chameleon.view.ChameleonMultiAutoCompleteTextView;
+import org.mariotaku.chameleon.view.ChameleonSwipeRefreshLayout;
+import org.mariotaku.chameleon.view.ChameleonTextView;
+import org.mariotaku.chameleon.view.ChameleonToolbar;
+
+/**
+ * Created by mariotaku on 2016/12/18.
+ */
+
+public class ChameleonInflationFactory implements LayoutInflaterFactory {
+
+ @NonNull
+ private final LayoutInflater mInflater;
+ @Nullable
+ private final Activity mActivity;
+ @Nullable
+ private final AppCompatDelegate mDelegate;
+ @Nullable
+ private final Chameleon.Theme mTheme;
+ private final ArrayMap mPostApplyViews;
+
+
+ public ChameleonInflationFactory(@NonNull LayoutInflater inflater,
+ @Nullable Activity activity,
+ @Nullable AppCompatDelegate delegate,
+ @Nullable Chameleon.Theme theme,
+ @NonNull ArrayMap postApplyViews) {
+ this.mInflater = inflater;
+ this.mActivity = activity;
+ this.mDelegate = delegate;
+ this.mTheme = theme;
+ this.mPostApplyViews = postApplyViews;
+ }
+
+ @Override
+ public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
+ View view = null;
+ if (shouldSkipTheming(parent)) {
+
+ } else switch (name) {
+ case "TextView":
+ case "android.support.v7.widget.AppCompatTextView": {
+ view = new ChameleonTextView(context, attrs);
+ break;
+ }
+ case "EditText":
+ case "android.support.v7.widget.AppCompatEditText": {
+ view = new ChameleonEditText(context, attrs);
+ break;
+ }
+ case "AutoCompleteTextView":
+ case "android.support.v7.widget.AppCompatAutoCompleteTextView": {
+ view = new ChameleonAutoCompleteTextView(context, attrs);
+ break;
+ }
+ case "MultiAutoCompleteTextView":
+ case "android.support.v7.widget.AppCompatMultiAutoCompleteTextView": {
+ view = new ChameleonMultiAutoCompleteTextView(context, attrs);
+ break;
+ }
+ case "android.support.design.widget.FloatingActionButton": {
+ view = new ChameleonFloatingActionButton(context, attrs);
+ break;
+ }
+ case "android.support.v7.widget.Toolbar": {
+ view = new ChameleonToolbar(context, attrs);
+ break;
+ }
+ case "android.support.v4.widget.SwipeRefreshLayout": {
+ view = new ChameleonSwipeRefreshLayout(context, attrs);
+ break;
+ }
+ }
+
+ if (view == null) {
+ // First, check if the AppCompatDelegate will give us a view, usually (maybe always) null.
+ if (mDelegate != null) {
+ view = mDelegate.createView(parent, name, context, attrs);
+ if (view == null && mActivity != null)
+ view = mActivity.onCreateView(parent, name, context, attrs);
+ else view = null;
+ } else {
+ view = null;
+ }
+
+ if (isExcluded(name))
+ return view;
+
+ // Mimic code of LayoutInflater using reflection tricks (this would normally be run when this factory returns null).
+ // We need to intercept the default behavior rather than allowing the LayoutInflater to handle it after this method returns.
+ if (view == null) {
+ try {
+ Context viewContext;
+ final boolean inheritContext = false; // TODO will this ever need to be true?
+ //noinspection PointlessBooleanExpression,ConstantConditions
+ if (parent != null && inheritContext) {
+ viewContext = parent.getContext();
+ } else {
+ viewContext = mInflater.getContext();
+ }
+ Context wrappedContext = LayoutInflaterInternal.getThemeWrapper(viewContext, attrs);
+ if (wrappedContext != null) {
+ viewContext = wrappedContext;
+ }
+
+ Object[] mConstructorArgs = LayoutInflaterInternal.getConstructorArgs(mInflater);
+
+ final Object lastContext = mConstructorArgs[0];
+ mConstructorArgs[0] = viewContext;
+ try {
+ if (-1 == name.indexOf('.')) {
+ view = LayoutInflaterInternal.onCreateView(mInflater, parent, name, attrs);
+ } else {
+ view = LayoutInflaterInternal.createView(mInflater, name, null, attrs);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ mConstructorArgs[0] = lastContext;
+ }
+ } catch (Throwable t) {
+ throw new RuntimeException(String.format("An error occurred while inflating View %s: %s", name, t.getMessage()), t);
+ }
+ }
+ }
+
+
+ if (view instanceof ChameleonView) {
+ final ChameleonView cv = (ChameleonView) view;
+ ChameleonView.Appearance appearance = cv.createAppearance(view.getContext(), attrs, mTheme);
+ if (appearance != null) {
+ if (cv.isPostApplyTheme()) {
+ mPostApplyViews.put(cv, appearance);
+ } else {
+ cv.applyAppearance(appearance);
+ }
+ }
+ }
+ return view;
+ }
+
+ private boolean isExcluded(@NonNull String name) {
+ switch (name) {
+ case "android.support.design.internal.NavigationMenuItemView":
+ case "ViewStub":
+ case "fragment":
+ case "include":
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private boolean shouldSkipTheming(View parent) {
+ if (parent == null) return false;
+ return "ignore".equals(parent.getTag());
+ }
+}
diff --git a/chameleon/src/main/java/org/mariotaku/chameleon/internal/LayoutInflaterInternal.java b/chameleon/src/main/java/org/mariotaku/chameleon/internal/LayoutInflaterInternal.java
new file mode 100644
index 000000000..d95d7197f
--- /dev/null
+++ b/chameleon/src/main/java/org/mariotaku/chameleon/internal/LayoutInflaterInternal.java
@@ -0,0 +1,106 @@
+package org.mariotaku.chameleon.internal;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.support.v7.view.ContextThemeWrapper;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Created by mariotaku on 2016/12/18.
+ */
+
+public class LayoutInflaterInternal {
+ private static Method mOnCreateViewMethod;
+ private static Method mCreateViewMethod;
+ private static Field mConstructorArgsField;
+ private static int[] ATTRS_THEME;
+
+ public static View onCreateView(LayoutInflater inflater, View view, String name, AttributeSet attrs) {
+ ensureAvailable();
+ try {
+ return (View) mOnCreateViewMethod.invoke(inflater, view, name, attrs);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static View createView(LayoutInflater inflater, String name, String prefix, AttributeSet attrs) {
+ ensureAvailable();
+ try {
+ return (View) mCreateViewMethod.invoke(inflater, name, null, attrs);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static Context getThemeWrapper(Context viewContext, AttributeSet attrs) {
+ ensureAvailable();
+ // Apply a theme wrapper, if requested.
+ if (ATTRS_THEME != null) {
+ final TypedArray ta = viewContext.obtainStyledAttributes(attrs, ATTRS_THEME);
+ try {
+ final int themeResId = ta.getResourceId(0, 0);
+ if (themeResId != 0) return new ContextThemeWrapper(viewContext, themeResId);
+ } finally {
+ ta.recycle();
+ }
+ }
+ return null;
+ }
+
+ public static Object[] getConstructorArgs(LayoutInflater inflater) {
+ try {
+ return (Object[]) mConstructorArgsField.get(inflater);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static void ensureAvailable() {
+ if (mOnCreateViewMethod == null) {
+ try {
+ mOnCreateViewMethod = LayoutInflater.class.getDeclaredMethod("onCreateView",
+ View.class, String.class, AttributeSet.class);
+ mOnCreateViewMethod.setAccessible(true);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException("Failed to retrieve the onCreateView method.", e);
+ }
+ }
+ if (mCreateViewMethod == null) {
+ try {
+ mCreateViewMethod = LayoutInflater.class.getDeclaredMethod("createView",
+ String.class, String.class, AttributeSet.class);
+ mCreateViewMethod.setAccessible(true);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException("Failed to retrieve the createView method.", e);
+ }
+ }
+ if (mConstructorArgsField == null) {
+ try {
+ mConstructorArgsField = LayoutInflater.class.getDeclaredField("mConstructorArgs");
+ mConstructorArgsField.setAccessible(true);
+ } catch (NoSuchFieldException e) {
+ throw new RuntimeException("Failed to retrieve the mConstructorArgs field.", e);
+ }
+ }
+ if (ATTRS_THEME == null) {
+ try {
+ final Field attrsThemeField = LayoutInflater.class.getDeclaredField("ATTRS_THEME");
+ attrsThemeField.setAccessible(true);
+ ATTRS_THEME = (int[]) attrsThemeField.get(null);
+ } catch (Throwable t) {
+ // Ignore
+ }
+ }
+ }
+}
diff --git a/chameleon/src/main/java/org/mariotaku/chameleon/view/ChameleonAutoCompleteTextView.java b/chameleon/src/main/java/org/mariotaku/chameleon/view/ChameleonAutoCompleteTextView.java
new file mode 100644
index 000000000..a8af476a4
--- /dev/null
+++ b/chameleon/src/main/java/org/mariotaku/chameleon/view/ChameleonAutoCompleteTextView.java
@@ -0,0 +1,47 @@
+package org.mariotaku.chameleon.view;
+
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.AppCompatAutoCompleteTextView;
+import android.util.AttributeSet;
+
+import org.mariotaku.chameleon.Chameleon;
+import org.mariotaku.chameleon.ChameleonView;
+
+/**
+ * Created by mariotaku on 2016/12/18.
+ */
+
+public class ChameleonAutoCompleteTextView extends AppCompatAutoCompleteTextView implements ChameleonView {
+ public ChameleonAutoCompleteTextView(Context context) {
+ super(context);
+ }
+
+ public ChameleonAutoCompleteTextView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public ChameleonAutoCompleteTextView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ public boolean isPostApplyTheme() {
+ return false;
+ }
+
+ @Nullable
+ @Override
+ public ChameleonEditText.Appearance createAppearance(Context context, AttributeSet attributeSet, Chameleon.Theme theme) {
+ return ChameleonEditText.Appearance.create(context, attributeSet, theme);
+ }
+
+
+ @Override
+ public void applyAppearance(@NonNull Appearance appearance) {
+ final ChameleonEditText.Appearance a = (ChameleonEditText.Appearance) appearance;
+ ChameleonEditText.Appearance.apply(this, a);
+ }
+
+}
diff --git a/chameleon/src/main/java/org/mariotaku/chameleon/view/ChameleonEditText.java b/chameleon/src/main/java/org/mariotaku/chameleon/view/ChameleonEditText.java
new file mode 100644
index 000000000..8737af0a4
--- /dev/null
+++ b/chameleon/src/main/java/org/mariotaku/chameleon/view/ChameleonEditText.java
@@ -0,0 +1,78 @@
+package org.mariotaku.chameleon.view;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.view.ViewCompat;
+import android.support.v7.widget.AppCompatEditText;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+import org.mariotaku.chameleon.Chameleon;
+import org.mariotaku.chameleon.ChameleonTypedArray;
+import org.mariotaku.chameleon.ChameleonView;
+import org.mariotaku.chameleon.R;
+
+/**
+ * Created by mariotaku on 2016/12/18.
+ */
+
+public class ChameleonEditText extends AppCompatEditText implements ChameleonView {
+ public ChameleonEditText(Context context) {
+ super(context);
+ }
+
+ public ChameleonEditText(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public ChameleonEditText(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ public boolean isPostApplyTheme() {
+ return false;
+ }
+
+ @Nullable
+ @Override
+ public Appearance createAppearance(Context context, AttributeSet attributeSet, Chameleon.Theme theme) {
+ return Appearance.create(context, attributeSet, theme);
+ }
+
+
+ @Override
+ public void applyAppearance(@NonNull ChameleonView.Appearance appearance) {
+ final Appearance a = (Appearance) appearance;
+ Appearance.apply(this, a);
+ }
+
+ public static class Appearance extends ChameleonTextView.Appearance {
+ private int backgroundColor;
+
+ public int getBackgroundColor() {
+ return backgroundColor;
+ }
+
+ public void setBackgroundColor(int backgroundColor) {
+ this.backgroundColor = backgroundColor;
+ }
+
+ public static void apply(TextView view, Appearance appearance) {
+ view.setLinkTextColor(appearance.getLinkTextColor());
+ ViewCompat.setBackgroundTintList(view, ColorStateList.valueOf(appearance.getBackgroundColor()));
+ }
+
+ public static Appearance create(Context context, AttributeSet attributeSet, Chameleon.Theme theme) {
+ Appearance appearance = new Appearance();
+ ChameleonTypedArray a = ChameleonTypedArray.obtain(context, attributeSet,
+ R.styleable.ChameleonEditText, theme);
+ appearance.setLinkTextColor(a.getColor(R.styleable.ChameleonEditText_android_textColorLink, theme.getColorAccent()));
+ appearance.setBackgroundColor(a.getColor(R.styleable.ChameleonEditText_backgroundTint, theme.getColorAccent()));
+ a.recycle();
+ return appearance;
+ }
+ }
+}
diff --git a/chameleon/src/main/java/org/mariotaku/chameleon/view/ChameleonFloatingActionButton.java b/chameleon/src/main/java/org/mariotaku/chameleon/view/ChameleonFloatingActionButton.java
new file mode 100644
index 000000000..f099c22a5
--- /dev/null
+++ b/chameleon/src/main/java/org/mariotaku/chameleon/view/ChameleonFloatingActionButton.java
@@ -0,0 +1,58 @@
+package org.mariotaku.chameleon.view;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.design.widget.FloatingActionButton;
+import android.util.AttributeSet;
+
+import org.mariotaku.chameleon.Chameleon;
+import org.mariotaku.chameleon.ChameleonTypedArray;
+import org.mariotaku.chameleon.ChameleonView;
+import org.mariotaku.chameleon.R;
+
+/**
+ * Created by mariotaku on 2016/12/18.
+ */
+
+public class ChameleonFloatingActionButton extends FloatingActionButton implements ChameleonView {
+ public ChameleonFloatingActionButton(Context context) {
+ super(context);
+ }
+
+ public ChameleonFloatingActionButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public ChameleonFloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ public boolean isPostApplyTheme() {
+ return false;
+ }
+
+ @Nullable
+ @Override
+ public Appearance createAppearance(Context context, AttributeSet attributeSet, Chameleon.Theme theme) {
+ Appearance appearance = new Appearance();
+ ChameleonTypedArray a = ChameleonTypedArray.obtain(context, attributeSet,
+ R.styleable.ChameleonFloatingActionButton, theme);
+ appearance.backgroundTint = a.getColor(R.styleable.ChameleonFloatingActionButton_backgroundTint, theme.getColorAccent());
+ a.recycle();
+ return appearance;
+ }
+
+ @Override
+ public void applyAppearance(@NonNull ChameleonView.Appearance appearance) {
+ Appearance a = (Appearance) appearance;
+ setBackgroundTintList(ColorStateList.valueOf(a.backgroundTint));
+ }
+
+ public static class Appearance implements ChameleonView.Appearance {
+ int backgroundTint;
+ }
+
+}
diff --git a/chameleon/src/main/java/org/mariotaku/chameleon/view/ChameleonMultiAutoCompleteTextView.java b/chameleon/src/main/java/org/mariotaku/chameleon/view/ChameleonMultiAutoCompleteTextView.java
new file mode 100644
index 000000000..f2b28af75
--- /dev/null
+++ b/chameleon/src/main/java/org/mariotaku/chameleon/view/ChameleonMultiAutoCompleteTextView.java
@@ -0,0 +1,47 @@
+package org.mariotaku.chameleon.view;
+
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.AppCompatMultiAutoCompleteTextView;
+import android.util.AttributeSet;
+
+import org.mariotaku.chameleon.Chameleon;
+import org.mariotaku.chameleon.ChameleonView;
+
+/**
+ * Created by mariotaku on 2016/12/18.
+ */
+
+public class ChameleonMultiAutoCompleteTextView extends AppCompatMultiAutoCompleteTextView implements ChameleonView {
+ public ChameleonMultiAutoCompleteTextView(Context context) {
+ super(context);
+ }
+
+ public ChameleonMultiAutoCompleteTextView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public ChameleonMultiAutoCompleteTextView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ public boolean isPostApplyTheme() {
+ return false;
+ }
+
+ @Nullable
+ @Override
+ public ChameleonEditText.Appearance createAppearance(Context context, AttributeSet attributeSet, Chameleon.Theme theme) {
+ return ChameleonEditText.Appearance.create(context, attributeSet, theme);
+ }
+
+
+ @Override
+ public void applyAppearance(@NonNull ChameleonView.Appearance appearance) {
+ final ChameleonEditText.Appearance a = (ChameleonEditText.Appearance) appearance;
+ ChameleonEditText.Appearance.apply(this, a);
+ }
+
+}
diff --git a/chameleon/src/main/java/org/mariotaku/chameleon/view/ChameleonSwipeRefreshLayout.java b/chameleon/src/main/java/org/mariotaku/chameleon/view/ChameleonSwipeRefreshLayout.java
new file mode 100644
index 000000000..6ba0603dd
--- /dev/null
+++ b/chameleon/src/main/java/org/mariotaku/chameleon/view/ChameleonSwipeRefreshLayout.java
@@ -0,0 +1,52 @@
+package org.mariotaku.chameleon.view;
+
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.widget.SwipeRefreshLayout;
+import android.util.AttributeSet;
+
+import org.mariotaku.chameleon.Chameleon;
+import org.mariotaku.chameleon.ChameleonView;
+
+/**
+ * Created by mariotaku on 2016/12/18.
+ */
+
+public class ChameleonSwipeRefreshLayout extends SwipeRefreshLayout implements ChameleonView {
+
+ public ChameleonSwipeRefreshLayout(Context context) {
+ super(context);
+ }
+
+ public ChameleonSwipeRefreshLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public boolean isPostApplyTheme() {
+ return false;
+ }
+
+ @Nullable
+ @Override
+ public Appearance createAppearance(Context context, AttributeSet attributeSet, Chameleon.Theme theme) {
+ Appearance appearance = new Appearance();
+ appearance.indicatorColor = theme.getColorAccent();
+ appearance.progressBackgroundColor = theme.getColorBackground();
+ return appearance;
+ }
+
+
+ @Override
+ public void applyAppearance(@NonNull ChameleonView.Appearance appearance) {
+ final Appearance a = (Appearance) appearance;
+ setColorSchemeColors(a.indicatorColor);
+ setProgressBackgroundColorSchemeColor(a.progressBackgroundColor);
+ }
+
+ public static class Appearance implements ChameleonView.Appearance {
+ int indicatorColor;
+ int progressBackgroundColor;
+ }
+}
diff --git a/chameleon/src/main/java/org/mariotaku/chameleon/view/ChameleonTextView.java b/chameleon/src/main/java/org/mariotaku/chameleon/view/ChameleonTextView.java
new file mode 100644
index 000000000..3f4059f72
--- /dev/null
+++ b/chameleon/src/main/java/org/mariotaku/chameleon/view/ChameleonTextView.java
@@ -0,0 +1,65 @@
+package org.mariotaku.chameleon.view;
+
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.AppCompatTextView;
+import android.util.AttributeSet;
+
+import org.mariotaku.chameleon.Chameleon;
+import org.mariotaku.chameleon.ChameleonTypedArray;
+import org.mariotaku.chameleon.ChameleonView;
+import org.mariotaku.chameleon.R;
+
+/**
+ * Created by mariotaku on 2016/12/18.
+ */
+
+public class ChameleonTextView extends AppCompatTextView implements ChameleonView {
+ public ChameleonTextView(Context context) {
+ super(context);
+ }
+
+ public ChameleonTextView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public ChameleonTextView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ public boolean isPostApplyTheme() {
+ return false;
+ }
+
+ @Nullable
+ @Override
+ public Appearance createAppearance(Context context, AttributeSet attributeSet, Chameleon.Theme theme) {
+ Appearance appearance = new Appearance();
+ ChameleonTypedArray a = ChameleonTypedArray.obtain(context, attributeSet,
+ R.styleable.ChameleonTextView, theme);
+ appearance.setLinkTextColor(a.getColor(R.styleable.ChameleonTextView_android_textColorLink, theme.getColorAccent()));
+ a.recycle();
+ return appearance;
+ }
+
+
+ @Override
+ public void applyAppearance(@NonNull ChameleonView.Appearance appearance) {
+ final Appearance a = (Appearance) appearance;
+ setLinkTextColor(a.getLinkTextColor());
+ }
+
+ public static class Appearance implements ChameleonView.Appearance {
+ private int linkTextColor;
+
+ public int getLinkTextColor() {
+ return linkTextColor;
+ }
+
+ public void setLinkTextColor(int linkTextColor) {
+ this.linkTextColor = linkTextColor;
+ }
+ }
+}
diff --git a/chameleon/src/main/java/org/mariotaku/chameleon/view/ChameleonToolbar.java b/chameleon/src/main/java/org/mariotaku/chameleon/view/ChameleonToolbar.java
new file mode 100644
index 000000000..b06e5689c
--- /dev/null
+++ b/chameleon/src/main/java/org/mariotaku/chameleon/view/ChameleonToolbar.java
@@ -0,0 +1,94 @@
+package org.mariotaku.chameleon.view;
+
+import android.content.Context;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.Toolbar;
+import android.util.AttributeSet;
+
+import org.mariotaku.chameleon.Chameleon;
+import org.mariotaku.chameleon.ChameleonTypedArray;
+import org.mariotaku.chameleon.ChameleonView;
+import org.mariotaku.chameleon.R;
+
+/**
+ * Created by mariotaku on 2016/12/18.
+ */
+
+public class ChameleonToolbar extends Toolbar implements ChameleonView {
+ public ChameleonToolbar(Context context) {
+ super(context);
+ }
+
+ public ChameleonToolbar(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public ChameleonToolbar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ public boolean isPostApplyTheme() {
+ return false;
+ }
+
+ @Nullable
+ @Override
+ public Appearance createAppearance(Context context, AttributeSet attributeSet, Chameleon.Theme theme) {
+ Appearance appearance = new Appearance();
+ ChameleonTypedArray a = ChameleonTypedArray.obtain(context, attributeSet,
+ R.styleable.ChameleonToolbar, theme);
+ final Drawable background = a.getDrawable(R.styleable.ChameleonToolbar_android_background);
+ if (background != null) {
+ appearance.setBackground(background);
+ } else {
+ appearance.setBackground(new ColorDrawable(theme.getColorToolbar()));
+ }
+ appearance.setTitleTextColor(a.getColor(R.styleable.ChameleonToolbar_titleTextColor));
+ appearance.setSubTitleTextColor(a.getColor(R.styleable.ChameleonToolbar_subtitleTextColor));
+ a.recycle();
+ return appearance;
+ }
+
+ @Override
+ public void applyAppearance(@NonNull ChameleonView.Appearance appearance) {
+ Appearance a = (Appearance) appearance;
+ setBackgroundDrawable(a.getDrawable());
+ setTitleTextColor(a.getTitleTextColor());
+ setSubtitleTextColor(a.getSubTitleTextColor());
+ }
+
+ public static class Appearance implements ChameleonView.Appearance {
+
+ private int titleTextColor;
+ private int subTitleTextColor;
+ private Drawable background;
+
+ public void setTitleTextColor(int titleTextColor) {
+ this.titleTextColor = titleTextColor;
+ }
+
+ public int getTitleTextColor() {
+ return titleTextColor;
+ }
+
+ public void setSubTitleTextColor(int subTitleTextColor) {
+ this.subTitleTextColor = subTitleTextColor;
+ }
+
+ public int getSubTitleTextColor() {
+ return subTitleTextColor;
+ }
+
+ public void setBackground(Drawable background) {
+ this.background = background;
+ }
+
+ public Drawable getDrawable() {
+ return background;
+ }
+ }
+}
diff --git a/chameleon/src/main/res/values/attrs.xml b/chameleon/src/main/res/values/attrs.xml
new file mode 100644
index 000000000..def4cf391
--- /dev/null
+++ b/chameleon/src/main/res/values/attrs.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chameleon/src/main/res/values/colors.xml b/chameleon/src/main/res/values/colors.xml
new file mode 100644
index 000000000..3ae9fa08f
--- /dev/null
+++ b/chameleon/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #00100001
+ #00100002
+ #00100003
+
\ No newline at end of file
diff --git a/chameleon/src/test/java/org/mariotaku/chameleon/ExampleUnitTest.java b/chameleon/src/test/java/org/mariotaku/chameleon/ExampleUnitTest.java
new file mode 100644
index 000000000..253f3c2da
--- /dev/null
+++ b/chameleon/src/test/java/org/mariotaku/chameleon/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package org.mariotaku.chameleon;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index 5a0cacc22..12e0414fb 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,4 +1,4 @@
-include ':twidere'
+include ':twidere', ':chameleon'
include ':twidere.component.common'
include ':twidere.library.extension'
include ':twidere.wear'
diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/SharedPreferenceConstants.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/SharedPreferenceConstants.java
index f40cdb7e8..3b1412a1a 100644
--- a/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/SharedPreferenceConstants.java
+++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/SharedPreferenceConstants.java
@@ -73,10 +73,6 @@ public interface SharedPreferenceConstants {
String VALUE_TAB_DISPLAY_OPTION_ICON = "icon";
String VALUE_TAB_DISPLAY_OPTION_LABEL = "label";
String VALUE_TAB_DISPLAY_OPTION_BOTH = "both";
- int VALUE_TAB_DISPLAY_OPTION_CODE_LABEL = 0x1;
- int VALUE_TAB_DISPLAY_OPTION_CODE_ICON = 0x2;
- int VALUE_TAB_DISPLAY_OPTION_CODE_BOTH = VALUE_TAB_DISPLAY_OPTION_CODE_ICON
- | VALUE_TAB_DISPLAY_OPTION_CODE_LABEL;
String VALUE_THEME_BACKGROUND_DEFAULT = "default";
String VALUE_THEME_BACKGROUND_SOLID = "solid";
diff --git a/twidere/build.gradle b/twidere/build.gradle
index 91848bb0f..3e56ecc98 100644
--- a/twidere/build.gradle
+++ b/twidere/build.gradle
@@ -95,6 +95,7 @@ dependencies {
compile project(':twidere.component.common')
compile project(':twidere.component.nyan')
+ compile project(':chameleon')
// START Non-FOSS component
googleCompile "com.google.android.gms:play-services-maps:$play_services_version"
diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/KeyboardShortcutPreferenceCompatActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/KeyboardShortcutPreferenceCompatActivity.java
deleted file mode 100644
index ee83fb7f1..000000000
--- a/twidere/src/main/java/org/mariotaku/twidere/activity/KeyboardShortcutPreferenceCompatActivity.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Twidere - Twitter client for Android
- *
- * Copyright (C) 2012-2015 Mariotaku Lee
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package org.mariotaku.twidere.activity;
-
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.text.TextUtils;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.TextView;
-
-import org.mariotaku.twidere.R;
-import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
-import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutSpec;
-
-/**
- * Created by mariotaku on 15/4/20.
- */
-public class KeyboardShortcutPreferenceCompatActivity extends BaseActivity implements
- OnClickListener {
-
- public static final String EXTRA_CONTEXT_TAG = "context_tag";
- public static final String EXTRA_KEY_ACTION = "key_action";
-
- private TextView mKeysLabel, mConflictLabel;
-
- private KeyboardShortcutSpec mKeySpec;
- private Button mButtonPositive, mButtonNegative, mButtonNeutral;
- private int mMetaState;
-
- @NonNull
- @Override
- public String getThemeBackgroundOption() {
- return VALUE_THEME_BACKGROUND_DEFAULT;
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_keyboard_shortcut_input);
- setTitle(KeyboardShortcutsHandler.getActionLabel(this, getKeyAction()));
-
- mButtonPositive.setOnClickListener(this);
- mButtonNegative.setOnClickListener(this);
- mButtonNeutral.setOnClickListener(this);
- }
-
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.button_positive: {
- if (mKeySpec == null) return;
- keyboardShortcutsHandler.register(mKeySpec, getKeyAction());
- finish();
- break;
- }
- case R.id.button_neutral: {
- keyboardShortcutsHandler.unregister(getKeyAction());
- finish();
- break;
- }
- case R.id.button_negative: {
- finish();
- break;
- }
- }
- }
-
- @Override
- public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
- if (KeyEvent.isModifierKey(keyCode)) {
- mMetaState |= KeyboardShortcutsHandler.getMetaStateForKeyCode(keyCode);
- }
- return super.onKeyDown(keyCode, event);
- }
-
- @Override
- public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
- if (KeyEvent.isModifierKey(keyCode)) {
- mMetaState &= ~KeyboardShortcutsHandler.getMetaStateForKeyCode(keyCode);
- }
- final String keyAction = getKeyAction();
- if (keyAction == null) return false;
- final KeyboardShortcutSpec spec = KeyboardShortcutsHandler.getKeyboardShortcutSpec(getContextTag(),
- keyCode, event, KeyEvent.normalizeMetaState(mMetaState | event.getMetaState()));
- if (spec == null || !spec.isValid()) {
- return super.onKeyUp(keyCode, event);
- }
- mKeySpec = spec;
- mKeysLabel.setText(spec.toKeyString());
- final String oldAction = keyboardShortcutsHandler.findAction(spec);
- final KeyboardShortcutSpec copyOfSpec = spec.copy();
- copyOfSpec.setContextTag(null);
- final String oldGeneralAction = keyboardShortcutsHandler.findAction(copyOfSpec);
- if (!TextUtils.isEmpty(oldAction) && !keyAction.equals(oldAction)) {
- // Conflicts with keys in same context tag
- mConflictLabel.setVisibility(View.VISIBLE);
- final String label = KeyboardShortcutsHandler.getActionLabel(this, oldAction);
- mConflictLabel.setText(getString(R.string.conflicts_with_name, label));
- //noinspection UnnecessaryParentheses
- mButtonPositive.setText((R.string.overwrite));
- } else if (!TextUtils.isEmpty(oldGeneralAction) && !keyAction.equals(oldGeneralAction)) {
- // Conflicts with keys in root context
- mConflictLabel.setVisibility(View.VISIBLE);
- final String label = KeyboardShortcutsHandler.getActionLabel(this, oldGeneralAction);
- mConflictLabel.setText(getString(R.string.conflicts_with_name, label));
- mButtonPositive.setText((R.string.overwrite));
- } else {
- mConflictLabel.setVisibility(View.GONE);
- mButtonPositive.setText(android.R.string.ok);
- }
- return true;
- }
-
- @Override
- public void onContentChanged() {
- super.onContentChanged();
- mKeysLabel = (TextView) findViewById(R.id.keys_label);
- mConflictLabel = (TextView) findViewById(R.id.conflict_label);
- mButtonPositive = (Button) findViewById(R.id.button_positive);
- mButtonNegative = (Button) findViewById(R.id.button_negative);
- mButtonNeutral = (Button) findViewById(R.id.button_neutral);
- }
-
- private String getContextTag() {
- return getIntent().getStringExtra(EXTRA_CONTEXT_TAG);
- }
-
- private String getKeyAction() {
- return getIntent().getStringExtra(EXTRA_KEY_ACTION);
- }
-}
diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/UserListSelectorActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/UserListSelectorActivity.java
index db38f708d..6520f6fc6 100644
--- a/twidere/src/main/java/org/mariotaku/twidere/activity/UserListSelectorActivity.java
+++ b/twidere/src/main/java/org/mariotaku/twidere/activity/UserListSelectorActivity.java
@@ -64,6 +64,13 @@ import java.util.ArrayList;
import java.util.List;
import static android.text.TextUtils.isEmpty;
+import static org.mariotaku.twidere.TwidereConstants.LOGTAG;
+import static org.mariotaku.twidere.constant.IntentConstants.EXTRA_ACCOUNT_KEY;
+import static org.mariotaku.twidere.constant.IntentConstants.EXTRA_IS_MY_ACCOUNT;
+import static org.mariotaku.twidere.constant.IntentConstants.EXTRA_SCREEN_NAME;
+import static org.mariotaku.twidere.constant.IntentConstants.EXTRA_USER;
+import static org.mariotaku.twidere.constant.IntentConstants.EXTRA_USER_LIST;
+import static org.mariotaku.twidere.constant.IntentConstants.INTENT_ACTION_SELECT_USER;
import static org.mariotaku.twidere.util.DataStoreUtils.getAccountScreenName;
public class UserListSelectorActivity extends BaseActivity implements OnClickListener,
diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/KeyboardShortcutsFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/KeyboardShortcutsFragment.java
index 23d3f90fa..6d69144e9 100644
--- a/twidere/src/main/java/org/mariotaku/twidere/fragment/KeyboardShortcutsFragment.java
+++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/KeyboardShortcutsFragment.java
@@ -102,8 +102,8 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment implements
protected void onClick() {
final Context context = getContext();
final Intent intent = new Intent(context, KeyboardShortcutPreferenceCompatActivity.class);
- intent.putExtra(KeyboardShortcutPreferenceCompatActivity.EXTRA_CONTEXT_TAG, mContextTag);
- intent.putExtra(KeyboardShortcutPreferenceCompatActivity.EXTRA_KEY_ACTION, mAction);
+ intent.putExtra(KeyboardShortcutPreferenceCompatActivity.Companion.getEXTRA_CONTEXT_TAG(), mContextTag);
+ intent.putExtra(KeyboardShortcutPreferenceCompatActivity.Companion.getEXTRA_KEY_ACTION(), mAction);
context.startActivity(intent);
}
diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java b/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java
index 3d347b38f..e1f9b664d 100644
--- a/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java
+++ b/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java
@@ -128,6 +128,7 @@ import org.mariotaku.twidere.util.TwidereLinkify.HighlightStyle;
import org.mariotaku.twidere.view.CardMediaContainer.PreviewStyle;
import org.mariotaku.twidere.view.ShapedImageView;
import org.mariotaku.twidere.view.ShapedImageView.ShapeStyle;
+import org.mariotaku.twidere.view.TabPagerIndicator;
import java.io.Closeable;
import java.io.File;
@@ -807,10 +808,10 @@ public final class Utils implements Constants {
public static int getTabDisplayOptionInt(final String option) {
if (VALUE_TAB_DISPLAY_OPTION_ICON.equals(option))
- return VALUE_TAB_DISPLAY_OPTION_CODE_ICON;
+ return TabPagerIndicator.DisplayOption.ICON;
else if (VALUE_TAB_DISPLAY_OPTION_LABEL.equals(option))
- return VALUE_TAB_DISPLAY_OPTION_CODE_LABEL;
- return VALUE_TAB_DISPLAY_OPTION_CODE_BOTH;
+ return TabPagerIndicator.DisplayOption.LABEL;
+ return TabPagerIndicator.DisplayOption.BOTH;
}
public static boolean hasNavBar(@NonNull Context context) {
diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/ExtendedSwipeRefreshLayout.java b/twidere/src/main/java/org/mariotaku/twidere/view/ExtendedSwipeRefreshLayout.java
index 37b919eca..cad5459fe 100644
--- a/twidere/src/main/java/org/mariotaku/twidere/view/ExtendedSwipeRefreshLayout.java
+++ b/twidere/src/main/java/org/mariotaku/twidere/view/ExtendedSwipeRefreshLayout.java
@@ -22,16 +22,16 @@ package org.mariotaku.twidere.view;
import android.content.Context;
import android.graphics.Rect;
import android.support.annotation.NonNull;
-import android.support.v4.widget.SwipeRefreshLayout;
import android.util.AttributeSet;
import android.view.MotionEvent;
+import org.mariotaku.chameleon.view.ChameleonSwipeRefreshLayout;
import org.mariotaku.twidere.view.iface.IExtendedView;
/**
* Created by mariotaku on 15/4/25.
*/
-public class ExtendedSwipeRefreshLayout extends SwipeRefreshLayout implements IExtendedView {
+public class ExtendedSwipeRefreshLayout extends ChameleonSwipeRefreshLayout implements IExtendedView {
private TouchInterceptor mTouchInterceptor;
private OnSizeChangedListener mOnSizeChangedListener;
diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/HomeDrawerLayout.java b/twidere/src/main/java/org/mariotaku/twidere/view/HomeDrawerLayout.java
index a0ecfb7ac..761a6c204 100644
--- a/twidere/src/main/java/org/mariotaku/twidere/view/HomeDrawerLayout.java
+++ b/twidere/src/main/java/org/mariotaku/twidere/view/HomeDrawerLayout.java
@@ -1,15 +1,22 @@
package org.mariotaku.twidere.view;
import android.content.Context;
+import android.graphics.Color;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.util.AttributeSet;
import android.view.MotionEvent;
-public class HomeDrawerLayout extends DrawerLayout {
+import org.mariotaku.chameleon.Chameleon;
+import org.mariotaku.chameleon.ChameleonUtils;
+import org.mariotaku.chameleon.ChameleonView;
+import org.mariotaku.twidere.util.support.WindowSupport;
+
+public class HomeDrawerLayout extends DrawerLayout implements ChameleonView, ChameleonView.StatusBarThemeable {
private ShouldDisableDecider mShouldDisableDecider;
- private int state;
private int mStartLockMode, mEndLockMode;
public HomeDrawerLayout(Context context) {
@@ -49,6 +56,43 @@ public class HomeDrawerLayout extends DrawerLayout {
return super.dispatchTouchEvent(ev);
}
+ @Override
+ public boolean isPostApplyTheme() {
+ return false;
+ }
+
+ @Nullable
+ @Override
+ public Appearance createAppearance(Context context, AttributeSet attributeSet, Chameleon.Theme theme) {
+ Appearance appearance = new Appearance();
+ WindowSupport.setStatusBarColor(ChameleonUtils.getActivity(context).getWindow(), Color.TRANSPARENT);
+ appearance.setStatusBarBackgroundColor(ChameleonUtils.darkenColor(theme.getColorToolbar()));
+ return appearance;
+ }
+
+ @Override
+ public void applyAppearance(@NonNull ChameleonView.Appearance appearance) {
+ Appearance a = (Appearance) appearance;
+ setStatusBarBackgroundColor(a.getStatusBarBackgroundColor());
+ }
+
+ @Override
+ public boolean isStatusBarColorHandled() {
+ return true;
+ }
+
+ public static class Appearance implements ChameleonView.Appearance {
+ int statusBarBackgroundColor;
+
+ public int getStatusBarBackgroundColor() {
+ return statusBarBackgroundColor;
+ }
+
+ public void setStatusBarBackgroundColor(int statusBarBackgroundColor) {
+ this.statusBarBackgroundColor = statusBarBackgroundColor;
+ }
+ }
+
public interface ShouldDisableDecider {
boolean shouldDisableTouch(MotionEvent e);
}
diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/TabPagerIndicator.java b/twidere/src/main/java/org/mariotaku/twidere/view/TabPagerIndicator.java
index cc7644df8..4cf9e1344 100644
--- a/twidere/src/main/java/org/mariotaku/twidere/view/TabPagerIndicator.java
+++ b/twidere/src/main/java/org/mariotaku/twidere/view/TabPagerIndicator.java
@@ -4,10 +4,14 @@ import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
+import android.support.annotation.ColorInt;
import android.support.annotation.IntDef;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPager;
@@ -24,7 +28,9 @@ import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
-import org.mariotaku.twidere.Constants;
+import org.mariotaku.chameleon.Chameleon;
+import org.mariotaku.chameleon.ChameleonUtils;
+import org.mariotaku.chameleon.ChameleonView;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration;
import org.mariotaku.twidere.util.ThemeUtils;
@@ -36,11 +42,8 @@ import java.lang.annotation.RetentionPolicy;
/**
* Created by mariotaku on 14/10/21.
*/
-public class TabPagerIndicator extends RecyclerView implements PagerIndicator, Constants {
+public class TabPagerIndicator extends RecyclerView implements PagerIndicator, ChameleonView {
- public static final int LABEL = VALUE_TAB_DISPLAY_OPTION_CODE_LABEL;
- public static final int ICON = VALUE_TAB_DISPLAY_OPTION_CODE_ICON;
- public static final int BOTH = VALUE_TAB_DISPLAY_OPTION_CODE_BOTH;
private final int mStripHeight;
private final TabPagerIndicatorAdapter mIndicatorAdapter;
@@ -61,7 +64,7 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
mIndicatorAdapter = new TabPagerIndicatorAdapter(this);
mItemDecoration = new DividerItemDecoration(context, HORIZONTAL);
mStripHeight = res.getDimensionPixelSize(R.dimen.element_spacing_small);
- ViewCompat.setOverScrollMode(this, ViewCompat.OVER_SCROLL_NEVER);
+ setOverScrollMode(OVER_SCROLL_NEVER);
setHorizontalScrollBarEnabled(false);
setVerticalScrollBarEnabled(false);
setLayoutManager(mLayoutManager = new TabLayoutManager(context, this));
@@ -74,7 +77,8 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
setStripColor(a.getColor(R.styleable.TabPagerIndicator_tabStripColor, 0));
setIconColor(a.getColor(R.styleable.TabPagerIndicator_tabIconColor, 0));
setLabelColor(a.getColor(R.styleable.TabPagerIndicator_tabLabelColor, ThemeUtils.getTextColorPrimary(context)));
- setTabDisplayOption(a.getInt(R.styleable.TabPagerIndicator_tabDisplayOption, ICON));
+ //noinspection WrongConstant
+ setTabDisplayOption(a.getInt(R.styleable.TabPagerIndicator_tabDisplayOption, DisplayOption.ICON));
setTabShowDivider(a.getBoolean(R.styleable.TabPagerIndicator_tabShowDivider, false));
final int dividerVerticalPadding = a.getDimensionPixelSize(R.styleable.TabPagerIndicator_tabDividerVerticalPadding, 0);
final int dividerHorizontalPadding = a.getDimensionPixelSize(R.styleable.TabPagerIndicator_tabDividerHorizontalPadding, 0);
@@ -102,9 +106,6 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
return mIndicatorAdapter.getItemContext();
}
- public void getTabSpecs() {
- }
-
public void setColumns(int columns) {
mColumns = columns;
notifyDataSetChanged();
@@ -221,6 +222,43 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
mIndicatorAdapter.setTabProvider((TabProvider) adapter);
}
+ @Override
+ public boolean isPostApplyTheme() {
+ return false;
+ }
+
+ @Nullable
+ @Override
+ public Appearance createAppearance(Context context, AttributeSet attributeSet, Chameleon.Theme theme) {
+ final Appearance appearance = new Appearance();
+ final int toolbarColor = theme.getColorToolbar();
+ final boolean isLight = ChameleonUtils.isColorLight(toolbarColor);
+ final int itemColor = isLight ? Color.BLACK : Color.WHITE;
+ appearance.setLabelColor(itemColor);
+ appearance.setIconColor(itemColor);
+ if (theme.isToolbarColored()) {
+ appearance.setStripColor(itemColor);
+ } else {
+ appearance.setStripColor(theme.getColorAccent());
+ }
+ return appearance;
+ }
+
+ @Override
+ public void applyAppearance(@NonNull ChameleonView.Appearance appearance) {
+ Appearance a = (Appearance) appearance;
+ setIconColor(a.getIconColor());
+ setLabelColor(a.getLabelColor());
+ setStripColor(a.getStripColor());
+ updateAppearance();
+ }
+
+ public void updateAppearance() {
+ final int positionStart = mLayoutManager.findFirstVisibleItemPosition();
+ final int itemCount = mLayoutManager.findLastVisibleItemPosition() - positionStart + 1;
+ mIndicatorAdapter.notifyItemRangeChanged(positionStart, itemCount);
+ }
+
private int getTabHorizontalPadding() {
return mHorizontalPadding;
}
@@ -230,11 +268,11 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
}
private boolean isIconDisplayed() {
- return (mOption & ICON) != 0;
+ return (mOption & DisplayOption.ICON) != 0;
}
private boolean isLabelDisplayed() {
- return (mOption & LABEL) != 0;
+ return (mOption & DisplayOption.LABEL) != 0;
}
private boolean isTabExpandEnabled() {
@@ -261,9 +299,56 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
mVerticalPadding = padding;
}
- @IntDef({ICON, LABEL, BOTH})
+ private boolean isTabSelected(int position) {
+ final int current = getCurrentItem();
+ final int columns = getColumns();
+ final int count = getCount();
+ if (current + columns > count) {
+ return position >= count - columns;
+ }
+ return position >= current && position < current + columns;
+ }
+
+ private int getColumns() {
+ if (mColumns > 0) return mColumns;
+ return 1;
+ }
+
+ public static class Appearance implements ChameleonView.Appearance {
+ @ColorInt
+ int iconColor, labelColor, stripColor;
+
+ public int getIconColor() {
+ return iconColor;
+ }
+
+ public void setIconColor(int iconColor) {
+ this.iconColor = iconColor;
+ }
+
+ public int getLabelColor() {
+ return labelColor;
+ }
+
+ public void setLabelColor(int labelColor) {
+ this.labelColor = labelColor;
+ }
+
+ public int getStripColor() {
+ return stripColor;
+ }
+
+ public void setStripColor(int stripColor) {
+ this.stripColor = stripColor;
+ }
+ }
+
+ @IntDef({DisplayOption.ICON, DisplayOption.LABEL, DisplayOption.BOTH})
@Retention(RetentionPolicy.SOURCE)
public @interface DisplayOption {
+ int LABEL = 0x1;
+ int ICON = 0x2;
+ int BOTH = LABEL | ICON;
}
public static final class SampleView extends LinearLayout {
@@ -299,7 +384,7 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
this.setStripColor(a.getColor(R.styleable.TabPagerIndicator_tabStripColor, 0));
this.setIconColor(a.getColor(R.styleable.TabPagerIndicator_tabIconColor, 0));
this.setLabelColor(a.getColor(R.styleable.TabPagerIndicator_tabLabelColor, ThemeUtils.getTextColorPrimary(context)));
- this.setTabDisplayOption(a.getInt(R.styleable.TabPagerIndicator_tabDisplayOption, ICON));
+ this.setTabDisplayOption(a.getInt(R.styleable.TabPagerIndicator_tabDisplayOption, DisplayOption.ICON));
this.setTabShowDivider(a.getBoolean(R.styleable.TabPagerIndicator_tabShowDivider, false));
a.recycle();
@@ -346,11 +431,11 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
tabIcon.setImageResource(icon);
tabIcon.setColorFilter(iconColor, PorterDuff.Mode.SRC_ATOP);
- tabIcon.setVisibility((tabDisplayOption & ICON) != 0 ? VISIBLE : GONE);
+ tabIcon.setVisibility((tabDisplayOption & DisplayOption.ICON) != 0 ? VISIBLE : GONE);
tabLabel.setText(label);
tabLabel.setTextColor(labelColor);
- tabLabel.setVisibility((tabDisplayOption & LABEL) != 0 ? VISIBLE : GONE);
+ tabLabel.setVisibility((tabDisplayOption & DisplayOption.LABEL) != 0 ? VISIBLE : GONE);
badgeView.setText(String.valueOf(unread));
badgeView.setVisibility(unread != 0 ? VISIBLE : GONE);
@@ -420,7 +505,7 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
private final TextView labelView;
private final BadgeView badgeView;
- public TabItemHolder(TabPagerIndicator indicator, View itemView) {
+ TabItemHolder(TabPagerIndicator indicator, View itemView) {
super(itemView);
this.indicator = indicator;
this.itemView = (ItemLayout) itemView;
@@ -443,17 +528,17 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
return indicator.dispatchTabLongClick(position);
}
- public void setBadge(int count, boolean display) {
+ void setBadge(int count, boolean display) {
badgeView.setText(String.valueOf(count));
badgeView.setVisibility(display && count > 0 ? VISIBLE : GONE);
}
- public void setDisplayOption(boolean iconDisplayed, boolean labelDisplayed) {
+ void setDisplayOption(boolean iconDisplayed, boolean labelDisplayed) {
iconView.setVisibility(iconDisplayed ? VISIBLE : GONE);
labelView.setVisibility(labelDisplayed ? VISIBLE : GONE);
}
- public void setIconColor(int color) {
+ void setIconColor(int color) {
if (color != 0) {
iconView.setColorFilter(color);
} else {
@@ -461,23 +546,23 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
}
}
- public void setLabelColor(int color) {
+ void setLabelColor(int color) {
labelView.setTextColor(color);
}
- public void setPadding(int horizontalPadding, int verticalPadding) {
+ void setPadding(int horizontalPadding, int verticalPadding) {
itemView.setPadding(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding);
}
- public void setStripColor(int color) {
+ void setStripColor(int color) {
itemView.setStripColor(color);
}
- public void setStripHeight(int stripHeight) {
+ void setStripHeight(int stripHeight) {
itemView.setStripHeight(stripHeight);
}
- public void setTabData(Drawable icon, CharSequence title, boolean activated) {
+ void setTabData(Drawable icon, CharSequence title, boolean activated) {
itemView.setContentDescription(title);
iconView.setImageDrawable(icon);
labelView.setText(title);
@@ -490,7 +575,7 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
private boolean mTabExpandEnabled;
private final RecyclerView mRecyclerView;
- public TabLayoutManager(Context context, RecyclerView recyclerView) {
+ TabLayoutManager(Context context, RecyclerView recyclerView) {
super(context, HORIZONTAL, false);
mRecyclerView = recyclerView;
setAutoMeasureEnabled(true);
@@ -518,21 +603,15 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
return false;
}
- public boolean isTabExpandEnabled() {
+ boolean isTabExpandEnabled() {
return mTabExpandEnabled;
}
- public void setTabExpandEnabled(boolean tabExpandEnabled) {
+ void setTabExpandEnabled(boolean tabExpandEnabled) {
mTabExpandEnabled = tabExpandEnabled;
}
}
- public void updateAppearance() {
- final int positionStart = mLayoutManager.findFirstVisibleItemPosition();
- final int itemCount = mLayoutManager.findLastVisibleItemPosition() - positionStart + 1;
- mIndicatorAdapter.notifyItemRangeChanged(positionStart, itemCount);
- }
-
private static class TabPagerIndicatorAdapter extends Adapter {
private final TabPagerIndicator mIndicator;
@@ -544,16 +623,16 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
private int mStripColor, mIconColor, mLabelColor;
private boolean mDisplayBadge;
- public TabPagerIndicatorAdapter(TabPagerIndicator indicator) {
+ TabPagerIndicatorAdapter(TabPagerIndicator indicator) {
mIndicator = indicator;
mUnreadCounts = new SparseIntArray();
}
- public Context getItemContext() {
+ Context getItemContext() {
return mItemContext;
}
- public void setItemContext(Context itemContext) {
+ void setItemContext(Context itemContext) {
mItemContext = itemContext;
mInflater = LayoutInflater.from(itemContext);
}
@@ -587,49 +666,34 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
return mTabProvider.getCount();
}
- public void setBadge(int position, int count) {
+ void setBadge(int position, int count) {
mUnreadCounts.put(position, count);
notifyItemChanged(position);
}
- public void clearBadge() {
+ void clearBadge() {
mUnreadCounts.clear();
notifyDataSetChanged();
}
- public void setDisplayBadge(boolean display) {
+ void setDisplayBadge(boolean display) {
mDisplayBadge = display;
}
- public void setIconColor(int color) {
+ void setIconColor(int color) {
mIconColor = color;
}
- public void setLabelColor(int color) {
+ void setLabelColor(int color) {
mLabelColor = color;
}
- public void setStripColor(int color) {
+ void setStripColor(int color) {
mStripColor = color;
}
- public void setTabProvider(TabProvider tabProvider) {
+ void setTabProvider(TabProvider tabProvider) {
mTabProvider = tabProvider;
}
}
-
- private boolean isTabSelected(int position) {
- final int current = getCurrentItem();
- final int columns = getColumns();
- final int count = getCount();
- if (current + columns > count) {
- return position >= count - columns;
- }
- return position >= current && position < current + columns;
- }
-
- private int getColumns() {
- if (mColumns > 0) return mColumns;
- return 1;
- }
}
diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/TintedStatusFrameLayout.java b/twidere/src/main/java/org/mariotaku/twidere/view/TintedStatusFrameLayout.java
index 76ad43609..db049a22a 100644
--- a/twidere/src/main/java/org/mariotaku/twidere/view/TintedStatusFrameLayout.java
+++ b/twidere/src/main/java/org/mariotaku/twidere/view/TintedStatusFrameLayout.java
@@ -27,18 +27,23 @@ import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Build;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.WindowInsetsCompat;
import android.util.AttributeSet;
import android.view.View;
+import org.mariotaku.chameleon.Chameleon;
+import org.mariotaku.chameleon.ChameleonUtils;
+import org.mariotaku.chameleon.ChameleonView;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.view.iface.TintedStatusLayout;
/**
* Created by mariotaku on 14/11/26.
*/
-public class TintedStatusFrameLayout extends ExtendedFrameLayout implements TintedStatusLayout {
+public class TintedStatusFrameLayout extends ExtendedFrameLayout implements TintedStatusLayout,
+ ChameleonView, ChameleonView.StatusBarThemeable {
private final Paint mColorPaint;
private boolean mSetPadding;
@@ -119,6 +124,42 @@ public class TintedStatusFrameLayout extends ExtendedFrameLayout implements Tint
mWindowInsetsListener = listener;
}
+ @Override
+ public boolean isPostApplyTheme() {
+ return false;
+ }
+
+ @Nullable
+ @Override
+ public Appearance createAppearance(Context context, AttributeSet attributeSet, Chameleon.Theme theme) {
+ Appearance appearance = new Appearance();
+ appearance.setColor(ChameleonUtils.darkenColor(theme.getColorToolbar()));
+ return appearance;
+ }
+
+ @Override
+ public void applyAppearance(@NonNull ChameleonView.Appearance appearance) {
+ Appearance a = (Appearance) appearance;
+ setStatusBarColor(a.getColor());
+ }
+
+ @Override
+ public boolean isStatusBarColorHandled() {
+ return true;
+ }
+
+ public static class Appearance implements ChameleonView.Appearance {
+ int color;
+
+ public int getColor() {
+ return color;
+ }
+
+ public void setColor(int color) {
+ this.color = color;
+ }
+ }
+
public interface WindowInsetsListener {
void onApplyWindowInsets(int left, int top, int right, int bottom);
}
diff --git a/twidere/src/main/kotlin/org/mariotaku/chameleon/Chameleon.java b/twidere/src/main/kotlin/org/mariotaku/chameleon/Chameleon.java
deleted file mode 100644
index bf1de53cd..000000000
--- a/twidere/src/main/kotlin/org/mariotaku/chameleon/Chameleon.java
+++ /dev/null
@@ -1,124 +0,0 @@
-package org.mariotaku.chameleon;
-
-import android.app.Activity;
-import android.content.Context;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.view.LayoutInflaterCompat;
-import android.view.LayoutInflater;
-
-import org.mariotaku.chameleon.internal.ChameleonInflationFactory;
-
-/**
- * Created by mariotaku on 2016/12/18.
- */
-
-public class Chameleon {
-
- private final Activity activity;
-
- private Chameleon(Activity activity) {
- this.activity = activity;
- }
-
- public static Chameleon getInstance(Activity activity) {
- return new Chameleon(activity);
- }
-
- public void preApply() {
- final LayoutInflater inflater = activity.getLayoutInflater();
- final ChameleonInflationFactory factory = new ChameleonInflationFactory();
- LayoutInflaterCompat.setFactory(inflater, factory);
- }
-
- public void postApply() {
-
- }
-
- public void invalidateActivity() {
-
- }
-
- public void cleanUp() {
-
- }
-
- public void themeOverflow() {
-
- }
-
- @NonNull
- public static Theme getOverrideTheme(Context context, Object obj) {
- if (obj instanceof Themeable) {
- return ((Themeable) obj).getOverrideTheme();
- }
- return Theme.from(context);
- }
-
- /**
- * Created by mariotaku on 2016/12/18.
- */
-
- public static class Theme {
- int primaryColor;
- int accentColor;
- int toolbarColor;
- boolean toolbarColored;
- int textColorPrimary;
-
- public int getAccentColor() {
- return accentColor;
- }
-
- public void setAccentColor(int accentColor) {
- this.accentColor = accentColor;
- }
-
- public int getPrimaryColor() {
- return primaryColor;
- }
-
- public void setPrimaryColor(int primaryColor) {
- this.primaryColor = primaryColor;
- }
-
- public int getToolbarColor() {
- return toolbarColor;
- }
-
- public void setToolbarColor(int toolbarColor) {
- this.toolbarColor = toolbarColor;
- }
-
- public boolean isToolbarColored() {
- return toolbarColored;
- }
-
- public void setToolbarColored(boolean toolbarColored) {
- this.toolbarColored = toolbarColored;
- }
-
- public int getTextColorPrimary() {
- return textColorPrimary;
- }
-
- public void setTextColorPrimary(int textColorPrimary) {
- this.textColorPrimary = textColorPrimary;
- }
-
- @NonNull
- public static Theme from(Context context) {
- Theme theme = new Theme();
- return theme;
- }
- }
-
- /**
- * Created by mariotaku on 2016/12/18.
- */
-
- public interface Themeable {
- @Nullable
- Theme getOverrideTheme();
- }
-}
diff --git a/twidere/src/main/kotlin/org/mariotaku/chameleon/internal/ChameleonInflationFactory.java b/twidere/src/main/kotlin/org/mariotaku/chameleon/internal/ChameleonInflationFactory.java
deleted file mode 100644
index fe8a0ab7a..000000000
--- a/twidere/src/main/kotlin/org/mariotaku/chameleon/internal/ChameleonInflationFactory.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.mariotaku.chameleon.internal;
-
-import android.content.Context;
-import android.support.v4.view.LayoutInflaterFactory;
-import android.util.AttributeSet;
-import android.view.View;
-
-/**
- * Created by mariotaku on 2016/12/18.
- */
-
-public class ChameleonInflationFactory implements LayoutInflaterFactory {
- @Override
- public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
- return null;
- }
-}
diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/BaseActivity.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/BaseActivity.kt
index a0dd84eed..5d5d8e6d7 100644
--- a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/BaseActivity.kt
+++ b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/BaseActivity.kt
@@ -42,7 +42,6 @@ import org.mariotaku.chameleon.Chameleon
import org.mariotaku.chameleon.ChameleonActivity
import org.mariotaku.kpreferences.KPreferences
import org.mariotaku.twidere.BuildConfig
-import org.mariotaku.twidere.Constants
import org.mariotaku.twidere.TwidereConstants.SHARED_PREFERENCES_NAME
import org.mariotaku.twidere.activity.iface.IControlBarActivity
import org.mariotaku.twidere.activity.iface.IExtendedActivity
@@ -58,7 +57,7 @@ import java.util.*
import javax.inject.Inject
@SuppressLint("Registered")
-open class BaseActivity : ChameleonActivity(), Constants, IExtendedActivity, IThemedActivity,
+open class BaseActivity : ChameleonActivity(), IExtendedActivity, IThemedActivity,
IControlBarActivity, OnFitSystemWindowsListener, SystemWindowsInsetsCallback,
KeyboardShortcutCallback, OnPreferenceDisplayDialogCallback {
@Inject
@@ -341,7 +340,13 @@ open class BaseActivity : ChameleonActivity(), Constants, IExtendedActivity, ITh
}
override fun getOverrideTheme(): Chameleon.Theme {
- return Chameleon.Theme()
+ val theme = Chameleon.Theme.from(this)
+ theme.colorAccent = ThemeUtils.getUserAccentColor(this)
+ theme.colorPrimary = ThemeUtils.getUserAccentColor(this)
+ if (theme.isToolbarColored) {
+ theme.colorToolbar = theme.colorPrimary
+ }
+ return theme
}
companion object {
diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/HomeActivity.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/HomeActivity.kt
index 1c974a2cb..d32103402 100644
--- a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/HomeActivity.kt
+++ b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/HomeActivity.kt
@@ -341,10 +341,10 @@ class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, Supp
mainTabs.setOnPageChangeListener(this)
mainTabs.setColumns(tabColumns)
if (tabDisplayOptionInt == 0) {
- tabDisplayOptionInt = TabPagerIndicator.ICON
+ tabDisplayOptionInt = TabPagerIndicator.DisplayOption.ICON
}
mainTabs.setTabDisplayOption(tabDisplayOptionInt)
- mainTabs.setTabExpandEnabled(tabDisplayOptionInt and TabPagerIndicator.LABEL == 0)
+ mainTabs.setTabExpandEnabled(tabDisplayOptionInt and TabPagerIndicator.DisplayOption.LABEL == 0)
mainTabs.setDisplayBadge(preferences.getBoolean(SharedPreferenceConstants.KEY_UNREAD_COUNT, true))
mainTabs.updateAppearance()
diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/KeyboardShortcutPreferenceCompatActivity.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/KeyboardShortcutPreferenceCompatActivity.kt
new file mode 100644
index 000000000..786cbeac4
--- /dev/null
+++ b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/KeyboardShortcutPreferenceCompatActivity.kt
@@ -0,0 +1,125 @@
+/*
+ * Twidere - Twitter client for Android
+ *
+ * Copyright (C) 2012-2015 Mariotaku Lee
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package org.mariotaku.twidere.activity
+
+import android.os.Bundle
+import android.text.TextUtils
+import android.view.KeyEvent
+import android.view.View
+import android.view.View.OnClickListener
+import kotlinx.android.synthetic.main.activity_keyboard_shortcut_input.*
+import org.mariotaku.twidere.R
+import org.mariotaku.twidere.constant.SharedPreferenceConstants.VALUE_THEME_BACKGROUND_DEFAULT
+import org.mariotaku.twidere.util.KeyboardShortcutsHandler
+import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutSpec
+
+/**
+ * Created by mariotaku on 15/4/20.
+ */
+class KeyboardShortcutPreferenceCompatActivity : BaseActivity(), OnClickListener {
+
+ private var keySpec: KeyboardShortcutSpec? = null
+ private var metaState: Int = 0
+
+ override val themeBackgroundOption: String
+ get() = VALUE_THEME_BACKGROUND_DEFAULT
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_keyboard_shortcut_input)
+ title = KeyboardShortcutsHandler.getActionLabel(this, keyAction)
+
+ buttonPositive.setOnClickListener(this)
+ buttonNegative.setOnClickListener(this)
+ buttonNeutral.setOnClickListener(this)
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.buttonPositive -> {
+ if (keySpec == null) return
+ keyboardShortcutsHandler.register(keySpec, keyAction)
+ finish()
+ }
+ R.id.buttonNeutral -> {
+ keyboardShortcutsHandler.unregister(keyAction)
+ finish()
+ }
+ R.id.buttonNegative -> {
+ finish()
+ }
+ }
+ }
+
+ override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
+ if (KeyEvent.isModifierKey(keyCode)) {
+ metaState = metaState or KeyboardShortcutsHandler.getMetaStateForKeyCode(keyCode)
+ }
+ return super.onKeyDown(keyCode, event)
+ }
+
+ override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean {
+ if (KeyEvent.isModifierKey(keyCode)) {
+ metaState = metaState and KeyboardShortcutsHandler.getMetaStateForKeyCode(keyCode).inv()
+ }
+ val keyAction = keyAction ?: return false
+ val spec = KeyboardShortcutsHandler.getKeyboardShortcutSpec(contextTag,
+ keyCode, event, KeyEvent.normalizeMetaState(metaState or event.metaState))
+ if (spec == null || !spec.isValid) {
+ return super.onKeyUp(keyCode, event)
+ }
+ keySpec = spec
+ keysLabel.text = spec.toKeyString()
+ val oldAction = keyboardShortcutsHandler.findAction(spec)
+ val copyOfSpec = spec.copy()
+ copyOfSpec.contextTag = null
+ val oldGeneralAction = keyboardShortcutsHandler.findAction(copyOfSpec)
+ if (!TextUtils.isEmpty(oldAction) && keyAction != oldAction) {
+ // Conflicts with keys in same context tag
+ conflictLabel.visibility = View.VISIBLE
+ val label = KeyboardShortcutsHandler.getActionLabel(this, oldAction)
+ conflictLabel.text = getString(R.string.conflicts_with_name, label)
+
+ buttonPositive.setText(R.string.overwrite)
+ } else if (!TextUtils.isEmpty(oldGeneralAction) && keyAction != oldGeneralAction) {
+ // Conflicts with keys in root context
+ conflictLabel.visibility = View.VISIBLE
+ val label = KeyboardShortcutsHandler.getActionLabel(this, oldGeneralAction)
+ conflictLabel.text = getString(R.string.conflicts_with_name, label)
+ buttonPositive.setText(R.string.overwrite)
+ } else {
+ conflictLabel.visibility = View.GONE
+ buttonPositive.setText(android.R.string.ok)
+ }
+ return true
+ }
+
+ private val contextTag: String
+ get() = intent.getStringExtra(EXTRA_CONTEXT_TAG)
+
+ private val keyAction: String?
+ get() = intent.getStringExtra(EXTRA_KEY_ACTION)
+
+ companion object {
+
+ val EXTRA_CONTEXT_TAG = "context_tag"
+ val EXTRA_KEY_ACTION = "key_action"
+ }
+}
diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsToolbarTabPagesFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsToolbarTabPagesFragment.kt
index 2c138f5d9..3c30f39e8 100644
--- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsToolbarTabPagesFragment.kt
+++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsToolbarTabPagesFragment.kt
@@ -48,7 +48,7 @@ abstract class AbsToolbarTabPagesFragment : BaseSupportFragment(), RefreshScroll
viewPager.offscreenPageLimit = 2
viewPager.addOnPageChangeListener(this)
toolbarTabs.setViewPager(viewPager)
- toolbarTabs.setTabDisplayOption(TabPagerIndicator.LABEL)
+ toolbarTabs.setTabDisplayOption(TabPagerIndicator.DisplayOption.LABEL)
addTabs(pagerAdapter!!)
diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/UserFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/UserFragment.kt
index 5c63a5db7..471670db1 100644
--- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/UserFragment.kt
+++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/UserFragment.kt
@@ -79,6 +79,7 @@ import nl.komponents.kovenant.ui.promiseOnUi
import nl.komponents.kovenant.ui.successUi
import org.apache.commons.lang3.ObjectUtils
import org.mariotaku.chameleon.Chameleon
+import org.mariotaku.chameleon.ChameleonUtils
import org.mariotaku.ktextension.Bundle
import org.mariotaku.ktextension.empty
import org.mariotaku.ktextension.set
@@ -430,7 +431,7 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
profileImage.visibility = View.GONE
profileType.visibility = View.GONE
val theme = Chameleon.getOverrideTheme(activity, activity)
- setUiColor(theme.primaryColor)
+ setUiColor(theme.colorPrimary)
return
}
val adapter = pagerAdapter
@@ -496,7 +497,7 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
setUiColor(user.link_color)
} else {
val theme = Chameleon.getOverrideTheme(activity, activity)
- setUiColor(theme.primaryColor)
+ setUiColor(theme.colorPrimary)
}
val defWidth = resources.displayMetrics.widthPixels
val width = if (bannerWidth > 0) bannerWidth else defWidth
@@ -678,7 +679,7 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
viewPager.offscreenPageLimit = 3
viewPager.adapter = pagerAdapter
toolbarTabs.setViewPager(viewPager)
- toolbarTabs.setTabDisplayOption(TabPagerIndicator.LABEL)
+ toolbarTabs.setTabDisplayOption(TabPagerIndicator.DisplayOption.LABEL)
toolbarTabs.setOnPageChangeListener(this)
followContainer.follow.setOnClickListener(this)
@@ -1277,15 +1278,12 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
}
val activity = activity as BaseActivity
val theme = Chameleon.getOverrideTheme(activity, activity)
- primaryColor = theme.primaryColor
- primaryColorDark = ThemeUtils.computeDarkColor(primaryColor)
if (theme.isToolbarColored) {
primaryColor = color
- primaryColorDark = ThemeUtils.computeDarkColor(color)
} else {
- primaryColor = theme.primaryColor
- primaryColorDark = Color.BLACK
+ primaryColor = theme.colorToolbar
}
+ primaryColorDark = ChameleonUtils.darkenColor(primaryColor)
if (actionBarBackground != null) {
actionBarBackground!!.color = primaryColor
}
@@ -1293,7 +1291,7 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
if (theme.isToolbarColored) {
taskColor = color
} else {
- taskColor = theme.toolbarColor
+ taskColor = theme.colorToolbar
}
if (user != null) {
val name = userColorNameManager.getDisplayName(user, nameFirst)
diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/view/ComposeEditText.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/view/ComposeEditText.kt
index e3a080104..aafcd05a9 100644
--- a/twidere/src/main/kotlin/org/mariotaku/twidere/view/ComposeEditText.kt
+++ b/twidere/src/main/kotlin/org/mariotaku/twidere/view/ComposeEditText.kt
@@ -20,13 +20,13 @@
package org.mariotaku.twidere.view
import android.content.Context
-import android.support.v7.widget.AppCompatMultiAutoCompleteTextView
import android.text.InputType
import android.text.Selection
import android.text.method.ArrowKeyMovementMethod
import android.text.method.MovementMethod
import android.util.AttributeSet
import android.widget.AdapterView
+import org.mariotaku.chameleon.view.ChameleonMultiAutoCompleteTextView
import org.mariotaku.twidere.adapter.ComposeAutoCompleteAdapter
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.util.EmojiSupportUtils
@@ -35,7 +35,7 @@ import org.mariotaku.twidere.util.widget.StatusTextTokenizer
class ComposeEditText @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
-) : AppCompatMultiAutoCompleteTextView(context, attrs) {
+) : ChameleonMultiAutoCompleteTextView(context, attrs) {
private var adapter: ComposeAutoCompleteAdapter? = null
var accountKey: UserKey? = null
diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/view/TimelineContentTextView.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/view/TimelineContentTextView.kt
index b902379a5..cd270c38c 100644
--- a/twidere/src/main/kotlin/org/mariotaku/twidere/view/TimelineContentTextView.kt
+++ b/twidere/src/main/kotlin/org/mariotaku/twidere/view/TimelineContentTextView.kt
@@ -20,7 +20,6 @@
package org.mariotaku.twidere.view
import android.content.Context
-import android.support.v7.widget.AppCompatTextView
import android.text.Spannable
import android.text.method.MovementMethod
import android.text.style.ClickableSpan
@@ -28,23 +27,20 @@ import android.util.AttributeSet
import android.view.KeyEvent
import android.view.MotionEvent
import android.widget.TextView
+import org.mariotaku.chameleon.view.ChameleonTextView
import org.mariotaku.twidere.util.EmojiSupportUtils
/**
* Returns true when not clicking links
* Created by mariotaku on 15/11/20.
*/
-class TimelineContentTextView : AppCompatTextView {
+class TimelineContentTextView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyle: Int = 0
+) : ChameleonTextView(context, attrs, defStyle) {
- constructor(context: Context) : super(context) {
- EmojiSupportUtils.initForTextView(this)
- }
-
- constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
- EmojiSupportUtils.initForTextView(this)
- }
-
- constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
+ init {
EmojiSupportUtils.initForTextView(this)
}
diff --git a/twidere/src/main/res/layout/activity_home_content.xml b/twidere/src/main/res/layout/activity_home_content.xml
index db17a67bd..d99a29d59 100644
--- a/twidere/src/main/res/layout/activity_home_content.xml
+++ b/twidere/src/main/res/layout/activity_home_content.xml
@@ -38,7 +38,6 @@
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:layout_alignParentTop="true"
- android:background="?colorPrimary"
android:elevation="@dimen/toolbar_elevation"
app:contentInsetEnd="0dp"
app:contentInsetStart="0dp">
@@ -87,7 +86,7 @@
android:layout_margin="@dimen/element_spacing_large"
android:clickable="true"
android:src="@drawable/ic_action_status_compose"
- android:tag="background|primary_color,tint|primary_color_dependent"
+ app:backgroundTint="?colorToolbar"
app:elevation="6dp"
app:pressedTranslationZ="12dp"/>
diff --git a/twidere/src/main/res/layout/activity_keyboard_shortcut_input.xml b/twidere/src/main/res/layout/activity_keyboard_shortcut_input.xml
index 2f481cf32..dd38096cb 100644
--- a/twidere/src/main/res/layout/activity_keyboard_shortcut_input.xml
+++ b/twidere/src/main/res/layout/activity_keyboard_shortcut_input.xml
@@ -19,13 +19,13 @@
~ along with this program. If not, see .
-->
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:divider="?android:attr/dividerHorizontal"
+ android:dividerPadding="0dip"
+ android:orientation="vertical"
+ android:showDividers="middle">
+ android:textAppearance="?android:textAppearanceMedium"/>
+ android:visibility="gone"/>
@@ -61,7 +61,7 @@
tools:ignore="UselessParent">
+ android:textSize="14sp"/>
+ android:textSize="14sp"/>
+ android:textSize="14sp"/>
\ No newline at end of file
diff --git a/twidere/src/main/res/values-notnight/themes.xml b/twidere/src/main/res/values-notnight/themes.xml
index b27ecd78e..b63da98f5 100644
--- a/twidere/src/main/res/values-notnight/themes.xml
+++ b/twidere/src/main/res/values-notnight/themes.xml
@@ -19,8 +19,8 @@
- @color/quote_indicator_background_light
- #dddddd
-
- - light
+ - ?colorPrimary
+ - true
- @null
- @style/PreferenceThemeOverlay.v14.Material
@@ -47,8 +47,8 @@
- @color/message_bubble_color_light
- @color/quote_indicator_background_light
-
- - light
+ - ?colorPrimary
+ - true
- @null
- @style/PreferenceThemeOverlay.v14.Material
@@ -74,8 +74,8 @@
- @color/message_bubble_color_light
- @color/quote_indicator_background_light
-
- - light
+ - ?colorPrimary
+ - true
- @null
- @style/PreferenceThemeOverlay.v14.Material
diff --git a/twidere/src/main/res/values/attrs.xml b/twidere/src/main/res/values/attrs.xml
index 0650b50ee..b2cbab4bb 100644
--- a/twidere/src/main/res/values/attrs.xml
+++ b/twidere/src/main/res/values/attrs.xml
@@ -13,8 +13,8 @@
-
+
diff --git a/twidere/src/main/res/values/themes.xml b/twidere/src/main/res/values/themes.xml
index 4e11fd910..b7cc65516 100644
--- a/twidere/src/main/res/values/themes.xml
+++ b/twidere/src/main/res/values/themes.xml
@@ -20,8 +20,8 @@
- @color/quote_indicator_background_dark
- #505050
-
- - dark
+ - @color/background_color_action_bar_dark
+ - false
- @null
- @style/PreferenceThemeOverlay.v14.Material
@@ -55,8 +55,8 @@
- @color/message_bubble_color_dark
- @color/quote_indicator_background_dark
-
- - dark
+ - @color/background_color_action_bar_dark
+ - false
- @null
- @style/PreferenceThemeOverlay.v14.Material
@@ -84,8 +84,8 @@
- @color/message_bubble_color_dark
- @color/quote_indicator_background_dark
-
- - dark
+ - @color/background_color_action_bar_dark
+ - false
- @null
- @style/PreferenceThemeOverlay.v14.Material
@@ -154,8 +154,8 @@
- @color/message_bubble_color_dark
- @color/quote_indicator_background_dark
-
- - dark
+ - @color/background_color_action_bar_dark
+ - false
- @null
- @style/PreferenceThemeOverlay.v14.Material