developing chameleon theme library - this library will be released in Apache license later
This commit is contained in:
parent
ebc79bf6a2
commit
983bd4cb70
|
@ -0,0 +1 @@
|
||||||
|
/build
|
|
@ -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'
|
||||||
|
}
|
|
@ -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 *;
|
||||||
|
#}
|
|
@ -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 <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||||
|
*/
|
||||||
|
@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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest package="org.mariotaku.chameleon"/>
|
|
@ -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<ChameleonView, ChameleonView.Appearance> 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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<ChameleonView, ChameleonView.Appearance> mPostApplyViews;
|
||||||
|
|
||||||
|
|
||||||
|
public ChameleonInflationFactory(@NonNull LayoutInflater inflater,
|
||||||
|
@Nullable Activity activity,
|
||||||
|
@Nullable AppCompatDelegate delegate,
|
||||||
|
@Nullable Chameleon.Theme theme,
|
||||||
|
@NonNull ArrayMap<ChameleonView, ChameleonView.Appearance> 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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<declare-styleable name="ChameleonTheme">
|
||||||
|
<attr name="colorPrimary"/>
|
||||||
|
<attr name="colorAccent"/>
|
||||||
|
<attr name="colorToolbar" format="color"/>
|
||||||
|
<attr name="android:colorForeground"/>
|
||||||
|
<attr name="android:colorBackground"/>
|
||||||
|
<attr name="isToolbarColored" format="boolean"/>
|
||||||
|
</declare-styleable>
|
||||||
|
<declare-styleable name="ChameleonTextView">
|
||||||
|
<attr name="android:textColorLink"/>
|
||||||
|
</declare-styleable>
|
||||||
|
<declare-styleable name="ChameleonEditText">
|
||||||
|
<attr name="android:textColorLink"/>
|
||||||
|
<attr name="backgroundTint"/>
|
||||||
|
</declare-styleable>
|
||||||
|
<declare-styleable name="ChameleonFloatingActionButton">
|
||||||
|
<attr name="backgroundTint"/>
|
||||||
|
</declare-styleable>
|
||||||
|
<declare-styleable name="ChameleonToolbar">
|
||||||
|
<attr name="android:background"/>
|
||||||
|
<attr name="titleTextColor"/>
|
||||||
|
<attr name="subtitleTextColor"/>
|
||||||
|
</declare-styleable>
|
||||||
|
</resources>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="color_reference_primary_color">#00100001</color>
|
||||||
|
<color name="color_reference_accent_color">#00100002</color>
|
||||||
|
<color name="color_reference_toolbar_color">#00100003</color>
|
||||||
|
</resources>
|
|
@ -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 <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||||
|
*/
|
||||||
|
public class ExampleUnitTest {
|
||||||
|
@Test
|
||||||
|
public void addition_isCorrect() throws Exception {
|
||||||
|
assertEquals(4, 2 + 2);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
include ':twidere'
|
include ':twidere', ':chameleon'
|
||||||
include ':twidere.component.common'
|
include ':twidere.component.common'
|
||||||
include ':twidere.library.extension'
|
include ':twidere.library.extension'
|
||||||
include ':twidere.wear'
|
include ':twidere.wear'
|
||||||
|
|
|
@ -73,10 +73,6 @@ public interface SharedPreferenceConstants {
|
||||||
String VALUE_TAB_DISPLAY_OPTION_ICON = "icon";
|
String VALUE_TAB_DISPLAY_OPTION_ICON = "icon";
|
||||||
String VALUE_TAB_DISPLAY_OPTION_LABEL = "label";
|
String VALUE_TAB_DISPLAY_OPTION_LABEL = "label";
|
||||||
String VALUE_TAB_DISPLAY_OPTION_BOTH = "both";
|
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_DEFAULT = "default";
|
||||||
String VALUE_THEME_BACKGROUND_SOLID = "solid";
|
String VALUE_THEME_BACKGROUND_SOLID = "solid";
|
||||||
|
|
|
@ -95,6 +95,7 @@ dependencies {
|
||||||
|
|
||||||
compile project(':twidere.component.common')
|
compile project(':twidere.component.common')
|
||||||
compile project(':twidere.component.nyan')
|
compile project(':twidere.component.nyan')
|
||||||
|
compile project(':chameleon')
|
||||||
|
|
||||||
// START Non-FOSS component
|
// START Non-FOSS component
|
||||||
googleCompile "com.google.android.gms:play-services-maps:$play_services_version"
|
googleCompile "com.google.android.gms:play-services-maps:$play_services_version"
|
||||||
|
|
|
@ -1,151 +0,0 @@
|
||||||
/*
|
|
||||||
* Twidere - Twitter client for Android
|
|
||||||
*
|
|
||||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -64,6 +64,13 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static android.text.TextUtils.isEmpty;
|
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;
|
import static org.mariotaku.twidere.util.DataStoreUtils.getAccountScreenName;
|
||||||
|
|
||||||
public class UserListSelectorActivity extends BaseActivity implements OnClickListener,
|
public class UserListSelectorActivity extends BaseActivity implements OnClickListener,
|
||||||
|
|
|
@ -102,8 +102,8 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment implements
|
||||||
protected void onClick() {
|
protected void onClick() {
|
||||||
final Context context = getContext();
|
final Context context = getContext();
|
||||||
final Intent intent = new Intent(context, KeyboardShortcutPreferenceCompatActivity.class);
|
final Intent intent = new Intent(context, KeyboardShortcutPreferenceCompatActivity.class);
|
||||||
intent.putExtra(KeyboardShortcutPreferenceCompatActivity.EXTRA_CONTEXT_TAG, mContextTag);
|
intent.putExtra(KeyboardShortcutPreferenceCompatActivity.Companion.getEXTRA_CONTEXT_TAG(), mContextTag);
|
||||||
intent.putExtra(KeyboardShortcutPreferenceCompatActivity.EXTRA_KEY_ACTION, mAction);
|
intent.putExtra(KeyboardShortcutPreferenceCompatActivity.Companion.getEXTRA_KEY_ACTION(), mAction);
|
||||||
context.startActivity(intent);
|
context.startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -128,6 +128,7 @@ import org.mariotaku.twidere.util.TwidereLinkify.HighlightStyle;
|
||||||
import org.mariotaku.twidere.view.CardMediaContainer.PreviewStyle;
|
import org.mariotaku.twidere.view.CardMediaContainer.PreviewStyle;
|
||||||
import org.mariotaku.twidere.view.ShapedImageView;
|
import org.mariotaku.twidere.view.ShapedImageView;
|
||||||
import org.mariotaku.twidere.view.ShapedImageView.ShapeStyle;
|
import org.mariotaku.twidere.view.ShapedImageView.ShapeStyle;
|
||||||
|
import org.mariotaku.twidere.view.TabPagerIndicator;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -807,10 +808,10 @@ public final class Utils implements Constants {
|
||||||
|
|
||||||
public static int getTabDisplayOptionInt(final String option) {
|
public static int getTabDisplayOptionInt(final String option) {
|
||||||
if (VALUE_TAB_DISPLAY_OPTION_ICON.equals(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))
|
else if (VALUE_TAB_DISPLAY_OPTION_LABEL.equals(option))
|
||||||
return VALUE_TAB_DISPLAY_OPTION_CODE_LABEL;
|
return TabPagerIndicator.DisplayOption.LABEL;
|
||||||
return VALUE_TAB_DISPLAY_OPTION_CODE_BOTH;
|
return TabPagerIndicator.DisplayOption.BOTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasNavBar(@NonNull Context context) {
|
public static boolean hasNavBar(@NonNull Context context) {
|
||||||
|
|
|
@ -22,16 +22,16 @@ package org.mariotaku.twidere.view;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v4.widget.SwipeRefreshLayout;
|
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
|
||||||
|
import org.mariotaku.chameleon.view.ChameleonSwipeRefreshLayout;
|
||||||
import org.mariotaku.twidere.view.iface.IExtendedView;
|
import org.mariotaku.twidere.view.iface.IExtendedView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mariotaku on 15/4/25.
|
* 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 TouchInterceptor mTouchInterceptor;
|
||||||
private OnSizeChangedListener mOnSizeChangedListener;
|
private OnSizeChangedListener mOnSizeChangedListener;
|
||||||
|
|
|
@ -1,15 +1,22 @@
|
||||||
package org.mariotaku.twidere.view;
|
package org.mariotaku.twidere.view;
|
||||||
|
|
||||||
import android.content.Context;
|
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.view.GravityCompat;
|
||||||
import android.support.v4.widget.DrawerLayout;
|
import android.support.v4.widget.DrawerLayout;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.MotionEvent;
|
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 ShouldDisableDecider mShouldDisableDecider;
|
||||||
private int state;
|
|
||||||
private int mStartLockMode, mEndLockMode;
|
private int mStartLockMode, mEndLockMode;
|
||||||
|
|
||||||
public HomeDrawerLayout(Context context) {
|
public HomeDrawerLayout(Context context) {
|
||||||
|
@ -49,6 +56,43 @@ public class HomeDrawerLayout extends DrawerLayout {
|
||||||
return super.dispatchTouchEvent(ev);
|
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 {
|
public interface ShouldDisableDecider {
|
||||||
boolean shouldDisableTouch(MotionEvent e);
|
boolean shouldDisableTouch(MotionEvent e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,14 @@ import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.support.annotation.ColorInt;
|
||||||
import android.support.annotation.IntDef;
|
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.PagerAdapter;
|
||||||
import android.support.v4.view.ViewCompat;
|
import android.support.v4.view.ViewCompat;
|
||||||
import android.support.v4.view.ViewPager;
|
import android.support.v4.view.ViewPager;
|
||||||
|
@ -24,7 +28,9 @@ import android.widget.LinearLayout;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
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.R;
|
||||||
import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration;
|
import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration;
|
||||||
import org.mariotaku.twidere.util.ThemeUtils;
|
import org.mariotaku.twidere.util.ThemeUtils;
|
||||||
|
@ -36,11 +42,8 @@ import java.lang.annotation.RetentionPolicy;
|
||||||
/**
|
/**
|
||||||
* Created by mariotaku on 14/10/21.
|
* 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 int mStripHeight;
|
||||||
private final TabPagerIndicatorAdapter mIndicatorAdapter;
|
private final TabPagerIndicatorAdapter mIndicatorAdapter;
|
||||||
|
@ -61,7 +64,7 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
|
||||||
mIndicatorAdapter = new TabPagerIndicatorAdapter(this);
|
mIndicatorAdapter = new TabPagerIndicatorAdapter(this);
|
||||||
mItemDecoration = new DividerItemDecoration(context, HORIZONTAL);
|
mItemDecoration = new DividerItemDecoration(context, HORIZONTAL);
|
||||||
mStripHeight = res.getDimensionPixelSize(R.dimen.element_spacing_small);
|
mStripHeight = res.getDimensionPixelSize(R.dimen.element_spacing_small);
|
||||||
ViewCompat.setOverScrollMode(this, ViewCompat.OVER_SCROLL_NEVER);
|
setOverScrollMode(OVER_SCROLL_NEVER);
|
||||||
setHorizontalScrollBarEnabled(false);
|
setHorizontalScrollBarEnabled(false);
|
||||||
setVerticalScrollBarEnabled(false);
|
setVerticalScrollBarEnabled(false);
|
||||||
setLayoutManager(mLayoutManager = new TabLayoutManager(context, this));
|
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));
|
setStripColor(a.getColor(R.styleable.TabPagerIndicator_tabStripColor, 0));
|
||||||
setIconColor(a.getColor(R.styleable.TabPagerIndicator_tabIconColor, 0));
|
setIconColor(a.getColor(R.styleable.TabPagerIndicator_tabIconColor, 0));
|
||||||
setLabelColor(a.getColor(R.styleable.TabPagerIndicator_tabLabelColor, ThemeUtils.getTextColorPrimary(context)));
|
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));
|
setTabShowDivider(a.getBoolean(R.styleable.TabPagerIndicator_tabShowDivider, false));
|
||||||
final int dividerVerticalPadding = a.getDimensionPixelSize(R.styleable.TabPagerIndicator_tabDividerVerticalPadding, 0);
|
final int dividerVerticalPadding = a.getDimensionPixelSize(R.styleable.TabPagerIndicator_tabDividerVerticalPadding, 0);
|
||||||
final int dividerHorizontalPadding = a.getDimensionPixelSize(R.styleable.TabPagerIndicator_tabDividerHorizontalPadding, 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();
|
return mIndicatorAdapter.getItemContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getTabSpecs() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setColumns(int columns) {
|
public void setColumns(int columns) {
|
||||||
mColumns = columns;
|
mColumns = columns;
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
|
@ -221,6 +222,43 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
|
||||||
mIndicatorAdapter.setTabProvider((TabProvider) adapter);
|
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() {
|
private int getTabHorizontalPadding() {
|
||||||
return mHorizontalPadding;
|
return mHorizontalPadding;
|
||||||
}
|
}
|
||||||
|
@ -230,11 +268,11 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isIconDisplayed() {
|
private boolean isIconDisplayed() {
|
||||||
return (mOption & ICON) != 0;
|
return (mOption & DisplayOption.ICON) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLabelDisplayed() {
|
private boolean isLabelDisplayed() {
|
||||||
return (mOption & LABEL) != 0;
|
return (mOption & DisplayOption.LABEL) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isTabExpandEnabled() {
|
private boolean isTabExpandEnabled() {
|
||||||
|
@ -261,9 +299,56 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
|
||||||
mVerticalPadding = padding;
|
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)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
public @interface DisplayOption {
|
public @interface DisplayOption {
|
||||||
|
int LABEL = 0x1;
|
||||||
|
int ICON = 0x2;
|
||||||
|
int BOTH = LABEL | ICON;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class SampleView extends LinearLayout {
|
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.setStripColor(a.getColor(R.styleable.TabPagerIndicator_tabStripColor, 0));
|
||||||
this.setIconColor(a.getColor(R.styleable.TabPagerIndicator_tabIconColor, 0));
|
this.setIconColor(a.getColor(R.styleable.TabPagerIndicator_tabIconColor, 0));
|
||||||
this.setLabelColor(a.getColor(R.styleable.TabPagerIndicator_tabLabelColor, ThemeUtils.getTextColorPrimary(context)));
|
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));
|
this.setTabShowDivider(a.getBoolean(R.styleable.TabPagerIndicator_tabShowDivider, false));
|
||||||
a.recycle();
|
a.recycle();
|
||||||
|
|
||||||
|
@ -346,11 +431,11 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
|
||||||
|
|
||||||
tabIcon.setImageResource(icon);
|
tabIcon.setImageResource(icon);
|
||||||
tabIcon.setColorFilter(iconColor, PorterDuff.Mode.SRC_ATOP);
|
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.setText(label);
|
||||||
tabLabel.setTextColor(labelColor);
|
tabLabel.setTextColor(labelColor);
|
||||||
tabLabel.setVisibility((tabDisplayOption & LABEL) != 0 ? VISIBLE : GONE);
|
tabLabel.setVisibility((tabDisplayOption & DisplayOption.LABEL) != 0 ? VISIBLE : GONE);
|
||||||
|
|
||||||
badgeView.setText(String.valueOf(unread));
|
badgeView.setText(String.valueOf(unread));
|
||||||
badgeView.setVisibility(unread != 0 ? VISIBLE : GONE);
|
badgeView.setVisibility(unread != 0 ? VISIBLE : GONE);
|
||||||
|
@ -420,7 +505,7 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
|
||||||
private final TextView labelView;
|
private final TextView labelView;
|
||||||
private final BadgeView badgeView;
|
private final BadgeView badgeView;
|
||||||
|
|
||||||
public TabItemHolder(TabPagerIndicator indicator, View itemView) {
|
TabItemHolder(TabPagerIndicator indicator, View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
this.indicator = indicator;
|
this.indicator = indicator;
|
||||||
this.itemView = (ItemLayout) itemView;
|
this.itemView = (ItemLayout) itemView;
|
||||||
|
@ -443,17 +528,17 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
|
||||||
return indicator.dispatchTabLongClick(position);
|
return indicator.dispatchTabLongClick(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBadge(int count, boolean display) {
|
void setBadge(int count, boolean display) {
|
||||||
badgeView.setText(String.valueOf(count));
|
badgeView.setText(String.valueOf(count));
|
||||||
badgeView.setVisibility(display && count > 0 ? VISIBLE : GONE);
|
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);
|
iconView.setVisibility(iconDisplayed ? VISIBLE : GONE);
|
||||||
labelView.setVisibility(labelDisplayed ? VISIBLE : GONE);
|
labelView.setVisibility(labelDisplayed ? VISIBLE : GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIconColor(int color) {
|
void setIconColor(int color) {
|
||||||
if (color != 0) {
|
if (color != 0) {
|
||||||
iconView.setColorFilter(color);
|
iconView.setColorFilter(color);
|
||||||
} else {
|
} 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);
|
labelView.setTextColor(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPadding(int horizontalPadding, int verticalPadding) {
|
void setPadding(int horizontalPadding, int verticalPadding) {
|
||||||
itemView.setPadding(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding);
|
itemView.setPadding(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStripColor(int color) {
|
void setStripColor(int color) {
|
||||||
itemView.setStripColor(color);
|
itemView.setStripColor(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStripHeight(int stripHeight) {
|
void setStripHeight(int stripHeight) {
|
||||||
itemView.setStripHeight(stripHeight);
|
itemView.setStripHeight(stripHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTabData(Drawable icon, CharSequence title, boolean activated) {
|
void setTabData(Drawable icon, CharSequence title, boolean activated) {
|
||||||
itemView.setContentDescription(title);
|
itemView.setContentDescription(title);
|
||||||
iconView.setImageDrawable(icon);
|
iconView.setImageDrawable(icon);
|
||||||
labelView.setText(title);
|
labelView.setText(title);
|
||||||
|
@ -490,7 +575,7 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
|
||||||
private boolean mTabExpandEnabled;
|
private boolean mTabExpandEnabled;
|
||||||
private final RecyclerView mRecyclerView;
|
private final RecyclerView mRecyclerView;
|
||||||
|
|
||||||
public TabLayoutManager(Context context, RecyclerView recyclerView) {
|
TabLayoutManager(Context context, RecyclerView recyclerView) {
|
||||||
super(context, HORIZONTAL, false);
|
super(context, HORIZONTAL, false);
|
||||||
mRecyclerView = recyclerView;
|
mRecyclerView = recyclerView;
|
||||||
setAutoMeasureEnabled(true);
|
setAutoMeasureEnabled(true);
|
||||||
|
@ -518,21 +603,15 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isTabExpandEnabled() {
|
boolean isTabExpandEnabled() {
|
||||||
return mTabExpandEnabled;
|
return mTabExpandEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTabExpandEnabled(boolean tabExpandEnabled) {
|
void setTabExpandEnabled(boolean tabExpandEnabled) {
|
||||||
mTabExpandEnabled = 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<TabItemHolder> {
|
private static class TabPagerIndicatorAdapter extends Adapter<TabItemHolder> {
|
||||||
|
|
||||||
private final TabPagerIndicator mIndicator;
|
private final TabPagerIndicator mIndicator;
|
||||||
|
@ -544,16 +623,16 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
|
||||||
private int mStripColor, mIconColor, mLabelColor;
|
private int mStripColor, mIconColor, mLabelColor;
|
||||||
private boolean mDisplayBadge;
|
private boolean mDisplayBadge;
|
||||||
|
|
||||||
public TabPagerIndicatorAdapter(TabPagerIndicator indicator) {
|
TabPagerIndicatorAdapter(TabPagerIndicator indicator) {
|
||||||
mIndicator = indicator;
|
mIndicator = indicator;
|
||||||
mUnreadCounts = new SparseIntArray();
|
mUnreadCounts = new SparseIntArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Context getItemContext() {
|
Context getItemContext() {
|
||||||
return mItemContext;
|
return mItemContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setItemContext(Context itemContext) {
|
void setItemContext(Context itemContext) {
|
||||||
mItemContext = itemContext;
|
mItemContext = itemContext;
|
||||||
mInflater = LayoutInflater.from(itemContext);
|
mInflater = LayoutInflater.from(itemContext);
|
||||||
}
|
}
|
||||||
|
@ -587,49 +666,34 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator, C
|
||||||
return mTabProvider.getCount();
|
return mTabProvider.getCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBadge(int position, int count) {
|
void setBadge(int position, int count) {
|
||||||
mUnreadCounts.put(position, count);
|
mUnreadCounts.put(position, count);
|
||||||
notifyItemChanged(position);
|
notifyItemChanged(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearBadge() {
|
void clearBadge() {
|
||||||
mUnreadCounts.clear();
|
mUnreadCounts.clear();
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDisplayBadge(boolean display) {
|
void setDisplayBadge(boolean display) {
|
||||||
mDisplayBadge = display;
|
mDisplayBadge = display;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIconColor(int color) {
|
void setIconColor(int color) {
|
||||||
mIconColor = color;
|
mIconColor = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLabelColor(int color) {
|
void setLabelColor(int color) {
|
||||||
mLabelColor = color;
|
mLabelColor = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStripColor(int color) {
|
void setStripColor(int color) {
|
||||||
mStripColor = color;
|
mStripColor = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTabProvider(TabProvider tabProvider) {
|
void setTabProvider(TabProvider tabProvider) {
|
||||||
mTabProvider = 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,18 +27,23 @@ import android.graphics.Paint;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.view.ViewCompat;
|
import android.support.v4.view.ViewCompat;
|
||||||
import android.support.v4.view.WindowInsetsCompat;
|
import android.support.v4.view.WindowInsetsCompat;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.View;
|
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.R;
|
||||||
import org.mariotaku.twidere.view.iface.TintedStatusLayout;
|
import org.mariotaku.twidere.view.iface.TintedStatusLayout;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mariotaku on 14/11/26.
|
* 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 final Paint mColorPaint;
|
||||||
private boolean mSetPadding;
|
private boolean mSetPadding;
|
||||||
|
@ -119,6 +124,42 @@ public class TintedStatusFrameLayout extends ExtendedFrameLayout implements Tint
|
||||||
mWindowInsetsListener = listener;
|
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 {
|
public interface WindowInsetsListener {
|
||||||
void onApplyWindowInsets(int left, int top, int right, int bottom);
|
void onApplyWindowInsets(int left, int top, int right, int bottom);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -42,7 +42,6 @@ import org.mariotaku.chameleon.Chameleon
|
||||||
import org.mariotaku.chameleon.ChameleonActivity
|
import org.mariotaku.chameleon.ChameleonActivity
|
||||||
import org.mariotaku.kpreferences.KPreferences
|
import org.mariotaku.kpreferences.KPreferences
|
||||||
import org.mariotaku.twidere.BuildConfig
|
import org.mariotaku.twidere.BuildConfig
|
||||||
import org.mariotaku.twidere.Constants
|
|
||||||
import org.mariotaku.twidere.TwidereConstants.SHARED_PREFERENCES_NAME
|
import org.mariotaku.twidere.TwidereConstants.SHARED_PREFERENCES_NAME
|
||||||
import org.mariotaku.twidere.activity.iface.IControlBarActivity
|
import org.mariotaku.twidere.activity.iface.IControlBarActivity
|
||||||
import org.mariotaku.twidere.activity.iface.IExtendedActivity
|
import org.mariotaku.twidere.activity.iface.IExtendedActivity
|
||||||
|
@ -58,7 +57,7 @@ import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@SuppressLint("Registered")
|
@SuppressLint("Registered")
|
||||||
open class BaseActivity : ChameleonActivity(), Constants, IExtendedActivity, IThemedActivity,
|
open class BaseActivity : ChameleonActivity(), IExtendedActivity, IThemedActivity,
|
||||||
IControlBarActivity, OnFitSystemWindowsListener, SystemWindowsInsetsCallback,
|
IControlBarActivity, OnFitSystemWindowsListener, SystemWindowsInsetsCallback,
|
||||||
KeyboardShortcutCallback, OnPreferenceDisplayDialogCallback {
|
KeyboardShortcutCallback, OnPreferenceDisplayDialogCallback {
|
||||||
@Inject
|
@Inject
|
||||||
|
@ -341,7 +340,13 @@ open class BaseActivity : ChameleonActivity(), Constants, IExtendedActivity, ITh
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getOverrideTheme(): Chameleon.Theme {
|
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 {
|
companion object {
|
||||||
|
|
|
@ -341,10 +341,10 @@ class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, Supp
|
||||||
mainTabs.setOnPageChangeListener(this)
|
mainTabs.setOnPageChangeListener(this)
|
||||||
mainTabs.setColumns(tabColumns)
|
mainTabs.setColumns(tabColumns)
|
||||||
if (tabDisplayOptionInt == 0) {
|
if (tabDisplayOptionInt == 0) {
|
||||||
tabDisplayOptionInt = TabPagerIndicator.ICON
|
tabDisplayOptionInt = TabPagerIndicator.DisplayOption.ICON
|
||||||
}
|
}
|
||||||
mainTabs.setTabDisplayOption(tabDisplayOptionInt)
|
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.setDisplayBadge(preferences.getBoolean(SharedPreferenceConstants.KEY_UNREAD_COUNT, true))
|
||||||
mainTabs.updateAppearance()
|
mainTabs.updateAppearance()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
* Twidere - Twitter client for Android
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
}
|
|
@ -48,7 +48,7 @@ abstract class AbsToolbarTabPagesFragment : BaseSupportFragment(), RefreshScroll
|
||||||
viewPager.offscreenPageLimit = 2
|
viewPager.offscreenPageLimit = 2
|
||||||
viewPager.addOnPageChangeListener(this)
|
viewPager.addOnPageChangeListener(this)
|
||||||
toolbarTabs.setViewPager(viewPager)
|
toolbarTabs.setViewPager(viewPager)
|
||||||
toolbarTabs.setTabDisplayOption(TabPagerIndicator.LABEL)
|
toolbarTabs.setTabDisplayOption(TabPagerIndicator.DisplayOption.LABEL)
|
||||||
|
|
||||||
|
|
||||||
addTabs(pagerAdapter!!)
|
addTabs(pagerAdapter!!)
|
||||||
|
|
|
@ -79,6 +79,7 @@ import nl.komponents.kovenant.ui.promiseOnUi
|
||||||
import nl.komponents.kovenant.ui.successUi
|
import nl.komponents.kovenant.ui.successUi
|
||||||
import org.apache.commons.lang3.ObjectUtils
|
import org.apache.commons.lang3.ObjectUtils
|
||||||
import org.mariotaku.chameleon.Chameleon
|
import org.mariotaku.chameleon.Chameleon
|
||||||
|
import org.mariotaku.chameleon.ChameleonUtils
|
||||||
import org.mariotaku.ktextension.Bundle
|
import org.mariotaku.ktextension.Bundle
|
||||||
import org.mariotaku.ktextension.empty
|
import org.mariotaku.ktextension.empty
|
||||||
import org.mariotaku.ktextension.set
|
import org.mariotaku.ktextension.set
|
||||||
|
@ -430,7 +431,7 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
|
||||||
profileImage.visibility = View.GONE
|
profileImage.visibility = View.GONE
|
||||||
profileType.visibility = View.GONE
|
profileType.visibility = View.GONE
|
||||||
val theme = Chameleon.getOverrideTheme(activity, activity)
|
val theme = Chameleon.getOverrideTheme(activity, activity)
|
||||||
setUiColor(theme.primaryColor)
|
setUiColor(theme.colorPrimary)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val adapter = pagerAdapter
|
val adapter = pagerAdapter
|
||||||
|
@ -496,7 +497,7 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
|
||||||
setUiColor(user.link_color)
|
setUiColor(user.link_color)
|
||||||
} else {
|
} else {
|
||||||
val theme = Chameleon.getOverrideTheme(activity, activity)
|
val theme = Chameleon.getOverrideTheme(activity, activity)
|
||||||
setUiColor(theme.primaryColor)
|
setUiColor(theme.colorPrimary)
|
||||||
}
|
}
|
||||||
val defWidth = resources.displayMetrics.widthPixels
|
val defWidth = resources.displayMetrics.widthPixels
|
||||||
val width = if (bannerWidth > 0) bannerWidth else defWidth
|
val width = if (bannerWidth > 0) bannerWidth else defWidth
|
||||||
|
@ -678,7 +679,7 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
|
||||||
viewPager.offscreenPageLimit = 3
|
viewPager.offscreenPageLimit = 3
|
||||||
viewPager.adapter = pagerAdapter
|
viewPager.adapter = pagerAdapter
|
||||||
toolbarTabs.setViewPager(viewPager)
|
toolbarTabs.setViewPager(viewPager)
|
||||||
toolbarTabs.setTabDisplayOption(TabPagerIndicator.LABEL)
|
toolbarTabs.setTabDisplayOption(TabPagerIndicator.DisplayOption.LABEL)
|
||||||
toolbarTabs.setOnPageChangeListener(this)
|
toolbarTabs.setOnPageChangeListener(this)
|
||||||
|
|
||||||
followContainer.follow.setOnClickListener(this)
|
followContainer.follow.setOnClickListener(this)
|
||||||
|
@ -1277,15 +1278,12 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
|
||||||
}
|
}
|
||||||
val activity = activity as BaseActivity
|
val activity = activity as BaseActivity
|
||||||
val theme = Chameleon.getOverrideTheme(activity, activity)
|
val theme = Chameleon.getOverrideTheme(activity, activity)
|
||||||
primaryColor = theme.primaryColor
|
|
||||||
primaryColorDark = ThemeUtils.computeDarkColor(primaryColor)
|
|
||||||
if (theme.isToolbarColored) {
|
if (theme.isToolbarColored) {
|
||||||
primaryColor = color
|
primaryColor = color
|
||||||
primaryColorDark = ThemeUtils.computeDarkColor(color)
|
|
||||||
} else {
|
} else {
|
||||||
primaryColor = theme.primaryColor
|
primaryColor = theme.colorToolbar
|
||||||
primaryColorDark = Color.BLACK
|
|
||||||
}
|
}
|
||||||
|
primaryColorDark = ChameleonUtils.darkenColor(primaryColor)
|
||||||
if (actionBarBackground != null) {
|
if (actionBarBackground != null) {
|
||||||
actionBarBackground!!.color = primaryColor
|
actionBarBackground!!.color = primaryColor
|
||||||
}
|
}
|
||||||
|
@ -1293,7 +1291,7 @@ class UserFragment : BaseSupportFragment(), OnClickListener, OnLinkClickListener
|
||||||
if (theme.isToolbarColored) {
|
if (theme.isToolbarColored) {
|
||||||
taskColor = color
|
taskColor = color
|
||||||
} else {
|
} else {
|
||||||
taskColor = theme.toolbarColor
|
taskColor = theme.colorToolbar
|
||||||
}
|
}
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
val name = userColorNameManager.getDisplayName(user, nameFirst)
|
val name = userColorNameManager.getDisplayName(user, nameFirst)
|
||||||
|
|
|
@ -20,13 +20,13 @@
|
||||||
package org.mariotaku.twidere.view
|
package org.mariotaku.twidere.view
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.support.v7.widget.AppCompatMultiAutoCompleteTextView
|
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
import android.text.Selection
|
import android.text.Selection
|
||||||
import android.text.method.ArrowKeyMovementMethod
|
import android.text.method.ArrowKeyMovementMethod
|
||||||
import android.text.method.MovementMethod
|
import android.text.method.MovementMethod
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.widget.AdapterView
|
import android.widget.AdapterView
|
||||||
|
import org.mariotaku.chameleon.view.ChameleonMultiAutoCompleteTextView
|
||||||
import org.mariotaku.twidere.adapter.ComposeAutoCompleteAdapter
|
import org.mariotaku.twidere.adapter.ComposeAutoCompleteAdapter
|
||||||
import org.mariotaku.twidere.model.UserKey
|
import org.mariotaku.twidere.model.UserKey
|
||||||
import org.mariotaku.twidere.util.EmojiSupportUtils
|
import org.mariotaku.twidere.util.EmojiSupportUtils
|
||||||
|
@ -35,7 +35,7 @@ import org.mariotaku.twidere.util.widget.StatusTextTokenizer
|
||||||
class ComposeEditText @JvmOverloads constructor(
|
class ComposeEditText @JvmOverloads constructor(
|
||||||
context: Context,
|
context: Context,
|
||||||
attrs: AttributeSet? = null
|
attrs: AttributeSet? = null
|
||||||
) : AppCompatMultiAutoCompleteTextView(context, attrs) {
|
) : ChameleonMultiAutoCompleteTextView(context, attrs) {
|
||||||
|
|
||||||
private var adapter: ComposeAutoCompleteAdapter? = null
|
private var adapter: ComposeAutoCompleteAdapter? = null
|
||||||
var accountKey: UserKey? = null
|
var accountKey: UserKey? = null
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
package org.mariotaku.twidere.view
|
package org.mariotaku.twidere.view
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.support.v7.widget.AppCompatTextView
|
|
||||||
import android.text.Spannable
|
import android.text.Spannable
|
||||||
import android.text.method.MovementMethod
|
import android.text.method.MovementMethod
|
||||||
import android.text.style.ClickableSpan
|
import android.text.style.ClickableSpan
|
||||||
|
@ -28,23 +27,20 @@ import android.util.AttributeSet
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import org.mariotaku.chameleon.view.ChameleonTextView
|
||||||
import org.mariotaku.twidere.util.EmojiSupportUtils
|
import org.mariotaku.twidere.util.EmojiSupportUtils
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true when not clicking links
|
* Returns true when not clicking links
|
||||||
* Created by mariotaku on 15/11/20.
|
* 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) {
|
init {
|
||||||
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) {
|
|
||||||
EmojiSupportUtils.initForTextView(this)
|
EmojiSupportUtils.initForTextView(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?actionBarSize"
|
android:layout_height="?actionBarSize"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:background="?colorPrimary"
|
|
||||||
android:elevation="@dimen/toolbar_elevation"
|
android:elevation="@dimen/toolbar_elevation"
|
||||||
app:contentInsetEnd="0dp"
|
app:contentInsetEnd="0dp"
|
||||||
app:contentInsetStart="0dp">
|
app:contentInsetStart="0dp">
|
||||||
|
@ -87,7 +86,7 @@
|
||||||
android:layout_margin="@dimen/element_spacing_large"
|
android:layout_margin="@dimen/element_spacing_large"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:src="@drawable/ic_action_status_compose"
|
android:src="@drawable/ic_action_status_compose"
|
||||||
android:tag="background|primary_color,tint|primary_color_dependent"
|
app:backgroundTint="?colorToolbar"
|
||||||
app:elevation="6dp"
|
app:elevation="6dp"
|
||||||
app:pressedTranslationZ="12dp"/>
|
app:pressedTranslationZ="12dp"/>
|
||||||
|
|
||||||
|
|
|
@ -19,13 +19,13 @@
|
||||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:divider="?android:attr/dividerHorizontal"
|
android:divider="?android:attr/dividerHorizontal"
|
||||||
android:dividerPadding="0dip"
|
android:dividerPadding="0dip"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:showDividers="middle">
|
android:showDividers="middle">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/keyboard_shortcut_input"
|
android:id="@+id/keyboard_shortcut_input"
|
||||||
|
@ -37,17 +37,17 @@
|
||||||
android:padding="@dimen/element_spacing_xlarge">
|
android:padding="@dimen/element_spacing_xlarge">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/keys_label"
|
android:id="@+id/keysLabel"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/keyboard_shortcut_hint"
|
android:text="@string/keyboard_shortcut_hint"
|
||||||
android:textAppearance="?android:textAppearanceMedium" />
|
android:textAppearance="?android:textAppearanceMedium"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/conflict_label"
|
android:id="@+id/conflictLabel"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:visibility="gone" />
|
android:visibility="gone"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@
|
||||||
tools:ignore="UselessParent">
|
tools:ignore="UselessParent">
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button_negative"
|
android:id="@+id/buttonNegative"
|
||||||
style="?android:attr/buttonBarButtonStyle"
|
style="?android:attr/buttonBarButtonStyle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -70,10 +70,10 @@
|
||||||
android:maxLines="2"
|
android:maxLines="2"
|
||||||
android:minHeight="@dimen/element_size_normal"
|
android:minHeight="@dimen/element_size_normal"
|
||||||
android:text="@android:string/cancel"
|
android:text="@android:string/cancel"
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp"/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button_neutral"
|
android:id="@+id/buttonNeutral"
|
||||||
style="?android:attr/buttonBarButtonStyle"
|
style="?android:attr/buttonBarButtonStyle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -82,10 +82,10 @@
|
||||||
android:maxLines="2"
|
android:maxLines="2"
|
||||||
android:minHeight="@dimen/element_size_normal"
|
android:minHeight="@dimen/element_size_normal"
|
||||||
android:text="@string/clear"
|
android:text="@string/clear"
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp"/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button_positive"
|
android:id="@+id/buttonPositive"
|
||||||
style="?android:attr/buttonBarButtonStyle"
|
style="?android:attr/buttonBarButtonStyle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -94,6 +94,6 @@
|
||||||
android:maxLines="2"
|
android:maxLines="2"
|
||||||
android:minHeight="@dimen/element_size_normal"
|
android:minHeight="@dimen/element_size_normal"
|
||||||
android:text="@android:string/ok"
|
android:text="@android:string/ok"
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -19,8 +19,8 @@
|
||||||
<item name="quoteIndicatorBackgroundColor">@color/quote_indicator_background_light</item>
|
<item name="quoteIndicatorBackgroundColor">@color/quote_indicator_background_light</item>
|
||||||
<item name="mediaLabelBackground">#dddddd</item>
|
<item name="mediaLabelBackground">#dddddd</item>
|
||||||
|
|
||||||
<!-- ATE attributes -->
|
<item name="colorToolbar">?colorPrimary</item>
|
||||||
<item name="ateThemeKey">light</item>
|
<item name="isToolbarColored">true</item>
|
||||||
|
|
||||||
<item name="actionBarTheme">@null</item>
|
<item name="actionBarTheme">@null</item>
|
||||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
||||||
|
@ -47,8 +47,8 @@
|
||||||
<item name="messageBubbleColor">@color/message_bubble_color_light</item>
|
<item name="messageBubbleColor">@color/message_bubble_color_light</item>
|
||||||
<item name="quoteIndicatorBackgroundColor">@color/quote_indicator_background_light</item>
|
<item name="quoteIndicatorBackgroundColor">@color/quote_indicator_background_light</item>
|
||||||
|
|
||||||
<!-- ATE attributes -->
|
<item name="colorToolbar">?colorPrimary</item>
|
||||||
<item name="ateThemeKey">light</item>
|
<item name="isToolbarColored">true</item>
|
||||||
|
|
||||||
<item name="actionBarTheme">@null</item>
|
<item name="actionBarTheme">@null</item>
|
||||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
||||||
|
@ -74,8 +74,8 @@
|
||||||
<item name="messageBubbleColor">@color/message_bubble_color_light</item>
|
<item name="messageBubbleColor">@color/message_bubble_color_light</item>
|
||||||
<item name="quoteIndicatorBackgroundColor">@color/quote_indicator_background_light</item>
|
<item name="quoteIndicatorBackgroundColor">@color/quote_indicator_background_light</item>
|
||||||
|
|
||||||
<!-- ATE attributes -->
|
<item name="colorToolbar">?colorPrimary</item>
|
||||||
<item name="ateThemeKey">light</item>
|
<item name="isToolbarColored">true</item>
|
||||||
|
|
||||||
<item name="actionBarTheme">@null</item>
|
<item name="actionBarTheme">@null</item>
|
||||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
<attr name="quoteIndicatorBackgroundColor" format="color"/>
|
<attr name="quoteIndicatorBackgroundColor" format="color"/>
|
||||||
<attr name="linePageIndicatorStyle" format="reference"/>
|
<attr name="linePageIndicatorStyle" format="reference"/>
|
||||||
<attr name="mediaLabelBackground" format="color"/>
|
<attr name="mediaLabelBackground" format="color"/>
|
||||||
<attr name="ateThemeKey" format="string"/>
|
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
<declare-styleable name="ColorLabelView">
|
<declare-styleable name="ColorLabelView">
|
||||||
<attr name="ignorePadding" format="boolean"/>
|
<attr name="ignorePadding" format="boolean"/>
|
||||||
<attr name="backgroundColor" format="color"/>
|
<attr name="backgroundColor" format="color"/>
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
<item name="quoteIndicatorBackgroundColor">@color/quote_indicator_background_dark</item>
|
<item name="quoteIndicatorBackgroundColor">@color/quote_indicator_background_dark</item>
|
||||||
<item name="mediaLabelBackground">#505050</item>
|
<item name="mediaLabelBackground">#505050</item>
|
||||||
|
|
||||||
<!-- ATE attributes -->
|
<item name="colorToolbar">@color/background_color_action_bar_dark</item>
|
||||||
<item name="ateThemeKey">dark</item>
|
<item name="isToolbarColored">false</item>
|
||||||
|
|
||||||
<item name="actionBarTheme">@null</item>
|
<item name="actionBarTheme">@null</item>
|
||||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
||||||
|
@ -55,8 +55,8 @@
|
||||||
<item name="messageBubbleColor">@color/message_bubble_color_dark</item>
|
<item name="messageBubbleColor">@color/message_bubble_color_dark</item>
|
||||||
<item name="quoteIndicatorBackgroundColor">@color/quote_indicator_background_dark</item>
|
<item name="quoteIndicatorBackgroundColor">@color/quote_indicator_background_dark</item>
|
||||||
|
|
||||||
<!-- ATE attributes -->
|
<item name="colorToolbar">@color/background_color_action_bar_dark</item>
|
||||||
<item name="ateThemeKey">dark</item>
|
<item name="isToolbarColored">false</item>
|
||||||
|
|
||||||
<item name="actionBarTheme">@null</item>
|
<item name="actionBarTheme">@null</item>
|
||||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
||||||
|
@ -84,8 +84,8 @@
|
||||||
<item name="messageBubbleColor">@color/message_bubble_color_dark</item>
|
<item name="messageBubbleColor">@color/message_bubble_color_dark</item>
|
||||||
<item name="quoteIndicatorBackgroundColor">@color/quote_indicator_background_dark</item>
|
<item name="quoteIndicatorBackgroundColor">@color/quote_indicator_background_dark</item>
|
||||||
|
|
||||||
<!-- ATE attributes -->
|
<item name="colorToolbar">@color/background_color_action_bar_dark</item>
|
||||||
<item name="ateThemeKey">dark</item>
|
<item name="isToolbarColored">false</item>
|
||||||
|
|
||||||
<item name="actionBarTheme">@null</item>
|
<item name="actionBarTheme">@null</item>
|
||||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
||||||
|
@ -154,8 +154,8 @@
|
||||||
<item name="messageBubbleColor">@color/message_bubble_color_dark</item>
|
<item name="messageBubbleColor">@color/message_bubble_color_dark</item>
|
||||||
<item name="quoteIndicatorBackgroundColor">@color/quote_indicator_background_dark</item>
|
<item name="quoteIndicatorBackgroundColor">@color/quote_indicator_background_dark</item>
|
||||||
|
|
||||||
<!-- ATE attributes -->
|
<item name="colorToolbar">@color/background_color_action_bar_dark</item>
|
||||||
<item name="ateThemeKey">dark</item>
|
<item name="isToolbarColored">false</item>
|
||||||
|
|
||||||
<item name="actionBarTheme">@null</item>
|
<item name="actionBarTheme">@null</item>
|
||||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
||||||
|
|
Loading…
Reference in New Issue