diff --git a/README.md b/README.md index 273d9ab4a7..5f9a55a69c 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,9 @@ A complete library to build apps for Android 14+ (ICS or above) devices with a b engine. It is built on top of the latest [app compat library](https://developer.android.com/topic/libraries/support-library/features.html) to provide best compatibility. +>Since v2.0.0, it uses [AndroidX](https://developer.android.com/jetpack/androidx/) so, first +[migrate](https://developer.android.com/jetpack/androidx/migrate) your project to AndroidX. + @@ -23,6 +26,7 @@ to provide best compatibility. - [Theme engine](https://github.com/pranavpandey/dynamic-support#theme-engine) - [Background aware](https://github.com/pranavpandey/dynamic-support#background-aware) - [Sample](https://github.com/pranavpandey/dynamic-support#sample) + - [Proguard](https://github.com/pranavpandey/dynamic-support#proguard) - [License](https://github.com/pranavpandey/dynamic-support#license) --- @@ -33,7 +37,11 @@ It can be installed by adding the following dependency to your `build.gradle` fi ```groovy dependencies { - implementation 'com.pranavpandey.android:dynamic-support:1.3.0' + // For AndroidX enabled projects. + implementation 'com.pranavpandey.android:dynamic-utils:2.0.0' + + // For legacy projects. + implementation 'com.pranavpandey.android:dynamic-utils:1.3.0' } ``` @@ -65,6 +73,57 @@ documentation. Basic documentation will be available soon. Checkout the `sample` to know more about the basic implementation. +### Proguard +This library uses reflection at some places to theme widgets at runtime. So, their original name +must be preserved to theme them properly. It will automatically apply the appropriate rules if +proguard is enabled in the project. + +The following rules will be applied by this library: + +```yml +dependencies { + # Keep application class. + -keep public class * extends android.app.Application + + # Keep methods in Activity that could be used in the XML. + -keepclassmembers class * extends android.app.Activity { + public void *(android.view.View); + } + + # Keep support library classes. + #-keep class androidx.appcompat.widget.** { *; } + #-keep class android.support.v4.widget.** { *; } + #-keep class android.support.v7.widget.** { *; } + #-keep class android.support.design.widget.** { *; } + #-keep class android.support.design.internal.** { *; } + + # Keep AndroidX classes. + -keep class androidx.core.widget.** { *; } + -keep class androidx.appcompat.view.menu.** { *; } + -keep class androidx.recyclerview.widget.** { *; } + -keep class androidx.viewpager.widget.** { *; } + + # Keep Material Components classes. + -keep class com.google.android.material.internal.** { *; } + -keep class com.google.android.material.navigation.** { *; } + -keep class com.google.android.material.textfield.** { *; } + + # Keep all the Dynamic Support models. + -keep class com.pranavpandey.android.dynamic.support.model.** { *; } + + # Gson uses generic type information stored in a class file when working with fields. + # Proguard removes such information by default, so configure it to keep all of it. + -keepattributes Signature + + # For using GSON @Expose annotation + -keepattributes *Annotation* + + # Gson specific classes + -keep class sun.misc.Unsafe { *; } + -keep class com.google.gson.** { *; } +} +``` + --- ## Apps using Dynamic Support diff --git a/build.gradle b/build.gradle index 4f8f12b685..f68cbfbee0 100644 --- a/build.gradle +++ b/build.gradle @@ -16,12 +16,15 @@ buildscript { ext.versions = [ - 'compileSdk' : 28, - 'minSdk' : 14, - 'targetSdk' : 28, - 'buildTools' : '28.0.3', - 'androidSupport': '28.0.0', - 'kotlin' : '1.3.10' + 'compileSdk': 28, + 'minSdk' : 14, + 'targetSdk' : 28, + 'buildTools': '28.0.3', + 'androidx' : '1.1.0-alpha02', + 'dynamic' : '2.1.0', + 'gson' : '2.8.5', + 'kotlin' : '1.3.11', + 'material' : '1.1.0-alpha02' ] repositories { @@ -64,8 +67,8 @@ ext { mavenGroup = 'com.pranavpandey.android' mavenArtifactId = 'dynamic-support' mavenInceptionYear = 2018 - mavenVersion = '1.3.0' - mavenVersionCode = 14 + mavenVersion = '2.0.0' + mavenVersionCode = 15 developerId = 'pranavpandey' developerName = 'Pranav Pandey' diff --git a/dynamic-support/bintray.gradle b/dynamic-support/bintray.gradle index 1a5df9b46f..792bfee52f 100644 --- a/dynamic-support/bintray.gradle +++ b/dynamic-support/bintray.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2017 Pranav Pandey + * Copyright 2018 Pranav Pandey * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/dynamic-support/build.gradle b/dynamic-support/build.gradle index c073288f4d..3f534e5cd4 100644 --- a/dynamic-support/build.gradle +++ b/dynamic-support/build.gradle @@ -27,6 +27,7 @@ android { versionName mavenVersion vectorDrawables.useSupportLibrary = true + consumerProguardFiles 'proguard-rules.pro' } sourceSets { @@ -35,9 +36,9 @@ android { } dependencies { - api "com.pranavpandey.android:dynamic-toasts:$mavenVersion" - api "com.android.support:design:${versions.androidSupport}" - api "com.android.support:cardview-v7:${versions.androidSupport}" + api "com.pranavpandey.android:dynamic-toasts:${versions.dynamic}" + api "com.google.android.material:material:${versions.material}" + api "com.google.code.gson:gson:${versions.gson}" } if (project.rootProject.file('local.properties').exists()) { @@ -52,8 +53,9 @@ project.afterEvaluate { description = "Generates javadocs" failOnError = false destinationDir = new File(destinationDir, variant.baseName) - source = files(variant.javaCompiler.source) - classpath = files(variant.javaCompiler.classpath.files) + files(android.bootClasspath) + source = android.sourceSets.main.java.srcDirs + classpath += configurations.compile + classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) options.windowTitle(referenceTitle) options.docTitle(referenceTitle) options.header(referenceTitle) @@ -63,4 +65,4 @@ project.afterEvaluate { } } } -} +} \ No newline at end of file diff --git a/dynamic-support/maven.gradle b/dynamic-support/maven.gradle index ee626db8fb..a7a3afd4ab 100644 --- a/dynamic-support/maven.gradle +++ b/dynamic-support/maven.gradle @@ -1,5 +1,5 @@ /* - * Copyright 2017 Pranav Pandey + * Copyright 2018 Pranav Pandey * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/dynamic-support/proguard-rules.pro b/dynamic-support/proguard-rules.pro index f9d39fab30..bbfd386c4e 100644 --- a/dynamic-support/proguard-rules.pro +++ b/dynamic-support/proguard-rules.pro @@ -15,3 +15,43 @@ #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} + +# Keep application class. +-keep public class * extends android.app.Application + +# Keep methods in Activity that could be used in the XML. +-keepclassmembers class * extends android.app.Activity { + public void *(android.view.View); +} + +# Keep support library classes. +#-keep class androidx.appcompat.widget.** { *; } +#-keep class android.support.v4.widget.** { *; } +#-keep class android.support.v7.widget.** { *; } +#-keep class android.support.design.widget.** { *; } +#-keep class android.support.design.internal.** { *; } + +# Keep AndroidX classes. +-keep class androidx.core.widget.** { *; } +-keep class androidx.appcompat.view.menu.** { *; } +-keep class androidx.recyclerview.widget.** { *; } +-keep class androidx.viewpager.widget.** { *; } + +# Keep Material Components classes. +-keep class com.google.android.material.internal.** { *; } +-keep class com.google.android.material.navigation.** { *; } +-keep class com.google.android.material.textfield.** { *; } + +# Keep all the Dynamic Support models. +-keep class com.pranavpandey.android.dynamic.support.model.** { *; } + +# Gson uses generic type information stored in a class file when working with fields. +# Proguard removes such information by default, so configure it to keep all of it. +-keepattributes Signature + +# For using GSON @Expose annotation +-keepattributes *Annotation* + +# Gson specific classes +-keep class sun.misc.Unsafe { *; } +-keep class com.google.gson.** { *; } \ No newline at end of file diff --git a/dynamic-support/src/main/AndroidManifest.xml b/dynamic-support/src/main/AndroidManifest.xml index 085ef855e9..dad96f0be1 100644 --- a/dynamic-support/src/main/AndroidManifest.xml +++ b/dynamic-support/src/main/AndroidManifest.xml @@ -16,7 +16,6 @@ --> diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/DynamicApplication.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/DynamicApplication.java index 8b875a6959..7b6576c6b8 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/DynamicApplication.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/DynamicApplication.java @@ -22,26 +22,28 @@ import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.preference.PreferenceManager; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StyleRes; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StyleRes; import com.pranavpandey.android.dynamic.support.listener.DynamicListener; import com.pranavpandey.android.dynamic.support.locale.DynamicLocale; import com.pranavpandey.android.dynamic.support.locale.DynamicLocaleUtils; +import com.pranavpandey.android.dynamic.support.model.DynamicAppTheme; import com.pranavpandey.android.dynamic.support.preference.DynamicPreferences; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; +import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils; import java.util.Locale; /** - * Base application class which can be extended to initialize the - * {@link DynamicTheme} and to perform theme change operations. + * Base application class which can be extended to initialize the {@link DynamicTheme} and to + * perform theme change operations. */ -public abstract class DynamicApplication extends Application implements - DynamicLocale, DynamicListener, - SharedPreferences.OnSharedPreferenceChangeListener { +public abstract class DynamicApplication extends Application implements DynamicLocale, + DynamicListener, SharedPreferences.OnSharedPreferenceChangeListener { /** * Dynamic context used by this application. @@ -70,7 +72,7 @@ public void onCreate() { .registerOnSharedPreferenceChangeListener(this); onInitialize(); - setThemeRes(); + setDynamicTheme(); onCustomiseTheme(); } @@ -79,30 +81,24 @@ public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); int diff = mConfiguration.diff(new Configuration(newConfig)); - if ((diff & ActivityInfo.CONFIG_LOCALE) != 0) { + if ((diff & ActivityInfo.CONFIG_LOCALE) != 0 + || (diff & ActivityInfo.CONFIG_ORIENTATION) != 0 + || (DynamicVersionUtils.isJellyBeanMR1() + && (diff & ActivityInfo.CONFIG_DENSITY) != 0)) { DynamicTheme.getInstance().onDynamicChange(true, false); mConfiguration = new Configuration(newConfig); } } /** - * Set the current theme resource for this application. - */ - protected void setThemeRes() { - if (getThemeRes() != DynamicResourceUtils.ADS_DEFAULT_RESOURCE_ID) { - DynamicTheme.getInstance().setTheme(getThemeRes(), true); - } - } - - /** - * This method will be Called inside the {@link #onCreate()} method - * before applying the theme. Do any initializations in this method. + * This method will be called inside the {@link #onCreate()} method before applying the theme. + *

Do any initializations in this method. */ protected abstract void onInitialize(); /** - * Get the style resource file to apply theme on ths application. - * Override this method to supply your own customised style. + * Get the style resource to apply theme on this application. + *

Override this method to supply your own customised style. * * @return Style resource to be applied on this activity. */ @@ -111,19 +107,41 @@ protected void setThemeRes() { } /** - * This method will be called inside the {@link #onCreate()} method - * after applying the theme. Override this method to customise the theme - * further. + * Get the dynamic app theme to be applied on this application. + *

Override this method to supply your own customised theme. + * + * @return The dynamic app theme for this application. + */ + protected @Nullable DynamicAppTheme getDynamicTheme() { + return null; + } + + /** + * This method will be called inside the {@link #onCreate()} method after applying the theme. + *

Override this method to customise the theme further. */ protected void onCustomiseTheme() { } /** + * Returns the dynamic context used by this application. + * * @return The dynamic context used by this application. */ public @NonNull Context getContext() { return mContext; } + /** + * Set the dynamic app theme and style resource for this application. + */ + protected void setDynamicTheme() { + if (getDynamicTheme() == null) { + DynamicTheme.getInstance().setThemeRes(getThemeRes(), true); + } else { + DynamicTheme.getInstance().setTheme(getDynamicTheme(), true); + } + } + @Override public @Nullable String[] getSupportedLocales() { return null; @@ -149,7 +167,7 @@ public void onDynamicChange(boolean context, boolean recreate) { DynamicTheme.getInstance().setContext(getContext()); } - setThemeRes(); + setDynamicTheme(); onCustomiseTheme(); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/activity/DynamicActivity.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/activity/DynamicActivity.java index f219f46c46..8736e5c27a 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/activity/DynamicActivity.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/activity/DynamicActivity.java @@ -16,31 +16,11 @@ package com.pranavpandey.android.dynamic.support.activity; -import android.annotation.SuppressLint; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; -import android.support.annotation.ColorInt; -import android.support.annotation.ColorRes; -import android.support.annotation.DrawableRes; -import android.support.annotation.IdRes; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.design.widget.AppBarLayout; -import android.support.design.widget.BaseTransientBottomBar; -import android.support.design.widget.CollapsingToolbarLayout; -import android.support.design.widget.CoordinatorLayout; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.Snackbar; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentTransaction; -import android.support.v4.content.ContextCompat; -import android.support.v7.app.ActionBar; -import android.support.v7.widget.Toolbar; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; @@ -51,26 +31,43 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; -import android.widget.TextView; +import androidx.annotation.ColorInt; +import androidx.annotation.ColorRes; +import androidx.annotation.DrawableRes; +import androidx.annotation.IdRes; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StringRes; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.widget.Toolbar; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentTransaction; + +import com.google.android.material.appbar.AppBarLayout; +import com.google.android.material.appbar.CollapsingToolbarLayout; +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import com.google.android.material.snackbar.Snackbar; import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.listener.DynamicSearchListener; -import com.pranavpandey.android.dynamic.support.splash.DynamicSplashFragment; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; import com.pranavpandey.android.dynamic.support.utils.DynamicFABUtils; import com.pranavpandey.android.dynamic.support.utils.DynamicHintUtils; import com.pranavpandey.android.dynamic.support.utils.DynamicInputUtils; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; +import com.pranavpandey.android.dynamic.utils.DynamicDrawableUtils; /** - * Base activity to handle everything related to design support and - * the app compat library. It has a fragment container to add fragments - * dynamically with many other useful methods to provide a good looking - * material design UI. + * Base activity to handle everything related to design support and the app compat library. + * It has a fragment container to add fragments dynamically with many other useful methods to + * provide a good looking material design UI. * - *

If {@link android.support.design.internal.NavigationMenu} is required - * then, please check {@link DynamicDrawerActivity}.

+ *

If {@link com.google.android.material.internal.NavigationMenu} is required then, + * please check {@link DynamicDrawerActivity}. */ public abstract class DynamicActivity extends DynamicStateActivity { @@ -91,15 +88,11 @@ public abstract class DynamicActivity extends DynamicStateActivity { /** * Root view of the toolbar search view. - * - * @see #mSearchViewEditText */ protected ViewGroup mSearchViewRoot; /** * Button to clear the toolbar search view edit text. - * - * @see #mSearchViewEditText */ protected ImageView mSearchViewClear; @@ -109,13 +102,8 @@ public abstract class DynamicActivity extends DynamicStateActivity { protected DynamicSearchListener mDynamicSearchListener; /** - * Title used by the app toolbar. - */ - protected TextView mTitle; - - /** - * Floating action button used by this activity. Use the methods - * {@link #setFAB(Drawable, int, View.OnClickListener)} or + * Floating action button used by this activity. + *

Use the methods {@link #setFAB(Drawable, int, View.OnClickListener)} or * {@link #setFAB(int, int, View.OnClickListener)} to enable it. */ protected FloatingActionButton mFAB; @@ -141,31 +129,31 @@ public abstract class DynamicActivity extends DynamicStateActivity { protected Menu mMenu; /** - * Back drop frame for the {@link CollapsingToolbarLayout}. + * Back drop frame for the collapsing toolbar layout. */ protected ViewGroup mFrameBackDrop; /** - * Header frame just below the app toolbar to add custom views - * like tabs, hints, etc. Use the methods {@link #addHeader(int, boolean)} - * or {@link #addHeader(View, boolean)} to add the views. - */ + * Header frame just below the app toolbar to add custom views like tabs, hints, etc. + *

Use the methods {@link #addHeader(int, boolean)} or {@link #addHeader(View, boolean)} + * to add the views. + */ protected ViewGroup mFrameHeader; /** - * Footer frame at the bottom of the screen to add custom views - * like bottom navigation bar, ads, etc. Use the methods - * {@link #addFooter(int, boolean)} or {@link #addFooter(View, boolean)} + * Footer frame at the bottom of the screen to add custom views like + * bottom navigation bar, ads, etc. + *

Use the methods {@link #addFooter(int, boolean)} or {@link #addFooter(View, boolean)} * to add the views. */ protected ViewGroup mFrameFooter; /** - * Frame layout to hold the content fragment. Use the methods - * {@link #switchFragment(Fragment, boolean, String)} or + * Frame layout to hold the content fragment. + *

Use the methods {@link #switchFragment(Fragment, boolean, String)} or * {@link #switchFragment(Fragment, boolean)} ot - * {@link #switchFragment(FragmentTransaction, Fragment, boolean, String)} - * to add or change the fragments. + * {@link #switchFragment(FragmentTransaction, Fragment, boolean, String)} to add or + * change the fragments. */ protected FrameLayout mFrameContent; @@ -192,7 +180,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { mCoordinatorLayout = findViewById(R.id.ads_coordinator_layout); mAppBarLayout = findViewById(R.id.ads_app_bar_layout); - mFrameContent.setBackgroundColor(DynamicTheme.getInstance().getBackgroundColor()); + mFrameContent.setBackgroundColor(DynamicTheme.getInstance().get().getBackgroundColor()); mAppBarLayout.addOnOffsetChangedListener(mAppBarStateListener); if (getContentRes() != ADS_DEFAULT_LAYOUT_RES) { @@ -203,7 +191,6 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { if (setCollapsingToolbarLayout()) { mCollapsingToolbarLayout = findViewById(R.id.ads_collapsing_toolbar_layout); mFrameBackDrop = findViewById(R.id.ads_backdrop_frame); - //mTitle = findViewById(R.id.ads_text_app_title); } setSupportActionBar(mToolbar); @@ -230,20 +217,22 @@ public void setStatusBarColor(@ColorInt int color) { if (!isDrawerActivity()) { if (mCoordinatorLayout != null) { - mCoordinatorLayout.setStatusBarBackgroundColor(color); + mCoordinatorLayout.setStatusBarBackgroundColor(getStatusBarColor()); } if (mCollapsingToolbarLayout != null) { - mCollapsingToolbarLayout.setStatusBarScrimColor(color); + mCollapsingToolbarLayout.setStatusBarScrimColor(getStatusBarColor()); mCollapsingToolbarLayout.setContentScrimColor( - DynamicTheme.getInstance().getPrimaryColor()); + DynamicTheme.getInstance().get().getPrimaryColor()); } else { - setWindowStatusBarColor(color); + setWindowStatusBarColor(getStatusBarColor()); } } } /** + * Checks whether the navigation drawer is added. + * * @return {@code true} if this activity is a drawer activity. */ protected boolean isDrawerActivity() { @@ -251,14 +240,14 @@ protected boolean isDrawerActivity() { } @Override - public void onSaveInstanceState(@NonNull Bundle savedInstanceState) { - super.onSaveInstanceState(savedInstanceState); + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); - savedInstanceState.putBoolean(ADS_STATE_APP_BAR_COLLAPSED, isAppBarCollapsed()); - savedInstanceState.putInt(ADS_STATE_FAB_VISIBLE, mFAB.getVisibility()); + outState.putBoolean(ADS_STATE_APP_BAR_COLLAPSED, isAppBarCollapsed()); + outState.putInt(ADS_STATE_FAB_VISIBLE, mFAB.getVisibility()); if (mSearchViewRoot != null) { - savedInstanceState.putBoolean(ADS_STATE_SEARCH_VIEW_VISIBLE, + outState.putBoolean(ADS_STATE_SEARCH_VIEW_VISIBLE, mSearchViewRoot.getVisibility() == View.VISIBLE); } } @@ -269,6 +258,15 @@ public boolean onCreateOptionsMenu(Menu menu) { return super.onCreateOptionsMenu(menu); } + @Override + public void onActionModeStarted(@NonNull android.view.ActionMode mode) { + super.onActionModeStarted(mode); + + DynamicDrawableUtils.setBackground(mode.getCustomView(), + DynamicDrawableUtils.colorizeDrawable(mode.getCustomView().getBackground(), + DynamicTheme.getInstance().get().getBackgroundColor())); + } + @Override public void setTitle(@Nullable CharSequence title) { super.setTitle(title); @@ -279,13 +277,12 @@ public void setTitle(@Nullable CharSequence title) { if (mCollapsingToolbarLayout != null) { mCollapsingToolbarLayout.setTitle(title); - //mTitle.setText(title); } } @Override - public void setTitle(@StringRes int titleId) { - setTitle(getText(titleId)); + public void setTitle(@StringRes int titleRes) { + setTitle(getText(titleRes)); } @Override @@ -301,8 +298,8 @@ protected boolean setCollapsingToolbarLayout() { } /** - * @return The custom layout resource id. Just return - * {@link #ADS_DEFAULT_LAYOUT_RES} to use the default inbuilt layouts. + * @return The custom layout resource. Just return {@link #ADS_DEFAULT_LAYOUT_RES} to use + * the default inbuilt layouts. */ protected @LayoutRes int getLayoutRes() { return setCollapsingToolbarLayout() @@ -310,20 +307,19 @@ protected boolean setCollapsingToolbarLayout() { } /** - * @return The custom content resource id if no fragment is required. - * It will automatically add this layout in the {@link #mFrameContent}. + * @return The custom content resource if no fragment is required. It will automatically + * add this layout in the {@link #mFrameContent}. */ protected abstract @LayoutRes int getContentRes(); /** - * Set the icon and on click listener for the back or up button in the - * app bar. + * Set the icon and on click listener for the back or up button in the app bar. * - * @param icon Drawable used for the back or up button. - * @param onClickListener On click listener for the back or up button. + * @param icon The drawable used for the back or up button. + * @param onClickListener The click listener for the back or up button. */ public void setNavigationClickListener(@Nullable Drawable icon, - @Nullable View.OnClickListener onClickListener) { + @Nullable View.OnClickListener onClickListener) { mToolbar.setNavigationIcon(icon); setSupportActionBar(mToolbar); @@ -337,23 +333,22 @@ public void setNavigationClickListener(@Nullable Drawable icon, } /** - * Set the icon and on click listener for the back or up button in the - * app bar. + * Set the icon and on click listener for the back or up button in the app bar. * - * @param iconRes Drawable resource id used for the back or up button. - * @param onClickListener On click listener for the back or up button. + * @param iconRes The drawable resource used for the back or up button. + * @param onClickListener The click listener for the back or up button. */ public void setNavigationClickListener(@DrawableRes int iconRes, - @Nullable View.OnClickListener onClickListener) { + @Nullable View.OnClickListener onClickListener) { setNavigationClickListener(DynamicResourceUtils.getDrawable( this, iconRes), onClickListener); } /** * Sets the on click listener for the back or up button in the app bar. - * If no listener is supplied then, it will automatically hide the button. + *

If no listener is supplied then, it will automatically hide the button. * - * @param onClickListener On click listener for the back or up button. + * @param onClickListener The click listener for the back or up button. */ public void setNavigationClickListener(@Nullable View.OnClickListener onClickListener) { setNavigationClickListener(onClickListener != null @@ -362,6 +357,8 @@ public void setNavigationClickListener(@Nullable View.OnClickListener onClickLis } /** + * Returns the app toolbar used by this activity. + * * @return The app toolbar used by this activity. */ public @Nullable Toolbar getToolbar() { @@ -369,14 +366,18 @@ public void setNavigationClickListener(@Nullable View.OnClickListener onClickLis } /** - * @return {@code true} if the app bar is visible. It will be used - * internally to maintain the app bar state. + * Returns whether the app bar is visible. + * + * @return {@code true} if the app bar is visible. It will be used internally to maintain + * the app bar state. */ public boolean isAppBarVisible() { return mAppBarVisible; } /** + * Returns the coordinator layout used by this activity. + * * @return The coordinator layout used by this activity. */ public @Nullable CoordinatorLayout getCoordinatorLayout() { @@ -384,6 +385,8 @@ public boolean isAppBarVisible() { } /** + * Returns the collapsing toolbar layout used by this activity. + * * @return The collapsing toolbar layout used by this activity. */ public CollapsingToolbarLayout getCollapsingToolbarLayout() { @@ -391,13 +394,12 @@ public CollapsingToolbarLayout getCollapsingToolbarLayout() { } /** - * Set layout scroll flags for the {@link #mCollapsingToolbarLayout}. - * Useful to change the collapse mode dynamically. + * Set layout scroll flags for the collapsing toolbar layout. + *

Useful to change the collapse mode dynamically. * - * @param flags Scroll flags for the collapsing toolbar layout. + * @param flags The scroll flags for the collapsing toolbar layout. */ - public void setCollapsingToolbarLayoutFlags( - @AppBarLayout.LayoutParams.ScrollFlags int flags) { + public void setCollapsingToolbarLayoutFlags(@AppBarLayout.LayoutParams.ScrollFlags int flags) { if (mCollapsingToolbarLayout != null) { AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) mCollapsingToolbarLayout.getLayoutParams(); @@ -407,13 +409,12 @@ public void setCollapsingToolbarLayoutFlags( } /** - * Set layout scroll flags for the {@link #mToolbar}. Useful to - * change the collapse mode dynamically. + * Set layout scroll flags for the toolbar. + *

Useful to change the collapse mode dynamically. * - * @param flags Scroll flags for the collapsing toolbar layout. + * @param flags The scroll flags for the collapsing toolbar layout. */ - public void setToolbarLayoutFlags( - @AppBarLayout.LayoutParams.ScrollFlags int flags) { + public void setToolbarLayoutFlags(@AppBarLayout.LayoutParams.ScrollFlags int flags) { if (mToolbar != null) { AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) mToolbar.getLayoutParams(); @@ -423,8 +424,8 @@ public void setToolbarLayoutFlags( } /** - * Set the {@link #mToolbar} or {@link #mCollapsingToolbarLayout} - * visibility (collectively known as app bar) if available. + * Set the toolbar or collapsing toolbar layout visibility (collectively known as app bar) + * if available. * * @param appBarVisible {@code true} to make the app bar visible. */ @@ -439,14 +440,18 @@ public void setAppBarVisible(boolean appBarVisible) { } /** - * Add a backdrop view for the {@link #mCollapsingToolbarLayout} which - * will be shown when it is expanded and will be hidden on collapsing - * the toolbar. + * Add a backdrop view for the collapsing toolbar layout which will be shown when it is + * expanded and will be hidden on collapsing the toolbar. * - * @param view View to be added as the backdrop frame. - * @param expandedTitleColor Title color when the toolbar is expanded. + * @param view The view to be added as the backdrop frame. + * @param expandedTitleColor The title color when the toolbar is expanded. */ public void setAppBarBackDrop(@Nullable View view, @ColorInt int expandedTitleColor) { + if (DynamicTheme.getInstance().get().isBackgroundAware()) { + expandedTitleColor = DynamicColorUtils.getContrastColor( + expandedTitleColor, DynamicTheme.getInstance().get().getPrimaryColor()); + } + if (mCollapsingToolbarLayout != null) { if (mFrameBackDrop.getChildCount() > 0) { mFrameBackDrop.removeAllViews(); @@ -455,37 +460,31 @@ public void setAppBarBackDrop(@Nullable View view, @ColorInt int expandedTitleCo if (view != null) { mFrameBackDrop.addView(view); setAppBarTransparent(true); - mCollapsingToolbarLayout - .setExpandedTitleColor(expandedTitleColor); - mCollapsingToolbarLayout - .setCollapsedTitleTextColor(expandedTitleColor); - //mTitle.setVisibility(View.GONE); + mCollapsingToolbarLayout.setExpandedTitleColor(expandedTitleColor); + mCollapsingToolbarLayout.setCollapsedTitleTextColor(expandedTitleColor); } } } /** - * Add a backdrop view for the {@link #mCollapsingToolbarLayout} which - * will be shown when it is expanded and will be hidden on collapsing - * the toolbar. + * Add a backdrop view for the collapsing toolbar layout which will be shown when it is + * expanded and will be hidden on collapsing the toolbar. * - * @param layoutId Layout resource id to be added as the backdrop frame. - * @param expandedTitleColorRes Title color resource id when the toolbar - * is expanded. + * @param layoutRes The layout resource to be added as the backdrop frame. + * @param expandedTitleColorRes The title color resource when the toolbar is expanded. */ - public void setAppBarBackDropRes(@LayoutRes int layoutId, - @ColorRes int expandedTitleColorRes) { - setAppBarBackDrop(LayoutInflater.from(this).inflate(layoutId, + public void setAppBarBackDropRes(@LayoutRes int layoutRes, + @ColorRes int expandedTitleColorRes) { + setAppBarBackDrop(LayoutInflater.from(this).inflate(layoutRes, new LinearLayout(this), false), ContextCompat.getColor(this, expandedTitleColorRes)); } /** - * Set the drawable for backdrop image used by the - * {@link #mCollapsingToolbarLayout} which will be shown when it is - * expanded and will be hidden on collapsing the toolbar. + * Set the drawable for backdrop image used by the collapsing toolbar layout which will be + * shown when it is expanded and will be hidden on collapsing the toolbar. * - * @param drawable Drawable for the backdrop image. + * @param drawable The drawable for the backdrop image. */ public void setAppBarBackDrop(@Nullable Drawable drawable) { View view = LayoutInflater.from(this).inflate(R.layout.ads_appbar_backdrop_image, @@ -493,23 +492,22 @@ public void setAppBarBackDrop(@Nullable Drawable drawable) { ((ImageView) view.findViewById(R.id.ads_image_backdrop)) .setImageDrawable(drawable); - setAppBarBackDrop(view, DynamicTheme.getInstance().getTintPrimaryColor()); + setAppBarBackDrop(view, DynamicTheme.getInstance().get().getTintPrimaryColor()); } /** - * Set the drawable id for backdrop image used by the - * {@link #mCollapsingToolbarLayout} hich will be shown when it is expanded - * and will be hidden on collapsing the toolbar. + * Set the drawable id for backdrop image used by the collapsing toolbar layout which will be + * shown when it is expanded and will be hidden on collapsing the toolbar. * - * @param drawableRes Drawable resource id for the backdrop image. + * @param drawableRes The drawable resource for the backdrop image. */ public void setAppBarBackDrop(@DrawableRes int drawableRes) { setAppBarBackDrop(DynamicResourceUtils.getDrawable(this, drawableRes)); } /** - * Make the app bar transparent or translucent. Useful to make it - * transparent if a backdrop view has been added. + * Make the app bar transparent or translucent. + *

Useful to make it transparent if a backdrop view has been added. * * @param transparent {@code true} to make the app bar transparent. */ @@ -517,7 +515,7 @@ public void setAppBarTransparent(boolean transparent) { if (getSupportActionBar() != null) { getSupportActionBar().setBackgroundDrawable( new ColorDrawable(transparent ? Color.TRANSPARENT - : DynamicTheme.getInstance().getPrimaryColor())); + : DynamicTheme.getInstance().get().getPrimaryColor())); } } @@ -532,22 +530,25 @@ public void showAppBarShadow(boolean visible) { } /** - * @return The header frame just below the app toolbar to add custom views - * like tabs, hints, etc. Use the methods {@link #addHeader(int, boolean)} - * or {@link #addHeader(View, boolean)} to add the views. + * Get the header frame just below the app toolbar to add custom views like tabs, hints, etc. + *

Use the methods {@link #addHeader(int, boolean)} or {@link #addHeader(View, boolean)} + * to add the views. + * + * @return The header frame just below the app toolbar to add custom views like tabs, + * hints, etc. */ public @Nullable ViewGroup getFrameHeader() { return mFrameHeader; } /** - * Add header view just below the app bar. Useful to add tabs or hints - * dynamically. Multiple views can be added and the default background - * will be the app bar background (theme primary color). Please check - * {@link DynamicSplashFragment} - * to add the tabs automatically. + * Add header view just below the app bar. + *

Useful to add tabs or hints dynamically. Multiple views can be added and the default + * background will be the app bar background (theme primary color). Please check + * {@link com.pranavpandey.android.dynamic.support.fragment.DynamicViewPagerFragment} to + * add the tabs automatically. * - * @param view View to be added in the header frame. + * @param view The view to be added in the header frame. * @param removePrevious {@code true} to remove the previously added views. */ public void addHeader(@Nullable View view, boolean removePrevious) { @@ -561,38 +562,39 @@ public void addHeader(@Nullable View view, boolean removePrevious) { } /** - * Add header view just below the app bar. Useful to add tabs or hints - * dynamically. Multiple views can be added and the default background - * will be the app bar background (theme primary color). Please check - * {@link DynamicSplashFragment} - * to add the tabs automatically. + * Add header view just below the app bar. + *

Useful to add tabs or hints dynamically. Multiple views can be added and the default + * background will be the app bar background (theme primary color). Please check + * {@link com.pranavpandey.android.dynamic.support.fragment.DynamicViewPagerFragment} to + * add the tabs automatically. * - * @param layoutId Layout resource id to be added in the header frame. + * @param layoutRes The layout resource to be added in the header frame. * @param removePrevious {@code true} to remove the previously added views. */ - public void addHeader(@LayoutRes int layoutId, boolean removePrevious) { - addHeader(LayoutInflater.from(this).inflate(layoutId, + public void addHeader(@LayoutRes int layoutRes, boolean removePrevious) { + addHeader(LayoutInflater.from(this).inflate(layoutRes, new LinearLayout(this), false), removePrevious); } /** - * @return The footer frame at the bottom of the screen to add custom views - * like bottom navigation bar, ads, etc. Use the methods - * {@link #addFooter(int, boolean)} or {@link #addFooter(View, boolean)} - * to add the views. + * Get the footer frame at the bottom of the screen to add custom views like + * bottom navigation bar, ads, etc. + *

Use the methods {@link #addFooter(int, boolean)} or {@link #addFooter(View, boolean)} + * to add the views. + * + * @return The footer frame at the bottom of the screen to add custom views like + * bottom navigation bar, ads, etc. */ public @Nullable ViewGroup getFrameFooter() { return mFrameFooter; } /** - * Add footer view at the bottom of the screen. Useful to add bottom navigation - * bar, ads, etc. dynamically. Multiple views can be added and the default - * background will be the app bar background (theme primary color). Please - * check {@link DynamicSplashFragment} - * to add the tabs automatically. + * Add footer view at the bottom of the screen. + *

Useful to add bottom navigation bar, ads, etc. dynamically. Multiple views can be + * added and the default background will be the app bar background (theme primary color). * - * @param view View to be added in the header frame. + * @param view The view to be added in the header frame. * @param removePrevious {@code true} to remove the previously added views. */ public void addFooter(@Nullable View view, boolean removePrevious) { @@ -606,17 +608,15 @@ public void addFooter(@Nullable View view, boolean removePrevious) { } /** - * Add footer view at the bottom of the screen. Useful to add bottom navigation - * bar, ads, etc. dynamically. Multiple views can be added and the default - * background will be the app bar background (theme primary color). Please - * check {@link DynamicSplashFragment} - * to add the tabs automatically. + * Add footer view at the bottom of the screen. + *

Useful to add bottom navigation bar, ads, etc. dynamically. Multiple views can be + * added and the default background will be the app bar background (theme primary color). * - * @param layoutId Layout resource id to be added in the header frame. + * @param layoutRes The layout resource to be added in the header frame. * @param removePrevious {@code true} to remove the previously added views. */ - public void addFooter(@LayoutRes int layoutId, boolean removePrevious) { - addFooter(LayoutInflater.from(this).inflate(layoutId, + public void addFooter(@LayoutRes int layoutRes, boolean removePrevious) { + addFooter(LayoutInflater.from(this).inflate(layoutRes, new LinearLayout(this), false), removePrevious); } @@ -653,8 +653,7 @@ public void onClick(View view) { if (mSearchViewEditText != null) { mSearchViewEditText.addTextChangedListener(new TextWatcher() { @Override - public void beforeTextChanged(CharSequence charSequence, - int i, int i1, int i2) { } + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { @@ -684,8 +683,7 @@ private void setSearchViewClearButton() { } /** - * Restore the search view state after the configuration - * change. + * Restore the search view state after the configuration change. */ public void restoreSearchViewState() { mSearchViewEditText.post(new Runnable() { @@ -704,8 +702,7 @@ public void run() { /** * Expand search view to start searching. * - * @param requestSoftInput {@code true} to request the soft input - * keyboard. + * @param requestSoftInput {@code true} to request the soft input keyboard. */ public void expandSearchView(boolean requestSoftInput) { if (mSearchViewRoot != null && mSearchViewRoot.getVisibility() == View.GONE) { @@ -751,16 +748,14 @@ public boolean isSearchViewExpanded() { } /** - * @return The listener to listen search view expand and collapse - * callbacks. + * @return The listener to listen search view expand and collapse callbacks. */ public @Nullable DynamicSearchListener getSearchViewListener() { return mDynamicSearchListener; } /** - * Sets the listener to listen search view expand and collapse - * callbacks. + * Sets the listener to listen search view expand and collapse callbacks. * * @param dynamicSearchListener The listener to be set. */ @@ -785,22 +780,19 @@ public void onBackPressed() { } /** - * Set a floating action button ({@link #mFAB}) used by this activity - * by supplying an image drawable, current visibility and a click - * listener. FAB will be tinted automatically according to the accent - * color used by this activity. + * Set a floating action button (FAB) used by this activity by supplying an image drawable, + * current visibility and a click listener. FAB will be tinted automatically according to the + * accent color used by this activity. * - *

Please use {@link #getFAB()} method to perform more operations - * dynamically.

+ *

Please use {@link #getFAB()} method to perform more operations dynamically. * - * @param drawable Image drawable for the floating action button. - * @param visibility Current FAB visibility. {@link View#VISIBLE}, - * {@link View#INVISIBLE} or {@link View#GONE}. - * @param onClickListener Callback that will run when this view is - * clicked. + * @param drawable The image drawable to be set. + * @param visibility The visibility to be set. + *

C{@link View#VISIBLE}, {@link View#INVISIBLE} or {@link View#GONE}. + * @param onClickListener Callback that will run when this view is clicked. */ public void setFAB(@Nullable Drawable drawable, int visibility, - @Nullable View.OnClickListener onClickListener) { + @Nullable View.OnClickListener onClickListener) { if (mFAB != null) { setFABImageDrawable(drawable); mFAB.setOnClickListener(onClickListener); @@ -809,56 +801,53 @@ public void setFAB(@Nullable Drawable drawable, int visibility, } /** - * Set a floating action button ({@link #mFAB}) used by this activity - * by supplying an image drawable resource, current visibility and a - * click listener. FAB will be tinted automatically according to the + * Set a floating action button (FAB) used by this activity by supplying an image drawable, + * current visibility and a click listener. FAB will be tinted automatically according to the * accent color used by this activity. * - *

Please use {@link #getFAB()} method to perform more operations - * dynamically.

+ *

Please use {@link #getFAB()} method to perform more operations dynamically. * - * @param drawableRes Image drawable resource for the floating action - * button. - * @param visibility Current FAB visibility. {@link View#VISIBLE}, - * {@link View#INVISIBLE} or {@link View#GONE}. - * @param onClickListener Callback that will run when this view is - * clicked. + * @param drawableRes The image drawable resource to be set. + * @param visibility The visibility to be set. + *

{@link View#VISIBLE}, {@link View#INVISIBLE} or {@link View#GONE}. + * @param onClickListener Callback that will run when this view is clicked. */ public void setFAB(@DrawableRes int drawableRes, int visibility, - @Nullable View.OnClickListener onClickListener) { + @Nullable View.OnClickListener onClickListener) { setFAB(DynamicResourceUtils.getDrawable( this, drawableRes), visibility, onClickListener); } /** - * Set the {@link #mFAB} image drawable. Image will be tinted automatically - * according to its background color to provide best visibility. + * Set the FAB image drawable resource. + *

Image will be tinted automatically according to its background color to provide + * best visibility. * - * @param drawable Image drawable for the floating action button. + * @param drawable The image drawable for the floating action button. */ - public void setFABImageDrawable(@Nullable Drawable drawable) { + public void setFABImageDrawable(final @Nullable Drawable drawable) { if (mFAB != null) { - if (drawable != null) { - mFAB.setImageDrawable(drawable); + mFAB.setImageDrawable(drawable); + + if (drawable == null) { + hideFAB(); } } } /** - * Set the {@link #mFAB} image drawable resource. Image will be tinted - * automatically according to its background color to provide best - * visibility. + * Set the FAB image drawable resource. + *

Image will be tinted automatically according to its background color to provide + * best visibility. * - * @param drawableRes Image drawable resource for the floating action - * button. + * @param drawableRes The image drawable resource for the floating action button. */ public void setFABImageDrawable(@DrawableRes int drawableRes) { setFABImageDrawable(DynamicResourceUtils.getDrawable(this, drawableRes)); } /** - * Set the {@link #mFAB} visibility to {@link View#VISIBLE}, - * {@link View#INVISIBLE} or {@link View#GONE} + * Set the FAB visibility to {@link View#VISIBLE}, {@link View#INVISIBLE} or {@link View#GONE}. */ public void setFABVisibility(int visibility) { if (mFAB != null && visibility != ADS_VISIBILITY_FAB_NO_CHANGE) { @@ -868,31 +857,29 @@ public void setFABVisibility(int visibility) { break; case View.INVISIBLE: case View.GONE: - DynamicFABUtils.show(mFAB); + DynamicFABUtils.hide(mFAB); break; } } } /** - * Show the {@link #mFAB} by setting its visibility to - * {@link View#VISIBLE}. + * Show the FAB by setting its visibility to {@link View#VISIBLE}. */ public void showFAB() { setFABVisibility(View.VISIBLE); } /** - * Hide the {@link #mFAB} by setting its visibility to - * {@link View#GONE}. + * Hide the FAB by setting its visibility to {@link View#GONE}. */ public void hideFAB() { - setFABVisibility(View.INVISIBLE); + setFABVisibility(View.GONE); } /** - * Remove the {@link #mFAB} associated with this activity. Please call - * the methods {@link #setFAB(int, int, View.OnClickListener)} or + * Remove the FAB associated with this activity. + *

Please call the methods {@link #setFAB(int, int, View.OnClickListener)} or * {@link #setFAB(Drawable, int, View.OnClickListener)} to set it again. */ public void removeFAB() { @@ -904,76 +891,69 @@ public void removeFAB() { } /** - * Make a themed snack bar with text and action. Background will be - * the current navigation bar color to blend it smoothly and it will - * automatically use its tint color for the text and action to provide - * best visibility. + * Make a themed snack bar with text and action. Background will be the tint background color + * to blend it smoothly and it will automatically use its tint color for the text and action + * to provide best visibility. * * @param text The text to show. Can be formatted text. - * @param duration The duration of the snack bar. Can be - * {@link Snackbar#LENGTH_SHORT}, - * {@link Snackbar#LENGTH_LONG} or - * {@link Snackbar#LENGTH_INDEFINITE}. + * @param duration The duration of the snack bar. + *

{@link Snackbar#LENGTH_SHORT}, {@link Snackbar#LENGTH_LONG} + * or {@link Snackbar#LENGTH_INDEFINITE}. * - * @return Snack bar with the supplied parameters. - * Use {@link Snackbar#show()} to display the snack bar. + * @return The snack bar with the supplied parameters. + *

Use {@link Snackbar#show()} to display the snack bar. */ public @NonNull Snackbar getSnackBar(@NonNull CharSequence text, - @BaseTransientBottomBar.Duration int duration) { + @Snackbar.Duration int duration) { return DynamicHintUtils.getSnackBar(mCoordinatorLayout, text, - getAppliedNavigationBarColor(), DynamicColorUtils.getTintColor( - getAppliedNavigationBarColor()), duration); + DynamicTheme.getInstance().get().getTintBackgroundColor(), + DynamicTheme.getInstance().get().getBackgroundColor(), duration); } /** - * Make a themed snack bar with text and action. Background will be - * the current navigation bar color to blend it smoothly and it will - * automatically use its tint color for the text and action to provide - * best visibility. + * Make a themed snack bar with text and action. Background will be the tint background color + * to blend it smoothly and it will automatically use its tint color for the text and action + * to provide best visibility. * - * @param stringId The string resource id. - * @param duration The duration of the snack bar. Can be - * {@link Snackbar#LENGTH_SHORT}, - * {@link Snackbar#LENGTH_LONG} or - * {@link Snackbar#LENGTH_INDEFINITE}. + * @param stringRes The string resource for the snack bar. + * @param duration The duration of the snack bar. + *

{@link Snackbar#LENGTH_SHORT}, {@link Snackbar#LENGTH_LONG} + * or {@link Snackbar#LENGTH_INDEFINITE}. * - * @return Snack bar with the supplied parameters. - * Use {@link Snackbar#show()} to display the snack bar. + * @return The snack bar with the supplied parameters. + *

Use {@link Snackbar#show()} to display the snack bar. */ - public @Nullable Snackbar getSnackBar(@StringRes int stringId, - @BaseTransientBottomBar.Duration int duration) { - return getSnackBar(getString(stringId), duration); + public @NonNull Snackbar getSnackBar(@StringRes int stringRes, + @Snackbar.Duration int duration) { + return getSnackBar(getString(stringRes), duration); } /** - * Make a themed snack bar with text and action. Background will be - * the current navigation bar color to blend it smoothly and it will - * automatically use its tint color for the text and action to provide - * best visibility. + * Make a themed snack bar with text and action. Background will be the tint background color + * to blend it smoothly and it will automatically use its tint color for the text and action + * to provide best visibility. * * @param text The text to show. Can be formatted text. * - * @return Snack bar with the supplied parameters. - * Use {@link Snackbar#show()} to display the snack bar. + * @return The snack bar with the supplied parameters. + *

Use {@link Snackbar#show()} to display the snack bar. */ - @SuppressLint("Range") public @NonNull Snackbar getSnackBar(@NonNull CharSequence text) { return getSnackBar(text, Snackbar.LENGTH_LONG); } /** - * Make a themed snack bar with text and action. Background will be - * the current navigation bar color to blend it smoothly and it will - * automatically use its tint color for the text and action to provide - * best visibility. + * Make a themed snack bar with text and action. Background will be the tint background color + * to blend it smoothly and it will automatically use its tint color for the text and action + * to provide best visibility. * - * @param stringId The string resource id. + * @param stringRes The string resource for the snack bar. * - * @return Snack bar with the supplied parameters. - * Use {@link Snackbar#show()} to display the snack bar. + * @return The snack bar with the supplied parameters. + *

Use {@link Snackbar#show()} to display the snack bar. */ - public @NonNull Snackbar getSnackBar(@StringRes int stringId) { - return getSnackBar(getString(stringId)); + public @NonNull Snackbar getSnackBar(@StringRes int stringRes) { + return getSnackBar(getString(stringRes)); } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/activity/DynamicDrawerActivity.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/activity/DynamicDrawerActivity.java index 02bad5dbfc..cf0c12d361 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/activity/DynamicDrawerActivity.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/activity/DynamicDrawerActivity.java @@ -21,32 +21,33 @@ import android.graphics.Color; import android.graphics.drawable.Drawable; import android.os.Bundle; -import android.support.annotation.ColorInt; -import android.support.annotation.DrawableRes; -import android.support.annotation.MenuRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.design.widget.NavigationView; -import android.support.v4.view.GravityCompat; -import android.support.v4.widget.DrawerLayout; -import android.support.v7.app.ActionBarDrawerToggle; import android.view.View; import android.view.ViewGroup; import android.view.animation.DecelerateInterpolator; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.ColorInt; +import androidx.annotation.DrawableRes; +import androidx.annotation.MenuRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StringRes; +import androidx.appcompat.app.ActionBarDrawerToggle; +import androidx.core.view.GravityCompat; +import androidx.drawerlayout.widget.DrawerLayout; + +import com.google.android.material.navigation.NavigationView; import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; import com.pranavpandey.android.dynamic.support.utils.DynamicLayoutUtils; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; +import com.pranavpandey.android.dynamic.support.utils.DynamicTintUtils; import com.pranavpandey.android.dynamic.utils.DynamicUnitUtils; /** - * Base drawer activity to handle everything related to the {@link DrawerLayout} - * and {@link android.support.design.internal.NavigationMenu}. It has many other - * useful functions to customise according to the need. + * Base drawer activity to handle everything related to the {@link DrawerLayout} and + * {@link com.google.android.material.internal.NavigationMenu}. + *

It also has many other useful functions to customise according to the need. */ public abstract class DynamicDrawerActivity extends DynamicActivity implements NavigationView.OnNavigationItemSelectedListener { @@ -67,17 +68,17 @@ public abstract class DynamicDrawerActivity extends DynamicActivity private NavigationView mNavigationView; /** - * Header image view used by the {@link #mNavigationView}. + * Header image view used by the navigation view. */ private ImageView mNavHeaderIcon; /** - * Title text view used by the {@link #mNavigationView}. + * Title text view used by the navigation view. */ private TextView mNavHeaderTitle; /** - * Subtitle text view used by the {@link #mNavigationView}. + * Subtitle text view used by the navigation view. */ private TextView mNavHeaderSubtitle; @@ -102,7 +103,6 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { .findViewById(R.id.ads_header_drawer_subtitle); mDrawer.setDrawerElevation(DynamicUnitUtils.convertDpToPixels(8)); - mNavigationView.setBackgroundColor(DynamicTheme.getInstance().getBackgroundColor()); setStatusBarColor(getStatusBarColor()); setupDrawer(); @@ -136,13 +136,15 @@ public void setStatusBarColor(@ColorInt int color) { if (isDrawerActivity()) { if (mDrawer != null) { - mDrawer.setStatusBarBackgroundColor(color); + mDrawer.setStatusBarBackgroundColor(getStatusBarColor()); mDrawer.setDrawerShadow(R.drawable.ads_drawer_shadow_start, GravityCompat.START); } } } /** + * Sets the action bar drawer toggle icon according to the returned value. + * * @return {@code true} to show the drawer toggle icon. */ protected boolean setActionBarDrawerToggle() { @@ -180,6 +182,8 @@ public void onDrawerStateChanged(int newState) { } }); mNavigationView.setNavigationItemSelectedListener(this); + DynamicTintUtils.setNavigationViewScrimColor(mNavigationView, getStatusBarColor()); + configureDrawer(); } @@ -210,8 +214,9 @@ public void run() { } /** - * @return {@code true} to make the drawer persistent by locking - * it in the open mode. + * Makes the drawer persistent according to the returned value. + * + * @return {@code true} to make the drawer persistent by locking it in the open mode. * * @see DrawerLayout#LOCK_MODE_LOCKED_OPEN */ @@ -221,6 +226,8 @@ public boolean isPersistentDrawer() { } /** + * Get the drawer layout used by this activity. + * * @return The drawer layout used by this activity. */ public @NonNull DrawerLayout getDrawer() { @@ -230,13 +237,12 @@ public boolean isPersistentDrawer() { /** * Close the drawer if it is not in the locked state. * - * @param gravity Gravity of the drawer to close it. + * @param gravity The gravity of the drawer to close it. * * @see DrawerLayout#LOCK_MODE_LOCKED_OPEN */ public void closeDrawer(int gravity) { - if (mDrawer.isDrawerVisible(gravity) - && mDrawer.getDrawerLockMode(gravity) + if (mDrawer.isDrawerVisible(gravity) && mDrawer.getDrawerLockMode(gravity) != DrawerLayout.LOCK_MODE_LOCKED_OPEN) { mDrawer.closeDrawer(gravity); } @@ -253,8 +259,9 @@ public void closeDrawers() { } /** - * @return {@code true} if the {@link #mDrawer} is in the locked - * mode. + * Checks whether the drawer is in the locked mode. + * + * @return {@code true} if the drawer is in the locked mode. */ public boolean isDrawerLocked() { return mDrawer.getDrawerLockMode(GravityCompat.START) @@ -264,6 +271,8 @@ public boolean isDrawerLocked() { } /** + * Returns the action bar drawer toggle used by this activity. + * * @return The action bar drawer toggle used by this activity. */ public ActionBarDrawerToggle getDrawerToggle() { @@ -271,23 +280,24 @@ public ActionBarDrawerToggle getDrawerToggle() { } /** - * Set the drawer toggle icon to open or close the navigation - * drawer. + * Set the drawer toggle icon to open or close the navigation drawer. * - * @param showDrawerIndicator {@code true} to show the drawer toggle - * icon. + * @param showDrawerIndicator {@code true} to show the drawer toggle icon. */ public void showDrawerToggle(boolean showDrawerIndicator) { if (mDrawerToggle != null && getSupportActionBar() != null) { if (!showDrawerIndicator) { mDrawerToggle.setDrawerIndicatorEnabled(false); getSupportActionBar().setDisplayHomeAsUpEnabled(true); - getToolbar().setNavigationOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - onBackPressed(); - } - }); + + if (getToolbar() != null) { + getToolbar().setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onBackPressed(); + } + }); + } } else { getSupportActionBar().setDisplayHomeAsUpEnabled(false); mDrawerToggle.setDrawerIndicatorEnabled(true); @@ -297,7 +307,7 @@ public void onClick(View v) { } /** - * Animate the {@link #mDrawerToggle} from one offset to another. + * Animate the drawer toggle icon from one offset to another. * * @param startOffSet The start offset. * @param endOffSet The end offset. @@ -348,6 +358,8 @@ public void onAnimationRepeat(Animator animator) { } /** + * Get the navigation view used by this activity. + * * @return The navigation view used by this activity. */ public @NonNull NavigationView getNavigationView() { @@ -355,66 +367,66 @@ public void onAnimationRepeat(Animator animator) { } /** - * Set the menu for {@link #mNavigationView}. + * Set menu for the navigation view. * - * @param menuId Menu resource id for the navigation view. + * @param menuRes The menu resource id for the navigation view. */ - public void setNavigationViewMenu(@MenuRes int menuId) { + public void setNavigationViewMenu(@MenuRes int menuRes) { mNavigationView.getMenu().clear(); - mNavigationView.inflateMenu(menuId); + mNavigationView.inflateMenu(menuRes); } /** - * Set the header icon for {@link #mNavigationView}. + * Set header icon for the navigation view. * - * @param drawable Drawable for the header image view. + * @param drawable The drawable for the header image view. */ public void setNavHeaderIcon(@Nullable Drawable drawable) { mNavHeaderIcon.setImageDrawable(drawable); } /** - * Set the header icon for {@link #mNavigationView}. + * Set header icon for the navigation view. * - * @param drawableId Drawable resource id for the header image view. + * @param drawableRes The drawable resource for the header image view. */ - public void setNavHeaderIcon(@DrawableRes int drawableId) { - setNavHeaderIcon(DynamicResourceUtils.getDrawable(this, drawableId)); + public void setNavHeaderIcon(@DrawableRes int drawableRes) { + setNavHeaderIcon(DynamicResourceUtils.getDrawable(this, drawableRes)); } /** - * Set the header title for {@link #mNavigationView}. + * Set header title for the navigation view. * - * @param string Text for the title text view. + * @param string The string for the title. */ public void setNavHeaderTitle(@Nullable String string) { mNavHeaderTitle.setText(string); } /** - * Set the header title for {@link #mNavigationView}. + * Set header title for the navigation view. * - * @param stringId String resource id for the title text view. + * @param stringRes The string resource for the title. */ - public void setNavHeaderTitle(@StringRes int stringId) { - mNavHeaderTitle.setText(stringId); + public void setNavHeaderTitle(@StringRes int stringRes) { + mNavHeaderTitle.setText(stringRes); } /** - * Set the header subtitle for {@link #mNavigationView}. + * Set header subtitle for the navigation view. * - * @param string Text for the subtitle text view. + * @param string The string for the subtitle. */ public void setNavHeaderSubtitle(@Nullable String string) { mNavHeaderSubtitle.setText(string); } /** - * Set the header subtitle for {@link #mNavigationView}. + * Set header subtitle for the navigation view. * - * @param stringId String resource id for the subtitle text view. + * @param stringRes The string resource for the subtitle. */ - public void setNavHeaderSubtitle(@StringRes int stringId) { - mNavHeaderSubtitle.setText(stringId); + public void setNavHeaderSubtitle(@StringRes int stringRes) { + mNavHeaderSubtitle.setText(stringRes); } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/activity/DynamicStateActivity.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/activity/DynamicStateActivity.java index 91bd4a2c82..dfd2440b3d 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/activity/DynamicStateActivity.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/activity/DynamicStateActivity.java @@ -17,21 +17,21 @@ package com.pranavpandey.android.dynamic.support.activity; import android.os.Bundle; -import android.support.annotation.IdRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.AppBarLayout; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentTransaction; +import androidx.annotation.IdRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; + +import com.google.android.material.appbar.AppBarLayout; import com.pranavpandey.android.dynamic.support.R; /** - * An activity extending {@link DynamicSystemActivity} to maintain state of - * the widgets and fragments. It will be very useful while handling - * orientation changes. It saves the current fragment state and reuses - * it while a configuration change takes place. + * An activity extending {@link DynamicSystemActivity} to maintain state of the widgets + * and fragments. It will be very useful while handling orientation changes. It saves the + * current fragment state and reuses it while a configuration change takes place. */ public abstract class DynamicStateActivity extends DynamicSystemActivity { @@ -41,8 +41,7 @@ public abstract class DynamicStateActivity extends DynamicSystemActivity { protected static final int STATE_DELAY = 400; /** - * Content fragment TAG key which will be used to find it - * during the configuration changes. + * Content fragment TAG key which will be used to find it during the configuration changes. */ protected static final String ADS_STATE_CONTENT_FRAGMENT_TAG = "ads_state_content_fragment_tag"; @@ -50,8 +49,7 @@ public abstract class DynamicStateActivity extends DynamicSystemActivity { /** * Status bar key to maintain its state. */ - protected static final String ADS_STATE_APP_BAR_COLLAPSED = - "ads_state_app_bar_collapsed"; + protected static final String ADS_STATE_APP_BAR_COLLAPSED = "ads_state_app_bar_collapsed"; /** * FAB key to maintain its state. @@ -61,8 +59,7 @@ public abstract class DynamicStateActivity extends DynamicSystemActivity { /** * Search key to maintain its state. */ - protected static final String ADS_STATE_SEARCH_VIEW_VISIBLE = - "ads_state_search_view_visible"; + protected static final String ADS_STATE_SEARCH_VIEW_VISIBLE = "ads_state_search_view_visible"; /** * FAB visibility constant for no change. @@ -75,8 +72,7 @@ public abstract class DynamicStateActivity extends DynamicSystemActivity { private Fragment mContentFragment; /** - * Content fragment TAG which will be used to find it during - * configuration changes. + * Content fragment TAG which will be used to find it during configuration changes. */ private String mContentFragmentTag; @@ -91,8 +87,7 @@ public abstract class DynamicStateActivity extends DynamicSystemActivity { private boolean mAppBarCollapsed; /** - * App bar off set change listener to identify whether it is in - * the collapsed state or not. + * App bar off set change listener to identify whether it is in the collapsed state. */ protected AppBarLayout.OnOffsetChangedListener mAppBarStateListener = new AppBarLayout.OnOffsetChangedListener() { @@ -129,41 +124,38 @@ public void onBackStackChanged() { if (savedInstanceState != null) { mFABVisibility = ADS_VISIBILITY_FAB_NO_CHANGE; - mContentFragmentTag = savedInstanceState - .getString(ADS_STATE_CONTENT_FRAGMENT_TAG); - mContentFragment = getSupportFragmentManager() - .findFragmentByTag(mContentFragmentTag); + mContentFragmentTag = savedInstanceState.getString(ADS_STATE_CONTENT_FRAGMENT_TAG); + mContentFragment = getSupportFragmentManager().findFragmentByTag(mContentFragmentTag); } } /** - * @return The fragment container id so that the fragment can be - * injected into that view. + * Retrieves the fragment container id. + *

This method must be implemented in the extended activity to show fragments inside + * this container. + * + * @return The fragment container id so that the fragment can be injected into this view. */ protected abstract @IdRes int getFragmentContainerId(); @Override - public void onSaveInstanceState(@NonNull Bundle savedInstanceState) { - super.onSaveInstanceState(savedInstanceState); + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); - savedInstanceState.putString( - ADS_STATE_CONTENT_FRAGMENT_TAG, mContentFragmentTag); + outState.putString(ADS_STATE_CONTENT_FRAGMENT_TAG, mContentFragmentTag); } /** - * Switch the content fragment use by this activity by using the supplied - * fragment transaction. + * Switch the content fragment use by this activity by using the supplied fragment transaction. * - * @param fragmentTransaction Customised fragment transaction to support - * animations and more. - * @param fragment Fragment to be used by this activity. - * @param addToBackStack {@code true} to put previous fragment to back - * stack. - * @param tag Fragment tag to maintain the back stack. + * @param fragmentTransaction The customised fragment transaction to support animations + * and more. + * @param fragment The fragment to be used by this activity. + * @param addToBackStack {@code true} to put previous fragment to back stack. + * @param tag The fragment tag to maintain the back stack. */ protected void switchFragment(@NonNull FragmentTransaction fragmentTransaction, - @NonNull Fragment fragment, boolean addToBackStack, - @Nullable String tag) { + @NonNull Fragment fragment, boolean addToBackStack, @Nullable String tag) { tag = tag != null ? tag : fragment.getClass().getSimpleName(); if (getSupportFragmentManager().findFragmentByTag(tag) != null) { fragment = getSupportFragmentManager().findFragmentByTag(tag); @@ -181,6 +173,11 @@ protected void switchFragment(@NonNull FragmentTransaction fragmentTransaction, setContentFragment(fragment, tag); } + /** + * Commit the fragment transaction. + * + * @param fragmentTransaction The fragment transaction to be committed. + */ private void commitFragmentTransaction(@NonNull FragmentTransaction fragmentTransaction) { try { fragmentTransaction.commit(); @@ -192,23 +189,20 @@ private void commitFragmentTransaction(@NonNull FragmentTransaction fragmentTran /** * Switch the content fragment use by this activity. * - * @param fragment Fragment to be used by this activity. - * @param addToBackStack {@code true} to put previous fragment to back - * stack. - * @param tag Fragment tag to maintain the back stack. + * @param fragment The fragment to be used by this activity. + * @param addToBackStack {@code true} to put previous fragment to back stack. + * @param tag The fragment tag to maintain the back stack. */ - protected void switchFragment(@NonNull Fragment fragment, boolean addToBackStack, - @Nullable String tag) { - FragmentTransaction fragmentTransaction = - getSupportFragmentManager().beginTransaction(); - + protected void switchFragment(@NonNull Fragment fragment, + boolean addToBackStack, @Nullable String tag) { + FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); switchFragment(fragmentTransaction, fragment, addToBackStack, tag); } /** * Switch the content fragment use by this activity. * - * @param fragment Fragment to be used by this activity. + * @param fragment The fragment to be used by this activity. * @param addToBackStack {@code true} to put previous fragment to back stack. */ protected void switchFragment(@NonNull Fragment fragment, boolean addToBackStack) { @@ -216,6 +210,8 @@ protected void switchFragment(@NonNull Fragment fragment, boolean addToBackStack } /** + * Returns the current displayed fragment. + * * @return The content fragment used by this activity. */ public @Nullable Fragment getContentFragment() { @@ -225,15 +221,17 @@ protected void switchFragment(@NonNull Fragment fragment, boolean addToBackStack /** * Set the current content fragment. * - * @param fragment Content fragment. - * @param tag Content fragment tag. + * @param fragment The fragment to be set. + * @param tag The content fragment tag. */ - public void setContentFragment(Fragment fragment, @NonNull String tag) { + public void setContentFragment(@Nullable Fragment fragment, @NonNull String tag) { this.mContentFragment = fragment; this.mContentFragmentTag = tag; } /** + * Returns the current FAB visibility. + * * @return The current FAB visibility. */ public int getFABVisibility() { @@ -241,7 +239,7 @@ public int getFABVisibility() { } /** - * Sets the current FAB visibility. + * Set the current FAB visibility. * * @param visibility The FAB visibility to be set. */ @@ -250,6 +248,8 @@ public void setFABVisibility(int visibility) { } /** + * Returns whether the app bar is in collapsed state. + * * @return {@code true} if the app bar is in collapsed state. */ public boolean isAppBarCollapsed() { diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/activity/DynamicSystemActivity.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/activity/DynamicSystemActivity.java index c4a645bbe0..70c8cdfcde 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/activity/DynamicSystemActivity.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/activity/DynamicSystemActivity.java @@ -24,22 +24,26 @@ import android.graphics.Color; import android.os.Build; import android.os.Bundle; +import android.os.Handler; import android.preference.PreferenceManager; -import android.support.annotation.ColorInt; -import android.support.annotation.ColorRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StyleRes; -import android.support.v4.content.ContextCompat; -import android.support.v7.app.AppCompatActivity; import android.view.WindowManager; +import androidx.annotation.ColorInt; +import androidx.annotation.ColorRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StyleRes; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.content.ContextCompat; + +import com.google.android.material.appbar.CollapsingToolbarLayout; import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.listener.DynamicListener; import com.pranavpandey.android.dynamic.support.locale.DynamicLocale; import com.pranavpandey.android.dynamic.support.locale.DynamicLocaleUtils; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; +import com.pranavpandey.android.dynamic.support.model.DynamicAppTheme; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils; @@ -49,18 +53,15 @@ import java.util.Locale; /** - * Base activity to perform all the system UI related tasks like status - * and navigation bar color, theme, etc. It is heavily depends on the - * {@link DynamicTheme} which can be customised by implementing the - * corresponding functions. + * Base activity to perform all the system UI related tasks like status and navigation bar color, + * theme, etc. It is heavily depends on the {@link DynamicTheme} which can be customised by + * implementing the corresponding functions. * - *

Just extend this activity and implement the various functions - * according to the need.

+ *

Just extend this activity and implement the various functions according to the need. */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) public abstract class DynamicSystemActivity extends AppCompatActivity implements - DynamicLocale, DynamicListener, - SharedPreferences.OnSharedPreferenceChangeListener { + DynamicLocale, DynamicListener, SharedPreferences.OnSharedPreferenceChangeListener { /** * Dynamic context used by this activity. @@ -70,38 +71,32 @@ public abstract class DynamicSystemActivity extends AppCompatActivity implements /** * Dynamic theme key to maintain its state. */ - protected static final String ADS_STATE_DYNAMIC_THEME = - "ads_state_dynamic_theme"; + protected static final String ADS_STATE_DYNAMIC_THEME = "ads_state_dynamic_theme"; /** * Status bar color key to maintain its state. */ - protected static final String ADS_STATE_STATUS_BAR_COLOR = - "ads_state_status_bar_color"; + protected static final String ADS_STATE_STATUS_BAR_COLOR = "ads_state_status_bar_color"; /** * Navigation bar color key to maintain its state. */ - protected static final String ADS_STATE_NAVIGATION_BAR_COLOR = - "ads_state_navigation_bar_color"; + protected static final String ADS_STATE_NAVIGATION_BAR_COLOR = "ads_state_navigation_bar_color"; /** - * Default tint color for the system UI elements like snack - * bars, etc. + * Default tint color for the system UI elements like snack bars, etc. */ protected static final @ColorInt int ADS_DEFAULT_SYSTEM_UI_COLOR = Color.parseColor("#F5F5F5"); /** - * Default background color for the system UI elements like - * status and navigation bar. + * Default background color for the system UI elements like status and navigation bar. */ protected static final @ColorInt int ADS_DEFAULT_SYSTEM_BG_COLOR = Color.parseColor("#000000"); /** - * Default overlay color for the system UI elements like - * status and navigation bar. + * Default overlay color for the system UI elements like status and navigation bar. */ protected static final @ColorInt int ADS_DEFAULT_SYSTEM_OVERLAY_COLOR = Color.parseColor("#1A000000"); @@ -131,6 +126,11 @@ public abstract class DynamicSystemActivity extends AppCompatActivity implements */ protected boolean mNavigationBarTheme; + /** + * Handler to update the theme. + */ + protected Handler mHandler; + @Override public void attachBaseContext(@NonNull Context base) { super.attachBaseContext(setLocale(base)); @@ -138,28 +138,24 @@ public void attachBaseContext(@NonNull Context base) { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { - setThemeRes(); + setDynamicTheme(); onCustomiseTheme(); super.onCreate(savedInstanceState); - mStatusBarColor = DynamicTheme.getInstance().getPrimaryColorDark(); - mNavigationBarColor = DynamicTheme.getInstance().getPrimaryColorDark(); - } - - @Override - protected void onPostCreate(@Nullable Bundle savedInstanceState) { - super.onPostCreate(savedInstanceState); + mHandler = new Handler(); + mStatusBarColor = DynamicTheme.getInstance().get().getPrimaryColorDark(); + mNavigationBarColor = DynamicTheme.getInstance().get().getPrimaryColorDark(); - updateTaskDescription(); + updateTaskDescription(DynamicTheme.getInstance().get().getPrimaryColor()); setNavigationBarColor(mNavigationBarColor); } @Override - public void onSaveInstanceState(@NonNull Bundle savedInstanceState) { - super.onSaveInstanceState(savedInstanceState); + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); - savedInstanceState.putInt(ADS_STATE_STATUS_BAR_COLOR, mStatusBarColor); - savedInstanceState.putInt(ADS_STATE_NAVIGATION_BAR_COLOR, mNavigationBarColor); + outState.putInt(ADS_STATE_STATUS_BAR_COLOR, mStatusBarColor); + outState.putInt(ADS_STATE_NAVIGATION_BAR_COLOR, mNavigationBarColor); } @Override @@ -182,8 +178,8 @@ public void onSaveInstanceState(@NonNull Bundle savedInstanceState) { } /** - * Get the style resource file to apply theme on ths activity. - * Override this method to supply your own customised style. + * Get the style resource to apply theme on this activity. + *

Override this method to supply your own customised style. * * @return The style resource to be applied on this activity. */ @@ -192,13 +188,25 @@ public void onSaveInstanceState(@NonNull Bundle savedInstanceState) { } /** - * This method will be called just before the {@link #onCreate(Bundle)} - * after applying the theme. Override this method to customise the theme - * further. + * Get the dynamic app theme to be applied on this activity. + *

Override this method to supply your own customised theme. + * + * @return The dynamic app theme for this activity. + */ + protected @Nullable DynamicAppTheme getDynamicTheme() { + return null; + } + + /** + * This method will be called just before the {@link #onCreate(Bundle)} after applying + * the theme. + *

Override this method to customise the theme further. */ protected void onCustomiseTheme() { } /** + * Get the dynamic theme context used by this activity. + * * @return The dynamic context used by this activity. */ public @NonNull Context getContext() { @@ -206,28 +214,32 @@ protected void onCustomiseTheme() { } } /** - * Set the current theme resource for this activity. + * Set the dynamic app theme and style resource for this activity. */ - private void setThemeRes() { - if (getThemeRes() != DynamicResourceUtils.ADS_DEFAULT_RESOURCE_ID) { - DynamicTheme.getInstance().attach(this).setLocalTheme(getThemeRes()); + private void setDynamicTheme() { + if (getDynamicTheme() == null) { + DynamicTheme.getInstance().attach(this).setLocalThemeRes(getThemeRes()); + } else { + DynamicTheme.getInstance().attach(this).setLocalTheme(getDynamicTheme()); } } /** - * @return {@code true} to apply navigation bar theme for this - * activity. It will be applied only on the Android L and above - * devices. + * Sets whether the navigation bar theme should be applied for this activity. + *

It will be applied only on the Android L and above devices. * - *

By default it will use the {@link DynamicColorType#PRIMARY} - * color, please use {@link #setNavigationBarColor(int)} to set a - * custom color.

+ *

By default it will use the {@link Theme.ColorType#PRIMARY_DARK} color, use + * {@link #setNavigationBarColor(int)} to set a custom color. + * + * @return {@code true} to apply navigation bar theme for this activity. */ protected boolean setNavigationBarTheme() { return false; } /** + * Returns whether the navigation bar theme is applied for this activity. + * * @return {@code true} if navigation bar theme is applied. */ public boolean isNavigationBarTheme() { @@ -235,30 +247,31 @@ public boolean isNavigationBarTheme() { } /** - * @return {@code true} to apply navigation bar theme for this - * activity in the landscape mode. It will be applied only on - * the Android L and above devices. + * Sets whether the navigation bar theme should be applied for this activity in landscape mode. + *

It will be applied only on the Android L and above devices. * - *

By default it will use the {@link DynamicColorType#PRIMARY} - * color, please use {@link #setNavigationBarColor(int)} to set a - * custom color.

+ *

By default it will use the {@link Theme.ColorType#PRIMARY_DARK} color, use + * {@link #setNavigationBarColor(int)} to set a custom color. + * + * @return {@code true} to apply navigation bar theme for this activity in the landscape mode. */ protected boolean setNavigationBarThemeInLandscape() { return getResources().getBoolean(R.bool.ads_navigation_bar_theme_landscape); } /** - * @return {@code true} to register a - * {@link SharedPreferences.OnSharedPreferenceChangeListener} - * to receive preference change callback. + * Sets whether register a shared preferences listener for this activity. + * + * @return {@code true} to register a {@link SharedPreferences.OnSharedPreferenceChangeListener} + * to receive preference change callback. */ - protected boolean setSharedPreferenceChangeListener() { + protected boolean setOnSharedPreferenceChangeListener() { return true; } /** - * Called after the theme has been changed. Override this method - * to perform operations after the theme has been changed like + * This method will be called after the theme has been changed. + *

Override this method to perform operations after the theme has been changed like * re-initialize the {@link DynamicTheme} with new colors, etc. */ protected void onAppThemeChange() { @@ -266,18 +279,17 @@ protected void onAppThemeChange() { } /** - * Called after the navigation bar theme has been changed. - * Override this method to perform operations after the - * navigation bar theme has been changed like update it with - * new colors. + * This method will be called after the navigation bar theme has been changed. + *

Override this method to perform operations after the navigation bar theme has been + * changed like update it with new colors. */ protected void navigationBarThemeChange() { setNavigationBarColor(getNavigationBarColor()); } /** - * Set the status bar color. It will be applied only on the - * Android L and above devices. + * Set the status bar color. + *

It will be applied only on the Android L and above devices. * * @param color Color to be applied on the status bar. */ @@ -288,10 +300,10 @@ protected void setWindowStatusBarColor(@ColorInt int color) { } /** - * Set the status bar color. It will be applied only on the - * Android L and above devices. + * Set the status bar color. + *

It will be applied only on the Android L and above devices. * - * @param color Color to be applied on the status bar. + * @param color The color to be applied. */ public void setStatusBarColor(@ColorInt int color) { if (DynamicVersionUtils.isLollipop()) { @@ -301,19 +313,18 @@ public void setStatusBarColor(@ColorInt int color) { } /** - * Set the status bar color resource. It will be applied only on the - * Android L and above devices. + * Set the status bar color resource. + *

It will be applied only on the Android L and above devices. * - * @param colorRes Color resource to be applied on the status bar. + * @param colorRes The color resource to be applied. */ public void setStatusBarColorRes(@ColorRes int colorRes) { setStatusBarColor(ContextCompat.getColor(this, colorRes)); } /** - * Set the translucent status bar flag, useful in case of - * {@link android.support.design.widget.CollapsingToolbarLayout}. - * It will be applied only on the Android L and above devices. + * Set the translucent status bar flag, useful in case of {@link CollapsingToolbarLayout}. + *

It will be applied only on the Android L and above devices. */ public void setTranslucentStatusBar() { if (DynamicVersionUtils.isLollipop()) { @@ -322,33 +333,32 @@ public void setTranslucentStatusBar() { } /** - * Update status bar color according to the supplied parameters. - * It will automatically check for the light or dark color and will - * change the status bar icons or background accordingly so that the - * icons will always be visible. + * Update status bar color according to the supplied parameters. It will automatically + * check for the light or dark color and will change the status bar icons or background + * accordingly so that the icons will always be visible. */ protected void updateStatusBar() { - if (!DynamicColorUtils.isColorDark(mStatusBarColor)) { + boolean isLightColor = !DynamicColorUtils.isColorDark(mStatusBarColor); + if (DynamicTheme.getInstance().get().isBackgroundAware() && isLightColor) { if (!DynamicVersionUtils.isMarshmallow()) { mStatusBarColor = DynamicColorUtils.getContrastColor( mStatusBarColor, ADS_DEFAULT_SYSTEM_UI_COLOR); } } - DynamicViewUtils.setLightStatusBar(getWindow().getDecorView(), - !DynamicColorUtils.isColorDark(mStatusBarColor)); + DynamicViewUtils.setLightStatusBar(getWindow().getDecorView(), isLightColor); } /** - * Set the navigation bar color. It will be applied only on the - * Android L and above devices. + * Set the navigation bar color. + *

It will be applied only on the Android L and above devices. * - * @param color Color to be applied on the navigation bar. + * @param color The color to be applied. */ public void setNavigationBarColor(@ColorInt int color) { - if (!DynamicVersionUtils.isOreo()) { - color = DynamicColorUtils.getContrastColor( - color, ADS_DEFAULT_SYSTEM_UI_COLOR); + if (DynamicTheme.getInstance().get().isBackgroundAware() + && !DynamicVersionUtils.isOreo()) { + color = DynamicColorUtils.getContrastColor(color, ADS_DEFAULT_SYSTEM_UI_COLOR); } int orientation = DynamicWindowUtils.getScreenOrientation(this); @@ -375,19 +385,19 @@ public void setNavigationBarColor(@ColorInt int color) { } /** - * Set the navigation bar color resource. It will be applied only - * on the Android L and above devices. + * Set the navigation bar color resource. + *

It will be applied only on the Android L and above devices. * - * @param colorRes Color resource to be applied on the navigation bar. + * @param colorRes The color resource to be applied. */ public void setNavigationBarColorRes(@ColorRes int colorRes) { setNavigationBarColor(ContextCompat.getColor(this, colorRes)); } /** - * Set the translucent navigation bar flag, useful in case of - * to sow the layout behind the navigation bar. It will be applied - * only on the Android L and above devices. + * Set the translucent navigation bar flag, useful in case of to show the layout behind the + * navigation bar. + *

It will be applied only on the Android L and above devices. */ public void setTranslucentNavigationBar() { if (DynamicVersionUtils.isLollipop()) { @@ -397,9 +407,9 @@ public void setTranslucentNavigationBar() { } /** - * Update navigation bar color according to the supplied parameters. - * It will automatically check for the light or dark color and will - * background accordingly so that the buttons will always be visible. + * Update navigation bar color according to the supplied parameters. It will automatically + * check for the light or dark color and will background accordingly so that the buttons will + * always be visible. */ protected void updateNavigationBar() { DynamicViewUtils.setLightNavigationBar(getWindow().getDecorView(), @@ -407,6 +417,8 @@ protected void updateNavigationBar() { } /** + * Get the current status bar color. + * * @return The current status bar color. */ public int getStatusBarColor() { @@ -414,13 +426,21 @@ public int getStatusBarColor() { } /** + * Get the current (original) navigation bar color. + *

It may be different from the actually applied color. To get the user visible color, + * use {@link #getAppliedNavigationBarColor()}. + * * @return The current navigation bar color. + * + * @see #getAppliedNavigationBarColor() */ public int getNavigationBarColor() { return mNavigationBarColor; } /** + * Get the applied navigation bar color. + * * @return The applied navigation bar color. */ public int getAppliedNavigationBarColor() { @@ -431,35 +451,48 @@ public int getAppliedNavigationBarColor() { public void onResume() { super.onResume(); - if (setSharedPreferenceChangeListener()) { + if (setOnSharedPreferenceChangeListener()) { PreferenceManager.getDefaultSharedPreferences(this) .registerOnSharedPreferenceChangeListener(this); } - setThemeRes(); - onCustomiseTheme(); - setNavigationBarColor(mNavigationBarColor); + if (!DynamicTheme.getInstance().isDynamicListener(this)) { + setDynamicTheme(); + onCustomiseTheme(); + setNavigationBarColor(mNavigationBarColor); + + mHandler.postDelayed(mDynamicChange, DynamicTheme.ADS_DELAY_THEME_CHANGE); + } + } - final String theme = DynamicTheme.getInstance().getLocalTheme(this); - if (theme != null && !theme.equals(DynamicTheme.getInstance().toString())) { - DynamicTheme.getInstance().onDynamicChange(false, true); - } else if (mCurrentLocale != null) { - if (!mCurrentLocale.equals(DynamicLocaleUtils.getLocale( - getLocale(), getDefaultLocale(this)))) { + /** + * Runnable to change dynamic theme on resume. + */ + private Runnable mDynamicChange = new Runnable() { + @Override + public void run() { + String theme = DynamicTheme.getInstance().getLocalTheme( + DynamicSystemActivity.this); + if (theme != null && !theme.equals(DynamicTheme.getInstance().toString())) { DynamicTheme.getInstance().onDynamicChange(false, true); + } else if (mCurrentLocale != null) { + if (!mCurrentLocale.equals(DynamicLocaleUtils.getLocale( + getLocale(), getDefaultLocale( + DynamicSystemActivity.this)))) { + DynamicTheme.getInstance().onDynamicChange(false, true); + } } } - } + }; @Override public void onPause() { - DynamicTheme.getInstance().onLocalDestroy(); - super.onPause(); - - if (setSharedPreferenceChangeListener()) { + if (setOnSharedPreferenceChangeListener()) { PreferenceManager.getDefaultSharedPreferences(this) .unregisterOnSharedPreferenceChangeListener(this); } + DynamicTheme.getInstance().onLocalDestroy(); + super.onPause(); } @Override @@ -488,14 +521,15 @@ public void onDynamicChange(boolean context, boolean recreate) { public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { } /** - * Update the task description on Android L and above devices to - * match it with the theme color. + * Update the task description on Android L and above devices to match it with the theme + * color. + * + * @param color The color to be set. */ - private void updateTaskDescription() { + protected void updateTaskDescription(@ColorInt int color) { if (DynamicVersionUtils.isLollipop()) { setTaskDescription(new ActivityManager.TaskDescription(null, null, - DynamicColorUtils.removeAlpha( - DynamicTheme.getInstance().getPrimaryColor()))); + DynamicColorUtils.removeAlpha(color))); } } } \ No newline at end of file diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/activity/DynamicWidgetActivity.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/activity/DynamicWidgetActivity.java index 0b635549e5..17b27e86c4 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/activity/DynamicWidgetActivity.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/activity/DynamicWidgetActivity.java @@ -19,14 +19,14 @@ import android.appwidget.AppWidgetManager; import android.content.Intent; import android.os.Bundle; -import android.support.annotation.Nullable; -import com.pranavpandey.android.dynamic.support.utils.DynamicAppWidgetUtils; +import androidx.annotation.Nullable; + +import com.pranavpandey.android.dynamic.support.intent.DynamicIntent; /** * An activity to configure widgets having basic configuration methods. - * Just extend this activity and add your own settings fragments - * according to the need. + *

Just extend this activity and add your own settings fragments according to the need. */ public abstract class DynamicWidgetActivity extends DynamicActivity { @@ -52,10 +52,10 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { Intent intent = getIntent(); Bundle extras = intent.getExtras(); if (extras != null) { - mAppWidgetId = extras.getInt( - AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); + mAppWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, + AppWidgetManager.INVALID_APPWIDGET_ID); mUpdateWidget = extras.getBoolean( - DynamicAppWidgetUtils.ADS_EXTRA_WIDGET_UPDATE, false); + DynamicIntent.EXTRA_WIDGET_UPDATE, false); } // If they gave us an intent without the widget id, just bail. diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/adapter/DynamicColorsAdapter.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/adapter/DynamicColorsAdapter.java index afdd5db52f..b5a3efc48f 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/adapter/DynamicColorsAdapter.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/adapter/DynamicColorsAdapter.java @@ -16,42 +16,31 @@ package com.pranavpandey.android.dynamic.support.adapter; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.R; +import com.pranavpandey.android.dynamic.support.listener.DynamicColorListener; import com.pranavpandey.android.dynamic.support.picker.color.DynamicColorShape; import com.pranavpandey.android.dynamic.support.picker.color.DynamicColorView; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; +import com.pranavpandey.android.dynamic.support.theme.Theme; +import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; /** - * A simple base adapter to hold an array of colors and displays - * them in a adapter view. + * A simple base adapter to hold an array of colors and displays them in a adapter view. */ public class DynamicColorsAdapter extends BaseAdapter { /** * Listener to get the callback when a color is selected. */ - public interface OnColorSelectedListener { - - /** - * Called when a color is selected. - * - * @param position The selected position. - * @param color The selected color. - */ - void onColorSelected(int position, @ColorInt int color); - } - - /** - * Listener to get the callback when a color is selected. - */ - private OnColorSelectedListener mOnColorSelectedListener; + private DynamicColorListener mDynamicColorListener; /** * Array of colors to be handled by this adapter. @@ -78,42 +67,39 @@ public interface OnColorSelectedListener { /** * Constructor to initialize an object of this class. * - * @param colors The array of colors to be handled by this - * adapter. + * @param colors The array of colors to be handled by this adapter. * @param colorShape The shape of the color swatches. * @param alpha {@code true} to enable alpha for the color. - * @param onColorSelectedListener The listener to get the callback - * when a color is selected. + * @param dynamicColorListener The listener to get the callback when a color is selected. */ public DynamicColorsAdapter(@NonNull @ColorInt Integer[] colors, - @DynamicColorShape int colorShape, boolean alpha, - @NonNull OnColorSelectedListener onColorSelectedListener) { - this(colors, DynamicColorType.UNKNOWN, colorShape, alpha, onColorSelectedListener); + @DynamicColorShape int colorShape, boolean alpha, + @NonNull DynamicColorListener dynamicColorListener) { + this(colors, Theme.ColorType.UNKNOWN, colorShape, alpha, dynamicColorListener); } /** * Constructor to initialize an object of this class. * - * @param colors The array of colors to be handled by this - * adapter. + * @param colors The array of colors to be handled by this adapter. * @param selectedColor The selected color. * @param colorShape The shape of the color swatches. * @param alpha {@code true} to enable alpha for the color. - * @param onColorSelectedListener The listener to get the callback - * when a color is selected. + * @param dynamicColorListener The listener to get the callback when a color is selected. */ - public DynamicColorsAdapter(@NonNull @ColorInt Integer[] colors, @ColorInt int selectedColor, - @DynamicColorShape int colorShape, boolean alpha, - @NonNull OnColorSelectedListener onColorSelectedListener) { + public DynamicColorsAdapter(@NonNull @ColorInt Integer[] colors, + @ColorInt int selectedColor, @DynamicColorShape int colorShape, boolean alpha, + @NonNull DynamicColorListener dynamicColorListener) { this.mDataSet = colors; this.mSelectedColor = selectedColor; this.mColorShape = colorShape; this.mAlpha = alpha; - this.mOnColorSelectedListener = onColorSelectedListener; + this.mDynamicColorListener = dynamicColorListener; } @Override - public View getView(final int position, View convertView, ViewGroup parent) { + public View getView(final int position, + @Nullable View convertView, @NonNull ViewGroup parent) { ViewHolder viewHolder; if (convertView == null) { @@ -125,20 +111,21 @@ public View getView(final int position, View convertView, ViewGroup parent) { viewHolder = (ViewHolder) convertView.getTag(); } - final int color = (int) getItem(position); + int color = (int) getItem(position); final DynamicColorView dynamicColorView = viewHolder.getDynamicColorView(); dynamicColorView.setColor(color); dynamicColorView.setColorShape(mColorShape); dynamicColorView.setAlpha(mAlpha); - if (mSelectedColor != DynamicColorType.UNKNOWN) { + if (mSelectedColor != DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE) { dynamicColorView.setSelected(mSelectedColor == color); } dynamicColorView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - if (mOnColorSelectedListener != null) { - mOnColorSelectedListener.onColorSelected(position, dynamicColorView.getColor()); + if (mDynamicColorListener != null) { + mDynamicColorListener.onColorSelected( + null, position, dynamicColorView.getColor()); mSelectedColor = dynamicColorView.getColor(); notifyDataSetChanged(); @@ -173,6 +160,8 @@ public long getItemId(int position) { } /** + * Get the data set handled by this adapter. + * * @return The array of colors to be handled by this adapter. */ public @NonNull @ColorInt Integer[] getDataSet() { @@ -191,27 +180,29 @@ public void setDataSet(@NonNull @ColorInt Integer[] dataSet) { } /** - * @return The listener to get the callback when a color is - * selected. + * Get the dynamic color listener. + * + * @return The listener to get the callback when a color is selected. */ - public OnColorSelectedListener getOnColorSelectedListener() { - return mOnColorSelectedListener; + public DynamicColorListener getDynamicColorListener() { + return mDynamicColorListener; } /** - * Sets the listener to get the callback when a color - * is selected. + * Sets the listener to get the callback when a color is selected. * - * @param onColorSelectedListener The listener to be set. + * @param dynamicColorListener The listener to be set. */ - public void setOnColorSelectedListener( - @NonNull OnColorSelectedListener onColorSelectedListener) { - this.mOnColorSelectedListener = onColorSelectedListener; + public void setDynamicColorListener( + @NonNull DynamicColorListener dynamicColorListener) { + this.mDynamicColorListener = dynamicColorListener; notifyDataSetChanged(); } /** + * Get the selected color. + * * @return The selected color. */ public int getSelectedColor() { @@ -230,9 +221,11 @@ public void setSelectedColor(@ColorInt int selectedColor) { } /** + * Get the shape of the color swatches. + * * @return The shape of the color swatches. */ - public int getColorShape() { + public @DynamicColorShape int getColorShape() { return mColorShape; } @@ -248,6 +241,8 @@ public void setColorShape(@DynamicColorShape int colorShape) { } /** + * Checks whether alpha is enabled for the colors. + * * @return {@code true} to enable alpha for the colors. */ public boolean isAlpha() { @@ -280,11 +275,13 @@ static class ViewHolder { * * @param view The view for this view holder. */ - public ViewHolder(@NonNull View view) { + ViewHolder(@NonNull View view) { dynamicColorView = view.findViewById(R.id.ads_color_item_view); } /** + * Get the color view to display color on the adapter view. + * * @return The color view to display color on the adapter view. */ DynamicColorView getDynamicColorView() { diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/adapter/DynamicFragmentsAdapter.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/adapter/DynamicFragmentsAdapter.java index 79292b3496..e2eec80f23 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/adapter/DynamicFragmentsAdapter.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/adapter/DynamicFragmentsAdapter.java @@ -19,19 +19,20 @@ import android.os.Bundle; import android.os.Parcelable; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentStatePagerAdapter; import android.util.SparseArray; import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentStatePagerAdapter; + /** * FragmentStatePagerAdapter that caches each pages. - * FragmentStatePagerAdapter is also originally caches pages, - * but its keys are not public nor documented, so depending - * on how it create cache key is dangerous. - *

- * This adapter caches pages by itself and provide getter method to the cache.

+ *

FragmentStatePagerAdapter is also originally caches pages, but its keys are not public + * nor documented, so depending on how it create cache key is dangerous. + * + *

This adapter caches pages by itself and provide getter method to the cache. */ public abstract class DynamicFragmentsAdapter extends FragmentStatePagerAdapter { @@ -109,10 +110,9 @@ public void restoreState(Parcelable state, ClassLoader loader) { /** * Get a new fragment instance. - * Each fragments are automatically cached in this method, - * so you don't have to do it by yourself. - * If you want to implement instantiation of fragments, - * you should override {@link #createItem(int)} instead. + *

Each fragments are automatically cached in this method, so you don't have to do it + * by yourself. If you want to implement instantiation of fragments, you should override + * {@link #createItem(int)} instead. * * {@inheritDoc} * @@ -129,7 +129,7 @@ public Fragment getItem(int position) { } @Override - public void destroyItem(ViewGroup container, int position, Object object) { + public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { if (0 <= mPages.indexOfKey(position)) { mPages.remove(position); } @@ -149,7 +149,7 @@ public Fragment getItemAt(int position) { /** * Create a new fragment instance. - * This will be called inside {@link #getItem(int)}. + *

This will be called inside {@link #getItem(int)}. * * @param position The position of the item in the adapter. * diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/adapter/DynamicSpinnerChoiceAdapter.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/adapter/DynamicSpinnerChoiceAdapter.java index b44265c794..c4d77a0c0e 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/adapter/DynamicSpinnerChoiceAdapter.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/adapter/DynamicSpinnerChoiceAdapter.java @@ -16,8 +16,6 @@ package com.pranavpandey.android.dynamic.support.adapter; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -26,11 +24,14 @@ import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.R; /** - * A simple base adapter to hold an array of char sequence and display them - * in a adapter view. + * A simple base adapter to hold an array of char sequence and display them in a adapter view. */ public class DynamicSpinnerChoiceAdapter extends BaseAdapter { @@ -54,20 +55,35 @@ public class DynamicSpinnerChoiceAdapter extends BaseAdapter { */ private int mSelectedPosition; + /** + * Constructor to initialize an object of this class. + * + * @param entries The array of texts to be handled by this adapter. + * @param onItemClickListener The listener to get the callback when an item is clicked. + */ public DynamicSpinnerChoiceAdapter(@NonNull CharSequence[] entries, - @NonNull AdapterView.OnItemClickListener onItemClickListener) { + @NonNull AdapterView.OnItemClickListener onItemClickListener) { this(entries, DEFAULT_SELECTED_POSITION, onItemClickListener); } + /** + * Constructor to initialize an object of this class. + * + * @param entries The array of texts to be handled by this adapter. + * @param selectedPosition The selected position. + * @param onItemClickListener The listener to get the callback when an item is clicked. + */ public DynamicSpinnerChoiceAdapter(@NonNull CharSequence[] entries, - @ColorInt int selectedPosition, - @NonNull AdapterView.OnItemClickListener onItemClickListener) { + @ColorInt int selectedPosition, + @NonNull AdapterView.OnItemClickListener onItemClickListener) { this.mDataSet = entries; this.mSelectedPosition = selectedPosition; this.mOnItemClickListener = onItemClickListener; } - - public View getView(final int position, View convertView, final ViewGroup parent) { + + @Override + public View getView(final int position, + @Nullable View convertView, final @NonNull ViewGroup parent) { ViewHolder viewHolder; if (convertView == null) { @@ -115,16 +131,16 @@ public long getItemId(int position) { } /** - * @return The array of char sequences handled by this - * adapter. + * Get the data set handled by this adapter. + * + * @return The array of char sequences handled by this adapter. */ public CharSequence[] getDataSet() { return mDataSet; } /** - * Sets the array of char sequences to be handled by - * this adapter. + * Sets the array of char sequences to be handled by this adapter. * * @param dataSet The array of char sequences to be set. */ @@ -135,16 +151,16 @@ public void setDataSet(@NonNull CharSequence[] dataSet) { } /** - * @return The listener to get the callback when an - * item is clicked. + * Get the item click listener. + * + * @return The listener to get the callback when an item is clicked. */ public AdapterView.OnItemClickListener getOnItemClickListener() { return mOnItemClickListener; } /** - * Sets the listener to get the callback when an - * item is clicked. + * Sets the listener to get the callback when an item is clicked. * * @param onItemClickListener The listener to be set. */ @@ -156,6 +172,8 @@ public void setOnItemClickListener( } /** + * Get the selected position. + * * @return The selected position. */ public int getSelectedPosition() { @@ -174,7 +192,7 @@ public void setSelectedPosition(int selectedPosition) { } /** - * Holder class to hold the item view. + * View holder class to hold the item view. */ static class ViewHolder { @@ -198,13 +216,15 @@ static class ViewHolder { * * @param view The view for this view holder. */ - public ViewHolder(@NonNull View view) { + ViewHolder(@NonNull View view) { itemView = view.findViewById(R.id.ads_array_item); textView = view.findViewById(R.id.ads_array_item_text); selectorView = view.findViewById(R.id.ads_array_item_selector); } /** + * Get the item view root. + * * @return The item view root. */ ViewGroup getItemView() { @@ -212,6 +232,8 @@ ViewGroup getItemView() { } /** + * Get the text view to display the entry. + * * @return The text view to display the entry. */ TextView getTextView() { @@ -219,6 +241,8 @@ TextView getTextView() { } /** + * Get the image view to show the selected item. + * * @return The image view to show the selected item. */ ImageView getSelectorView() { diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/adapter/DynamicSpinnerImageAdapter.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/adapter/DynamicSpinnerImageAdapter.java index 0db40fb628..c40960d151 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/adapter/DynamicSpinnerImageAdapter.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/adapter/DynamicSpinnerImageAdapter.java @@ -17,23 +17,24 @@ package com.pranavpandey.android.dynamic.support.adapter; import android.content.Context; -import android.support.annotation.IdRes; -import android.support.annotation.NonNull; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.IdRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.model.DynamicSpinnerItem; import java.util.List; /** - * A simple array adapter for the {@link android.widget.Spinner} which - * can display an icon and text together as an item. Use the constructor - * to pass the layout resource, image and the text id with a list of items - * according to the need. + * A simple array adapter for the {@link android.widget.Spinner} which can display an icon + * and text together as an item. Use the constructor to pass the layout resource, image and the + * text id with a list of items according to the need. */ public class DynamicSpinnerImageAdapter extends ArrayAdapter { @@ -47,9 +48,18 @@ public class DynamicSpinnerImageAdapter extends ArrayAdapter */ private @IdRes int mTextViewResourceId; - public DynamicSpinnerImageAdapter( - @NonNull Context context, int resource, int imageViewResourceId, - int textViewResourceId, @NonNull List data) { + /** + * Constructor to initialize an object of this class. + * + * @param context The context to retrieve the resources. + * @param resource The layout resource to be used. + * @param imageViewResourceId The resource id for the image view. + * @param textViewResourceId The resource id for the text view. + * @param data The data set to be handled by this adapter. + */ + public DynamicSpinnerImageAdapter(@NonNull Context context, + int resource, int imageViewResourceId, int textViewResourceId, + @NonNull List data) { super(context, resource, textViewResourceId, data); this.mImageViewResourceId = imageViewResourceId; @@ -57,7 +67,8 @@ public DynamicSpinnerImageAdapter( } @Override - public @NonNull View getView(int position, View convertView, @NonNull ViewGroup parent) { + public @NonNull View getView(int position, + @Nullable View convertView, @NonNull ViewGroup parent) { View itemView = super.getView(position, convertView, parent); ImageView imageView = itemView.findViewById(mImageViewResourceId); TextView textView = itemView.findViewById(mTextViewResourceId); @@ -87,8 +98,8 @@ public DynamicSpinnerImageAdapter( } @Override - public @NonNull View getDropDownView(int position, View convertView, - @NonNull ViewGroup parent) { + public @NonNull View getDropDownView(int position, + @Nullable View convertView, @NonNull ViewGroup parent) { return getView(position, convertView, parent); } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/annotation/Exclude.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/annotation/Exclude.java new file mode 100644 index 0000000000..43fedc9cbc --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/annotation/Exclude.java @@ -0,0 +1,31 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * A {@link com.google.gson.Gson} annotation to exclude the field from the json string. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Exclude { + +} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/behavior/DynamicDragListener.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/behavior/DynamicDragListener.java index 40e62dcb95..c16e7c449f 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/behavior/DynamicDragListener.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/behavior/DynamicDragListener.java @@ -16,7 +16,7 @@ package com.pranavpandey.android.dynamic.support.behavior; -import android.support.v7.widget.RecyclerView; +import androidx.recyclerview.widget.RecyclerView; /** * Interface to listen start of a drag event requested by a view. @@ -24,9 +24,9 @@ public interface DynamicDragListener { /** - * Called when a view is requesting a start of a drag. + * This method will be called when a view is requesting a start of a drag. * * @param viewHolder The holder of the view to drag. */ void onStartDrag(RecyclerView.ViewHolder viewHolder); -} \ No newline at end of file +} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/behavior/DynamicFABScrollBehavior.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/behavior/DynamicFABScrollBehavior.java index 7aa868f320..8f52670b8b 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/behavior/DynamicFABScrollBehavior.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/behavior/DynamicFABScrollBehavior.java @@ -17,25 +17,27 @@ package com.pranavpandey.android.dynamic.support.behavior; import android.content.Context; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.AppBarLayout; -import android.support.design.widget.CoordinatorLayout; -import android.support.design.widget.FloatingActionButton; -import android.support.v4.view.ViewCompat; import android.util.AttributeSet; import android.view.View; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.core.view.ViewCompat; + +import com.google.android.material.appbar.AppBarLayout; +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import com.pranavpandey.android.dynamic.support.utils.DynamicFABUtils; + import java.util.List; /** - * A {@link FloatingActionButton} behavior to automatically show or hide it - * according to the nested scroll. Set this behavior in the layout file having - * {@link CoordinatorLayout} as root element to show or hide the FAB according - * to the scroll direction. + * A {@link FloatingActionButton} behavior to automatically show or hide it according to the + * nested scroll. Set this behavior in the layout file having {@link CoordinatorLayout} as root + * element to show or hide the FAB according to the scroll direction. * - *

Scrolling in upwards direction will hide the FAB and scrolling in downwards - * direction will make it visible.

+ *

Scrolling in upwards direction will hide the FAB and scrolling in downwards direction + * will make it visible. */ public class DynamicFABScrollBehavior extends AppBarLayout.ScrollingViewBehavior { @@ -51,8 +53,8 @@ public boolean layoutDependsOn(CoordinatorLayout parent, View child, View depend @Override public boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, - @NonNull View child, @NonNull View directTargetChild, - @NonNull View target, int nestedScrollAxes, final int type) { + @NonNull View child, @NonNull View directTargetChild, + @NonNull View target, int nestedScrollAxes, final int type) { // Ensure we react to vertical scrolling return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL || super.onStartNestedScroll(coordinatorLayout, child, @@ -60,25 +62,27 @@ public boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, } @Override - public void onNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull View child, - @NonNull View target, int dxConsumed, int dyConsumed, - int dxUnconsumed, int dyUnconsumed, int type) { + public void onNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, + @NonNull View child, @NonNull View target, int dxConsumed, int dyConsumed, + int dxUnconsumed, int dyUnconsumed, int type) { super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type); if (dyConsumed > 0) { // User scrolled down -> hide the FAB List dependencies = coordinatorLayout.getDependencies(child); for (View view : dependencies) { - if (view instanceof FloatingActionButton) { - ((FloatingActionButton) view).hide(); + if (view instanceof FloatingActionButton + && ((FloatingActionButton) view).getDrawable() != null) { + DynamicFABUtils.hide((FloatingActionButton) view); } } } else if (dyConsumed < 0) { // User scrolled up -> show the FAB List dependencies = coordinatorLayout.getDependencies(child); for (View view : dependencies) { - if (view instanceof FloatingActionButton && view.getVisibility() == View.GONE) { - ((FloatingActionButton) view).show(); + if (view instanceof FloatingActionButton + && ((FloatingActionButton) view).getDrawable() != null) { + DynamicFABUtils.show((FloatingActionButton) view); } } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/behavior/DynamicTouchAdapter.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/behavior/DynamicTouchAdapter.java index 743e209eba..f81ad33e7d 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/behavior/DynamicTouchAdapter.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/behavior/DynamicTouchAdapter.java @@ -17,27 +17,25 @@ package com.pranavpandey.android.dynamic.support.behavior; /** - * Interface to listen movement of an item inside the recycler view - * adapter. Implement this interface in the adapter class to receive - * item movement callbacks. + * Interface to listen movement of an item inside the recycler view adapter. + *

Implement this interface in the adapter class to receive item movement callbacks. */ public interface DynamicTouchAdapter { /** - * Called when item starts moving from one position to other. + * This method will be called when item starts moving from one position to other. * - * @param fromPosition Current position of the item. - * @param toPosition New position of the item. + * @param fromPosition The current position of the item. + * @param toPosition The new position of the item. * * @return {@code true} if item starts moving. */ boolean onItemMove(int fromPosition, int toPosition); /** - * Called when item is dismissed or removed from a particular - * position. + * This method will be called when item is dismissed or removed from a particular position. * - * @param position Position of the dismissed item. + * @param position The position of the dismissed item. */ void onItemDismiss(int position); -} \ No newline at end of file +} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/behavior/DynamicTouchListener.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/behavior/DynamicTouchListener.java index b661d76ac9..42a4a91685 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/behavior/DynamicTouchListener.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/behavior/DynamicTouchListener.java @@ -16,14 +16,13 @@ package com.pranavpandey.android.dynamic.support.behavior; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.helper.ItemTouchHelper; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.ItemTouchHelper; +import androidx.recyclerview.widget.RecyclerView; /** - * Simple item touch helper extending - * {@link android.support.v7.widget.helper.ItemTouchHelper.Callback} which - * can be used with {@link DynamicTouchAdapter} to provide basic touch - * callbacks depending on your use case. + * Simple item touch helper extending {@link ItemTouchHelper.Callback} which can be used with + * {@link DynamicTouchAdapter} to provide basic touch callbacks depending on your use case. */ public class DynamicTouchListener extends ItemTouchHelper.Callback { @@ -37,7 +36,7 @@ public class DynamicTouchListener extends ItemTouchHelper.Callback { * * @param adapter The adapter to receive callbacks on touch. */ - public DynamicTouchListener(DynamicTouchAdapter adapter) { + public DynamicTouchListener(@NonNull DynamicTouchAdapter adapter) { mAdapter = adapter; } @@ -52,8 +51,8 @@ public boolean isItemViewSwipeEnabled() { } @Override - public int getMovementFlags( - RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { + public int getMovementFlags(@NonNull RecyclerView recyclerView, + @NonNull RecyclerView.ViewHolder viewHolder) { int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END; @@ -61,16 +60,16 @@ public int getMovementFlags( } @Override - public boolean onMove( - RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, - RecyclerView.ViewHolder target) { + public boolean onMove(@NonNull RecyclerView recyclerView, + @NonNull RecyclerView.ViewHolder viewHolder, + @NonNull RecyclerView.ViewHolder target) { mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition()); return true; } @Override - public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { + public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { mAdapter.onItemDismiss(viewHolder.getAdapterPosition()); } } \ No newline at end of file diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/dialog/DynamicAlertController.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/dialog/DynamicAlertController.java index 889d273dd7..b28f00d8ec 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/dialog/DynamicAlertController.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/dialog/DynamicAlertController.java @@ -21,17 +21,12 @@ import android.content.DialogInterface; import android.content.res.TypedArray; import android.database.Cursor; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Handler; import android.os.Message; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.RestrictTo; -import android.support.v4.view.ViewCompat; -import android.support.v4.widget.NestedScrollView; -import android.support.v7.app.AppCompatDialog; -import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.util.AttributeSet; import android.util.TypedValue; @@ -46,6 +41,7 @@ import android.view.WindowManager; import android.widget.AbsListView; import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CheckedTextView; @@ -58,21 +54,29 @@ import android.widget.SimpleCursorAdapter; import android.widget.TextView; +import androidx.annotation.Nullable; +import androidx.annotation.RestrictTo; +import androidx.appcompat.app.AppCompatDialog; +import androidx.core.view.ViewCompat; +import androidx.core.widget.NestedScrollView; +import androidx.recyclerview.widget.RecyclerView; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; import com.pranavpandey.android.dynamic.support.widget.DynamicListView; -import com.pranavpandey.android.dynamic.support.widget.DynamicNestedScrollView; +import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; import java.lang.ref.WeakReference; -import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; @RestrictTo(LIBRARY_GROUP) class DynamicAlertController { private final Context mContext; final AppCompatDialog mDialog; private final Window mWindow; + private final int mButtonIconDimen; private CharSequence mTitle; private CharSequence mMessage; @@ -92,16 +96,19 @@ class DynamicAlertController { Button mButtonPositive; private CharSequence mButtonPositiveText; Message mButtonPositiveMessage; + private Drawable mButtonPositiveIcon; Button mButtonNegative; private CharSequence mButtonNegativeText; Message mButtonNegativeMessage; + private Drawable mButtonNegativeIcon; Button mButtonNeutral; private CharSequence mButtonNeutralText; Message mButtonNeutralMessage; + private Drawable mButtonNeutralIcon; - DynamicNestedScrollView mScrollView; + NestedScrollView mScrollView; private int mIconId = 0; private Drawable mIcon; @@ -147,7 +154,7 @@ public void onClick(View v) { } // Post a message so we dismiss after the above handlers are executed - mHandler.obtainMessage(DynamicAlertController.ButtonHandler.MSG_DISMISS_DIALOG, mDialog) + mHandler.obtainMessage(ButtonHandler.MSG_DISMISS_DIALOG, mDialog) .sendToTarget(); } }; @@ -178,10 +185,9 @@ public void handleMessage(Message msg) { } } - private static boolean shouldCenterSingleButton(@NonNull Context context) { + private static boolean shouldCenterSingleButton(Context context) { final TypedValue outValue = new TypedValue(); - context.getTheme().resolveAttribute( - android.support.v7.appcompat.R.attr.alertDialogCenterButtons, outValue, true); + context.getTheme().resolveAttribute(R.attr.alertDialogCenterButtons, outValue, true); return outValue.data != 0; } @@ -189,10 +195,10 @@ public DynamicAlertController(Context context, AppCompatDialog di, Window window mContext = context; mDialog = di; mWindow = window; - mHandler = new DynamicAlertController.ButtonHandler(di); + mHandler = new ButtonHandler(di); - final TypedArray a = context.obtainStyledAttributes(null, R.styleable.DynamicDialog, - android.support.v7.appcompat.R.attr.alertDialogStyle, 0); + final TypedArray a = context.obtainStyledAttributes(null, R.styleable.AlertDialog, + R.attr.alertDialogStyle, 0); mAlertDialogLayout = a.getResourceId(R.styleable.DynamicDialog_android_layout, 0); mButtonPanelSideLayout = a.getResourceId(R.styleable.DynamicDialog_buttonPanelSideLayout, 0); @@ -203,6 +209,7 @@ public DynamicAlertController(Context context, AppCompatDialog di, Window window .getResourceId(R.styleable.DynamicDialog_singleChoiceItemLayout, 0); mListItemLayout = a.getResourceId(R.styleable.DynamicDialog_listItemLayout, 0); mShowTitle = a.getBoolean(R.styleable.DynamicDialog_showTitle, true); + mButtonIconDimen = a.getDimensionPixelSize(R.styleable.DynamicDialog_buttonIconDimen, 0); a.recycle(); @@ -250,6 +257,9 @@ private int selectContentView() { public void setTitle(CharSequence title) { mTitle = title; + // Fix title not visible issue. + mShowTitle = true; + if (mTitleView != null) { mTitleView.setText(title); } @@ -278,22 +288,6 @@ public void setView(int layoutResId) { mViewSpacingSpecified = false; } - /** - * Set the view root id to add scroll indicators if the content can be - * scrolled. - */ - public void setViewRoot(int viewRootId) { - mViewRootId = viewRootId; - } - - /** - * Set the view root to add scroll indicators if the content can be - * scrolled. - */ - public void setViewRoot(View viewRoot) { - mViewRoot = viewRoot; - } - /** * Set the view to display in the dialog. */ @@ -307,7 +301,7 @@ public void setView(View view) { * Set the view to display in the dialog along with the spacing around that view */ public void setView(View view, int viewSpacingLeft, int viewSpacingTop, int viewSpacingRight, - int viewSpacingBottom) { + int viewSpacingBottom) { mView = view; mViewLayoutResId = 0; mViewSpacingSpecified = true; @@ -317,6 +311,24 @@ public void setView(View view, int viewSpacingLeft, int viewSpacingTop, int view mViewSpacingBottom = viewSpacingBottom; } + /** + * Set the view root id to add scroll indicators if the content can be scrolled. + * + * @param viewRootId The root view id of the custom view. + */ + public void setViewRoot(int viewRootId) { + mViewRootId = viewRootId; + } + + /** + * Set the view root to add scroll indicators if the content can be scrolled. + * + * @param viewRoot The root view of the custom view. + */ + public void setViewRoot(View viewRoot) { + mViewRoot = viewRoot; + } + /** * Sets a hint for the best button panel layout. */ @@ -325,8 +337,8 @@ public void setButtonPanelLayoutHint(int layoutHint) { } /** - * Sets a click listener or a message to be sent when the button is clicked. - * You only need to pass one of {@code listener} or {@code msg}. + * Sets an icon, a click listener or a message to be sent when the button is clicked. + * You only need to pass one of {@code icon}, {@code listener} or {@code msg}. * * @param whichButton Which button, can be one of * {@link DialogInterface#BUTTON_POSITIVE}, @@ -335,9 +347,11 @@ public void setButtonPanelLayoutHint(int layoutHint) { * @param text The text to display in positive button. * @param listener The {@link DialogInterface.OnClickListener} to use. * @param msg The {@link Message} to be sent when clicked. + * @param icon The (@link Drawable) to be used as an icon for the button. + * */ public void setButton(int whichButton, CharSequence text, - DialogInterface.OnClickListener listener, Message msg) { + DialogInterface.OnClickListener listener, Message msg, Drawable icon) { if (msg == null && listener != null) { msg = mHandler.obtainMessage(whichButton, listener); @@ -348,16 +362,19 @@ public void setButton(int whichButton, CharSequence text, case DialogInterface.BUTTON_POSITIVE: mButtonPositiveText = text; mButtonPositiveMessage = msg; + mButtonPositiveIcon = icon; break; case DialogInterface.BUTTON_NEGATIVE: mButtonNegativeText = text; mButtonNegativeMessage = msg; + mButtonNegativeIcon = icon; break; case DialogInterface.BUTTON_NEUTRAL: mButtonNeutralText = text; mButtonNeutralMessage = msg; + mButtonNeutralIcon = icon; break; default: @@ -481,21 +498,21 @@ private ViewGroup resolvePanel(@Nullable View customPanel, @Nullable View defaul private void setupView() { final View parentPanel = mWindow.findViewById(R.id.parentPanel); - final View defaultTopPanel = parentPanel.findViewById(android.support.v7.appcompat.R.id.topPanel); + final View defaultTopPanel = parentPanel.findViewById(R.id.topPanel); final View defaultContentPanel = parentPanel.findViewById(R.id.contentPanel); - final View defaultButtonPanel = parentPanel.findViewById(android.support.v7.appcompat.R.id.buttonPanel); + final View defaultButtonPanel = parentPanel.findViewById(R.id.buttonPanel); - // Set background color according to the theme. - parentPanel.setBackgroundColor(DynamicTheme.getInstance().getBackgroundColor()); + // Make default drawable transparent as we are using card view as background. + mWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); // Install custom content before setting up the title or buttons so // that we can handle panel overrides. final ViewGroup customPanel = parentPanel.findViewById(R.id.customPanel); setupCustomContent(customPanel); - final View customTopPanel = customPanel.findViewById(android.support.v7.appcompat.R.id.topPanel); - final View customContentPanel = customPanel.findViewById(android.support.v7.appcompat.R.id.contentPanel); - final View customButtonPanel = customPanel.findViewById(android.support.v7.appcompat.R.id.buttonPanel); + final View customTopPanel = customPanel.findViewById(R.id.topPanel); + final View customContentPanel = customPanel.findViewById(R.id.contentPanel); + final View customButtonPanel = customPanel.findViewById(R.id.buttonPanel); // Resolve the correct panels and remove the defaults, if needed. final ViewGroup topPanel = resolvePanel(customTopPanel, defaultTopPanel); @@ -532,8 +549,7 @@ private void setupView() { // Only show the divider if we have a title. View divider = null; if (mMessage != null || mListView != null || hasCustomPanel) { - divider = topPanel.findViewById( - android.support.v7.appcompat.R.id.titleDividerNoCustom); + divider = topPanel.findViewById(R.id.titleDividerNoCustom); } if (divider != null) { @@ -583,7 +599,7 @@ private void setupView() { } private void setScrollIndicators(ViewGroup contentPanel, View content, - final int indicators, final int mask) { + final int indicators, final int mask) { // Set up scroll indicators (if present). View indicatorUp = mWindow.findViewById(R.id.scrollIndicatorUp); View indicatorDown = mWindow.findViewById(R.id.scrollIndicatorDown); @@ -619,8 +635,8 @@ private void setScrollIndicators(ViewGroup contentPanel, View content, new NestedScrollView.OnScrollChangeListener() { @Override public void onScrollChange(NestedScrollView v, int scrollX, - int scrollY, - int oldScrollX, int oldScrollY) { + int scrollY, + int oldScrollX, int oldScrollY) { manageScrollIndicators(v, top, bottom); } }); @@ -639,7 +655,7 @@ public void onScrollStateChanged(AbsListView view, int scrollState) {} @Override public void onScroll(AbsListView v, int firstVisibleItem, - int visibleItemCount, int totalItemCount) { + int visibleItemCount, int totalItemCount) { manageScrollIndicators(v, top, bottom); } }); @@ -656,8 +672,8 @@ public void run() { new NestedScrollView.OnScrollChangeListener() { @Override public void onScrollChange(NestedScrollView v, int scrollX, - int scrollY, - int oldScrollX, int oldScrollY) { + int scrollY, + int oldScrollX, int oldScrollY) { manageScrollIndicators(v, top, bottom); } }); @@ -675,7 +691,7 @@ public void onScrollStateChanged(AbsListView view, int scrollState) {} @Override public void onScroll(AbsListView v, int firstVisibleItem, - int visibleItemCount, int totalItemCount) { + int visibleItemCount, int totalItemCount) { manageScrollIndicators(v, top, bottom); } }); @@ -771,7 +787,7 @@ private void setupTitle(ViewGroup topPanel) { topPanel.addView(mCustomTitleView, 0, lp); // Hide the title template - View titleTemplate = mWindow.findViewById(android.support.v7.appcompat.R.id.title_template); + View titleTemplate = mWindow.findViewById(R.id.title_template); titleTemplate.setVisibility(View.GONE); } else { mIconView = mWindow.findViewById(android.R.id.icon); @@ -779,9 +795,16 @@ private void setupTitle(ViewGroup topPanel) { final boolean hasTextTitle = !TextUtils.isEmpty(mTitle); if (hasTextTitle && mShowTitle) { // Display the title if a title is supplied, else hide it. - mTitleView = mWindow.findViewById(android.support.v7.appcompat.R.id.alertTitle); + mTitleView = mWindow.findViewById(R.id.alertTitle); mTitleView.setText(mTitle); + // Set title color to match the theme. + mTitleView.setTextColor(!DynamicTheme.getInstance().get().isBackgroundAware() + ? DynamicTheme.getInstance().get().getTextPrimaryColor() + : DynamicColorUtils.getContrastColor( + DynamicTheme.getInstance().get().getTextPrimaryColor(), + DynamicTheme.getInstance().get().getBackgroundColor())); + // Do this last so that if the user has supplied any icons we // use them instead of the default ones. If the user has // specified 0 then make it disappear. @@ -800,7 +823,7 @@ private void setupTitle(ViewGroup topPanel) { } } else { // Hide the title template - final View titleTemplate = mWindow.findViewById(android.support.v7.appcompat.R.id.title_template); + final View titleTemplate = mWindow.findViewById(R.id.title_template); titleTemplate.setVisibility(View.GONE); mIconView.setVisibility(View.GONE); topPanel.setVisibility(View.GONE); @@ -840,11 +863,11 @@ private void setupContent(ViewGroup contentPanel) { static void manageScrollIndicators(View v, View upIndicator, View downIndicator) { if (upIndicator != null) { upIndicator.setVisibility( - ViewCompat.canScrollVertically(v, -1) ? View.VISIBLE : View.INVISIBLE); + v.canScrollVertically(-1) ? View.VISIBLE : View.INVISIBLE); } if (downIndicator != null) { downIndicator.setVisibility( - ViewCompat.canScrollVertically(v, 1) ? View.VISIBLE : View.INVISIBLE); + v.canScrollVertically(1) ? View.VISIBLE : View.INVISIBLE); } } @@ -853,14 +876,17 @@ private void setupButtons(ViewGroup buttonPanel) { int BIT_BUTTON_NEGATIVE = 2; int BIT_BUTTON_NEUTRAL = 4; int whichButtons = 0; - - mButtonPositive = buttonPanel.findViewById(android.R.id.button1); + mButtonPositive = (Button) buttonPanel.findViewById(android.R.id.button1); mButtonPositive.setOnClickListener(mButtonHandler); - if (TextUtils.isEmpty(mButtonPositiveText)) { + if (TextUtils.isEmpty(mButtonPositiveText) && mButtonPositiveIcon == null) { mButtonPositive.setVisibility(View.GONE); } else { mButtonPositive.setText(mButtonPositiveText); + if (mButtonPositiveIcon != null) { + mButtonPositiveIcon.setBounds(0, 0, mButtonIconDimen, mButtonIconDimen); + mButtonPositive.setCompoundDrawables(mButtonPositiveIcon, null, null, null); + } mButtonPositive.setVisibility(View.VISIBLE); whichButtons = whichButtons | BIT_BUTTON_POSITIVE; } @@ -868,24 +894,30 @@ private void setupButtons(ViewGroup buttonPanel) { mButtonNegative = buttonPanel.findViewById(android.R.id.button2); mButtonNegative.setOnClickListener(mButtonHandler); - if (TextUtils.isEmpty(mButtonNegativeText)) { + if (TextUtils.isEmpty(mButtonNegativeText) && mButtonNegativeIcon == null) { mButtonNegative.setVisibility(View.GONE); } else { mButtonNegative.setText(mButtonNegativeText); + if (mButtonNegativeIcon != null) { + mButtonNegativeIcon.setBounds(0, 0, mButtonIconDimen, mButtonIconDimen); + mButtonNegative.setCompoundDrawables(mButtonNegativeIcon, null, null, null); + } mButtonNegative.setVisibility(View.VISIBLE); - whichButtons = whichButtons | BIT_BUTTON_NEGATIVE; } - mButtonNeutral = buttonPanel.findViewById(android.R.id.button3); + mButtonNeutral = (Button) buttonPanel.findViewById(android.R.id.button3); mButtonNeutral.setOnClickListener(mButtonHandler); - if (TextUtils.isEmpty(mButtonNeutralText)) { + if (TextUtils.isEmpty(mButtonNeutralText) && mButtonNeutralIcon == null) { mButtonNeutral.setVisibility(View.GONE); } else { mButtonNeutral.setText(mButtonNeutralText); + if (mButtonPositiveIcon != null) { + mButtonPositiveIcon.setBounds(0, 0, mButtonIconDimen, mButtonIconDimen); + mButtonPositive.setCompoundDrawables(mButtonPositiveIcon, null, null, null); + } mButtonNeutral.setVisibility(View.VISIBLE); - whichButtons = whichButtons | BIT_BUTTON_NEUTRAL; } @@ -920,23 +952,19 @@ public static class RecycleListView extends DynamicListView { private final int mPaddingTopNoTitle; private final int mPaddingBottomNoButtons; - public RecycleListView(@NonNull Context context) { + public RecycleListView(Context context) { this(context, null); } - public RecycleListView(@NonNull Context context, @Nullable AttributeSet attrs) { + public RecycleListView(Context context, AttributeSet attrs) { super(context, attrs); - setBackgroundAware(true); - final TypedArray ta = context.obtainStyledAttributes( attrs, R.styleable.RecycleListView); mPaddingBottomNoButtons = ta.getDimensionPixelOffset( R.styleable.RecycleListView_paddingBottomNoButtons, -1); mPaddingTopNoTitle = ta.getDimensionPixelOffset( R.styleable.RecycleListView_paddingTopNoTitle, -1); - - ta.recycle(); } public void setHasDecor(boolean hasTitle, boolean hasButtons) { @@ -961,10 +989,13 @@ public static class AlertParams { public View mCustomTitleView; public CharSequence mMessage; public CharSequence mPositiveButtonText; + public Drawable mPositiveButtonIcon; public DialogInterface.OnClickListener mPositiveButtonListener; public CharSequence mNegativeButtonText; + public Drawable mNegativeButtonIcon; public DialogInterface.OnClickListener mNegativeButtonListener; public CharSequence mNeutralButtonText; + public Drawable mNeutralButtonIcon; public DialogInterface.OnClickListener mNeutralButtonListener; public boolean mCancelable; public DialogInterface.OnCancelListener mOnCancelListener; @@ -992,7 +1023,7 @@ public static class AlertParams { public String mIsCheckedColumn; public boolean mForceInverseBackground; public AdapterView.OnItemSelectedListener mOnItemSelectedListener; - public DynamicAlertController.AlertParams.OnPrepareListViewListener mOnPrepareListViewListener; + public OnPrepareListViewListener mOnPrepareListViewListener; public boolean mRecycleOnMeasure = true; /** @@ -1002,13 +1033,13 @@ public static class AlertParams { public interface OnPrepareListViewListener { /** - * Called before the ListView is bound to an adapter. + * This method will be called before the ListView is bound to an adapter. * @param listView The ListView that will be shown in the dialog. */ void onPrepareListView(ListView listView); } - public AlertParams(@NonNull Context context) { + public AlertParams(Context context) { mContext = context; mCancelable = true; mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); @@ -1034,17 +1065,17 @@ public void apply(DynamicAlertController dialog) { if (mMessage != null) { dialog.setMessage(mMessage); } - if (mPositiveButtonText != null) { + if (mPositiveButtonText != null || mPositiveButtonIcon != null) { dialog.setButton(DialogInterface.BUTTON_POSITIVE, mPositiveButtonText, - mPositiveButtonListener, null); + mPositiveButtonListener, null, mPositiveButtonIcon); } - if (mNegativeButtonText != null) { + if (mNegativeButtonText != null || mNegativeButtonIcon != null) { dialog.setButton(DialogInterface.BUTTON_NEGATIVE, mNegativeButtonText, - mNegativeButtonListener, null); + mNegativeButtonListener, null, mNegativeButtonIcon); } - if (mNeutralButtonText != null) { + if (mNeutralButtonText != null || mNeutralButtonIcon != null) { dialog.setButton(DialogInterface.BUTTON_NEUTRAL, mNeutralButtonText, - mNeutralButtonListener, null); + mNeutralButtonListener, null, mNeutralButtonIcon); } // For a list, the client can either supply an array of items or an // adapter or a cursor @@ -1077,8 +1108,8 @@ public void apply(DynamicAlertController dialog) { } private void createListView(final DynamicAlertController dialog) { - final DynamicAlertController.RecycleListView listView = - (DynamicAlertController.RecycleListView) mInflater.inflate(dialog.mListLayout, null); + final RecycleListView listView = + (RecycleListView) mInflater.inflate(dialog.mListLayout, null); final ListAdapter adapter; if (mIsMultiChoice) { @@ -1110,7 +1141,8 @@ public View getView(int position, View convertView, ViewGroup parent) { @Override public void bindView(View view, Context context, Cursor cursor) { - CheckedTextView text = view.findViewById(android.R.id.text1); + CheckedTextView text = (CheckedTextView) view.findViewById( + android.R.id.text1); text.setText(cursor.getString(mLabelIndex)); listView.setItemChecked(cursor.getPosition(), cursor.getInt(mIsCheckedIndex) == 1); @@ -1121,6 +1153,7 @@ public View newView(Context context, Cursor cursor, ViewGroup parent) { return mInflater.inflate(dialog.mMultiChoiceItemLayout, parent, false); } + }; } } else { @@ -1137,7 +1170,7 @@ public View newView(Context context, Cursor cursor, ViewGroup parent) { } else if (mAdapter != null) { adapter = mAdapter; } else { - adapter = new DynamicAlertController.CheckedItemAdapter(mContext, layout, android.R.id.text1, mItems); + adapter = new CheckedItemAdapter(mContext, layout, android.R.id.text1, mItems); } } @@ -1152,7 +1185,7 @@ public View newView(Context context, Cursor cursor, ViewGroup parent) { dialog.mCheckedItem = mCheckedItem; if (mOnClickListener != null) { - listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View v, int position, long id) { mOnClickListener.onClick(dialog.mDialog, position); @@ -1162,7 +1195,7 @@ public void onItemClick(AdapterView parent, View v, int position, long id) { } }); } else if (mOnCheckboxClickListener != null) { - listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View v, int position, long id) { if (mCheckedItems != null) { @@ -1190,7 +1223,7 @@ public void onItemClick(AdapterView parent, View v, int position, long id) { private static class CheckedItemAdapter extends ArrayAdapter { public CheckedItemAdapter(Context context, int resource, int textViewResourceId, - CharSequence[] objects) { + CharSequence[] objects) { super(context, resource, textViewResourceId, objects); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/dialog/DynamicDialog.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/dialog/DynamicDialog.java index 81d0c457a9..cde5c0da17 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/dialog/DynamicDialog.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/dialog/DynamicDialog.java @@ -17,7 +17,6 @@ package com.pranavpandey.android.dynamic.support.dialog; -import android.annotation.SuppressLint; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; @@ -25,16 +24,6 @@ import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Message; -import android.support.annotation.ArrayRes; -import android.support.annotation.AttrRes; -import android.support.annotation.DrawableRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.RestrictTo; -import android.support.annotation.StringRes; -import android.support.annotation.StyleRes; -import android.support.v7.app.AppCompatDialog; -import android.support.v7.appcompat.R; import android.util.TypedValue; import android.view.ContextThemeWrapper; import android.view.KeyEvent; @@ -44,7 +33,19 @@ import android.widget.ListAdapter; import android.widget.ListView; -import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP; +import androidx.annotation.ArrayRes; +import androidx.annotation.AttrRes; +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.RestrictTo; +import androidx.annotation.StringRes; +import androidx.annotation.StyleRes; +import androidx.appcompat.app.AppCompatDialog; + +import com.pranavpandey.android.dynamic.support.R; + +import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; /** * A subclass of Dialog that can display one, two or three buttons. If you only want to @@ -94,7 +95,7 @@ protected DynamicDialog(@NonNull Context context) { * Construct an DynamicDialog that uses an explicit theme. The actual style * that an DynamicDialog uses is a private implementation, however you can * here supply either the name of an attribute in the theme from which - * to get the dialog's style (such as {@link R.attr#alertDialogTheme}. + * to get the dialog's style (such as {@link androidx.appcompat.R.attr#alertDialogTheme}. */ protected DynamicDialog(@NonNull Context context, @StyleRes int themeResId) { super(context, resolveDialogTheme(context, themeResId)); @@ -102,15 +103,15 @@ protected DynamicDialog(@NonNull Context context, @StyleRes int themeResId) { } protected DynamicDialog(@NonNull Context context, boolean cancelable, - @Nullable OnCancelListener cancelListener) { + @Nullable OnCancelListener cancelListener) { this(context, 0); setCancelable(cancelable); setOnCancelListener(cancelListener); } - @SuppressLint("ResourceType") static int resolveDialogTheme(@NonNull Context context, @StyleRes int resid) { - if (resid >= 0x01000000) { // start of real resource IDs. + // Check to see if this resourceId has a valid package ID. + if (((resid >>> 24) & 0x000000ff) >= 0x00000001) { // start of real resource IDs. return resid; } else { TypedValue outValue = new TypedValue(); @@ -158,7 +159,7 @@ public void setCustomTitle(View customTitleView) { } /** - * Set the message to display. + * Sets the message to display. * * @param message The message to display in the dialog. */ @@ -174,14 +175,6 @@ public void setView(View view) { mAlert.setView(view); } - /** - * Set the view root to add scroll indicators if the content can be scrolled. - * This method has no effect if called after {@link #show()}. - */ - public void setViewRoot(View view) { - mAlert.setViewRoot(view); - } - /** * Set the view to display in the dialog, specifying the spacing to appear around that * view. This method has no effect if called after {@link #show()}. @@ -192,14 +185,24 @@ public void setViewRoot(View view) { * @param viewSpacingRight Extra space to appear to the right of {@code view} * @param viewSpacingBottom Extra space to appear below {@code view} */ - public void setView(View view, int viewSpacingLeft, int viewSpacingTop, - int viewSpacingRight, int viewSpacingBottom) { + public void setView(View view, int viewSpacingLeft, int viewSpacingTop, int viewSpacingRight, + int viewSpacingBottom) { mAlert.setView(view, viewSpacingLeft, viewSpacingTop, viewSpacingRight, viewSpacingBottom); } + /** + * Set the view root to add scroll indicators if the content can be scrolled. + *

This method has no effect if called after {@link #show()}. + */ + public void setViewRoot(View view) { + mAlert.setViewRoot(view); + } + /** * Internal api to allow hinting for the best button panel layout. + * @hide */ + @RestrictTo(LIBRARY_GROUP) void setButtonPanelLayoutHint(int layoutHint) { mAlert.setButtonPanelLayoutHint(layoutHint); } @@ -216,7 +219,7 @@ void setButtonPanelLayoutHint(int layoutHint) { * @param msg The {@link Message} to be sent when clicked. */ public void setButton(int whichButton, CharSequence text, Message msg) { - mAlert.setButton(whichButton, text, null, msg); + mAlert.setButton(whichButton, text, null, msg, null); } /** @@ -231,7 +234,25 @@ public void setButton(int whichButton, CharSequence text, Message msg) { * @param listener The {@link DialogInterface.OnClickListener} to use. */ public void setButton(int whichButton, CharSequence text, OnClickListener listener) { - mAlert.setButton(whichButton, text, listener, null); + mAlert.setButton(whichButton, text, listener, null, null); + } + + /** + * Sets an icon to be displayed along with the button text and a listener to be invoked when + * the positive button of the dialog is pressed. This method has no effect if called after + * {@link #show()}. + * + * @param whichButton Which button to set the listener on, can be one of + * {@link DialogInterface#BUTTON_POSITIVE}, + * {@link DialogInterface#BUTTON_NEGATIVE}, or + * {@link DialogInterface#BUTTON_NEUTRAL} + * @param text The text to display in positive button. + * @param listener The {@link DialogInterface.OnClickListener} to use. + * @param icon The {@link Drawable} to be set as an icon for the button. + */ + public void setButton(int whichButton, CharSequence text, Drawable icon, + OnClickListener listener) { + mAlert.setButton(whichButton, text, listener, null, icon); } /** @@ -264,7 +285,7 @@ public void setIconAttribute(int attrId) { } @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { + protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mAlert.installContent(); } @@ -310,13 +331,13 @@ public Builder(@NonNull Context context) { * The specified theme resource ({@code themeResId}) is applied on top * of the parent {@code context}'s theme. It may be specified as a * style resource containing a fully-populated theme, such as - * {@link R.style#Theme_AppCompat_Dialog}, to replace all + * {@link androidx.appcompat.R.style#Theme_AppCompat_Dialog}, to replace all * attributes in the parent {@code context}'s theme including primary * and accent colors. *

* To preserve attributes such as primary and accent colors, the * {@code themeResId} may instead be specified as an overlay theme such - * as {@link R.style#ThemeOverlay_AppCompat_Dialog}. This will + * as {@link androidx.appcompat.R.style#ThemeOverlay_AppCompat_Dialog}. This will * override only the window attributes necessary to style the alert * window as a dialog. *

@@ -478,6 +499,16 @@ public Builder setPositiveButton(CharSequence text, final OnClickListener listen return this; } + /** + * Set an icon to be displayed for the positive button. + * @param icon The icon to be displayed + * @return This Builder object to allow for chaining of calls to set methods + */ + public Builder setPositiveButtonIcon(Drawable icon) { + P.mPositiveButtonIcon = icon; + return this; + } + /** * Set a listener to be invoked when the negative button of the dialog is pressed. * @param textId The resource id of the text to display in the negative button @@ -504,6 +535,16 @@ public Builder setNegativeButton(CharSequence text, final OnClickListener listen return this; } + /** + * Set an icon to be displayed for the negative button. + * @param icon The icon to be displayed + * @return This Builder object to allow for chaining of calls to set methods + */ + public Builder setNegativeButtonIcon(Drawable icon) { + P.mNegativeButtonIcon = icon; + return this; + } + /** * Set a listener to be invoked when the neutral button of the dialog is pressed. * @param textId The resource id of the text to display in the neutral button @@ -530,6 +571,16 @@ public Builder setNeutralButton(CharSequence text, final OnClickListener listene return this; } + /** + * Set an icon to be displayed for the neutral button. + * @param icon The icon to be displayed + * @return This Builder object to allow for chaining of calls to set methods + */ + public Builder setNeutralButtonIcon(Drawable icon) { + P.mNeutralButtonIcon = icon; + return this; + } + /** * Sets whether the dialog is cancelable or not. Default is true. * @@ -634,7 +685,7 @@ public Builder setAdapter(final ListAdapter adapter, final OnClickListener liste * @return This Builder object to allow for chaining of calls to set methods */ public Builder setCursor(final Cursor cursor, final OnClickListener listener, - String labelColumn) { + String labelColumn) { P.mCursor = cursor; P.mLabelColumn = labelColumn; P.mOnClickListener = listener; @@ -660,7 +711,7 @@ public Builder setCursor(final Cursor cursor, final OnClickListener listener, * @return This Builder object to allow for chaining of calls to set methods */ public Builder setMultiChoiceItems(@ArrayRes int itemsId, boolean[] checkedItems, - final OnMultiChoiceClickListener listener) { + final OnMultiChoiceClickListener listener) { P.mItems = P.mContext.getResources().getTextArray(itemsId); P.mOnCheckboxClickListener = listener; P.mCheckedItems = checkedItems; @@ -686,7 +737,7 @@ public Builder setMultiChoiceItems(@ArrayRes int itemsId, boolean[] checkedItems * @return This Builder object to allow for chaining of calls to set methods */ public Builder setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems, - final OnMultiChoiceClickListener listener) { + final OnMultiChoiceClickListener listener) { P.mItems = items; P.mOnCheckboxClickListener = listener; P.mCheckedItems = checkedItems; @@ -714,7 +765,7 @@ public Builder setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems, * @return This Builder object to allow for chaining of calls to set methods */ public Builder setMultiChoiceItems(Cursor cursor, String isCheckedColumn, String labelColumn, - final OnMultiChoiceClickListener listener) { + final OnMultiChoiceClickListener listener) { P.mCursor = cursor; P.mOnCheckboxClickListener = listener; P.mIsCheckedColumn = isCheckedColumn; @@ -739,7 +790,7 @@ public Builder setMultiChoiceItems(Cursor cursor, String isCheckedColumn, String * @return This Builder object to allow for chaining of calls to set methods */ public Builder setSingleChoiceItems(@ArrayRes int itemsId, int checkedItem, - final OnClickListener listener) { + final OnClickListener listener) { P.mItems = P.mContext.getResources().getTextArray(itemsId); P.mOnClickListener = listener; P.mCheckedItem = checkedItem; @@ -764,7 +815,7 @@ public Builder setSingleChoiceItems(@ArrayRes int itemsId, int checkedItem, * @return This Builder object to allow for chaining of calls to set methods */ public Builder setSingleChoiceItems(Cursor cursor, int checkedItem, String labelColumn, - final OnClickListener listener) { + final OnClickListener listener) { P.mCursor = cursor; P.mOnClickListener = listener; P.mCheckedItem = checkedItem; @@ -787,8 +838,7 @@ public Builder setSingleChoiceItems(Cursor cursor, int checkedItem, String label * * @return This Builder object to allow for chaining of calls to set methods */ - public Builder setSingleChoiceItems(CharSequence[] items, int checkedItem, - final OnClickListener listener) { + public Builder setSingleChoiceItems(CharSequence[] items, int checkedItem, final OnClickListener listener) { P.mItems = items; P.mOnClickListener = listener; P.mCheckedItem = checkedItem; @@ -810,8 +860,7 @@ public Builder setSingleChoiceItems(CharSequence[] items, int checkedItem, * * @return This Builder object to allow for chaining of calls to set methods */ - public Builder setSingleChoiceItems(ListAdapter adapter, int checkedItem, - final OnClickListener listener) { + public Builder setSingleChoiceItems(ListAdapter adapter, int checkedItem, final OnClickListener listener) { P.mAdapter = adapter; P.mOnClickListener = listener; P.mCheckedItem = checkedItem; @@ -867,34 +916,6 @@ public Builder setView(View view) { return this; } - /** - * Set the view root id to add scroll indicators if the content can - * be scrolled. - * - * @param viewRootId Root view id of the custom view. - * @return this Builder object to allow for chaining of calls to set - * methods - */ - public Builder setViewRoot(int viewRootId) { - P.mViewRoot = null; - P.mViewRootId = viewRootId; - return this; - } - - /** - * Set the view root to add scroll indicators if the content can - * be scrolled. - * - * @param viewRoot Root view of the custom view. - * @return this Builder object to allow for chaining of calls to set - * methods - */ - public Builder setViewRoot(View viewRoot) { - P.mViewRoot = viewRoot; - P.mViewRootId = 0; - return this; - } - /** * Set a custom view to be the contents of the Dialog, specifying the * spacing to appear around that view. If the supplied view is an @@ -920,7 +941,7 @@ public Builder setViewRoot(View viewRoot) { @RestrictTo(LIBRARY_GROUP) @Deprecated public Builder setView(View view, int viewSpacingLeft, int viewSpacingTop, - int viewSpacingRight, int viewSpacingBottom) { + int viewSpacingRight, int viewSpacingBottom) { P.mView = view; P.mViewLayoutResId = 0; P.mViewSpacingSpecified = true; @@ -931,6 +952,34 @@ public Builder setView(View view, int viewSpacingLeft, int viewSpacingTop, return this; } + /** + * Set the view root id to add scroll indicators if the content can be scrolled. + * + * @param viewRootId The root view id of the custom view. + * + * @return this Builder object to allow for chaining of calls to set + * methods + */ + public Builder setViewRoot(int viewRootId) { + P.mViewRoot = null; + P.mViewRootId = viewRootId; + return this; + } + + /** + * Set the view root to add scroll indicators if the content can be scrolled. + * + * @param viewRoot The root view of the custom view. + * + * @return this Builder object to allow for chaining of calls to set + * methods + */ + public Builder setViewRoot(View viewRoot) { + P.mViewRoot = viewRoot; + P.mViewRootId = 0; + return this; + } + /** * Sets the Dialog to use the inverse background, regardless of what the * contents is. @@ -965,6 +1014,7 @@ public Builder setRecycleOnMeasureEnabled(boolean enabled) { * processing is needed, {@link #show()} may be called instead to both * create and display the dialog. */ + @NonNull public DynamicDialog create() { // We can't use Dialog's 3-arg constructor with the createThemeContextWrapper param, // so we always have to re-set the theme diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/dialog/fragment/DynamicDialogFragment.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/dialog/fragment/DynamicDialogFragment.java index cd07c00494..81ed6221de 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/dialog/fragment/DynamicDialogFragment.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/dialog/fragment/DynamicDialogFragment.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 Pranav Pandey + * Copyright 2018 Pranav Pandey * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,20 +20,20 @@ import android.app.Dialog; import android.content.DialogInterface; import android.os.Bundle; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.FragmentActivity; -import android.support.v7.app.AlertDialog; -import android.support.v7.app.AppCompatDialogFragment; import android.view.KeyEvent; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.app.AppCompatDialogFragment; +import androidx.fragment.app.FragmentActivity; + import com.pranavpandey.android.dynamic.support.dialog.DynamicDialog; /** - * Base dialog fragment to provide all the functionality of - * {@link DynamicDialog} inside a fragment. It can be extended to - * customise it further by overriding the supported methods. + * Base dialog fragment to provide all the functionality of,{@link DynamicDialog} inside a + * fragment. It can be extended to customise it further by overriding the supported methods. * * @see #onCustomiseBuilder(DynamicDialog.Builder, Bundle) * @see #onCustomiseBuilder(DynamicDialog.Builder, Bundle) @@ -41,31 +41,29 @@ public class DynamicDialogFragment extends AppCompatDialogFragment { /** - * Default button color. it will be used internally - * if there is no button color is applied. + * Default button color. it will be used internally if there is no button color is applied. */ public static final int ADS_DEFAULT_BUTTON_COLOR = -1; /** - * Button color used by this dialog fragment. + * Button color used by the dialog. */ private @ColorInt int mButtonColor = ADS_DEFAULT_BUTTON_COLOR; /** * {@code true} to make the dialog cancelable. - * The default value is {@code true}. + *

The default value is {@code true}. */ private boolean mIsCancelable = true; /** * {@code true} to dismiss the dialog in pause state. - * The default value is {@code false}. + *

The default value is {@code false}. */ private boolean mAutoDismiss = false; /** - * Dialog builder to customise this fragment according - * to the need. + * Dialog builder to customise this fragment according to the need. */ private DynamicDialog.Builder mDynamicDialogBuilder; @@ -80,12 +78,12 @@ public class DynamicDialogFragment extends AppCompatDialogFragment { private DynamicDialog.OnDismissListener mOnDismissListener; /** - * Callback when this dialog fragment has been cancelled. + * Callback when this dialog fragment has been canceled. */ private DynamicDialog.OnCancelListener mOnCancelListener; /** - * Callback when a key is pressed in this dialog fragment. + * Callback when a key is pressed inside the dialog. */ private DynamicDialog.OnKeyListener mOnKeyListener; @@ -143,7 +141,7 @@ public void onShow(DialogInterface dialog) { alertDialog.setOnKeyListener(new DialogInterface.OnKeyListener() { @Override public boolean onKey(DialogInterface dialogInterface, - int i, KeyEvent keyEvent) { + int i, KeyEvent keyEvent) { if (mOnKeyListener != null) { mOnKeyListener.onKey(dialogInterface, i, keyEvent); } @@ -157,11 +155,10 @@ public boolean onKey(DialogInterface dialogInterface, @Override public void onPause() { - super.onPause(); - if (mAutoDismiss) { dismiss(); } + super.onPause(); } @Override @@ -175,7 +172,7 @@ public void onDestroyView() { } @Override - public void onDismiss(@Nullable DialogInterface dialog) { + public void onDismiss(@NonNull DialogInterface dialog) { super.onDismiss(dialog); if (mOnDismissListener != null) { @@ -184,7 +181,7 @@ public void onDismiss(@Nullable DialogInterface dialog) { } @Override - public void onCancel(@Nullable DialogInterface dialog) { + public void onCancel(@NonNull DialogInterface dialog) { super.onCancel(dialog); if (mOnCancelListener != null) { @@ -193,14 +190,12 @@ public void onCancel(@Nullable DialogInterface dialog) { } /** - * Override this method to customise the {@link #mDynamicDialogBuilder} - * before creating the dialog. + * Override this method to customise the dynamic dialog builder before creating the dialog. * * @param dialogBuilder The current builder to be customised. - * @param savedInstanceState The saved state of the fragment to restore it - * later. + * @param savedInstanceState The saved state of the fragment to restore it later. * - * @return Customised {@link DynamicDialog.Builder}. + * @return The customised dynamic dialog builder. */ protected @NonNull DynamicDialog.Builder onCustomiseBuilder( @NonNull DynamicDialog.Builder dialogBuilder, @Nullable Bundle savedInstanceState) { @@ -208,17 +203,16 @@ public void onCancel(@Nullable DialogInterface dialog) { } /** - * Override this method to customise the {@link DynamicDialog} - * before attaching it with this fragment. + * Override this method to customise the dynamic dialog before attaching it with + * this fragment. * * @param alertDialog The current dialog to be customised. - * @param savedInstanceState The saved state of the fragment to restore it - * later. + * @param savedInstanceState The saved state of the fragment to restore it later. * - * @return Customised {@link DynamicDialog}. + * @return The customised dynamic dialog. */ protected @NonNull DynamicDialog onCustomiseDialog(@NonNull DynamicDialog alertDialog, - @Nullable Bundle savedInstanceState) { + @Nullable Bundle savedInstanceState) { return alertDialog; } @@ -227,24 +221,26 @@ public void onCancel(@Nullable DialogInterface dialog) { */ protected void finishActivity() { if (getActivity() != null && !getActivity().isFinishing()) { - finishActivity(); + getActivity().finish(); } } /** + * Get the button color for the dialog. + * * @return The button color used by this dialog fragment. */ - public int getButtonColor() { + public @ColorInt int getButtonColor() { return mButtonColor; } /** - * Sets the button color for this dialog fragment. + * Set the button color for the dialog. * * @param buttonColor The button color to be set. * - * @return {@link DynamicDialogFragment} object to allow for - * chaining of calls to set methods. + * @return The {@link DynamicDialogFragment} object to allow for chaining of calls to + * set methods. */ public DynamicDialogFragment setButtonColor(@ColorInt int buttonColor) { this.mButtonColor = buttonColor; @@ -253,21 +249,22 @@ public DynamicDialogFragment setButtonColor(@ColorInt int buttonColor) { } /** + * Returns whether this dialog is cancelable. + * * @return {@code true} to make the dialog cancelable. - * The default value is {@code true}. + *

The default value is {@code true}. */ public boolean isCancelable() { return mIsCancelable; } /** - * Sets this dialog fragment cancellable or not. + * Control whether the dialog is cancelable. * - * @param cancelable {@code true} to make the dialog - * cancelable. + * @param cancelable {@code true} to make the dialog cancelable. * - * @return {@link DynamicDialogFragment} object to allow for - * chaining of calls to set methods. + * @return The {@link DynamicDialogFragment} object to allow for chaining of calls to + * set methods. */ public DynamicDialogFragment setIsCancelable(boolean cancelable) { this.mIsCancelable = cancelable; @@ -277,21 +274,22 @@ public DynamicDialogFragment setIsCancelable(boolean cancelable) { } /** + * Returns whether the dialog is auto dismissible. + * * @return {@code true} to dismiss the dialog in pause state. - * The default value is {@code false}. + *

The default value is {@code false}. */ protected boolean isAutoDismiss() { return mAutoDismiss; } /** - * Sets this dialog fragment auto dismissible or not. + * Control whether the dialog is auto dismissible. * - * @param autoDismiss {@code true} to dismiss the dialog in - * pause state. + * @param autoDismiss {@code true} to dismiss the dialog in pause state. * - * @return {@link DynamicDialogFragment} object to allow for - * chaining of calls to set methods. + * @return The {@link DynamicDialogFragment} object to allow for chaining of calls to + * set methods. */ public DynamicDialogFragment setAutoDismiss(boolean autoDismiss) { this.mAutoDismiss = autoDismiss; @@ -300,8 +298,9 @@ public DynamicDialogFragment setAutoDismiss(boolean autoDismiss) { } /** - * @return The dialog builder to customise this fragment - * according to the need. + * The dynamic dialog builder set for this fragment. + * + * @return The dialog builder to customise this fragment according to the need. */ protected @Nullable DynamicDialog.Builder getBuilder() { return mDynamicDialogBuilder; @@ -310,11 +309,10 @@ public DynamicDialogFragment setAutoDismiss(boolean autoDismiss) { /** * Sets a dynamic dialog builder for this dialog fragment. * - * @param dynamicAlertDialogBuilder The dynamic dialog builder - * to be set. + * @param dynamicAlertDialogBuilder The dynamic dialog builder to be set. * - * @return {@link DynamicDialogFragment} object to allow for - * chaining of calls to set methods. + * @return The {@link DynamicDialogFragment} object to allow for chaining of calls to + * set methods. */ public DynamicDialogFragment setBuilder( @NonNull DynamicDialog.Builder dynamicAlertDialogBuilder) { @@ -324,6 +322,8 @@ public DynamicDialogFragment setBuilder( } /** + * Get the on show listener set for the dialog. + * * @return The callback when this dialog fragment is displayed. */ protected @Nullable DynamicDialog.OnShowListener getOnShowListener() { @@ -331,12 +331,12 @@ public DynamicDialogFragment setBuilder( } /** - * Sets on show listener for this dialog fragment. + * Set an show listener for the dialog. * * @param onShowListener The on show listener to be set. * - * @return {@link DynamicDialogFragment} object to allow for - * chaining of calls to set methods. + * @return The {@link DynamicDialogFragment} object to allow for chaining of calls to + * set methods. */ public DynamicDialogFragment setOnShowListener( @Nullable DynamicDialog.OnShowListener onShowListener) { @@ -346,20 +346,21 @@ public DynamicDialogFragment setOnShowListener( } /** - * @return The callback when this dialog fragment has been - * dismissed. + * Get the on dismiss listener set for the dialog. + * + * @return The callback when this dialog fragment has been dismissed. */ protected @Nullable DynamicDialog.OnDismissListener getOnDismissListener() { return mOnDismissListener; } /** - * Sets on dismiss listener for this dialog fragment. + * Set an on dismiss listener for the dialog. * * @param onDismissListener The on dismiss listener to be set. * - * @return {@link DynamicDialogFragment} object to allow for - * chaining of calls to set methods. + * @return The {@link DynamicDialogFragment} object to allow for chaining of calls to + * set methods. */ public DynamicDialogFragment setOnDismissListener( @Nullable DynamicDialog.OnDismissListener onDismissListener) { @@ -369,20 +370,21 @@ public DynamicDialogFragment setOnDismissListener( } /** - * @return The callback when this dialog fragment has been - * cancelled. + * Get the on cancel listener set for the dialog. + * + * @return The callback when this dialog fragment has been cancelled. */ protected @Nullable DynamicDialog.OnCancelListener getOnCancelListener() { return mOnCancelListener; } /** - * Sets on cancel listener for this dialog fragment. + * Set an on cancel listener for the dialog. * * @param onCancelListener The on cancel listener to be set. * - * @return {@link DynamicDialogFragment} object to allow for - * chaining of calls to set methods. + * @return The {@link DynamicDialogFragment} object to allow for chaining of calls to + * set methods. */ public DynamicDialogFragment setOnCancelListener( @Nullable DynamicDialog.OnCancelListener onCancelListener) { @@ -392,20 +394,21 @@ public DynamicDialogFragment setOnCancelListener( } /** - * @return The callback when a key is pressed in this dialog - * fragment. + * Get the on key listener set for the dialog. + * + * @return The callback when a key is pressed in this dialog fragment. */ protected @Nullable DynamicDialog.OnKeyListener getOnKeyListener() { return mOnKeyListener; } /** - * Sets on key listener for this dialog fragment. + * Set an on key listener for the dialog. * * @param onKeyListener The on key listener to be set. * - * @return {@link DynamicDialogFragment} object to allow for - * chaining of calls to set methods. + * @return The {@link DynamicDialogFragment} object to allow for chaining of calls to + * set methods. */ public DynamicDialogFragment setOnKeyListener( @Nullable DynamicDialog.OnKeyListener onKeyListener) { @@ -415,18 +418,18 @@ public DynamicDialogFragment setOnKeyListener( } /** - * Show this dialog fragment and attach it to the supplied - * activity. + * Show this dialog fragment and attach it to the supplied activity. * - * @param fragmentActivity The fragment activity to attach this - * dialog fragment. + * @param fragmentActivity The fragment activity to attach this dialog fragment. */ public void showDialog(@NonNull FragmentActivity fragmentActivity) { show(fragmentActivity.getSupportFragmentManager(), getClass().getName()); } /** - * @return {@link DynamicDialog} created by this fragment. + * Returns the dialog shown by this fragment. + * + * @return The {@link DynamicDialog} shown by this fragment. */ public @Nullable DynamicDialog getDynamicDialog() { return (DynamicDialog) getDialog(); diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/fragment/DynamicFragment.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/fragment/DynamicFragment.java index 0f921a6b3d..26866b62c6 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/fragment/DynamicFragment.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/fragment/DynamicFragment.java @@ -17,25 +17,62 @@ package com.pranavpandey.android.dynamic.support.fragment; import android.app.Activity; +import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.os.Bundle; -import android.support.annotation.IdRes; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.support.v7.app.AppCompatActivity; +import android.os.Parcelable; +import android.preference.PreferenceManager; + +import androidx.annotation.IdRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; import com.pranavpandey.android.dynamic.support.activity.DynamicActivity; import com.pranavpandey.android.dynamic.support.activity.DynamicDrawerActivity; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; /** - * Base fragment class to provide basic functionality and to work - * with the {@link DynamicActivity}. Extend this fragment to add - * more functionality according to the need + * Base fragment class to provide basic functionality and to work with the {@link DynamicActivity}. + *

Extend this fragment to add more functionality according to the need */ -public abstract class DynamicFragment extends Fragment { +public class DynamicFragment extends Fragment implements + SharedPreferences.OnSharedPreferenceChangeListener { + + /** + * Get boolean to control the shared preferences listener. + * + * @return {@code true} to set a shared preferences listener. + *

The default values is {@code false}. + */ + protected boolean setSharedPreferenceChangeListener() { + return false; + } + + @Override + public void onAttach(@NonNull Context context) { + super.onAttach(context); + + if (setSharedPreferenceChangeListener()) { + PreferenceManager.getDefaultSharedPreferences(getActivity()) + .registerOnSharedPreferenceChangeListener(this); + } + } + + @Override + public void onDetach() { + if (setSharedPreferenceChangeListener()) { + PreferenceManager.getDefaultSharedPreferences(getActivity()) + .unregisterOnSharedPreferenceChangeListener(this); + } + super.onDetach(); + } /** + * Returns the title used by the parent activity. + * * @return The title used by the parent activity. */ protected @Nullable CharSequence getTitle() { @@ -47,6 +84,8 @@ public abstract class DynamicFragment extends Fragment { } /** + * Returns the subtitle used by the parent activity. + * * @return The subtitle used by the parent activity. */ protected @Nullable CharSequence getSubtitle() { @@ -58,8 +97,10 @@ public abstract class DynamicFragment extends Fragment { } /** - * @return The menu item id to make it checked if the parent activity - * is a {@link DynamicDrawerActivity}. + * Get the menu item id to make it checked in case of a drawer activity. + * + * @return The menu item id to make it checked if the parent activity is a + * {@link DynamicDrawerActivity}. */ protected @IdRes int setNavigationViewCheckedItem() { return DynamicResourceUtils.ADS_DEFAULT_RESOURCE_ID; @@ -85,14 +126,17 @@ && getActivity() instanceof DynamicDrawerActivity) { } /** - * @return {@code true} if the parent activity is an - * {@link AppCompatActivity}. + * Checks whether the parent activity is a app compat activity. + * + * @return {@code true} if the parent activity is an {@link AppCompatActivity}. */ protected boolean isAppCompatActivity() { return getActivity() != null && getActivity() instanceof AppCompatActivity; } /** + * Checks whether the support action bar is applied to the parent activity. + * * @return {@code true} if the support action bar is not {@code null}. */ protected boolean isSupportActionBar() { @@ -101,8 +145,49 @@ protected boolean isSupportActionBar() { } /** - * Set result for the parent activity to notify the requester about - * the action. + * Retrieves a parcelable form the fragment arguments associated with the supplied key. + * + * @param key The key to be retrieved. + * + * @return The parcelable form the fragment arguments. + * + * @see Fragment#getArguments() + */ + public @Nullable T getParcelableFromArguments(@Nullable String key) { + if (getArguments() == null) { + return null; + } + + try { + return getArguments().getParcelable(key); + } catch (Exception ignored) { + return null; + } + } + + /** + * Retrieves a string form the fragment arguments associated with the supplied key. + * + * @param key The key to be retrieved. + * + * @return The string form the fragment arguments. + * + * @see Fragment#getArguments() + */ + public @Nullable String getStringFromArguments(@Nullable String key) { + if (getArguments() == null) { + return null; + } + + try { + return getArguments().getString(key); + } catch (Exception ignored) { + return null; + } + } + + /** + * Set result for the parent activity to notify the requester about the action. * * @param resultCode The result code for the activity. * @param intent The result intent to provide any data as an extra. @@ -123,8 +208,7 @@ protected void setResult(int resultCode, @Nullable Intent intent, boolean finish } /** - * Set result for the parent activity to notify the requester about - * the action. + * Set result for the parent activity to notify the requester about the action. * * @param resultCode The result code for the activity. * @param intent The result intent to provide any data as an extra. @@ -134,8 +218,7 @@ protected void setResult(int resultCode, @Nullable Intent intent) { } /** - * Set result for the parent activity to notify the requester about - * the action. + * Set result for the parent activity to notify the requester about the action. * * @param resultCode The result code for the activity. * @param finish {@code true} to finish the activity. @@ -145,8 +228,7 @@ protected void setResult(int resultCode, boolean finish) { } /** - * Set result for the parent activity to notify the requester about - * the action. + * Set result for the parent activity to notify the requester about the action. * * @param resultCode The result code for the activity. */ @@ -164,9 +246,14 @@ protected void finishActivity() { } /** + * Get the parent activity. + * * @return The parent activity as the instance of {@link DynamicActivity}. */ public DynamicActivity getDynamicActivity() { return (DynamicActivity) getActivity(); } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/fragment/DynamicViewPagerFragment.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/fragment/DynamicViewPagerFragment.java index 9b29c066a5..a2c0eaa94f 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/fragment/DynamicViewPagerFragment.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/fragment/DynamicViewPagerFragment.java @@ -17,16 +17,17 @@ package com.pranavpandey.android.dynamic.support.fragment; import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.TabLayout; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.view.ViewPager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.viewpager.widget.ViewPager; + +import com.google.android.material.tabs.TabLayout; import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.activity.DynamicActivity; import com.pranavpandey.android.dynamic.support.adapter.DynamicFragmentsAdapter; @@ -34,9 +35,9 @@ import java.util.List; /** - * An abstract {@link ViewPager} fragment to display multiple fragments - * inside the view pager along with the tabs. Just extend this fragment - * and implement the necessary functions to use it inside an activity. + * An abstract {@link ViewPager} fragment to display multiple fragments inside the view pager + * along with the tabs. Just extend this fragment and implement the necessary functions to use + * it inside an activity. * * @see #getTitles() * @see #getPages() @@ -59,12 +60,12 @@ public abstract class DynamicViewPagerFragment extends DynamicFragment { private TabLayout mTabLayout; /** - * List of tab titles to use with the {@link #mTabLayout}. + * List of tab titles to use with the tab layout. */ private List mTitles; /** - * List of fragments to show in the {@link #mViewPager}. + * List of fragments to show in the view pager. */ private List mPages; @@ -83,24 +84,22 @@ public void onCreate(@Nullable Bundle savedInstanceState) { } /** - * Abstract method to initialize a list of tab titles to be - * used with the tab layout. + * Abstract method to initialize a list of tab titles to be used with the tab layout. * * @return A list containing the tab titles. */ protected abstract List getTitles(); /** - * Abstract method to initialize a list fragments to be shown - * in the view pager. + * Abstract method to initialize a list fragments to be shown in the view pager. * * @return A list containing the fragments. */ protected abstract List getPages(); @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, + @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.ads_fragment_view_pager, container, false); } @@ -118,12 +117,13 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) { ((DynamicActivity) getActivity()).addHeader(R.layout.ads_tabs, true); mTabLayout = getActivity().findViewById(R.id.ads_tab_layout); - mViewPager.setOffscreenPageLimit(mAdapter.getCount()); mViewPager.setAdapter(mAdapter); mTabLayout.setupWithViewPager(mViewPager); } /** + * Get the tab layout used by this fragment. + * * @return The tab layout used by this fragment. */ public TabLayout getTabLayout() { @@ -131,6 +131,8 @@ public TabLayout getTabLayout() { } /** + * Get the view pager used by this fragment. + * * @return The view pager used by this fragment. */ public ViewPager getViewPager() { @@ -138,6 +140,8 @@ public ViewPager getViewPager() { } /** + * Returns the currently selected view pager page or position. + * * @return The currently selected view pager page or position. */ public int getCurrentPage() { @@ -154,8 +158,7 @@ public void setPage(final int page) { } /** - * View pager adapter to display the supplied fragments with tab - * titles. + * View pager adapter to display the supplied fragments with tab titles. */ static class ViewPagerAdapter extends DynamicFragmentsAdapter { @@ -169,8 +172,15 @@ static class ViewPagerAdapter extends DynamicFragmentsAdapter { */ private final List pages; - ViewPagerAdapter(@NonNull FragmentManager fragmentManager, @NonNull List titles, - @NonNull List pages) { + /** + * Constructor to initialize an object of this class. + * + * @param fragmentManager The fragment manager for this adapter. + * @param titles The tab titles list for this adapter. + * @param pages The fragments list for this adapter. + */ + ViewPagerAdapter(@NonNull FragmentManager fragmentManager, + @NonNull List titles, @NonNull List pages) { super(fragmentManager); this.titles = titles; diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/intent/DynamicIntent.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/intent/DynamicIntent.java new file mode 100644 index 0000000000..705e80c7b8 --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/intent/DynamicIntent.java @@ -0,0 +1,118 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.intent; + +import android.annotation.TargetApi; +import android.os.Build; +import android.provider.Settings; + +/** + * Helper class to manage the intent and extras. + */ +@TargetApi(Build.VERSION_CODES.M) +public class DynamicIntent { + + /** + * Constant for dynamic permission request. + */ + public static final int REQUEST_PERMISSIONS = 0; + + /** + * Constant for dynamic theme request. + */ + public static final int REQUEST_THEME = 0; + + /** + * Constant for dynamic day theme request. + */ + public static final int REQUEST_THEME_DAY = 1; + + /** + * Constant for dynamic night theme request. + */ + public static final int REQUEST_THEME_NIGHT = 2; + + /** + * Constant for dynamic theme action. + */ + public static final String ACTION_THEME = + "com.pranavpandey.android.dynamic.support.intent.action.THEME"; + + /** + * Constant for permissions action. + */ + public static final String ACTION_PERMISSIONS = + "com.pranavpandey.android.dynamic.support.intent.action.PERMISSIONS"; + + /** + * Settings action constant for write system settings. + * + * @see Settings#ACTION_MANAGE_WRITE_SETTINGS + */ + public static final String ACTION_WRITE_SYSTEM_SETTINGS = Settings.ACTION_MANAGE_WRITE_SETTINGS; + /** + * Settings action constant for overlay settings. + * + * @see Settings#ACTION_MANAGE_OVERLAY_PERMISSION + */ + public static final String ACTION_OVERLAY_SETTINGS = Settings.ACTION_MANAGE_OVERLAY_PERMISSION; + /** + * Settings action constant for usage access settings. + * + * @see Settings#ACTION_USAGE_ACCESS_SETTINGS + */ + public static final String ACTION_USAGE_ACCESS_SETTINGS = Settings.ACTION_USAGE_ACCESS_SETTINGS; + + /** + * Constant for text extra. + */ + public static final String EXTRA_TEXT = + "com.pranavpandey.android.dynamic.support.intent.extra.TEXT"; + + /** + * Constant for dynamic theme extra. + */ + public static final String EXTRA_THEME = + "com.pranavpandey.android.dynamic.support.intent.extra.THEME"; + + /** + * Constant for default dynamic theme extra. + */ + public static final String EXTRA_THEME_DEFAULT = + "com.pranavpandey.android.dynamic.support.intent.extra.THEME_DEFAULT"; + + /** + * Constant for permissions extra. + */ + public static final String EXTRA_PERMISSIONS = + "com.pranavpandey.android.dynamic.support.intent.extra.PERMISSIONS"; + /** + * Constant for permissions extra intent to perform it when all the permissions are granted. + */ + public static final String EXTRA_PERMISSIONS_INTENT = + "com.pranavpandey.android.dynamic.support.intent.extra.PERMISSIONS_INTENT"; + /** + * Constant for permissions extra action to perform it when all the permissions are granted. + */ + public static final String EXTRA_PERMISSIONS_ACTION = + "com.pranavpandey.android.dynamic.support.intent.extra.PERMISSIONS_ACTION"; + /** + * Constant for intent extra if updating the widget. + */ + public static final String EXTRA_WIDGET_UPDATE = + "com.pranavpandey.android.dynamic.support.intent.extra.WIDGET_UPDATE"; +} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/listener/DynamicColorListener.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/listener/DynamicColorListener.java new file mode 100644 index 0000000000..d2e876e7f0 --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/listener/DynamicColorListener.java @@ -0,0 +1,34 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.listener; + +import androidx.annotation.Nullable; + +/** + * An interface to get the various color callbacks. + */ +public interface DynamicColorListener { + + /** + * This method will be called when a color is selected. + * + * @param tag The optional tag to differentiate between various callbacks. + * @param position The selected position. + * @param color The selected color. + */ + void onColorSelected(@Nullable String tag, int position, int color); +} \ No newline at end of file diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/listener/DynamicColorResolver.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/listener/DynamicColorResolver.java new file mode 100644 index 0000000000..58fc0f8d86 --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/listener/DynamicColorResolver.java @@ -0,0 +1,44 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.listener; + +import androidx.annotation.ColorInt; +import androidx.annotation.Nullable; + +/** + * An interface to get the various callbacks related to the automatic color generation. + */ +public interface DynamicColorResolver { + + /** + * Get default color for this resolver. + * + * @param tag The optional tag to differentiate between various callbacks. + * + * @return The default color. + */ + int getDefaultColor(@Nullable String tag); + + /** + * Get automatically generated color for this resolver. + * + * @param tag The optional tag to differentiate between various callbacks. + * + * @return The automatically generated color. + */ + @ColorInt int getAutoColor(@Nullable String tag); +} \ No newline at end of file diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/listener/DynamicListener.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/listener/DynamicListener.java index 6af470f430..dd9ecaa547 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/listener/DynamicListener.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/listener/DynamicListener.java @@ -22,20 +22,17 @@ public interface DynamicListener { /** - * Called when the navigation bar theme has been changed. + * This method will be called when the navigation bar theme has been changed. */ void onNavigationBarThemeChange(); /** - * Called when the dynamic change event occurs (like theme or locale - * change). Re-create the activity or application here to adapt - * changes. + * This method will be called when the dynamic change event occurs (like theme, locale, etc.). + *

Re-create the activity or application here to adapt changes. * - * @param context {@code true} if there is a context change and it - * must be reinitialized. + * @param context {@code true} if there is a context change and it must be reinitialized. * - * @param recreate {@code true} if listener must be - * recreated to adapt the changes. + * @param recreate {@code true} if listener must be recreated to adapt the changes. */ void onDynamicChange(boolean context, boolean recreate); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/listener/DynamicSearchListener.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/listener/DynamicSearchListener.java index b878f51dd2..71bc73c9aa 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/listener/DynamicSearchListener.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/listener/DynamicSearchListener.java @@ -22,12 +22,12 @@ public interface DynamicSearchListener { /** - * Called when the search view is expanded. + * This method will be called when the search view is expanded. */ void onSearchViewExpanded(); /** - * Called when the search view is collapsed. + * This method will be called when the search view is collapsed. */ void onSearchViewCollapsed(); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/listener/DynamicWindowResolver.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/listener/DynamicWindowResolver.java new file mode 100644 index 0000000000..dd28fc1d97 --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/listener/DynamicWindowResolver.java @@ -0,0 +1,36 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.listener; + +import androidx.annotation.ColorInt; + +/** + * An interface to get the various callbacks related to the window color generation like + * status bar or navigation bar color. + */ +public interface DynamicWindowResolver { + + /** + * Get color for the status and navigation bar. + * + * @param optionalColor The optional color to provide some additional information like + * the background color. + * + * @return The color for the status and navigation bar. + */ + @ColorInt int getSystemUIColor(@ColorInt int optionalColor); +} \ No newline at end of file diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/locale/DynamicLocale.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/locale/DynamicLocale.java index 24b0ccbb9f..f659f449df 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/locale/DynamicLocale.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/locale/DynamicLocale.java @@ -18,27 +18,26 @@ import android.content.Context; import android.content.res.Configuration; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import java.util.Locale; /** - * An interface to implement the dynamic locale changes throughout - * the app. + * An interface to implement the dynamic locale changes throughout the app. */ public interface DynamicLocale { /** * @return The array of supported locales. * - * @see android.support.v4.os.ConfigurationCompat#getLocales(Configuration) + * @see androidx.core.os.ConfigurationCompat#getLocales(Configuration) */ @Nullable String[] getSupportedLocales(); /** - * @return The default locale to be used if no dynamic locale - * support is provided. + * @return The default locale to be used if no dynamic locale support is provided. * * @param context The context to get configuration. * diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/locale/DynamicLocaleUtils.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/locale/DynamicLocaleUtils.java index 62f644e1be..0d197e8432 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/locale/DynamicLocaleUtils.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/locale/DynamicLocaleUtils.java @@ -21,9 +21,10 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.os.Build; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.os.ConfigurationCompat; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.os.ConfigurationCompat; import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils; @@ -44,6 +45,11 @@ public class DynamicLocaleUtils { */ public static final String ADS_LOCALE_SPANISH = "es"; + /** + * Constant value for the Indonesian (Indonesia) locale. + */ + public static final String ADS_LOCALE_INDONESIA = "in"; + /** * Constant value for the Turkish (Türkçe) locale. */ @@ -55,13 +61,12 @@ public class DynamicLocaleUtils { public static final String ADE_LOCALE_SPLIT = ","; /** - * Get locale from the locale string in the format: - * {@code language,region} + * Get locale from the locale string in the format: {@code language,region}. * * @param locale The locale string to be converted. * * @return The converted locale from the locale string. - * Return {@code null} for the default locale value. + *

Return {@code null} for the default locale value. * * @see #ADS_LOCALE_SYSTEM */ @@ -70,7 +75,7 @@ public class DynamicLocaleUtils { if (locale == null || locale.equals(DynamicLocaleUtils.ADS_LOCALE_SYSTEM)) { localeWithRegion = null; } else { - String localeFormat[] = locale.split(ADE_LOCALE_SPLIT); + String[] localeFormat = locale.split(ADE_LOCALE_SPLIT); localeWithRegion = new Locale(localeFormat[0]); if (localeFormat.length > 1) { localeWithRegion = new Locale(localeFormat[0], localeFormat[1]); @@ -88,27 +93,28 @@ public class DynamicLocaleUtils { * * @return The default locale according to the supported locales. */ - public static @NonNull Locale getDefaultLocale(@NonNull Context context, - @Nullable String[] supportedLocales) { + public static @NonNull Locale getDefaultLocale( + @NonNull Context context, @Nullable String[] supportedLocales) { if (supportedLocales == null) { return ConfigurationCompat.getLocales( Resources.getSystem().getConfiguration()).get(0); } else { - return ConfigurationCompat.getLocales( - Resources.getSystem().getConfiguration()) - .getFirstMatch(supportedLocales); + Locale defaultLocale = ConfigurationCompat.getLocales( + Resources.getSystem().getConfiguration()).getFirstMatch(supportedLocales); + return defaultLocale != null ? defaultLocale : Locale.getDefault(); } } /** - * @return The locale after performing safety checks. + * Returns the locale after performing safety checks. * * @param locale The locale to be checked. - * @param defaultLocale The default locale if current locale does - * not passes checks. + * @param defaultLocale The default locale if current locale does not passes checks. + * + * @return The locale after performing safety checks. */ public static @NonNull Locale getLocale(@Nullable Locale locale, - @NonNull Locale defaultLocale) { + @NonNull Locale defaultLocale) { return locale == null ? defaultLocale : locale; } @@ -120,8 +126,7 @@ public class DynamicLocaleUtils { * * @return The modified context after applying the locale. */ - public static @NonNull Context setLocale( - @NonNull Context context, @Nullable Locale locale) { + public static @NonNull Context setLocale(@NonNull Context context, @Nullable Locale locale) { if (locale == null) { return context; } @@ -134,13 +139,11 @@ public class DynamicLocaleUtils { } /** - * Update resources for a given context after setting the - * locale on {@link Build.VERSION_CODES#JELLY_BEAN_MR1} or - * above devices. + * Update resources for a given context after setting the locale on + * {@link Build.VERSION_CODES#JELLY_BEAN_MR1} or above devices. * * @param context The context to set update resources. - * @param locale The locale to be used for the context - * resources. + * @param locale The locale to be used for the context resources. * * @return The modified context after applying the locale. */ @@ -164,13 +167,11 @@ public class DynamicLocaleUtils { } /** - * Update resources for a given context after setting the - * locale on {@link Build.VERSION_CODES#JELLY_BEAN} or - * below devices. + * Update resources for a given context after setting the locale on + * {@link Build.VERSION_CODES#JELLY_BEAN} or below devices. * * @param context The context to set update resources. - * @param locale The locale to be used for the context - * resources. + * @param locale The locale to be used for the context resources. * * @return The modified context after applying the locale. */ diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissionsAction.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicAction.java similarity index 62% rename from dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissionsAction.java rename to dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicAction.java index d0b945f05b..b3aada7d3b 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissionsAction.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicAction.java @@ -14,27 +14,27 @@ * limitations under the License. */ -package com.pranavpandey.android.dynamic.support.permission; +package com.pranavpandey.android.dynamic.support.model; import android.content.Context; import android.content.Intent; -import android.support.annotation.IntDef; + +import androidx.annotation.IntDef; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import static com.pranavpandey.android.dynamic.support.permission.DynamicPermissionsAction.NONE; -import static com.pranavpandey.android.dynamic.support.permission.DynamicPermissionsAction.START_ACTIVITY; -import static com.pranavpandey.android.dynamic.support.permission.DynamicPermissionsAction.START_FOREGROUND_SERVICE; -import static com.pranavpandey.android.dynamic.support.permission.DynamicPermissionsAction.START_SERVICE; +import static com.pranavpandey.android.dynamic.support.model.DynamicAction.NONE; +import static com.pranavpandey.android.dynamic.support.model.DynamicAction.START_ACTIVITY; +import static com.pranavpandey.android.dynamic.support.model.DynamicAction.START_FOREGROUND_SERVICE; +import static com.pranavpandey.android.dynamic.support.model.DynamicAction.START_SERVICE; /** - * Interface to hold the permissions action which will be called when all - * the permissions are granted. + * Interface to hold the various dynamic actions. */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = {NONE, START_SERVICE, START_FOREGROUND_SERVICE, START_ACTIVITY }) -public @interface DynamicPermissionsAction { +public @interface DynamicAction { /** * Constant for no action. @@ -51,7 +51,7 @@ /** * Constant to start a foreground service. * - * @see android.support.v4.content.ContextCompat#startForegroundService(Context, Intent) + * @see androidx.core.content.ContextCompat#startForegroundService(Context, Intent) */ int START_FOREGROUND_SERVICE = 1; diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicAppTheme.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicAppTheme.java new file mode 100644 index 0000000000..fdeade5a77 --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicAppTheme.java @@ -0,0 +1,1267 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.model; + +import android.os.Parcel; +import android.os.Parcelable; + +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.StyleRes; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.annotations.SerializedName; +import com.pranavpandey.android.dynamic.support.annotation.Exclude; +import com.pranavpandey.android.dynamic.support.model.adapter.DynamicThemeTypeAdapter; +import com.pranavpandey.android.dynamic.support.strategy.ExcludeStrategy; +import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; +import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; +import com.pranavpandey.android.dynamic.support.utils.DynamicThemeUtils; +import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; +import com.pranavpandey.android.dynamic.utils.DynamicUnitUtils; + +/** + * Dynamic app theme class to store various colors and attributes which can be modified at runtime. + */ +public class DynamicAppTheme implements Parcelable { + + /** + * Constant for the auto color value. + */ + public static final int AUTO = Theme.AUTO; + + /** + * DynamicAppTheme resource used by this theme. + */ + @Exclude + @SerializedName(DynamicThemeUtils.ADS_NAME_THEME_RES) + private @StyleRes int themeRes; + + /** + * Background color used by this theme. + */ + @SerializedName(DynamicThemeUtils.ADS_NAME_BACKGROUND_COLOR) + private @ColorInt int backgroundColor; + + /** + * Primary color used by this theme. + */ + @SerializedName(DynamicThemeUtils.ADS_NAME_PRIMARY_COLOR) + private @ColorInt int primaryColor; + + /** + * Dark primary color used by this theme. + */ + @SerializedName(DynamicThemeUtils.ADS_NAME_PRIMARY_COLOR_DARK) + private @ColorInt int primaryColorDark; + + /** + * Accent color used by this theme. + */ + @SerializedName(DynamicThemeUtils.ADS_NAME_ACCENT_COLOR) + private @ColorInt int accentColor; + + /** + * Dark accent color used by this theme. + */ + @SerializedName(DynamicThemeUtils.ADS_NAME_ACCENT_COLOR_DARK) + private @ColorInt int accentColorDark; + + /** + * Tint color according to the background color. + */ + @SerializedName(DynamicThemeUtils.ADS_NAME_TINT_BACKGROUND_COLOR) + private @ColorInt int tintBackgroundColor; + + /** + * Tint color according to the primary color. + */ + @SerializedName(DynamicThemeUtils.ADS_NAME_TINT_PRIMARY_COLOR) + private @ColorInt int tintPrimaryColor; + + /** + * Tint color according to the dark primary color. + */ + @SerializedName(DynamicThemeUtils.ADS_NAME_TINT_PRIMARY_COLOR_DARK) + private @ColorInt int tintPrimaryColorDark; + + /** + * Tint color according to the accent color. + */ + @SerializedName(DynamicThemeUtils.ADS_NAME_TINT_ACCENT_COLOR) + private @ColorInt int tintAccentColor; + + /** + * Tint color according to the dark accent color. + */ + @SerializedName(DynamicThemeUtils.ADS_NAME_TINT_ACCENT_COLOR_DARK) + private @ColorInt int tintAccentColorDark; + + /** + * Primary text color used by this theme. + */ + @SerializedName(DynamicThemeUtils.ADS_NAME_TEXT_PRIMARY_COLOR) + private @ColorInt int textPrimaryColor; + + /** + * Secondary text color used by this theme. + */ + @SerializedName(DynamicThemeUtils.ADS_NAME_TEXT_SECONDARY_COLOR) + private @ColorInt int textSecondaryColor; + + /** + * Inverse color for the primary text color. + */ + @SerializedName(DynamicThemeUtils.ADS_NAME_TEXT_PRIMARY_COLOR_INVERSE) + private @ColorInt int textPrimaryColorInverse; + + /** + * Inverse color for the secondary text color. + */ + @SerializedName(DynamicThemeUtils.ADS_NAME_TEXT_SECONDARY_COLOR_INVERSE) + private @ColorInt int textSecondaryColorInverse; + + /** + * Corner radius used by this theme in pixels. + */ + @SerializedName(DynamicThemeUtils.ADS_NAME_CORNER_RADIUS) + private int cornerRadius; + + /** + * Background aware functionality used by this theme. + */ + @SerializedName(DynamicThemeUtils.ADS_NAME_BACKGROUND_AWARE) + private @Theme.BackgroundAware int backgroundAware; + + /** + * Constructor to initialize an object of this class. + */ + public DynamicAppTheme() { + this.themeRes = DynamicResourceUtils.ADS_DEFAULT_RESOURCE_ID; + this.backgroundColor = AUTO; + this.primaryColor = AUTO; + this.primaryColorDark = AUTO; + this.accentColor = AUTO; + this.accentColorDark = AUTO; + this.tintBackgroundColor = AUTO; + this.tintPrimaryColor = AUTO; + this.tintPrimaryColorDark = AUTO; + this.tintAccentColor = AUTO; + this.tintAccentColorDark = AUTO; + this.textPrimaryColor = AUTO; + this.textSecondaryColor = AUTO; + this.textPrimaryColorInverse = AUTO; + this.textSecondaryColorInverse = AUTO; + this.cornerRadius = AUTO; + this.backgroundAware = Theme.BackgroundAware.AUTO; + } + + /** + * Constructor to initialize an object of this class from the dynamic string. + * + * @param theme The dynamic string to initialize the instance. + */ + public DynamicAppTheme(@NonNull String theme) throws Exception { + this(new GsonBuilder().setExclusionStrategies(new ExcludeStrategy()) + .registerTypeAdapter(DynamicAppTheme.class, new DynamicThemeTypeAdapter<>()) + .create().fromJson(DynamicThemeUtils + .formatDynamicTheme(theme), DynamicAppTheme.class)); + } + + /** + * Constructor to initialize an object of this class. + * + * @param dynamicAppTheme The dynamic app theme to copy the theme. + */ + public DynamicAppTheme(@NonNull DynamicAppTheme dynamicAppTheme) { + this.themeRes = dynamicAppTheme.getThemeRes(); + this.backgroundColor = dynamicAppTheme.getBackgroundColor(false); + this.primaryColor = dynamicAppTheme.getPrimaryColor(false); + this.primaryColorDark = dynamicAppTheme.getPrimaryColorDark(false); + this.accentColor = dynamicAppTheme.getAccentColor(false); + this.accentColorDark = dynamicAppTheme.getAccentColorDark(false); + this.tintBackgroundColor = dynamicAppTheme.getTintBackgroundColor(false); + this.tintPrimaryColor = dynamicAppTheme.getTintPrimaryColor(false); + this.tintPrimaryColorDark = dynamicAppTheme.getTintPrimaryColorDark(false); + this.tintAccentColor = dynamicAppTheme.getTintAccentColor(false); + this.tintAccentColorDark = dynamicAppTheme.getTintAccentColorDark(false); + this.textPrimaryColor = dynamicAppTheme.getTextPrimaryColor(false); + this.textSecondaryColor = dynamicAppTheme.getTextSecondaryColor(false); + this.textPrimaryColorInverse = dynamicAppTheme.getTextPrimaryColorInverse(false); + this.textSecondaryColorInverse = dynamicAppTheme.getTextSecondaryColorInverse(false); + this.cornerRadius = dynamicAppTheme.getCornerRadius(false); + this.backgroundAware = dynamicAppTheme.getBackgroundAware(false); + } + + /** + * Constructor to initialize an object of this class. + * + * @param primaryColor The primary color for this theme. + * @param primaryColorDark The dark primary color for this theme. + * @param accentColor The accent color for this theme. + * @param cornerRadius The corner size for this theme. + * @param backgroundAware The background aware functionality for this theme. + */ + public DynamicAppTheme(@ColorInt int primaryColor, + @ColorInt int primaryColorDark, @ColorInt int accentColor, int cornerRadius, + @Theme.BackgroundAware int backgroundAware) { + this(AUTO, primaryColor, primaryColorDark, accentColor, AUTO, AUTO, AUTO, + AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, AUTO, cornerRadius, backgroundAware); + } + + /** + * Constructor to initialize an object of this class. + * + * @param backgroundColor The background color for this theme. + * @param primaryColor The primary color for this theme. + * @param accentColor The accent color for this theme. + * @param textPrimaryColor The primary text color for this theme. + * @param textSecondaryColor The secondary text color for this theme. + * @param backgroundAware The background aware functionality for this theme. + */ + public DynamicAppTheme(@ColorInt int backgroundColor, @ColorInt int primaryColor, + @ColorInt int accentColor, @ColorInt int textPrimaryColor, + @ColorInt int textSecondaryColor, @Theme.BackgroundAware int backgroundAware) { + this(backgroundColor, primaryColor, accentColor, + DynamicColorUtils.getTintColor(backgroundColor), + DynamicColorUtils.getTintColor(primaryColor), + DynamicColorUtils.getTintColor(accentColor), + textPrimaryColor, textSecondaryColor, + DynamicColorUtils.getTintColor(textPrimaryColor), + DynamicColorUtils.getTintColor(textSecondaryColor), backgroundAware); + } + + /** + * Constructor to initialize an object of this class. + * + * @param backgroundColor The background color for this theme. + * @param primaryColor The primary color for this theme. + * @param accentColor The accent color for this theme. + * @param tintBackgroundColor Tint color according to the background color. + * @param tintPrimaryColor Tint color according to the primary color. + * @param tintAccentColor Tint color according to the accent color. + * @param textPrimaryColor The primary text color for this theme. + * @param textSecondaryColor The secondary text color for this theme. + * @param textPrimaryColorInverse Inverse color for the primary text color. + * @param textSecondaryColorInverse Inverse color for the secondary text color. + * @param backgroundAware The background aware functionality for this theme. + */ + public DynamicAppTheme(@ColorInt int backgroundColor, @ColorInt int primaryColor, + @ColorInt int accentColor, @ColorInt int tintBackgroundColor, + @ColorInt int tintPrimaryColor, @ColorInt int tintAccentColor, + @ColorInt int textPrimaryColor, @ColorInt int textSecondaryColor, + @ColorInt int textPrimaryColorInverse, @ColorInt int textSecondaryColorInverse, + @Theme.BackgroundAware int backgroundAware) { + this(backgroundColor, primaryColor, primaryColor, accentColor, accentColor, + tintBackgroundColor, tintPrimaryColor, tintPrimaryColor, tintAccentColor, + tintAccentColor, textPrimaryColor, textSecondaryColor, textPrimaryColorInverse, + textSecondaryColorInverse, AUTO, backgroundAware); + } + + /** + * Constructor to initialize an object of this class. + * + * @param backgroundColor The background color for this theme. + * @param primaryColor The primary color for this theme. + * @param primaryColorDark The dark primary color for this theme. + * @param accentColor The accent color for this theme. + * @param accentColorDark The dark accent color for this theme. + * @param tintBackgroundColor Tint color according to the background color. + * @param tintPrimaryColor Tint color according to the primary color. + * @param tintPrimaryColorDark Tint color according to the dark primary color. + * @param tintAccentColor Tint color according to the accent color. + * @param tintAccentColorDark Tint color according to the dark accent color. + * @param textPrimaryColor The primary text color for this theme. + * @param textSecondaryColor The secondary text color for this theme. + * @param textPrimaryColorInverse Inverse color for the primary text color. + * @param textSecondaryColorInverse Inverse color for the secondary text color. + * @param cornerRadius The corner size for this theme. + * @param backgroundAware The background aware functionality for this theme. + */ + public DynamicAppTheme(@ColorInt int backgroundColor, @ColorInt int primaryColor, + @ColorInt int primaryColorDark, @ColorInt int accentColor, + @ColorInt int accentColorDark, @ColorInt int tintBackgroundColor, + @ColorInt int tintPrimaryColor, @ColorInt int tintPrimaryColorDark, + @ColorInt int tintAccentColor, @ColorInt int tintAccentColorDark, + @ColorInt int textPrimaryColor, @ColorInt int textSecondaryColor, + @ColorInt int textPrimaryColorInverse, @ColorInt int textSecondaryColorInverse, + int cornerRadius, @Theme.BackgroundAware int backgroundAware) { + this.themeRes = DynamicResourceUtils.ADS_DEFAULT_RESOURCE_ID; + this.backgroundColor = backgroundColor; + this.primaryColor = primaryColor; + this.primaryColorDark = primaryColorDark; + this.accentColor = accentColor; + this.accentColorDark = accentColorDark; + this.tintBackgroundColor = tintBackgroundColor; + this.tintPrimaryColor = tintPrimaryColor; + this.tintPrimaryColorDark = tintPrimaryColorDark; + this.tintAccentColor = tintAccentColor; + this.tintAccentColorDark = tintAccentColorDark; + this.textPrimaryColor = textPrimaryColor; + this.textSecondaryColor = textSecondaryColor; + this.textPrimaryColorInverse = textPrimaryColorInverse; + this.textSecondaryColorInverse = textSecondaryColorInverse; + this.cornerRadius = cornerRadius; + this.backgroundAware = backgroundAware; + } + + /** + * Parcelable creator to create from parcel. + */ + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public DynamicAppTheme createFromParcel(Parcel in) { + return new DynamicAppTheme(in); + } + + @Override + public DynamicAppTheme[] newArray(int size) { + return new DynamicAppTheme[size]; + } + }; + + /** + * Read an object of this class from the parcel. + * + * @param in The parcel to read the values. + */ + public DynamicAppTheme(Parcel in) { + this.themeRes = in.readInt(); + this.backgroundColor = in.readInt(); + this.primaryColor = in.readInt(); + this.primaryColorDark = in.readInt(); + this.accentColor = in.readInt(); + this.accentColorDark = in.readInt(); + this.tintBackgroundColor = in.readInt(); + this.tintPrimaryColor = in.readInt(); + this.tintPrimaryColorDark = in.readInt(); + this.tintAccentColor = in.readInt(); + this.tintAccentColorDark = in.readInt(); + this.textPrimaryColor = in.readInt(); + this.textSecondaryColor = in.readInt(); + this.textPrimaryColorInverse = in.readInt(); + this.textSecondaryColorInverse = in.readInt(); + this.cornerRadius = in.readInt(); + this.backgroundAware = in.readInt(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(themeRes); + dest.writeInt(backgroundColor); + dest.writeInt(primaryColor); + dest.writeInt(primaryColorDark); + dest.writeInt(accentColor); + dest.writeInt(accentColorDark); + dest.writeInt(tintBackgroundColor); + dest.writeInt(tintPrimaryColor); + dest.writeInt(tintPrimaryColorDark); + dest.writeInt(tintAccentColor); + dest.writeInt(tintAccentColorDark); + dest.writeInt(textPrimaryColor); + dest.writeInt(textSecondaryColor); + dest.writeInt(textPrimaryColorInverse); + dest.writeInt(textSecondaryColorInverse); + dest.writeInt(cornerRadius); + dest.writeInt(backgroundAware); + } + + /** + * @return The theme resource used by this theme. + */ + public @StyleRes int getThemeRes() { + return themeRes; + } + + /** + * Set the theme resource used by this theme. + * + * @param themeRes The theme resource to be set. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + */ + public @NonNull DynamicAppTheme setThemeRes(@StyleRes int themeRes) { + this.themeRes = themeRes; + + return this; + } + + /** + * @return The background color used by this theme. + * + * @param resolve {@code true} to resolve the auto color. + */ + public @ColorInt int getBackgroundColor(boolean resolve) { + if (resolve && backgroundColor == AUTO) { + if (DynamicTheme.getInstance().getDefault().getBackgroundColor() == AUTO) { + throw new IllegalArgumentException( + "Background color cannot be auto for the default theme."); + } + + return DynamicTheme.getInstance().getDefault().getBackgroundColor(); + } + + return backgroundColor; + } + + /** + * @return The background color used by this theme. + */ + public @ColorInt int getBackgroundColor() { + return getBackgroundColor(true); + } + + /** + * Set the background color used by this theme. + * + * @param backgroundColor The background color to be set. + * @param generateTint {@code true} to automatically generate the tint color also. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + * + * @see #setTintBackgroundColor(int) + */ + public @NonNull DynamicAppTheme setBackgroundColor( + @ColorInt int backgroundColor, boolean generateTint) { + this.backgroundColor = backgroundColor; + if (generateTint && backgroundColor != AUTO) { + setTintBackgroundColor(DynamicColorUtils.getTintColor(backgroundColor)); + } + + return this; + } + + /** + * Set the background color used by this theme. + *

It will automatically generate the tint color also. + * + * @param backgroundColor The background color to be set. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + * + * @see #setBackgroundColor(int, boolean) + * @see #setTintBackgroundColor(int) + */ + public @NonNull DynamicAppTheme setBackgroundColor(@ColorInt int backgroundColor) { + return setBackgroundColor(backgroundColor, true); + } + + /** + * Returns the primary color used by this theme. + * + * @param resolve {@code true} to resolve the auto color. + * + * @return The primary color used by this theme. + */ + public @ColorInt int getPrimaryColor(boolean resolve) { + if (resolve && primaryColor == AUTO) { + return DynamicTheme.getInstance().getDefault().getPrimaryColor(); + } + + return primaryColor; + } + + /** + * Returns the primary color used by this theme. + * + * @return The primary color used by this theme. + */ + public @ColorInt int getPrimaryColor() { + return getPrimaryColor(true); + } + + /** + * Set the primary color used by this theme. + * + * @param primaryColor The primary color to be set. + * @param generateTint {@code true} to automatically generate the tint color also. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + * + * @see #setTintPrimaryColor(int) + */ + public @NonNull DynamicAppTheme setPrimaryColor( + @ColorInt int primaryColor, boolean generateTint) { + this.primaryColor = primaryColor; + if (generateTint && primaryColor != AUTO) { + setTintPrimaryColor(DynamicColorUtils.getTintColor(primaryColor)); + } + + return this; + } + + /** + * Set the primary color used by this theme. + *

It will automatically generate the tint color also. + * + * @param primaryColor The primary color to be set. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + * + * @see #setPrimaryColor(int, boolean) + * @see #setTintPrimaryColor(int) + */ + public @NonNull DynamicAppTheme setPrimaryColor(@ColorInt int primaryColor) { + return setPrimaryColor(primaryColor, true); + } + + /** + * Returns the dark primary color used by this theme. + * + * @param resolve {@code true} to resolve the auto color. + * + * @return The dark primary color used by this theme. + */ + public @ColorInt int getPrimaryColorDark(boolean resolve) { + if (resolve && primaryColorDark == AUTO) { + return DynamicTheme.getInstance().generateDarkColor(getPrimaryColor()); + } + + return primaryColorDark; + } + + /** + * Returns the dark primary color used by this theme. + * + * @return The dark primary color used by this theme. + */ + public @ColorInt int getPrimaryColorDark() { + return getPrimaryColorDark(true); + } + + /** + * Set the dark primary color used by this theme. + * + * @param primaryColorDark The dark primary color to be set. + * @param generateTint {@code true} to automatically generate the tint color also. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + * + * @see #setTintPrimaryColorDark(int) + */ + public @NonNull DynamicAppTheme setPrimaryColorDark( + @ColorInt int primaryColorDark, boolean generateTint) { + this.primaryColorDark = primaryColorDark; + if (generateTint && primaryColorDark != AUTO) { + setTintPrimaryColorDark(DynamicColorUtils.getTintColor(primaryColorDark)); + } + + return this; + } + + /** + * Set the dark primary color used by this theme. + *

It will automatically generate the tint color also. + * + * @param primaryColorDark The dark primary color to be set. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + * + * @see #setPrimaryColorDark(int, boolean) + * @see #setTintPrimaryColorDark(int) + */ + public @NonNull DynamicAppTheme setPrimaryColorDark(@ColorInt int primaryColorDark) { + return setPrimaryColorDark(primaryColorDark, true); + } + + /** + * Returns the accent color used by this theme. + * + * @param resolve {@code true} to resolve the auto color. + * + * @return The accent color used by this theme. + */ + public @ColorInt int getAccentColor(boolean resolve) { + if (resolve && accentColor == AUTO) { + return DynamicTheme.getInstance().getDefault().getAccentColor(); + } + + return accentColor; + } + + /** + * Returns the accent color used by this theme. + * + * @return The accent color used by this theme. + */ + public @ColorInt int getAccentColor() { + return getAccentColor(true); + } + + /** + * Set the accent color used by this theme. + * + * @param accentColor The accent color to be set. + * @param generateTint {@code true} to automatically generate the tint color also. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + * + * @see #setTintAccentColor(int) + */ + public @NonNull DynamicAppTheme setAccentColor( + @ColorInt int accentColor, boolean generateTint) { + this.accentColor = accentColor; + if (generateTint && accentColor != AUTO) { + setTintAccentColor(DynamicColorUtils.getTintColor(accentColor)); + } + + return this; + } + + /** + * Set the accent color used by this theme. + *

It will automatically generate the tint color also. + * + * @param accentColor The accent color to be set. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + * + * @see #setAccentColor(int, boolean) + * @see #setTintAccentColor(int) + */ + public @NonNull DynamicAppTheme setAccentColor(@ColorInt int accentColor) { + return setAccentColor(accentColor, true); + } + + /** + * Returns the dark accent color used by this theme. + * + * @param resolve {@code true} to resolve the auto color. + * + * @return The dark accent color used by this theme. + */ + public @ColorInt int getAccentColorDark(boolean resolve) { + if (resolve && accentColorDark == AUTO) { + return DynamicTheme.getInstance().generateDarkColor(getAccentColor()); + } + + return accentColorDark; + } + + /** + * Returns the dark accent color used by this theme. + * + * @return The dark accent color used by this theme. + */ + public @ColorInt int getAccentColorDark() { + return getAccentColorDark(true); + } + + /** + * Set the dark accent color used by this theme. + * + * @param accentColorDark The dark accent color to be set. + * @param generateTint {@code true} to automatically generate the tint color also. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + * + * @see #setTintAccentColorDark(int) + */ + public @NonNull DynamicAppTheme setAccentColorDark( + @ColorInt int accentColorDark, boolean generateTint) { + this.accentColorDark = accentColorDark; + if (generateTint && accentColorDark != AUTO) { + setTintAccentColorDark(DynamicColorUtils.getTintColor(accentColorDark)); + } + + return this; + } + + /** + * Set the dark accent color used by this theme. + *

It will automatically generate the tint color also. + * + * @param accentColorDark The dark accent color to be set. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + * + * @see #setAccentColorDark(int, boolean) + * @see #setTintAccentColorDark(int) + */ + public @NonNull DynamicAppTheme setAccentColorDark(@ColorInt int accentColorDark) { + return setAccentColorDark(accentColorDark, true); + } + + /** + * Returns the background tint color used by this theme. + * + * @param resolve {@code true} to resolve the auto color. + * + * @return The background tint color used by this theme. + */ + public @ColorInt int getTintBackgroundColor(boolean resolve) { + if (resolve && tintBackgroundColor == AUTO) { + return DynamicColorUtils.getTintColor(getBackgroundColor()); + } + + return tintBackgroundColor; + } + + /** + * Returns the background tint color used by this theme. + * + * @return The background tint color used by this theme. + */ + public @ColorInt int getTintBackgroundColor() { + return getTintBackgroundColor(true); + } + + /** + * Set the background tint color used by this theme. + * + * @param tintBackgroundColor The background tint color to be set. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + */ + public @NonNull DynamicAppTheme setTintBackgroundColor(@ColorInt int tintBackgroundColor) { + this.tintBackgroundColor = tintBackgroundColor; + + return this; + } + + /** + * Returns the primary tint color used by this theme. + * + * @param resolve {@code true} to resolve the auto color. + * + * @return The primary tint color used by this theme. + */ + public @ColorInt int getTintPrimaryColor(boolean resolve) { + if (resolve && tintPrimaryColor == AUTO) { + return DynamicColorUtils.getTintColor(getPrimaryColor()); + } + + return tintPrimaryColor; + } + + /** + * Returns the primary tint color used by this theme. + * + * @return The primary tint color used by this theme. + */ + public @ColorInt int getTintPrimaryColor() { + return getTintPrimaryColor(true); + } + + /** + * Set the primary tint color used by this theme. + * + * @param tintPrimaryColor The primary tint color to be set. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + */ + public @NonNull DynamicAppTheme setTintPrimaryColor(@ColorInt int tintPrimaryColor) { + this.tintPrimaryColor = tintPrimaryColor; + + return this; + } + + /** + * Returns the dark primary tint color used by this theme. + * + * @param resolve {@code true} to resolve the auto color. + * + * @return The dark primary tint color used by this theme. + */ + public @ColorInt int getTintPrimaryColorDark(boolean resolve) { + if (resolve && tintPrimaryColorDark == AUTO) { + return DynamicColorUtils.getTintColor(getPrimaryColorDark()); + } + + return tintPrimaryColorDark; + } + + /** + * Returns the dark primary tint color used by this theme. + * + * @return The dark primary tint color used by this theme. + */ + public @ColorInt int getTintPrimaryColorDark() { + return getTintPrimaryColorDark(true); + } + + /** + * Set the dark primary tint color used by this theme. + * + * @param tintPrimaryColorDark The dark primary tint color to be set. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + */ + public @NonNull DynamicAppTheme setTintPrimaryColorDark(@ColorInt int tintPrimaryColorDark) { + this.tintPrimaryColorDark = tintPrimaryColorDark; + + return this; + } + + /** + * Returns the accent tint color used by this theme. + * + * @param resolve {@code true} to resolve the auto color. + * + * @return The accent tint color used by this theme. + */ + public @ColorInt int getTintAccentColor(boolean resolve) { + if (resolve && tintAccentColor == AUTO) { + return DynamicColorUtils.getTintColor(getAccentColor()); + } + + return tintAccentColor; + } + + /** + * Returns the accent tint color used by this theme. + * + * @return The accent tint color used by this theme. + */ + public @ColorInt int getTintAccentColor() { + return getTintAccentColor(true); + } + + /** + * Set the accent tint color used by this theme. + * + * @param tintAccentColor The accent tint color to be set. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + */ + public @NonNull DynamicAppTheme setTintAccentColor(@ColorInt int tintAccentColor) { + this.tintAccentColor = tintAccentColor; + + return this; + } + + /** + * Returns the dark accent tint color used by this theme. + * + * @param resolve {@code true} to resolve the auto color. + * + * @return The dark accent tint color used by this theme. + */ + public @ColorInt int getTintAccentColorDark(boolean resolve) { + if (resolve && tintAccentColorDark == AUTO) { + return DynamicColorUtils.getTintColor(getAccentColorDark()); + } + + return tintAccentColorDark; + } + + /** + * Returns the dark accent tint color used by this theme. + * + * @return The dark accent tint color used by this theme. + */ + public @ColorInt int getTintAccentColorDark() { + return getTintAccentColorDark(true); + } + + /** + * Set the dark accent tint color used by this theme. + * + * @param tintAccentColorDark The dark accent tint color to be set. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + */ + public @NonNull DynamicAppTheme setTintAccentColorDark(@ColorInt int tintAccentColorDark) { + this.tintAccentColorDark = tintAccentColorDark; + + return this; + } + + + /** + * Returns the primary text color used by this theme. + * + * @param resolve {@code true} to resolve the auto color. + * + * @return The primary text color used by this theme. + */ + public @ColorInt int getTextPrimaryColor(boolean resolve) { + if (resolve && textPrimaryColor == AUTO) { + return DynamicTheme.getInstance().getDefault().getTextPrimaryColor(); + } + + return textPrimaryColor; + } + + /** + * Returns the primary text color used by this theme. + * + * @return The primary text color used by this theme. + */ + public @ColorInt int getTextPrimaryColor() { + return getTextPrimaryColor(true); + } + + /** + * Set the primary text color used by this theme. + * + * @param textPrimaryColor The primary text color to be set. + * @param generateInverse {@code true} to automatically generate the inverse color also. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + * + * @see #setTextPrimaryColorInverse(int) + */ + public @NonNull DynamicAppTheme setTextPrimaryColor( + @ColorInt int textPrimaryColor, boolean generateInverse) { + this.textPrimaryColor = textPrimaryColor; + if (generateInverse && textPrimaryColor != AUTO) { + setTextPrimaryColorInverse(DynamicColorUtils.getTintColor(textPrimaryColor)); + } + + return this; + } + + /** + * Set the primary text color used by this theme. + *

It will automatically generate the inverse color also. + * + * @param textPrimaryColor The primary text color to be set. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + * + * @see #setTextPrimaryColor(int, boolean) + * @see #setTextPrimaryColorInverse(int) + */ + public @NonNull DynamicAppTheme setTextPrimaryColor(@ColorInt int textPrimaryColor) { + return setTextPrimaryColor(textPrimaryColor, true); + } + + /** + * Returns the secondary text color used by this theme. + * + * @param resolve {@code true} to resolve the auto color. + * + * @return The secondary text color used by this theme. + */ + public @ColorInt int getTextSecondaryColor(boolean resolve) { + if (resolve && textSecondaryColor == AUTO) { + return DynamicTheme.getInstance().getDefault().getTextSecondaryColor(); + } + + return textSecondaryColor; + } + + /** + * Returns the secondary text color used by this theme. + * + * @return The secondary text color used by this theme. + */ + public @ColorInt int getTextSecondaryColor() { + return getTextSecondaryColor(true); + } + + /** + * Set the secondary text color used by this theme. + * + * @param textSecondaryColor The secondary text color to be set. + * @param generateInverse {@code true} to automatically generate the inverse color also. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + * + * @see #setTextSecondaryColorInverse(int) + */ + public @NonNull DynamicAppTheme setTextSecondaryColor( + @ColorInt int textSecondaryColor, boolean generateInverse) { + this.textSecondaryColor = textSecondaryColor; + if (generateInverse && textSecondaryColor != AUTO) { + setTextSecondaryColorInverse(DynamicColorUtils.getTintColor(textSecondaryColor)); + } + + return this; + } + + /** + * Set the secondary text color used by this theme. + *

It will automatically generate the inverse color also. + * + * @param textSecondaryColor The secondary text color to be set. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + * + * @see #setTextSecondaryColor(int, boolean) + * @see #setTextSecondaryColorInverse(int) + */ + public @NonNull DynamicAppTheme setTextSecondaryColor(@ColorInt int textSecondaryColor) { + return setTextSecondaryColor(textSecondaryColor, true); + } + + /** + * Returns the inverse color for the primary text color. + * + * @param resolve {@code true} to resolve the auto color. + * + * @return The inverse color for the primary text color. + */ + public @ColorInt int getTextPrimaryColorInverse(boolean resolve) { + if (resolve && textPrimaryColorInverse == AUTO) { + return DynamicColorUtils.getTintColor(getTextPrimaryColor()); + } + + return textPrimaryColorInverse; + } + + /** + * Returns the inverse color for the primary text color. + * + * @return The inverse color for the primary text color. + */ + public @ColorInt int getTextPrimaryColorInverse() { + return getTextPrimaryColorInverse(true); + } + + /** + * Set the primary text inverse color used by this theme. + * + * @param textPrimaryColorInverse The primary text inverse color to be set. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + */ + public @NonNull DynamicAppTheme setTextPrimaryColorInverse(int textPrimaryColorInverse) { + this.textPrimaryColorInverse = textPrimaryColorInverse; + + return this; + } + + /** + * Returns the inverse color for the secondary text color. + * + * @param resolve {@code true} to resolve the auto color. + * + * @return The inverse color for the secondary text color. + */ + public @ColorInt int getTextSecondaryColorInverse(boolean resolve) { + if (resolve && textSecondaryColorInverse == AUTO) { + return DynamicColorUtils.getTintColor(getTextSecondaryColor()); + } + + return textSecondaryColorInverse; + } + + /** + * Returns the inverse color for the secondary text color. + * + * @return The inverse color for the secondary text color. + */ + public @ColorInt int getTextSecondaryColorInverse() { + return getTextSecondaryColorInverse(true); + } + + /** + * Set the secondary text inverse color used by this theme. + * + * @param textSecondaryColorInverse The secondary text inverse color to be set. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + */ + public @NonNull DynamicAppTheme setTextSecondaryColorInverse(int textSecondaryColorInverse) { + this.textSecondaryColorInverse = textSecondaryColorInverse; + + return this; + } + + /** + * Returns the corner size used by this theme in pixels. + * + * @param resolve {@code true} to resolve auto corner size. + * + * @return The corner size used by this theme in pixels. + */ + public int getCornerRadius(boolean resolve) { + if (resolve && cornerRadius == AUTO) { + return DynamicTheme.getInstance().getDefault().getCornerRadius(); + } + + return cornerRadius; + } + + /** + * Returns the corner size used by this theme in pixels. + * + * @return The corner size used by this theme in pixels. + */ + public int getCornerRadius() { + return getCornerRadius(true); + } + + /** + * Returns the corner size used by this theme in dips. + * + * @return The corner size used by this theme in dips. + */ + public int getCornerSizeDp() { + return DynamicUnitUtils.convertPixelsToDp(getCornerRadius()); + } + + /** + * Set the corner size used by this theme. + * + * @param cornerRadius The corner size to be set in pixels. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + */ + public @NonNull DynamicAppTheme setCornerRadius(int cornerRadius) { + this.cornerRadius = cornerRadius; + + return this; + } + + /** + * Set the corner size used by this theme. + * + * @param cornerSize The corner size to be set in dips. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + */ + public @NonNull DynamicAppTheme setCornerRadiusDp(float cornerSize) { + return setCornerRadius((int) cornerSize == AUTO ? (int) cornerSize + : DynamicUnitUtils.convertDpToPixels(cornerSize)); + } + + /** + * Returns the background aware functionality used by this theme. + * + * @param resolve {@code true} to resolve auto background aware. + * + * @return The background aware functionality used by this theme. + */ + public @Theme.BackgroundAware int getBackgroundAware(boolean resolve) { + if (resolve && backgroundAware == Theme.BackgroundAware.AUTO) { + return DynamicTheme.getInstance().getDefault().getBackgroundAware(); + } + + return backgroundAware; + } + + /** + * Returns the background aware functionality used by this theme. + * + * @return The background aware functionality used by this theme. + */ + public @Theme.BackgroundAware int getBackgroundAware() { + return getBackgroundAware(true); + } + + /** + * Checks whether the background functionality is enabled. + * + * @return {@code true} if the background aware functionality is enabled. + */ + public boolean isBackgroundAware() { + return getBackgroundAware(true) != Theme.BackgroundAware.DISABLE; + } + + /** + * Set the background aware functionality used by this theme. + * + * @param backgroundAware The background aware functionality to be set. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + */ + public @NonNull DynamicAppTheme setBackgroundAware( + @Theme.BackgroundAware int backgroundAware) { + this.backgroundAware = backgroundAware; + + return this; + } + + /** + * Returns {@code true} if this theme is dark. + * + * @return {@code true} if this theme is dark. + */ + public boolean isDarkTheme() { + return DynamicColorUtils.isColorDark(getBackgroundColor()); + } + + /** + * Auto generate tint or inverse colors according to the base colors. They can be set + * individually by calling the appropriate methods. + * + * @param tint {@code true} to generate tint colors. + * @param inverse {@code true} to generate inverse colors. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + */ + public @NonNull DynamicAppTheme autoGenerateColors(boolean tint, boolean inverse) { + if (tint) { + setTintBackgroundColor(DynamicColorUtils.getTintColor(getBackgroundColor())); + setTintPrimaryColor(DynamicColorUtils.getTintColor(getPrimaryColor())); + setTintPrimaryColorDark(DynamicColorUtils.getTintColor(getAccentColorDark())); + setTintAccentColor(DynamicColorUtils.getTintColor(getAccentColor())); + setTintAccentColorDark(DynamicColorUtils.getTintColor(getAccentColorDark())); + } + + if (inverse) { + setTextPrimaryColorInverse(DynamicColorUtils.getTintColor(getTextPrimaryColor())); + setTextSecondaryColorInverse(DynamicColorUtils.getTintColor(getTextSecondaryColor())); + } + + return this; + } + + /** + * Auto generate tint or inverse colors according to the base colors. They can be set + * individually by calling the appropriate methods. + * + * @return The {@link DynamicAppTheme} object to allow for chaining of calls to set methods. + * + * @see #autoGenerateColors(boolean, boolean) + */ + public @NonNull DynamicAppTheme autoGenerateColors() { + return autoGenerateColors(true, true); + } + + /** + * Converts this theme into its Json equivalent. + * + * @return The Json equivalent of this theme. + */ + public @NonNull String toJsonString() { + return new Gson().toJson(new DynamicAppTheme(this)); + } + + /** + * Convert this theme into a pretty json string. + * + * @return The converted json string. + */ + public @NonNull String toDynamicString() { + return new GsonBuilder().setExclusionStrategies(new ExcludeStrategy()) + .registerTypeAdapter(DynamicAppTheme.class, new DynamicThemeTypeAdapter<>()) + .setPrettyPrinting().create().toJson(new DynamicAppTheme(this)); + } + + @Override + public @NonNull String toString() { + return "DynamicAppTheme{" + + themeRes + backgroundColor + primaryColor + primaryColorDark + + accentColor + accentColorDark + tintBackgroundColor + tintPrimaryColor + + tintPrimaryColorDark + tintAccentColor + tintAccentColorDark + textPrimaryColor + + textSecondaryColor + textPrimaryColorInverse + textSecondaryColorInverse + + cornerRadius + backgroundAware + + '}'; + } +} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicInfo.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicInfo.java index d0f3f27df3..30fc34ad44 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicInfo.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicInfo.java @@ -17,13 +17,14 @@ package com.pranavpandey.android.dynamic.support.model; import android.graphics.drawable.Drawable; -import android.support.annotation.ArrayRes; -import android.support.annotation.ColorInt; -import android.support.annotation.Nullable; + +import androidx.annotation.ArrayRes; +import androidx.annotation.ColorInt; +import androidx.annotation.Nullable; /** - * A model class to hold the dynamic information which can be used - * by the {@link com.pranavpandey.android.dynamic.support.view.DynamicInfoView}. + * A model class to hold the dynamic information which can be used by the + * {@link com.pranavpandey.android.dynamic.support.view.DynamicInfoView}. */ public class DynamicInfo { @@ -68,14 +69,12 @@ public class DynamicInfo { private CharSequence[] linksUrls; /** - * Icon drawables array resource for the links - * used by this info. + * Icon drawables array resource for the links used by this info. */ private @ArrayRes int linksIconsResId; /** - * Icon tint colors array resource for the links - * used by this info. + * Icon tint colors array resource for the links used by this info. */ private @ArrayRes int linksColorsResId; @@ -90,6 +89,8 @@ public class DynamicInfo { private @ColorInt Integer[] linksColors; /** + * Ge the icon used by this info. + * * @return The icon used by this info. */ public @Nullable Drawable getIcon() { @@ -101,8 +102,7 @@ public class DynamicInfo { * * @param icon The icon to be set. * - * @return The {@link DynamicInfo} object to allow for chaining - * of calls to set methods. + * @return The {@link DynamicInfo} object to allow for chaining of calls to set methods. */ public DynamicInfo setIcon(@Nullable Drawable icon) { this.icon = icon; @@ -111,6 +111,8 @@ public DynamicInfo setIcon(@Nullable Drawable icon) { } /** + * Get the big fallback icon used by this info. + * * @return The big fallback icon used by this info. */ public @Nullable Drawable getIconBig() { @@ -122,8 +124,7 @@ public DynamicInfo setIcon(@Nullable Drawable icon) { * * @param iconBig The big fallback icon to be set. * - * @return The {@link DynamicInfo} object to allow for chaining - * of calls to set methods. + * @return The {@link DynamicInfo} object to allow for chaining of calls to set methods. */ public DynamicInfo setIconBig(@Nullable Drawable iconBig) { this.iconBig = iconBig; @@ -132,6 +133,8 @@ public DynamicInfo setIconBig(@Nullable Drawable iconBig) { } /** + * Get the title used by this info. + * * @return The title used by this info. */ public @Nullable CharSequence getTitle() { @@ -143,8 +146,7 @@ public DynamicInfo setIconBig(@Nullable Drawable iconBig) { * * @param title The title to be set. * - * @return The {@link DynamicInfo} object to allow for chaining - * of calls to set methods. + * @return The {@link DynamicInfo} object to allow for chaining of calls to set methods. */ public DynamicInfo setTitle(@Nullable CharSequence title) { this.title = title; @@ -153,6 +155,8 @@ public DynamicInfo setTitle(@Nullable CharSequence title) { } /** + * Get the subtitle used by this info. + * * @return The subtitle used by this info. */ public @Nullable CharSequence getSubtitle() { @@ -164,8 +168,7 @@ public DynamicInfo setTitle(@Nullable CharSequence title) { * * @param subtitle The subtitle to be set. * - * @return The {@link DynamicInfo} object to allow for chaining - * of calls to set methods. + * @return The {@link DynamicInfo} object to allow for chaining of calls to set methods. */ public DynamicInfo setSubtitle(@Nullable CharSequence subtitle) { this.subtitle = subtitle; @@ -174,6 +177,8 @@ public DynamicInfo setSubtitle(@Nullable CharSequence subtitle) { } /** + * Ge the description used by this info. + * * @return The description used by this info. */ public @Nullable CharSequence getDescription() { @@ -185,8 +190,7 @@ public DynamicInfo setSubtitle(@Nullable CharSequence subtitle) { * * @param description The description to be set. * - * @return The {@link DynamicInfo} object to allow for chaining - * of calls to set methods. + * @return The {@link DynamicInfo} object to allow for chaining of calls to set methods. */ public DynamicInfo setDescription(@Nullable CharSequence description) { this.description = description; @@ -195,6 +199,8 @@ public DynamicInfo setDescription(@Nullable CharSequence description) { } /** + * Get the title for the links used by this info. + * * @return The title for the links used by this info. */ public @Nullable CharSequence[] getLinks() { @@ -206,8 +212,7 @@ public DynamicInfo setDescription(@Nullable CharSequence description) { * * @param links The titles for the links to be set. * - * @return The {@link DynamicInfo} object to allow for chaining - * of calls to set methods. + * @return The {@link DynamicInfo} object to allow for chaining of calls to set methods. */ public DynamicInfo setLinks(@Nullable CharSequence[] links) { this.links = links; @@ -216,6 +221,8 @@ public DynamicInfo setLinks(@Nullable CharSequence[] links) { } /** + * Get the subtitle for the links used by this info. + * * @return The subtitle for the links used by this info. */ public @Nullable CharSequence[] getLinksSubtitles() { @@ -227,8 +234,7 @@ public DynamicInfo setLinks(@Nullable CharSequence[] links) { * * @param linksSubtitles The subtitles for the links to be set. * - * @return The {@link DynamicInfo} object to allow for chaining - * of calls to set methods. + * @return The {@link DynamicInfo} object to allow for chaining of calls to set methods. */ public DynamicInfo setLinksSubtitles(@Nullable CharSequence[] linksSubtitles) { this.linksSubtitles = linksSubtitles; @@ -237,6 +243,8 @@ public DynamicInfo setLinksSubtitles(@Nullable CharSequence[] linksSubtitles) { } /** + * Get the url for the links used by this info. + * * @return The url for the links used by this info. */ public @Nullable CharSequence[] getLinksUrls() { @@ -248,8 +256,7 @@ public DynamicInfo setLinksSubtitles(@Nullable CharSequence[] linksSubtitles) { * * @param linksUrls The urls for the links to be set. * - * @return The {@link DynamicInfo} object to allow for chaining - * of calls to set methods. + * @return The {@link DynamicInfo} object to allow for chaining of calls to set methods. */ public DynamicInfo setLinksUrls(@Nullable CharSequence[] linksUrls) { this.linksUrls = linksUrls; @@ -258,22 +265,20 @@ public DynamicInfo setLinksUrls(@Nullable CharSequence[] linksUrls) { } /** - * @return The icons array resource for the links - * used by this info. + * Get the icons array resource for the links used by this info. + * + * @return The icons array resource for the links used by this info. */ public @ArrayRes int getLinksIconsResId() { return linksIconsResId; } /** - * Set the icons array resource for the links - * used by this info. + * Set the icons array resource for the links used by this info. * - * @param linksIconsResId The icon drawables array resource for - * the links to be set. + * @param linksIconsResId The icon drawables array resource for the links to be set. * - * @return The {@link DynamicInfo} object to allow for chaining - * of calls to set methods. + * @return The {@link DynamicInfo} object to allow for chaining of calls to set methods. */ public DynamicInfo setLinksIconsResId(@ArrayRes int linksIconsResId) { this.linksIconsResId = linksIconsResId; @@ -282,22 +287,20 @@ public DynamicInfo setLinksIconsResId(@ArrayRes int linksIconsResId) { } /** - * @return The icon tint colors array resource for the links - * used by this info. + * Get the icon tint colors array resource for the links used by this info. + * + * @return The icon tint colors array resource for the links used by this info. */ public @ArrayRes int getLinksColorsResId() { return linksColorsResId; } /** - * Set the icon tint colors array resource for the links - * used by this info. + * Set the icon tint colors array resource for the links used by this info. * - * @param linksColorsResId The icon tint colors array resource for - * the links to be set. + * @param linksColorsResId The icon tint colors array resource for the links to be set. * - * @return The {@link DynamicInfo} object to allow for chaining - * of calls to set methods. + * @return The {@link DynamicInfo} object to allow for chaining of calls to set methods. */ public DynamicInfo setLinksColorsResId(@ArrayRes int linksColorsResId) { this.linksColorsResId = linksColorsResId; @@ -306,6 +309,8 @@ public DynamicInfo setLinksColorsResId(@ArrayRes int linksColorsResId) { } /** + * Get the icon for the links used by this info. + * * @return The icon for the links used by this info. */ public @Nullable Drawable[] getLinksDrawables() { @@ -315,11 +320,9 @@ public DynamicInfo setLinksColorsResId(@ArrayRes int linksColorsResId) { /** * Set the icon for the links used by this info. * - * @param linksDrawables The icon drawables for the links - * to be set. + * @param linksDrawables The icon drawables for the links to be set. * - * @return The {@link DynamicInfo} object to allow for chaining - * of calls to set methods. + * @return The {@link DynamicInfo} object to allow for chaining of calls to set methods. */ public DynamicInfo setLinksDrawables(@Nullable Drawable[] linksDrawables) { this.linksDrawables = linksDrawables; @@ -328,6 +331,8 @@ public DynamicInfo setLinksDrawables(@Nullable Drawable[] linksDrawables) { } /** + * Get the icon tint color for the links used by this info. + * * @return The icon tint color for the links used by this info. */ public @Nullable @ColorInt Integer[] getLinksColors() { @@ -337,11 +342,9 @@ public DynamicInfo setLinksDrawables(@Nullable Drawable[] linksDrawables) { /** * Set the icon tint color for the links used by this info. * - * @param linksColors The icon tint color for the links - * to be set. + * @param linksColors The icon tint color for the links to be set. * - * @return The {@link DynamicInfo} object to allow for chaining - * of calls to set methods. + * @return The {@link DynamicInfo} object to allow for chaining of calls to set methods. */ public DynamicInfo setLinksColors(@Nullable @ColorInt Integer[] linksColors) { this.linksColors = linksColors; diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicItem.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicItem.java index 81e0474cc0..d19b13711c 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicItem.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicItem.java @@ -17,15 +17,16 @@ package com.pranavpandey.android.dynamic.support.model; import android.graphics.drawable.Drawable; -import android.support.annotation.ColorInt; -import android.support.annotation.Nullable; import android.view.View; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; +import androidx.annotation.ColorInt; +import androidx.annotation.Nullable; + +import com.pranavpandey.android.dynamic.support.theme.Theme; /** - * A model class to hold the dynamic item information which can be used - * by the {@link com.pranavpandey.android.dynamic.support.view.DynamicItemView}. + * A model class to hold the dynamic item information which can be used by the + * {@link com.pranavpandey.android.dynamic.support.view.DynamicItemView}. */ public class DynamicItem { @@ -52,16 +53,16 @@ public class DynamicItem { /** * Icon tint color type used by this item. */ - private @DynamicColorType int colorType; + private @Theme.ColorType int colorType; /** * {@code true} to show horizontal divider. - * Useful to display in a list view. + *

Useful to display in a list view. */ private boolean showDivider; /** - * On click listener used by this item. + * Click listener used by this item. */ private View.OnClickListener onClickListener; @@ -76,8 +77,8 @@ public class DynamicItem { * @param showDivider {@code true} to show horizontal divider. */ public DynamicItem(@Nullable Drawable icon, @Nullable CharSequence title, - @Nullable CharSequence subtitle, int color, - @DynamicColorType int colorType, boolean showDivider) { + @Nullable CharSequence subtitle, int color, + @Theme.ColorType int colorType, boolean showDivider) { this.icon = icon; this.title = title; this.subtitle = subtitle; @@ -87,6 +88,8 @@ public DynamicItem(@Nullable Drawable icon, @Nullable CharSequence title, } /** + * Get the icon used by this item. + * * @return The icon used by this item. */ public @Nullable Drawable getIcon() { @@ -98,8 +101,7 @@ public DynamicItem(@Nullable Drawable icon, @Nullable CharSequence title, * * @param icon The icon to be set. * - * @return The {@link DynamicItem} object to allow for chaining - * of calls to set methods. + * @return The {@link DynamicItem} object to allow for chaining of calls to set methods. */ public DynamicItem setIcon(@Nullable Drawable icon) { this.icon = icon; @@ -108,6 +110,8 @@ public DynamicItem setIcon(@Nullable Drawable icon) { } /** + * Get the title used by this item. + * * @return The title used by this item. */ public @Nullable CharSequence getTitle() { @@ -119,8 +123,7 @@ public DynamicItem setIcon(@Nullable Drawable icon) { * * @param title The title to be set. * - * @return The {@link DynamicItem} object to allow for chaining - * of calls to set methods. + * @return The {@link DynamicItem} object to allow for chaining of calls to set methods. */ public DynamicItem setTitle(@Nullable CharSequence title) { this.title = title; @@ -129,6 +132,8 @@ public DynamicItem setTitle(@Nullable CharSequence title) { } /** + * Get the subtitle used by this item. + * * @return The subtitle used by this item. */ public @Nullable CharSequence getSubtitle() { @@ -140,8 +145,7 @@ public DynamicItem setTitle(@Nullable CharSequence title) { * * @param subtitle The subtitle to be set. * - * @return The {@link DynamicItem} object to allow for chaining - * of calls to set methods. + * @return The {@link DynamicItem} object to allow for chaining of calls to set methods. */ public DynamicItem setSubtitle(@Nullable CharSequence subtitle) { this.subtitle = subtitle; @@ -150,11 +154,13 @@ public DynamicItem setSubtitle(@Nullable CharSequence subtitle) { } /** + * Get the icon tint color type used by this item. + * * @return The icon tint color type used by this item. * - * @see DynamicColorType + * @see Theme.ColorType */ - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return colorType; } @@ -163,18 +169,19 @@ public DynamicItem setSubtitle(@Nullable CharSequence subtitle) { * * @param colorType The icon tint color type to be set. * - * @return The {@link DynamicItem} object to allow for chaining - * of calls to set methods. + * @return The {@link DynamicItem} object to allow for chaining of calls to set methods. * - * @see DynamicColorType + * @see Theme.ColorType */ - public DynamicItem setColorType(@DynamicColorType int colorType) { + public DynamicItem setColorType(@Theme.ColorType int colorType) { this.colorType = colorType; return this; } /** + * Get the icon tint color used by this item. + * * @return The icon tint color used by this item. */ public @ColorInt int getColor() { @@ -186,19 +193,20 @@ public DynamicItem setColorType(@DynamicColorType int colorType) { * * @param color The icon tint color to be set. * - * @return The {@link DynamicItem} object to allow for chaining - * of calls to set methods. + * @return The {@link DynamicItem} object to allow for chaining of calls to set methods. */ public DynamicItem setColor(@ColorInt int color) { - this.colorType = DynamicColorType.CUSTOM; + this.colorType = Theme.ColorType.CUSTOM; this.color = color; return this; } /** + * Returns whether to show the horizontal divider for this item. + * * @return {@code true} to show horizontal divider. - * Useful to display in a list view. + *

Useful to display in a list view. */ public boolean isShowDivider() { return showDivider; @@ -206,13 +214,11 @@ public boolean isShowDivider() { /** * Set the horizontal divider fro this item. - * Useful to display in a list view. + *

Useful to display in a list view. * - * @param showDivider {@code true} to show horizontal - * divider. + * @param showDivider {@code true} to show horizontal divider. * - * @return The {@link DynamicItem} object to allow for chaining - * of calls to set methods. + * @return The {@link DynamicItem} object to allow for chaining of calls to set methods. */ public DynamicItem setShowDivider(boolean showDivider) { this.showDivider = showDivider; @@ -221,6 +227,8 @@ public DynamicItem setShowDivider(boolean showDivider) { } /** + * Get the on click listener used by this item. + * * @return The on click listener used by this item. */ public @Nullable View.OnClickListener getOnClickListener() { @@ -232,8 +240,7 @@ public DynamicItem setShowDivider(boolean showDivider) { * * @param onClickListener The on click listener to be set. * - * @return The {@link DynamicItem} object to allow for chaining - * of calls to set methods. + * @return The {@link DynamicItem} object to allow for chaining of calls to set methods. */ public DynamicItem setOnClickListener(@Nullable View.OnClickListener onClickListener) { this.onClickListener = onClickListener; diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermission.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicPermission.java similarity index 78% rename from dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermission.java rename to dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicPermission.java index 01cb6d3635..80aeec635d 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermission.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicPermission.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.pranavpandey.android.dynamic.support.permission; +package com.pranavpandey.android.dynamic.support.model; import android.app.Activity; import android.content.res.Resources; @@ -23,12 +23,15 @@ import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.pranavpandey.android.dynamic.support.permission.DynamicPermissions; /** - * A model class to hold the permission details that will be used - * by the app. It will be used internally by the {@link DynamicPermissions}. + * A model class to hold the permission details that will be used by the app. + *

It will be used internally by the {@link DynamicPermissions}. */ public class DynamicPermission implements Parcelable { @@ -66,14 +69,14 @@ public class DynamicPermission implements Parcelable { private boolean dangerous; /** - * {@code true} if the permission is granted. + * {@code true} if the permission is allowed. */ - private boolean granted; + private boolean allowed; /** * {@code true} if request this permission again. * - * @see android.support.v4.app.ActivityCompat#shouldShowRequestPermissionRationale(Activity, String) + * @see androidx.core.app.ActivityCompat#shouldShowRequestPermissionRationale(Activity, String) */ private boolean askAgain; @@ -102,7 +105,7 @@ public DynamicPermission(@NonNull String permission, @Nullable String descriptio * @param subtitle The subtitle for this permission. */ public DynamicPermission(@NonNull String permission, @Nullable Drawable icon, - @NonNull String title, @Nullable String subtitle) { + @NonNull String title, @Nullable String subtitle) { this.permission = permission; this.icon = icon; this.title = title; @@ -110,6 +113,59 @@ public DynamicPermission(@NonNull String permission, @Nullable Drawable icon, } /** + * Parcelable creator to create from parcel. + */ + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public DynamicPermission createFromParcel(Parcel in) { + return new DynamicPermission(in); + } + + @Override + public DynamicPermission[] newArray(int size) { + return new DynamicPermission[size]; + } + }; + + /** + * Read an object of this class from the parcel. + * + * @param in The parcel to read the values. + */ + public DynamicPermission(Parcel in) { + this.permission = in.readString(); + this.title = in.readString(); + this.subtitle = in.readString(); + this.description = in.readString(); + this.dangerous = in.readByte() != 0; + this.allowed = in.readByte() != 0; + this.askAgain = in.readByte() != 0; + Bitmap bitmap = in.readParcelable(getClass().getClassLoader()); + this.icon = new BitmapDrawable(Resources.getSystem(), bitmap); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(permission); + dest.writeString(title); + dest.writeString(subtitle); + dest.writeString(description); + dest.writeByte((byte) (dangerous ? 1 : 0)); + dest.writeByte((byte) (allowed ? 1 : 0)); + dest.writeByte((byte) (askAgain ? 1 : 0)); + Bitmap bitmap = ((BitmapDrawable) icon).getBitmap(); + dest.writeParcelable(bitmap, flags); + } + + /** + * Get the permission string. + * * @return The permission string. */ public @NonNull String getPermission() { @@ -126,6 +182,8 @@ public void setPermission(@NonNull String permission) { } /** + * Get the icon used by this permission. + * * @return The icon used by this permission. */ public @Nullable Drawable getIcon() { @@ -142,6 +200,8 @@ public void setIcon(@Nullable Drawable icon) { } /** + * Get the title used by this permission. + * * @return The title used by this permission. */ public @Nullable String getTitle() { @@ -158,6 +218,8 @@ public void setTitle(@Nullable String title) { } /** + * Get the subtitle used by this permission. + * * @return The subtitle used by this permission. */ public @Nullable String getSubtitle() { @@ -174,6 +236,8 @@ public void setSubtitle(@Nullable String subtitle) { } /** + * Ge the description used by this permission. + * * @return The description used by this permission. */ public @Nullable String getDescription() { @@ -190,6 +254,8 @@ public void setDescription(@NonNull String description) { } /** + * Returns whether this permission is dangerous. + * * @return {@code true} if the permission is dangerous. */ public boolean isDangerous() { @@ -199,31 +265,33 @@ public boolean isDangerous() { /** * Sets this permission as dangerous or normal. * - * @param dangerous {@code true} if the permission is - * dangerous. + * @param dangerous {@code true} if the permission is dangerous. */ public void setDangerous(boolean dangerous) { this.dangerous = dangerous; } /** - * @return {@code true} if the permission is granted. + * Returns whether this permission is allowed. + * + * @return {@code true} if the permission is allowed. */ - public boolean isGranted() { - return granted; + public boolean isAllowed() { + return allowed; } /** - * Sets this permission as granted or denied. + * Sets this permission as allowed or denied. * - * @param granted {@code true} if the permission is - * granted. + * @param allowed {@code true} if the permission is allowed. */ - public void setGranted(boolean granted) { - this.granted = granted; + public void setAllowed(boolean allowed) { + this.allowed = allowed; } /** + * Returns whether to request this permission again. + * * @return {@code true} if request this permission again. */ public boolean isAskAgain() { @@ -233,58 +301,9 @@ public boolean isAskAgain() { /** * Sets this permission to request again or not. * - * @param askAgain {@code true} if request this - * permission again. + * @param askAgain {@code true} if request this permission again. */ public void setAskAgain(boolean askAgain) { this.askAgain = askAgain; } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(permission); - dest.writeString(title); - dest.writeString(subtitle); - dest.writeString(description); - dest.writeByte((byte) (dangerous ? 1 : 0)); - dest.writeByte((byte) (granted ? 1 : 0)); - dest.writeByte((byte) (askAgain ? 1 : 0)); - Bitmap bitmap = ((BitmapDrawable) icon).getBitmap(); - dest.writeParcelable(bitmap, flags); - } - - /** - * Parcelable creator to create from parcel. - */ - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - public DynamicPermission createFromParcel(Parcel in) { - return new DynamicPermission(in); - } - - public DynamicPermission[] newArray(int size) { - return new DynamicPermission[size]; - } - }; - - /** - * De-parcel {@link DynamicPermission} object. - * - * @param in The parcel to read the values. - */ - public DynamicPermission(Parcel in) { - this.permission = in.readString(); - this.title = in.readString(); - this.subtitle = in.readString(); - this.description = in.readString(); - this.dangerous = in.readByte() != 0; - this.granted = in.readByte() != 0; - this.askAgain = in.readByte() != 0; - Bitmap bitmap = in.readParcelable(getClass().getClassLoader()); - this.icon = new BitmapDrawable(Resources.getSystem(), bitmap); - } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicSpinnerItem.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicSpinnerItem.java index 117a86cd71..db0ebe44f3 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicSpinnerItem.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicSpinnerItem.java @@ -17,11 +17,11 @@ package com.pranavpandey.android.dynamic.support.model; import android.graphics.drawable.Drawable; -import android.support.annotation.Nullable; + +import androidx.annotation.Nullable; /** - * A model class to store {@link android.widget.Spinner} item - * information with a icon and a text. + * A model class to store {@link android.widget.Spinner} item information with an icon and a text. */ public class DynamicSpinnerItem { @@ -47,6 +47,8 @@ public DynamicSpinnerItem(@Nullable Drawable icon, @Nullable CharSequence text) } /** + * Get the icon used by this item. + * * @return The icon used by this item. */ public @Nullable Drawable getIcon() { @@ -58,8 +60,7 @@ public DynamicSpinnerItem(@Nullable Drawable icon, @Nullable CharSequence text) * * @param icon The icon to be set. * - * @return The {@link DynamicSpinnerItem} object to allow - * for chaining of calls to set methods. + * @return The {@link DynamicSpinnerItem} object to allow for chaining of calls to set methods. */ public DynamicSpinnerItem setIcon(@Nullable Drawable icon) { this.icon = icon; @@ -68,6 +69,8 @@ public DynamicSpinnerItem setIcon(@Nullable Drawable icon) { } /** + * Get the text used by this item. + * * @return The text used by this item. */ public @Nullable CharSequence getText() { @@ -79,8 +82,7 @@ public DynamicSpinnerItem setIcon(@Nullable Drawable icon) { * * @param text The text to be set. * - * @return The {@link DynamicSpinnerItem} object to allow - * for chaining of calls to set methods. + * @return The {@link DynamicSpinnerItem} object to allow for chaining of calls to set methods. */ public DynamicSpinnerItem setText(@Nullable CharSequence text) { this.text = text; diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicWidgetTheme.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicWidgetTheme.java new file mode 100644 index 0000000000..4ce768b711 --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/DynamicWidgetTheme.java @@ -0,0 +1,427 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.model; + +import android.os.Parcel; +import android.os.Parcelable; + +import androidx.annotation.ColorInt; +import androidx.annotation.IntRange; +import androidx.annotation.NonNull; +import androidx.annotation.StyleRes; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.annotations.SerializedName; +import com.pranavpandey.android.dynamic.support.annotation.Exclude; +import com.pranavpandey.android.dynamic.support.model.adapter.DynamicThemeTypeAdapter; +import com.pranavpandey.android.dynamic.support.strategy.ExcludeStrategy; +import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; +import com.pranavpandey.android.dynamic.support.utils.DynamicThemeUtils; + +/** + * DynamicAppTheme class to store various colors and attributes for app widget which can be + * modified at runtime. + */ +public class DynamicWidgetTheme extends DynamicAppTheme { + + /** + * Default value for the opacity. + */ + public static final int ADS_OPACITY_DEFAULT = 255; + + /** + * App widget id used by this theme. + */ + @Exclude + @SerializedName(DynamicThemeUtils.ADS_NAME_WIDGET_ID) + private int widgetId; + + /** + * Header state used by this theme. + */ + @SerializedName(DynamicThemeUtils.ADS_NAME_HEADER) + private @Theme.Visibility int header; + + /** + * Opacity value used by this theme. + */ + @SerializedName(DynamicThemeUtils.ADS_NAME_OPACITY) + private int opacity; + + /** + * Constructor to initialize an object of this class. + */ + public DynamicWidgetTheme() { + super(); + + this.header = Theme.Visibility.AUTO; + this.opacity = ADS_OPACITY_DEFAULT; + } + + /** + * Constructor to initialize an object of this class. + * + * @param widgetId The widget id to be used. + */ + public DynamicWidgetTheme(int widgetId) { + this(); + + this.widgetId = widgetId; + } + + /** + * Constructor to initialize an object of this class from the dynamic string. + * + * @param theme The dynamic string to initialize the instance. + */ + public DynamicWidgetTheme(@NonNull String theme) throws Exception { + this(new GsonBuilder().setExclusionStrategies(new ExcludeStrategy()) + .registerTypeAdapter(DynamicWidgetTheme.class, + new DynamicThemeTypeAdapter()).create() + .fromJson(DynamicThemeUtils.formatDynamicTheme(theme), DynamicWidgetTheme.class)); + } + + /** + * Constructor to initialize an object of this class. + * + * @param dynamicAppTheme The dynamic app theme to copy the theme. + */ + public DynamicWidgetTheme(@NonNull DynamicAppTheme dynamicAppTheme) { + super(dynamicAppTheme); + + this.header = Theme.Visibility.AUTO; + this.opacity = ADS_OPACITY_DEFAULT; + } + + /** + * Constructor to initialize an object of this class. + * + * @param dynamicWidgetTheme The dynamic widget theme to copy the theme. + */ + public DynamicWidgetTheme(@NonNull DynamicWidgetTheme dynamicWidgetTheme) { + super(dynamicWidgetTheme); + + this.header = dynamicWidgetTheme.getHeader(); + this.opacity = dynamicWidgetTheme.getOpacity(); + } + + /** + * Parcelable creator to create from parcel. + */ + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public DynamicWidgetTheme createFromParcel(Parcel in) { + return new DynamicWidgetTheme(in); + } + + @Override + public DynamicWidgetTheme[] newArray(int size) { + return new DynamicWidgetTheme[size]; + } + }; + + /** + * Read an object of this class from the parcel. + * + * @param in The parcel to read the values. + */ + public DynamicWidgetTheme(Parcel in) { + super(in); + + this.widgetId = in.readInt(); + this.header = in.readInt(); + this.opacity = in.readInt(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + + dest.writeInt(widgetId); + dest.writeInt(header); + dest.writeInt(opacity); + } + + /** + * Get the app widget id used by this theme. + * + * @return The app widget id used by this theme. + */ + public int getWidgetId() { + return widgetId; + } + + /** + * Set the widget id used by this theme. + * + * @param widgetId The widget id to be set. + * + * @return The {@link DynamicWidgetTheme} object to allow for chaining of calls to set methods. + */ + public @NonNull DynamicWidgetTheme setWidgetId(int widgetId) { + this.widgetId = widgetId; + + return this; + } + + /** + * Get the header state used by this theme. + * + * @return The header state used by this theme. + */ + public @Theme.Visibility int getHeader() { + return header; + } + + /** + * Returns the header state string used by this theme. + * + * @return The header state string used by this theme. + */ + public @NonNull @Theme.Visibility.ToString String getHeaderString() { + return String.valueOf(header); + } + + /** + * Set the header state used by this theme. + * + * @param header The header state to be set. + * + * @return The {@link DynamicWidgetTheme} object to allow for chaining of calls to set methods. + */ + public @NonNull DynamicWidgetTheme setHeader(@Theme.Visibility int header) { + this.header = header; + + return this; + } + + /** + * Set the header state used by this theme. + * + * @param header The header state to be set. + * + * @return The {@link DynamicWidgetTheme} object to allow for chaining of calls to set methods. + */ + public @NonNull DynamicWidgetTheme setHeaderString( + @NonNull@Theme.Visibility.ToString String header) { + this.header = Integer.valueOf(header); + + return this; + } + + /** + * Get the opacity value used by this theme. + * + * @return The opacity value used by this theme. + */ + public int getOpacity() { + return opacity; + } + + /** + * Set the opacity value used by this theme. + * + * @param opacity The opacity value to be set. + * + * @return The {@link DynamicWidgetTheme} object to allow for chaining of calls to set methods. + */ + public @NonNull DynamicWidgetTheme setOpacity(@IntRange(from = 0, to = 255) int opacity) { + this.opacity = opacity; + + return this; + } + + @Override + public @StyleRes int getThemeRes() { + return DynamicTheme.getInstance().getApplication().getThemeRes(); + } + + @Override + public @ColorInt int getBackgroundColor(boolean resolve) { + if (resolve && super.getBackgroundColor(false) == AUTO) { + return DynamicTheme.getInstance().getApplication().getBackgroundColor(); + } + + return super.getBackgroundColor(resolve); + } + + @Override + public @ColorInt int getPrimaryColor(boolean resolve) { + if (resolve && super.getPrimaryColor(false) == AUTO) { + return DynamicTheme.getInstance().getApplication().getPrimaryColor(); + } + + return super.getPrimaryColor(resolve); + } + + @Override + public @ColorInt int getPrimaryColorDark(boolean resolve) { + if (resolve && super.getPrimaryColorDark(false) == AUTO) { + return DynamicTheme.getInstance().getApplication().getPrimaryColorDark(); + } + + return super.getPrimaryColorDark(resolve); + } + + @Override + public @ColorInt int getAccentColor(boolean resolve) { + if (resolve && super.getAccentColor(false) == AUTO) { + return DynamicTheme.getInstance().getApplication().getAccentColor(); + } + + return super.getAccentColor(resolve); + } + + @Override + public @ColorInt int getAccentColorDark(boolean resolve) { + if (resolve && super.getAccentColorDark(false) == AUTO) { + return DynamicTheme.getInstance().getApplication().getAccentColorDark(); + } + + return super.getAccentColorDark(resolve); + } + + @Override + public @ColorInt int getTintBackgroundColor(boolean resolve) { + if (resolve && super.getTintBackgroundColor(false) == AUTO) { + return DynamicTheme.getInstance().getApplication().getTintBackgroundColor(); + } + + return super.getTintBackgroundColor(resolve); + } + + @Override + public @ColorInt int getTintPrimaryColor(boolean resolve) { + if (resolve && super.getTintPrimaryColor(false) == AUTO) { + return DynamicTheme.getInstance().getApplication().getTintPrimaryColor(); + } + + return super.getTintPrimaryColor(resolve); + } + + @Override + public @ColorInt int getTintPrimaryColorDark(boolean resolve) { + if (resolve && super.getTintPrimaryColorDark(false) == AUTO) { + return DynamicTheme.getInstance().getApplication().getTintPrimaryColorDark(); + } + + return super.getTintPrimaryColorDark(resolve); + } + + @Override + public @ColorInt int getTintAccentColor(boolean resolve) { + if (resolve && super.getTintAccentColor(false) == AUTO) { + return DynamicTheme.getInstance().getApplication().getTintAccentColor(); + } + + return super.getTintAccentColor(resolve); + } + + @Override + public @ColorInt int getTintAccentColorDark(boolean resolve) { + if (resolve && super.getTintAccentColorDark(false) == AUTO) { + return DynamicTheme.getInstance().getApplication().getTintAccentColorDark(); + } + + return super.getTintAccentColorDark(resolve); + } + + @Override + public @ColorInt int getTextPrimaryColor(boolean resolve) { + if (resolve && super.getTextPrimaryColor(false) == AUTO) { + return DynamicTheme.getInstance().getApplication().getTextPrimaryColor(); + } + + return super.getTextPrimaryColor(resolve); + } + + @Override + public @ColorInt int getTextSecondaryColor(boolean resolve) { + if (resolve && super.getTextSecondaryColor(false) == AUTO) { + return DynamicTheme.getInstance().getApplication().getTextSecondaryColor(); + } + + return super.getTextSecondaryColor(resolve); + } + + @Override + public @ColorInt int getTextPrimaryColorInverse(boolean resolve) { + if (resolve && super.getTextPrimaryColorInverse(false) == AUTO) { + return DynamicTheme.getInstance().getApplication().getTextPrimaryColorInverse(); + } + + return super.getTextPrimaryColorInverse(resolve); + } + + @Override + public @ColorInt int getTextSecondaryColorInverse(boolean resolve) { + if (resolve && super.getTextSecondaryColorInverse(false) == AUTO) { + return DynamicTheme.getInstance().getApplication().getTextSecondaryColorInverse(); + } + + return super.getTextSecondaryColorInverse(resolve); + } + + @Override + public @Theme.BackgroundAware int getBackgroundAware(boolean resolve) { + if (resolve && super.getBackgroundAware(false) == Theme.BackgroundAware.AUTO) { + return DynamicTheme.getInstance().getApplication().getBackgroundAware(); + } + + return super.getBackgroundAware(resolve); + } + + @Override + public int getCornerRadius(boolean resolve) { + if (resolve && super.getCornerRadius(false) == AUTO) { + return DynamicTheme.getInstance().getApplication().getCornerRadius(); + } + + return super.getCornerRadius(resolve); + } + + @Override + public @NonNull String toJsonString() { + return new Gson().toJson(new DynamicWidgetTheme(this)); + } + + @Override + public @NonNull String toDynamicString() { + return new GsonBuilder().setExclusionStrategies(new ExcludeStrategy()) + .registerTypeAdapter(DynamicWidgetTheme.class, + new DynamicThemeTypeAdapter()) + .setPrettyPrinting().create().toJson(new DynamicWidgetTheme(this)); + } + + @Override + public @NonNull String toString() { + return "DynamicWidgetTheme{" + + getThemeRes() + getBackgroundColor(false) + getPrimaryColor(false) + + getPrimaryColorDark(false) + getAccentColor(false) + + getAccentColorDark(false) + getTintBackgroundColor(false) + + getTintPrimaryColor(false) + getTintPrimaryColorDark(false) + + getTintAccentColor(false) + getTintAccentColorDark(false) + + getTextPrimaryColor(false) + getTextSecondaryColor(false) + + getTextPrimaryColorInverse(false) + getTextSecondaryColorInverse(false) + + getCornerRadius(false) + getBackgroundAware(false) + + widgetId + header + opacity + + '}'; + } +} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/adapter/DynamicThemeTypeAdapter.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/adapter/DynamicThemeTypeAdapter.java new file mode 100644 index 0000000000..1af4c64a01 --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/model/adapter/DynamicThemeTypeAdapter.java @@ -0,0 +1,205 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.model.adapter; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import com.pranavpandey.android.dynamic.support.model.DynamicAppTheme; +import com.pranavpandey.android.dynamic.support.model.DynamicWidgetTheme; +import com.pranavpandey.android.dynamic.support.utils.DynamicThemeUtils; + +import java.io.IOException; + +/** + * Gson type adapter to export or import the dynamic theme. + * + * @see DynamicAppTheme + * @see DynamicWidgetTheme + */ +public class DynamicThemeTypeAdapter extends TypeAdapter { + + @Override + public void write(JsonWriter writer, T value) throws IOException { + try { + writer.beginObject(); + + writer.name(DynamicThemeUtils.ADS_NAME_BACKGROUND_COLOR); + writer.value(DynamicThemeUtils.getValueFromColor( + value.getBackgroundColor(false))); + writer.name(DynamicThemeUtils.ADS_NAME_TINT_BACKGROUND_COLOR); + writer.value(DynamicThemeUtils.getValueFromColor( + value.getTintBackgroundColor(false))); + writer.name(DynamicThemeUtils.ADS_NAME_PRIMARY_COLOR); + writer.value(DynamicThemeUtils.getValueFromColor( + value.getPrimaryColor(false))); + writer.name(DynamicThemeUtils.ADS_NAME_TINT_PRIMARY_COLOR); + writer.value(DynamicThemeUtils.getValueFromColor( + value.getTintPrimaryColor(false))); + writer.name(DynamicThemeUtils.ADS_NAME_PRIMARY_COLOR_DARK); + writer.value(DynamicThemeUtils.getValueFromColor( + value.getPrimaryColorDark(false))); + writer.name(DynamicThemeUtils.ADS_NAME_TINT_PRIMARY_COLOR_DARK); + writer.value(DynamicThemeUtils.getValueFromColor( + value.getTintPrimaryColorDark(false))); + writer.name(DynamicThemeUtils.ADS_NAME_ACCENT_COLOR); + writer.value(DynamicThemeUtils.getValueFromColor( + value.getAccentColor(false))); + writer.name(DynamicThemeUtils.ADS_NAME_TINT_ACCENT_COLOR); + writer.value(DynamicThemeUtils.getValueFromColor( + value.getTintAccentColor(false))); + writer.name(DynamicThemeUtils.ADS_NAME_ACCENT_COLOR_DARK); + writer.value(DynamicThemeUtils.getValueFromColor( + value.getAccentColorDark(false))); + writer.name(DynamicThemeUtils.ADS_NAME_TINT_ACCENT_COLOR_DARK); + writer.value(DynamicThemeUtils.getValueFromColor( + value.getTintAccentColorDark(false))); + writer.name(DynamicThemeUtils.ADS_NAME_TEXT_PRIMARY_COLOR); + writer.value(DynamicThemeUtils.getValueFromColor( + value.getTextPrimaryColor(false))); + writer.name(DynamicThemeUtils.ADS_NAME_TEXT_PRIMARY_COLOR_INVERSE); + writer.value(DynamicThemeUtils.getValueFromColor( + value.getTextPrimaryColorInverse(false))); + writer.name(DynamicThemeUtils.ADS_NAME_TEXT_SECONDARY_COLOR); + writer.value(DynamicThemeUtils.getValueFromColor( + value.getTextSecondaryColor(false))); + writer.name(DynamicThemeUtils.ADS_NAME_TEXT_SECONDARY_COLOR_INVERSE); + writer.value(DynamicThemeUtils.getValueFromColor( + value.getTextSecondaryColorInverse(false))); + writer.name(DynamicThemeUtils.ADS_NAME_CORNER_RADIUS); + writer.value(DynamicThemeUtils.getValueFromCornerRadius( + value.getCornerRadius(false))); + writer.name(DynamicThemeUtils.ADS_NAME_BACKGROUND_AWARE); + writer.value(DynamicThemeUtils.getValueFromBackgroundAware( + value.getBackgroundAware(false))); + + if (value instanceof DynamicWidgetTheme) { + writer.name(DynamicThemeUtils.ADS_NAME_HEADER); + writer.value(DynamicThemeUtils.getValueFromVisibility( + ((DynamicWidgetTheme) value).getHeader())); + writer.name(DynamicThemeUtils.ADS_NAME_OPACITY); + writer.value(((DynamicWidgetTheme) value).getOpacity()); + } + + writer.endObject(); + } catch (Exception ignored) { + } + } + + @SuppressWarnings("unchecked") + @Override + public T read(JsonReader reader) throws IOException { + T theme = (T) new DynamicWidgetTheme(); + + try { + JsonToken token = reader.peek(); + if (token.equals(JsonToken.BEGIN_OBJECT)) { + reader.beginObject(); + + while (!reader.peek().equals(JsonToken.END_OBJECT)) { + if (reader.peek().equals(JsonToken.NAME)) { + switch (reader.nextName()) { + default: + reader.skipValue(); + break; + case DynamicThemeUtils.ADS_NAME_BACKGROUND_COLOR: + theme.setBackgroundColor(DynamicThemeUtils + .getValueFromColor(reader.nextString()), false); + break; + case DynamicThemeUtils.ADS_NAME_TINT_BACKGROUND_COLOR: + theme.setTintBackgroundColor(DynamicThemeUtils + .getValueFromColor(reader.nextString())); + break; + case DynamicThemeUtils.ADS_NAME_PRIMARY_COLOR: + theme.setPrimaryColor(DynamicThemeUtils.getValueFromColor( + reader.nextString()), false); + break; + case DynamicThemeUtils.ADS_NAME_TINT_PRIMARY_COLOR: + theme.setTintPrimaryColor(DynamicThemeUtils + .getValueFromColor(reader.nextString())); + break; + case DynamicThemeUtils.ADS_NAME_PRIMARY_COLOR_DARK: + theme.setPrimaryColorDark(DynamicThemeUtils + .getValueFromColor(reader.nextString()), false); + break; + case DynamicThemeUtils.ADS_NAME_TINT_PRIMARY_COLOR_DARK: + theme.setTintPrimaryColorDark(DynamicThemeUtils + .getValueFromColor(reader.nextString())); + break; + case DynamicThemeUtils.ADS_NAME_ACCENT_COLOR: + theme.setAccentColor(DynamicThemeUtils + .getValueFromColor(reader.nextString()), false); + break; + case DynamicThemeUtils.ADS_NAME_TINT_ACCENT_COLOR: + theme.setTintAccentColor(DynamicThemeUtils + .getValueFromColor(reader.nextString())); + break; + case DynamicThemeUtils.ADS_NAME_ACCENT_COLOR_DARK: + theme.setAccentColorDark(DynamicThemeUtils + .getValueFromColor(reader.nextString()), false); + break; + case DynamicThemeUtils.ADS_NAME_TINT_ACCENT_COLOR_DARK: + theme.setTintAccentColorDark(DynamicThemeUtils + .getValueFromColor(reader.nextString())); + break; + case DynamicThemeUtils.ADS_NAME_TEXT_PRIMARY_COLOR: + theme.setTextPrimaryColor(DynamicThemeUtils + .getValueFromColor(reader.nextString()), false); + break; + case DynamicThemeUtils.ADS_NAME_TEXT_PRIMARY_COLOR_INVERSE: + theme.setTextPrimaryColorInverse(DynamicThemeUtils + .getValueFromColor(reader.nextString())); + break; + case DynamicThemeUtils.ADS_NAME_TEXT_SECONDARY_COLOR: + theme.setTextSecondaryColor(DynamicThemeUtils + .getValueFromColor(reader.nextString()), false); + break; + case DynamicThemeUtils.ADS_NAME_TEXT_SECONDARY_COLOR_INVERSE: + theme.setTextSecondaryColorInverse(DynamicThemeUtils + .getValueFromColor(reader.nextString())); + break; + case DynamicThemeUtils.ADS_NAME_CORNER_RADIUS: + theme.setCornerRadiusDp(DynamicThemeUtils + .getValueFromCornerRadius(reader.nextString())); + break; + case DynamicThemeUtils.ADS_NAME_BACKGROUND_AWARE: + theme.setBackgroundAware(DynamicThemeUtils + .getValueFromBackgroundAware(reader.nextString())); + break; + case DynamicThemeUtils.ADS_NAME_HEADER: + ((DynamicWidgetTheme) theme).setHeader(DynamicThemeUtils + .getValueFromVisibility(reader.nextString())); + break; + case DynamicThemeUtils.ADS_NAME_OPACITY: + ((DynamicWidgetTheme) theme).setOpacity(reader.nextInt()); + break; + } + } else { + reader.skipValue(); + } + } + + reader.endObject(); + } + } catch (Exception ignored) { + theme = null; + } + + return theme; + } +} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissions.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissions.java index cac1ea7dc0..28c4ea8870 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissions.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissions.java @@ -18,6 +18,7 @@ import android.Manifest; import android.annotation.TargetApi; +import android.app.Activity; import android.app.AppOpsManager; import android.content.Context; import android.content.Intent; @@ -27,10 +28,17 @@ import android.content.pm.PermissionInfo; import android.os.Build; import android.provider.Settings; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.content.ContextCompat; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; + +import com.pranavpandey.android.dynamic.support.intent.DynamicIntent; +import com.pranavpandey.android.dynamic.support.model.DynamicAction; +import com.pranavpandey.android.dynamic.support.model.DynamicPermission; +import com.pranavpandey.android.dynamic.support.permission.activity.DynamicPermissionsActivity; +import com.pranavpandey.android.dynamic.support.utils.DynamicPermissionUtils; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils; @@ -38,12 +46,10 @@ /** * Help class to request and manage runtime permissions introduced in Android M. - * It must be initialized before using any of its functions or requesting any - * permissions. + *

It must be initialized before using any of its functions or requesting any permissions. * - *

Register the {@link DynamicPermissionsActivity} via - * {@link #setPermissionActivity(Class)} to request the permissions via this - * manager.

+ *

Register the {@link DynamicPermissionsActivity} via {@link #setPermissionActivity(Class)} + * to request the permissions via this manager. * * @see * Requesting Permissions at Run Time @@ -51,52 +57,6 @@ @TargetApi(Build.VERSION_CODES.M) public class DynamicPermissions { - /** - * Constant for permissions intent. - */ - public static final String ADS_INTENT_PERMISSIONS = "permissions_intent"; - - /** - * Constant for permissions intent extra. - */ - public static final String ADS_INTENT_EXTRA_PERMISSIONS = "permissions"; - - /** - * Constant for permissions intent extra intent to perform it when - * all the permissions are granted. - */ - public static final String ADS_INTENT_EXTRA_INTENT = "permissions_extra_intent"; - - /** - * Constant for permissions intent extra action to perform it when - * all the permissions are granted. - */ - public static final String ADS_INTENT_EXTRA_ACTION = "permissions_extra_action"; - - /** - * Settings intent action constant for write system settings. - * - * @see Settings#ACTION_MANAGE_WRITE_SETTINGS - */ - public static final String ADS_ACTION_WRITE_SYSTEM_SETTINGS - = Settings.ACTION_MANAGE_WRITE_SETTINGS; - - /** - * Settings intent action constant for overlay settings. - * - * @see Settings#ACTION_MANAGE_OVERLAY_PERMISSION - */ - public static final String ADS_ACTION_OVERLAY_SETTINGS - = Settings.ACTION_MANAGE_OVERLAY_PERMISSION; - - /** - * Settings intent action constant for usage access settings. - * - * @see Settings#ACTION_USAGE_ACCESS_SETTINGS - */ - public static final String ADS_ACTION_USAGE_ACCESS_SETTINGS - = Settings.ACTION_USAGE_ACCESS_SETTINGS; - /** * Singleton instance of {@link DynamicPermissions}. */ @@ -113,8 +73,8 @@ public class DynamicPermissions { private Class mPermissionActivity; /** - * Making default constructor private so that it cannot be initialized - * without a context. Use {@link #initializeInstance(Context)} instead. + * Making the default constructor private so that it cannot be initialized without a context. + *

Use {@link #initializeInstance(Context)} instead. */ private DynamicPermissions() { } @@ -123,8 +83,8 @@ private DynamicPermissions(@NonNull Context context) { } /** - * Initialize permissions when application starts. - * Must be initialized once. + * Initialize permissions when application starts. + *

Must be initialized once. * * @param context The context to request and manage permissions. */ @@ -139,6 +99,8 @@ public static synchronized void initializeInstance(@Nullable Context context) { } /** + * Returns the context used by this instance. + * * @return The context used by this instance. */ public @NonNull Context getContext() { @@ -155,8 +117,7 @@ public void setContext(@NonNull Context context) { } /** - * Get instance to access public methods. Must be called before - * accessing the methods. + * Get instance to access public methods. Must be called before accessing the methods. * * @return The singleton instance of this class. */ @@ -170,6 +131,8 @@ public static synchronized DynamicPermissions getInstance() { } /** + * Get the permission activity used by this manager. + * * @return The permission activity used by this manager. */ public Class getPermissionActivity() { @@ -179,51 +142,245 @@ public Class getPermissionActivity() { /** * Sets the permission activity for this instance. * - * @param permissionActivity The permission activity class - * to be set. + * @param permissionActivity The permission activity class to be set. */ public void setPermissionActivity(Class permissionActivity) { this.mPermissionActivity = permissionActivity; } /** - * @return {@code true} if all the supplied permissions has been granted. - * It can also be used to automatically request the permissions those are - * denied or not requested yet by using the {@link #mPermissionActivity}. + * Request the supplied permissions if not granted. * + * @param context The context to start the activity. * @param permissions The array of permissions to be requested. - * @param request {@code true} to automatically request the permissions - * if not granted. - * @param actionIntent The intent which should be called after all the - * permissions has been granted. + * @param history {@code false} to exclude the system settings activity from the recents. + * @param actionIntent The intent which should be called after all the permissions has been + * granted. * @param action The intent action, either start an activity or a service. + * @param requestCode The request code for the result. */ - public boolean isGranted(@NonNull String[] permissions, boolean request, - @Nullable Intent actionIntent, @DynamicPermissionsAction int action) { + public void requestPermissions(@NonNull Context context, + @NonNull String[] permissions, boolean history, @Nullable Intent actionIntent, + @DynamicAction int action, int requestCode) { + Intent intent = new Intent(context, mPermissionActivity); + intent.setAction(DynamicIntent.ACTION_PERMISSIONS); + intent.putExtra(DynamicIntent.EXTRA_PERMISSIONS, permissions); + if (!history) { + intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + } + + if (actionIntent != null) { + intent.putExtra(DynamicIntent.EXTRA_PERMISSIONS_INTENT, actionIntent); + intent.putExtra(DynamicIntent.EXTRA_PERMISSIONS_ACTION, action); + } + + if (context instanceof Activity) { + ((Activity) context).startActivityForResult(intent, requestCode); + } else { + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + } + + /** + * Request the supplied permissions if not granted. + * + * @param fragment The fragment to start the activity. + * @param permissions The array of permissions to be requested. + * @param history {@code false} to exclude the system settings activity from the recents. + * @param actionIntent The intent which should be called after all the permissions has been + * granted. + * @param action The intent action, either start an activity or a service. + * @param requestCode The request code for the result. + */ + public void requestPermissions(@NonNull Fragment fragment, + @NonNull String[] permissions, boolean history, @Nullable Intent actionIntent, + @DynamicAction int action, int requestCode) { + Intent intent = new Intent(fragment.getContext(), mPermissionActivity); + intent.setAction(DynamicIntent.ACTION_PERMISSIONS); + intent.putExtra(DynamicIntent.EXTRA_PERMISSIONS, permissions); + if (!history) { + intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + } + + if (actionIntent != null) { + intent.putExtra(DynamicIntent.EXTRA_PERMISSIONS_INTENT, actionIntent); + intent.putExtra(DynamicIntent.EXTRA_PERMISSIONS_ACTION, action); + } + + fragment.startActivityForResult(intent, requestCode); + } + + /** + * Request the supplied permissions if not granted. + * + * @param context The context to start the activity. + * @param permissions The array of permissions to be requested. + * @param history {@code false} to exclude the system settings activity from the recents. + * @param actionIntent The intent which should be called after all the permissions has been + * granted. + * @param action The intent action, either start an activity or a service. + */ + public void requestPermissions(@NonNull Context context, @NonNull String[] permissions, + boolean history, @Nullable Intent actionIntent, @DynamicAction int action) { + requestPermissions(context, permissions, history, actionIntent, + action, DynamicIntent.REQUEST_PERMISSIONS); + } + + /** + * Request the supplied permissions if not granted. + * + * @param fragment The fragment to start the activity. + * @param permissions The array of permissions to be requested. + * @param history {@code false} to exclude the system settings activity from the recents. + * @param actionIntent The intent which should be called after all the permissions has been + * granted. + * @param action The intent action, either start an activity or a service. + */ + public void requestPermissions(@NonNull Fragment fragment, @NonNull String[] permissions, + boolean history, @Nullable Intent actionIntent, @DynamicAction int action) { + requestPermissions(fragment, permissions, history, actionIntent, + action, DynamicIntent.REQUEST_PERMISSIONS); + } + + /** + * Request the supplied permissions if not granted. + * + * @param permissions The array of permissions to be requested. + * @param history {@code false} to exclude the system settings activity from the recents. + * @param actionIntent The intent which should be called after all the permissions has been + * granted. + * @param action The intent action, either start an activity or a service. + */ + public void requestPermissions(@NonNull String[] permissions, boolean history, + @Nullable Intent actionIntent, @DynamicAction int action) { + requestPermissions(mContext, permissions, history, actionIntent, action); + } + + /** + * Checks whether the supplied permissions have been granted. It can also be used to + * automatically request the permissions those are denied or not requested yet by using the + * permission activity. + * + * @param context The context to start the activity. + * @param permissions The array of permissions to be requested. + * @param request {@code true} to automatically request the permissions if not granted. + * @param actionIntent The intent which should be called after all the permissions has been + * granted. + * @param action The intent action, either start an activity or a service. + * @param requestCode The request code for the result. + * + * @return {@code true} if all the supplied permissions has been granted. + */ + public boolean isGranted(@NonNull Context context, + @NonNull String[] permissions, boolean request, @Nullable Intent actionIntent, + @DynamicAction int action, int requestCode) { String[] permissionsNotGranted = isGranted(permissions); + if (request && permissionsNotGranted.length != 0) { + requestPermissions(context, permissions, true, actionIntent, action, requestCode); + } + + return permissionsNotGranted.length == 0; + } + /** + * Checks whether the supplied permissions have been granted. It can also be used to + * automatically request the permissions those are denied or not requested yet by using the + * permission activity. + * + * @param fragment The fragment to start the activity. + * @param permissions The array of permissions to be requested. + * @param request {@code true} to automatically request the permissions if not granted. + * @param actionIntent The intent which should be called after all the permissions has been + * granted. + * @param action The intent action, either start an activity or a service. + * @param requestCode The request code for the result. + * + * @return {@code true} if all the supplied permissions has been granted. + */ + public boolean isGranted(@NonNull Fragment fragment, + @NonNull String[] permissions, boolean request, @Nullable Intent actionIntent, + @DynamicAction int action, int requestCode) { + String[] permissionsNotGranted = isGranted(permissions); if (request && permissionsNotGranted.length != 0) { - requestPermissions(permissions, true, actionIntent, action); + requestPermissions(fragment, permissions, true, actionIntent, action, requestCode); } return permissionsNotGranted.length == 0; } /** + * Checks whether the supplied permissions have been granted. It can also be used to + * automatically request the permissions those are denied or not requested yet by using the + * permission activity. + * + * @param permissions The array of permissions to be requested. + * @param request {@code true} to automatically request the permissions if not granted. + * @param actionIntent The intent which should be called after all the permissions has been + * granted. + * @param action The intent action, either start an activity or a service. + * + * @return {@code true} if all the supplied permissions has been granted. + */ + public boolean isGranted(@NonNull String[] permissions, boolean request, + @Nullable Intent actionIntent, @DynamicAction int action) { + return isGranted(mContext, permissions, request, actionIntent, + action, DynamicIntent.REQUEST_PERMISSIONS); + } + + /** + * Checks whether the supplied permissions have been granted. It can also be used to + * automatically request the permissions those are denied or not requested yet by using the + * permission activity. + * + * @param context The context to start the activity. + * @param permissions The array of permissions to be requested. + * @param request {@code true} to automatically request the permissions if not granted. + * @param requestCode The request code for the result. + * + * @return {@code true} if all the supplied permissions has been granted. + */ + public boolean isGranted(@NonNull Context context, + @NonNull String[] permissions, boolean request, int requestCode) { + return isGranted(context, permissions, request, + null, DynamicAction.NONE, requestCode); + } + + /** + * Checks whether the supplied permissions have been granted. It can also be used to + * automatically request the permissions those are denied or not requested yet by using the + * permission activity. + * + * @param fragment The fragment to start the activity. + * @param permissions The array of permissions to be requested. + * @param request {@code true} to automatically request the permissions if not granted. + * @param requestCode The request code for the result. + * * @return {@code true} if all the supplied permissions has been granted. - * It can also be used to automatically request the permissions those are - * denied or not requested yet by using the {@link #mPermissionActivity}. + */ + public boolean isGranted(@NonNull Fragment fragment, + @NonNull String[] permissions, boolean request, int requestCode) { + return isGranted(fragment, permissions, request, + null, DynamicAction.NONE, requestCode); + } + + /** + * Checks whether the supplied permissions have been granted. It can also be used to + * automatically request the permissions those are denied or not requested yet by using the + * permission activity. * * @param permissions The array of permissions to be requested. - * @param request {@code true} to automatically request the permissions - * if not granted. + * @param request {@code true} to automatically request the permissions if not granted. + * + * @return {@code true} if all the supplied permissions has been granted. */ public boolean isGranted(@NonNull String[] permissions, boolean request) { - return isGranted(permissions, request, - null, DynamicPermissionsAction.NONE); + return isGranted(permissions, request, null, DynamicAction.NONE); } /** + * Checks whether the supplied permissions have been granted. + * * @return {@code true} if all the supplied permissions has been granted. * * @param permissions The array of permissions to be requested. @@ -261,34 +418,8 @@ private String[] isGranted(@NonNull String[] permissions) { } /** - * Request the supplied permissions if not granted. + * Checks whether the package can write system settings. * - * @param permissions The array of permissions to be requested. - * @param history {@code false} to exclude the system settings activity - * from the recents. - * @param actionIntent The intent which should be called after all the - * permissions has been granted. - * @param action The intent action, either start an activity or a service. - */ - public void requestPermissions(@NonNull String[] permissions, boolean history, - @Nullable Intent actionIntent, - @DynamicPermissionsAction int action) { - Intent intent = new Intent(mContext, mPermissionActivity); - intent.putExtra(ADS_INTENT_EXTRA_PERMISSIONS, permissions); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - if (!history) { - intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); - } - - if (actionIntent != null) { - intent.putExtra(ADS_INTENT_EXTRA_INTENT, actionIntent); - intent.putExtra(ADS_INTENT_EXTRA_ACTION, action); - } - - mContext.startActivity(intent); - } - - /** * @return {@code true} if can write system settings. * * @see Manifest.permission#WRITE_SETTINGS @@ -299,6 +430,8 @@ public boolean canWriteSystemSettings() { } /** + * Checks whether the package has overlay permission. + * * @return {@code true} if can draw overlays. * * @see Manifest.permission#SYSTEM_ALERT_WINDOW @@ -308,6 +441,8 @@ public boolean canDrawOverlays() { } /** + * Checks whether the package has usage access permission. + * * @return {@code true} if has usage access. * * @see Manifest.permission#PACKAGE_USAGE_STATS @@ -337,8 +472,7 @@ public boolean hasUsageAccess() { } /** - * Convert The array of permissions to the array list of - * {@link DynamicPermissions}. + * Converts the array of permissions to the array list of {@link DynamicPermissions}. * * @param permissions The permissions array to be converted. * @@ -361,15 +495,15 @@ public ArrayList getPermissionItemArrayList( mContext.getString(DynamicPermissionUtils.getPermissionSubtitle(permission))); if (permission.equals(Manifest.permission.WRITE_SETTINGS)) { - dynamicPermission.setGranted(canWriteSystemSettings()); + dynamicPermission.setAllowed(canWriteSystemSettings()); } if (permission.equals(Manifest.permission.PACKAGE_USAGE_STATS)) { - dynamicPermission.setGranted(hasUsageAccess()); + dynamicPermission.setAllowed(hasUsageAccess()); } if (permission.equals(Manifest.permission.SYSTEM_ALERT_WINDOW)) { - dynamicPermission.setGranted(canDrawOverlays()); + dynamicPermission.setAllowed(canDrawOverlays()); } permissionsList.add(dynamicPermission); @@ -387,7 +521,7 @@ public ArrayList getPermissionItemArrayList( permGroupInfo.loadDescription(packageManager).toString()); dynamicPermission.setDangerous(true); - dynamicPermission.setGranted(ContextCompat.checkSelfPermission(mContext, + dynamicPermission.setAllowed(ContextCompat.checkSelfPermission(mContext, permission) == PackageManager.PERMISSION_GRANTED); diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissionsActivity.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/activity/DynamicPermissionsActivity.java similarity index 64% rename from dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissionsActivity.java rename to dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/activity/DynamicPermissionsActivity.java index 304f5d8efd..c9ca510a5c 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissionsActivity.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/activity/DynamicPermissionsActivity.java @@ -14,30 +14,34 @@ * limitations under the License. */ -package com.pranavpandey.android.dynamic.support.permission; +package com.pranavpandey.android.dynamic.support.permission.activity; import android.content.Intent; import android.os.Bundle; -import android.support.annotation.Nullable; import android.view.View; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.activity.DynamicActivity; +import com.pranavpandey.android.dynamic.support.model.DynamicPermission; +import com.pranavpandey.android.dynamic.support.permission.DynamicPermissions; +import com.pranavpandey.android.dynamic.support.permission.fragment.DynamicPermissionsFragment; /** - * Base activity to request the {@link DynamicPermission}. It will be useful - * to request a permission from anywhere, even from a service. Just extend - * this activity in your app and add it in the manifest. Rest of the things + * Base activity to request the {@link DynamicPermission}. It will be useful to request a + * permission from anywhere, even from a service. Just extend this activity in your app and add + * it in the manifest. Rest of the things * *

Then, register that activity to request the permissions via - * {@link DynamicPermissions#setPermissionActivity(Class)}. Rest of the things - * will be handled by the {@link DynamicPermissionsFragment}.

+ * {@link DynamicPermissions#setPermissionActivity(Class)}. Rest of the things will be handled + * by the {@link DynamicPermissionsFragment}. * *

To request permissions, just call - * {@link DynamicPermissions#requestPermissions(String[], boolean, Intent, int)} - * method anywhere within the app.

+ * {@link DynamicPermissions#requestPermissions(String[], boolean, Intent, int)} method anywhere + * within the app. */ public abstract class DynamicPermissionsActivity extends DynamicActivity { @@ -60,9 +64,14 @@ public void onClick(View v) { ((TextView) findViewById(R.id.ads_header_toolbar_title)) .setText(getApplicationInfo().loadLabel(getPackageManager())); - if (getContentFragment() == null) { - switchFragment(DynamicPermissionsFragment.newInstance(getIntent()), false); - } + setupFragment(getIntent(), false); + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + + setupFragment(intent, true); } @Override @@ -75,11 +84,24 @@ protected boolean setCollapsingToolbarLayout() { return true; } + /** + * Setup fragment according to the intent. + * + * @param intent The received intent. + * @param newIntent {@code true} if updating from the new intent. + */ + private void setupFragment(@Nullable Intent intent, boolean newIntent) { + if (intent != null && intent.getAction() != null) { + if (getContentFragment() == null || newIntent) { + switchFragment(DynamicPermissionsFragment.newInstance(getIntent()), false); + } + } + } + /** * Update subtitle according to the permissions count. * - * @param count The no. of permissions shown by this - * activity. + * @param count The no. of permissions shown by this activity. */ public void updateSubtitle(int count) { ((TextView) findViewById(R.id.ads_header_toolbar_subtitle)) diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissionsAdapter.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/adapter/DynamicPermissionsAdapter.java similarity index 82% rename from dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissionsAdapter.java rename to dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/adapter/DynamicPermissionsAdapter.java index 2142add65b..1dbfd46368 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissionsAdapter.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/adapter/DynamicPermissionsAdapter.java @@ -14,18 +14,22 @@ * limitations under the License. */ -package com.pranavpandey.android.dynamic.support.permission; +package com.pranavpandey.android.dynamic.support.permission.adapter; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.RecyclerView; + import com.pranavpandey.android.dynamic.support.R; +import com.pranavpandey.android.dynamic.support.model.DynamicPermission; +import com.pranavpandey.android.dynamic.support.permission.DynamicPermissions; +import com.pranavpandey.android.dynamic.support.permission.view.DynamicPermissionsView; import java.util.ArrayList; @@ -50,7 +54,7 @@ public class DynamicPermissionsAdapter extends /** * View holder to hold the permission layout. */ - public static class ViewHolder extends RecyclerView.ViewHolder { + static class ViewHolder extends RecyclerView.ViewHolder { /** * Layout used by this view holder. @@ -97,7 +101,7 @@ public static class ViewHolder extends RecyclerView.ViewHolder { * * @param view The view for this view holder. */ - public ViewHolder(@NonNull View view) { + ViewHolder(@NonNull View view) { super(view); layout = view.findViewById(R.id.ads_info_layout); @@ -111,64 +115,79 @@ public ViewHolder(@NonNull View view) { } /** + * Get the layout used by this view holder. + * * @return The layout used by this view holder. */ - public ViewGroup getLayout() { + ViewGroup getLayout() { return layout; } /** + * Get the image view to show the permission status icon. + * * @return The image view to show the permission status icon. */ - public ImageView getStatusIcon() { + ImageView getStatusIcon() { return statusIcon; } /** + * Get the image view to show the permission icon. + * * @return The image view to show the permission icon. */ - public ImageView getIcon() { + ImageView getIcon() { return icon; } /** + * Get the text view to show the permission title. + * * @return The text view to show the permission title. */ - public TextView getTitle() { + TextView getTitle() { return title; } /** + * Get the text view to show the permission subtitle. + * * @return The text view to show the permission subtitle. */ - public TextView getSubtitle() { + TextView getSubtitle() { return subtitle; } /** + * Get the text view to show the permission info. + * * @return The text view to show the permission info. */ - public TextView getInfo() { + TextView getInfo() { return info; } /** + * Get the text view to show the permission description. + * * @return The text view to show the permission description. */ - public TextView getDescription() { + TextView getDescription() { return description; } /** + * Get the text view to show the permission status. + * * @return The text view to show the permission status. */ - public TextView getStatus() { + TextView getStatus() { return status; } } - public DynamicPermissionsAdapter( - @NonNull ArrayList dataSet, + public DynamicPermissionsAdapter(@NonNull ArrayList dataSet, @Nullable DynamicPermissionsView.PermissionListener permissionListener) { mPermissions = dataSet; mPermissionListener = permissionListener; @@ -183,13 +202,12 @@ public DynamicPermissionsAdapter( } @Override - public void onBindViewHolder(@NonNull final ViewHolder viewHolder, int position) { + public void onBindViewHolder(@NonNull final ViewHolder viewHolder, final int position) { if (mPermissionListener != null) { viewHolder.getLayout().setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - mPermissionListener.onPermissionSelected(v, viewHolder.getAdapterPosition(), - getItem(viewHolder.getAdapterPosition())); + mPermissionListener.onPermissionSelected(v, position, getItem(position)); } }); } else { @@ -226,7 +244,7 @@ public void onClick(View v) { viewHolder.getDescription().setVisibility(GONE); } - if (dynamicPermission.isGranted()) { + if (dynamicPermission.isAllowed()) { viewHolder.getStatusIcon().setImageResource(R.drawable.ads_ic_check); viewHolder.getInfo().setText(R.string.ads_perm_granted_desc); viewHolder.getStatus().setText(R.string.ads_perm_granted); @@ -260,8 +278,7 @@ public long getItemId(int position) { * * @param position The position of the adapter. * - * @return The dynamic permission according to the - * supplied position. + * @return The dynamic permission according to the supplied position. */ public DynamicPermission getItem(int position) { return mPermissions.get(position); diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissionsFragment.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/fragment/DynamicPermissionsFragment.java similarity index 72% rename from dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissionsFragment.java rename to dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/fragment/DynamicPermissionsFragment.java index 81b6b1d6c1..0679df80ef 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissionsFragment.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/fragment/DynamicPermissionsFragment.java @@ -14,20 +14,13 @@ * limitations under the License. */ -package com.pranavpandey.android.dynamic.support.permission; +package com.pranavpandey.android.dynamic.support.permission.fragment; import android.Manifest; -import android.annotation.SuppressLint; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.Snackbar; -import android.support.v4.app.ActivityCompat; -import android.support.v4.app.Fragment; -import android.support.v4.content.ContextCompat; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -35,20 +28,28 @@ import android.view.View; import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; + +import com.google.android.material.snackbar.Snackbar; import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.fragment.DynamicFragment; +import com.pranavpandey.android.dynamic.support.intent.DynamicIntent; +import com.pranavpandey.android.dynamic.support.model.DynamicAction; +import com.pranavpandey.android.dynamic.support.model.DynamicPermission; +import com.pranavpandey.android.dynamic.support.permission.DynamicPermissions; +import com.pranavpandey.android.dynamic.support.permission.activity.DynamicPermissionsActivity; +import com.pranavpandey.android.dynamic.support.permission.view.DynamicPermissionsView; +import com.pranavpandey.android.dynamic.support.utils.DynamicPermissionUtils; import java.util.ArrayList; -import static com.pranavpandey.android.dynamic.support.permission.DynamicPermissions.ADS_INTENT_EXTRA_ACTION; -import static com.pranavpandey.android.dynamic.support.permission.DynamicPermissions.ADS_INTENT_EXTRA_INTENT; -import static com.pranavpandey.android.dynamic.support.permission.DynamicPermissions.ADS_INTENT_EXTRA_PERMISSIONS; -import static com.pranavpandey.android.dynamic.support.permission.DynamicPermissions.ADS_INTENT_PERMISSIONS; - /** - * Base fragment class to show a list of required permissions in a - * recycler view. It will be used internally by the {@link DynamicPermissionsActivity} - * to request or manage permissions. + * Base fragment class to show a list of required permissions in a recycler view. It will be used + * internally by the {@link DynamicPermissionsActivity} to request or manage permissions. */ public class DynamicPermissionsFragment extends DynamicFragment { @@ -64,8 +65,7 @@ public class DynamicPermissionsFragment extends DynamicFragment { public static final int ADS_PERMISSIONS_DANGEROUS_MAX_COUNT = 1; /** - * Constant for permission request delay to update the status - * accordingly. + * Constant for permission request delay to update the status accordingly. */ public static final long ADS_PERMISSION_REQUEST_DELAY = 300; @@ -99,19 +99,24 @@ public class DynamicPermissionsFragment extends DynamicFragment { */ private boolean mRequestDangerousPermissions = true; + /** + * {@code true} if requesting the dangerous permissions. + */ + private boolean mRequestingDangerousPermissions; + /** * Initialize the new instance of this fragment. * - * @param permissionsIntent The intent with all the requested permissions - * and action. + * @param permissionsIntent The intent with all the requested permissions and action. * - * @return A instance of {@link DynamicPermissionsFragment}. + * @return An instance of {@link DynamicPermissionsFragment}. */ public static Fragment newInstance(@Nullable Intent permissionsIntent) { DynamicPermissionsFragment fragment = new DynamicPermissionsFragment(); Bundle args = new Bundle(); - args.putParcelable(ADS_INTENT_PERMISSIONS, permissionsIntent); + args.putParcelable(DynamicIntent.ACTION_PERMISSIONS, permissionsIntent); fragment.setArguments(args); + return fragment; } @@ -119,13 +124,15 @@ public static Fragment newInstance(@Nullable Intent permissionsIntent) { public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setResult(Activity.RESULT_CANCELED, null, false); + setRetainInstance(true); setHasOptionsMenu(true); } @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, + @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.ads_fragment_permissions, container, false); } @@ -173,16 +180,26 @@ public boolean onOptionsItemSelected(@Nullable MenuItem item) { public void onResume() { super.onResume(); + initPermissions(); + + if (!mRequestingDangerousPermissions) { + resumePermissionsRequest(); + } + } + + private void resumePermissionsRequest() { (new Handler()).postDelayed(new Runnable() { @Override public void run() { - initPermissions(); - if (mRequestDangerousPermissions) { - requestDangerousPermissions(mDynamicPermissionsView.getDangerousPermissions()); - mRequestDangerousPermissions = false; - } + if (!mRequestingDangerousPermissions) { + if (mRequestDangerousPermissions) { + requestDangerousPermissions( + mDynamicPermissionsView.getDangerousPermissions()); + mRequestDangerousPermissions = false; + } - requestAllPermissions(); + requestAllPermissions(); + } } }, ADS_PERMISSION_REQUEST_DELAY); } @@ -199,8 +216,7 @@ private void resetRequestCounter(boolean request) { } /** - * Request all the permissions at once including dangerous and - * special permissions. + * Request all the permissions at once including dangerous and special permissions. */ private void requestAllPermissions() { if (mDangerousPermissionsRequest <= ADS_PERMISSIONS_DANGEROUS_MAX_COUNT @@ -209,14 +225,16 @@ private void requestAllPermissions() { if (mDynamicPermissionsView.isDangerousPermissionsLeft()) { mDangerousPermissionsRequest++; if (mDangerousPermissionsRequest <= ADS_PERMISSIONS_DANGEROUS_MAX_COUNT) { - requestDangerousPermissions(mDynamicPermissionsView.getDangerousPermissionsLeft()); + requestDangerousPermissions(mDynamicPermissionsView + .getDangerousPermissionsLeft()); } else { requestAllPermissions(); } } else if (mDynamicPermissionsView.isSpecialPermissionsLeft()) { mSpecialPermissionsRequest++; if (mSpecialPermissionsRequest <= mSpecialPermissionsSize) { - requestPermission(mDynamicPermissionsView.getSpecialPermissionsLeft().get(0)); + requestPermission(mDynamicPermissionsView + .getSpecialPermissionsLeft().get(0)); } else { requestAllPermissions(); } @@ -231,8 +249,7 @@ private void requestAllPermissions() { } /** - * Initialize the permissions view according to the requested - * permissions status. + * Initialize the permissions view according to the requested permissions status. */ public void initPermissions() { String[] permissionsArray = getPermissions(); @@ -267,7 +284,10 @@ public void onPermissionSelected(@NonNull View view, int position, if (!mDynamicPermissionsView.isPermissionsLeft()) { checkForAction(); - finishActivity(); + + Intent intent = new Intent(); + intent.putExtra(DynamicIntent.EXTRA_PERMISSIONS, getPermissions()); + setResult(Activity.RESULT_OK, intent); } } else { getDynamicActivity().showFAB(); @@ -277,32 +297,32 @@ public void onPermissionSelected(@NonNull View view, int position, /** * Show hint if permission request is cancelled by the user. */ - @SuppressLint("Range") private void showHint() { getDynamicActivity().getSnackBar( R.string.ads_perm_info_grant_all, Snackbar.LENGTH_LONG).show(); } /** - * @return The permissions to be requested from the supplied - * arguments. + * Get the permissions intent from the supplied arguments. + * + * @return The permissions intent from the supplied arguments. */ - public String[] getPermissions() { - return getIntent().getStringArrayExtra(ADS_INTENT_EXTRA_PERMISSIONS); + public Intent getPermissionsIntent() { + return getParcelableFromArguments(DynamicIntent.ACTION_PERMISSIONS); } /** - * @return The permissions extra from the fragment arguments. + * Get the permissions to be requested from the supplied arguments. * - * @see Fragment#getArguments() + * @return The permissions to be requested from the supplied arguments. */ - public Intent getIntent() { - return getArguments().getParcelable(ADS_INTENT_PERMISSIONS); + public String[] getPermissions() { + return getPermissionsIntent().getStringArrayExtra(DynamicIntent.EXTRA_PERMISSIONS); } /** * Request a dynamic permission according to its type. - * Either dangerous or special. + *

Either dangerous or special. */ private void requestPermission(@NonNull DynamicPermission dynamicPermission) { String permission = dynamicPermission.getPermission(); @@ -331,28 +351,28 @@ private void requestPermission(@NonNull DynamicPermission dynamicPermission) { */ private void requestDangerousPermissions(@NonNull String... permissions) { if (permissions.length != 0) { - ActivityCompat.requestPermissions( - getActivity(), permissions, ADS_PERMISSIONS_REQUEST_CODE); + requestPermissions(permissions, ADS_PERMISSIONS_REQUEST_CODE); + mRequestingDangerousPermissions = true; } } /** - * Check if there is any action to be performed after allowing - * all the permissions. + * Checks whether there is any action to be performed after allowing all the permissions. */ private void checkForAction() { - Intent actionIntent = getIntent().getParcelableExtra(ADS_INTENT_EXTRA_INTENT); + Intent actionIntent = getPermissionsIntent() + .getParcelableExtra(DynamicIntent.EXTRA_PERMISSIONS_INTENT); if (actionIntent != null) { - switch (getIntent().getIntExtra( - ADS_INTENT_EXTRA_ACTION, DynamicPermissionsAction.NONE)) { - case DynamicPermissionsAction.START_SERVICE: + switch (getPermissionsIntent().getIntExtra( + DynamicIntent.EXTRA_PERMISSIONS_ACTION, DynamicAction.NONE)) { + case DynamicAction.START_SERVICE: getContext().startService(actionIntent); break; - case DynamicPermissionsAction.START_FOREGROUND_SERVICE: + case DynamicAction.START_FOREGROUND_SERVICE: ContextCompat.startForegroundService(getContext(), actionIntent); break; - case DynamicPermissionsAction.START_ACTIVITY: + case DynamicAction.START_ACTIVITY: getContext().startActivity(actionIntent); break; } @@ -360,22 +380,14 @@ private void checkForAction() { } @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, - @NonNull int[] grantResults) { + public void onRequestPermissionsResult(int requestCode, + @NonNull String[] permissions, @NonNull int[] grantResults) { + mRequestingDangerousPermissions = false; + resumePermissionsRequest(); + switch (requestCode) { case ADS_PERMISSIONS_REQUEST_CODE: break; } } - - @Override - public void onDestroy() { - super.onDestroy(); - - if (mDynamicPermissionsView.isPermissionsLeft()) { - setResult(Activity.RESULT_CANCELED); - } else { - setResult(Activity.RESULT_OK); - } - } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissionsView.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/view/DynamicPermissionsView.java similarity index 73% rename from dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissionsView.java rename to dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/view/DynamicPermissionsView.java index 3ec462632b..010814ea3b 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissionsView.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/view/DynamicPermissionsView.java @@ -14,25 +14,30 @@ * limitations under the License. */ -package com.pranavpandey.android.dynamic.support.permission; +package com.pranavpandey.android.dynamic.support.permission.view; import android.app.Activity; import android.content.Context; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.ActivityCompat; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.view.View; +import androidx.annotation.AttrRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.app.ActivityCompat; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.pranavpandey.android.dynamic.support.model.DynamicPermission; +import com.pranavpandey.android.dynamic.support.permission.adapter.DynamicPermissionsAdapter; import com.pranavpandey.android.dynamic.support.recyclerview.DynamicRecyclerViewFrame; +import com.pranavpandey.android.dynamic.support.utils.DynamicLayoutUtils; import java.util.ArrayList; /** - * A {@link android.widget.FrameLayout} containing a {@link RecyclerView} - * to show the list of required permissions. + * A {@link android.widget.FrameLayout} containing a {@link RecyclerView} to show the list of + * required permissions. */ public class DynamicPermissionsView extends DynamicRecyclerViewFrame { @@ -49,7 +54,7 @@ public interface PermissionListener { * @param dynamicPermission The selected permission. */ void onPermissionSelected(@NonNull View view, int position, - @NonNull DynamicPermission dynamicPermission); + @NonNull DynamicPermission dynamicPermission); } /** @@ -90,23 +95,23 @@ public DynamicPermissionsView(@NonNull Context context, @Nullable AttributeSet a super(context, attrs); } - public DynamicPermissionsView(Context context, AttributeSet attrs, int defStyleAttr) { + public DynamicPermissionsView(@NonNull Context context, + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public RecyclerView.LayoutManager getRecyclerViewLayoutManager() { - return new LinearLayoutManager(getContext(), - LinearLayoutManager.VERTICAL, false); + return DynamicLayoutUtils.getLinearLayoutManager( + getContext(), LinearLayoutManager.VERTICAL); } /** - * Set the permissions to be shown by this view. Generally, it will - * be the required permissions to perform a particular action. + * Set the permissions to be shown by this view. + *

Generally, it will be the required permissions to perform a particular action. * * @param permissions The permissions to be shown by this view. - * @param permissionListener The listener to receive callback when a - * permission is selected. + * @param permissionListener The listener to receive callback when a permission is selected. * */ public void setPermissions(@NonNull ArrayList permissions, @@ -118,13 +123,14 @@ public void setPermissions(@NonNull ArrayList permissions, mDangerousPermissionsLeft = new ArrayList<>(); for (DynamicPermission dynamicPermission : mPermissions) { - if (!dynamicPermission.isGranted()) { + if (!dynamicPermission.isAllowed()) { mPermissionsLeft.add(dynamicPermission); if (dynamicPermission.isDangerous()) { mDangerousPermissions.add(dynamicPermission); - dynamicPermission.setAskAgain(ActivityCompat.shouldShowRequestPermissionRationale( + dynamicPermission.setAskAgain( + ActivityCompat.shouldShowRequestPermissionRationale( (Activity) getContext(), dynamicPermission.getPermission())); if (dynamicPermission.isAskAgain()) { @@ -142,6 +148,8 @@ public void setPermissions(@NonNull ArrayList permissions, } /** + * Get the array of all the dangerous permissions. + * * @return The array of all the dangerous permissions. */ public String[] getDangerousPermissions() { @@ -154,6 +162,8 @@ public String[] getDangerousPermissions() { } /** + * Get the array of unrequested or denied dangerous permissions. + * * @return The array of unrequested or denied dangerous permissions. */ public String[] getDangerousPermissionsLeft() { @@ -166,40 +176,48 @@ public String[] getDangerousPermissionsLeft() { } /** - * @return The list to store the unrequested or denied special - * permissions. + * Get the list of unrequested or denied special permissions. + * + * @return the list of unrequested or denied special permissions. */ public ArrayList getSpecialPermissionsLeft() { return mSpecialPermissionsLeft; } /** - * @return {@code true} if all the permissions shown by this view has - * been granted. + * Checks whether all the permissions shown by this view are granted. + * + * @return {@code true} if all the permissions shown by this view have been granted. */ public boolean isAllPermissionsGranted() { return !isSpecialPermissionsLeft() && !isDangerousPermissionsLeft(); } /** - * @return {@code true} if there is any permission shown by this view - * has not been requested or denied. + * Checks whether there is any permission left. + * + * @return {@code true} if there is any permission shown by this view has not been + * requested or denied. */ public boolean isPermissionsLeft() { return !mPermissionsLeft.isEmpty(); } /** - * @return {@code true} if there is any dangerous permission shown by this - * view has not been requested or denied. + * Checks whether there is any dangerous permission left. + * + * @return {@code true} if there is any dangerous permission shown by this view has not been + * requested or denied. */ public boolean isDangerousPermissionsLeft() { return !mDangerousPermissionsLeft.isEmpty(); } /** - * @return {@code true} if there is any special permission shown by this - * view has not been requested or denied. + * Checks whether there is any special permission left. + * + * @return {@code true} if there is any special permission shown by this view has not been + * requested or denied. */ public boolean isSpecialPermissionsLeft() { return !mSpecialPermissionsLeft.isEmpty(); diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/DynamicPickerType.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/DynamicPickerType.java index 9bf7cefb5a..1b0ba8d21c 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/DynamicPickerType.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/DynamicPickerType.java @@ -16,7 +16,7 @@ package com.pranavpandey.android.dynamic.support.picker; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -25,8 +25,8 @@ import static com.pranavpandey.android.dynamic.support.picker.DynamicPickerType.PRESETS; /** - * Interface to hold the color type constant values to provide - * show presets or custom view accordingly. + * Interface to hold the color type constant values to provide show presets or custom view + * accordingly. */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = { PRESETS, CUSTOM }) diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorControl.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorControl.java index 068efba285..c3ee0580fd 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorControl.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorControl.java @@ -16,7 +16,7 @@ package com.pranavpandey.android.dynamic.support.picker.color; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -27,8 +27,7 @@ import static com.pranavpandey.android.dynamic.support.picker.color.DynamicColorControl.RGB; /** - * Interface to hold the color control constant values to provide - * color sliders accordingly. + * Interface to hold the color control constant values to provide color sliders accordingly. */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = { ALL, HSV, RGB, CMYK }) diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorDialog.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorDialog.java index 8686aacc2b..418da300ad 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorDialog.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorDialog.java @@ -18,47 +18,44 @@ import android.content.DialogInterface; import android.os.Bundle; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.view.View; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.adapter.DynamicColorsAdapter; import com.pranavpandey.android.dynamic.support.dialog.DynamicDialog; import com.pranavpandey.android.dynamic.support.dialog.fragment.DynamicDialogFragment; +import com.pranavpandey.android.dynamic.support.listener.DynamicColorListener; import com.pranavpandey.android.dynamic.support.picker.DynamicPickerType; /** - * A color picker dialog fragment to display multiple grids of colors - * and their shades. It will be used internally by the + * A color picker dialog fragment to display multiple grids of colors and their shades. + *

It will be used internally by the * {@link com.pranavpandey.android.dynamic.support.setting.DynamicColorPreference} * but can be used by the other views also. */ public class DynamicColorDialog extends DynamicDialogFragment { /** - * State key to save the previously selected color so that it can - * be restored later. + * State key to save the previously selected color so that it can be restored later. */ private static final String ADS_STATE_PICKER_PREVIOUS_COLOR = "ads_state_picker_previous_color"; /** - * State key to save the currently selected color so that it can - * be restored later. + * State key to save the currently selected color so that it can be restored later. */ private static final String ADS_STATE_PICKER_COLOR = "ads_state_picker_color"; /** - * State key to save the color picker type so that it can be - * restored later. + * State key to save the color picker type so that it can be restored later. */ private static final String ADS_STATE_PICKER_TYPE = "ads_state_picker_type"; /** - * State key to save the color picker control so that it can be - * restored later. + * State key to save the color picker control so that it can be restored later. */ private static final String ADS_STATE_PICKER_CONTROL = "ads_state_picker_control"; @@ -107,7 +104,7 @@ public class DynamicColorDialog extends DynamicDialogFragment { /** * Color listener to get the selected color. */ - private DynamicColorsAdapter.OnColorSelectedListener mOnColorSelectedListener; + private DynamicColorListener mDynamicColorListener; /** * The color picker used by this dialog. @@ -144,14 +141,13 @@ public static DynamicColorDialog newInstance() { mDynamicColorPicker.setSelectedColor(mSelectedColor); mDynamicColorPicker.setType(mType); mDynamicColorPicker.setControl(mControl); - mDynamicColorPicker.setOnColorSelectedListener( - new DynamicColorsAdapter.OnColorSelectedListener() { + mDynamicColorPicker.setDynamicColorListener(new DynamicColorListener() { @Override - public void onColorSelected(int position, int color) { + public void onColorSelected(@Nullable String tag, int position, int color) { dismiss(); - if (mOnColorSelectedListener != null) { - mOnColorSelectedListener.onColorSelected(position, color); + if (mDynamicColorListener != null) { + mDynamicColorListener.onColorSelected(tag, position, color); } } }); @@ -176,7 +172,7 @@ public void onClick(DialogInterface dialogInterface, int i) { setOnShowListener(new DialogInterface.OnShowListener() { @Override public void onShow(DialogInterface dialogInterface) { - mDynamicColorPicker.update(); + mDynamicColorPicker.onUpdate(); if (savedInstanceState == null) { showView(mDynamicColorPicker.getType()); } else { @@ -233,7 +229,7 @@ protected void showCustom() { } @Override - public void onSaveInstanceState(Bundle outState) { + public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); outState.putInt(ADS_STATE_PICKER_PREVIOUS_COLOR, mDynamicColorPicker.getPreviousColor()); @@ -243,6 +239,8 @@ public void onSaveInstanceState(Bundle outState) { } /** + * Ge the color entries used by the picker. + * * @return The color entries used by the picker. */ public Integer[] getColors() { @@ -250,6 +248,8 @@ public Integer[] getColors() { } /** + * Get the shade entries used by the picker. + * * @return The shade entries used by the picker. */ public Integer[][] getShades() { @@ -262,11 +262,10 @@ public Integer[][] getShades() { * @param colors The color entries to be set. * @param shades The shade entries to be set. * - * @return The {@link DynamicColorDialog} object to allow for - * chaining of calls to set methods. + * @return The {@link DynamicColorDialog} object to allow for chaining of calls to set methods. */ public DynamicColorDialog setColors(@NonNull @ColorInt Integer[] colors, - @Nullable @ColorInt Integer[][] shades) { + @Nullable @ColorInt Integer[][] shades) { this.mColors = colors; this.mShades = shades; @@ -274,6 +273,8 @@ public DynamicColorDialog setColors(@NonNull @ColorInt Integer[] colors, } /** + * Get the previous color. + * * @return The previous color. */ public @ColorInt int getPreviousColor() { @@ -285,8 +286,7 @@ public DynamicColorDialog setColors(@NonNull @ColorInt Integer[] colors, * * @param previousColor The previous color to be set. * - * @return The {@link DynamicColorDialog} object to allow for - * chaining of calls to set methods. + * @return The {@link DynamicColorDialog} object to allow for chaining of calls to set methods. */ public DynamicColorDialog setPreviousColor(@ColorInt int previousColor) { this.mPreviousColor = previousColor; @@ -295,6 +295,8 @@ public DynamicColorDialog setPreviousColor(@ColorInt int previousColor) { } /** + * Get the selected color. + * * @return The selected color. */ public @ColorInt int getSelectedColor() { @@ -306,8 +308,7 @@ public DynamicColorDialog setPreviousColor(@ColorInt int previousColor) { * * @param selectedColor The color to be selected. * - * @return The {@link DynamicColorDialog} object to allow for - * chaining of calls to set methods. + * @return The {@link DynamicColorDialog} object to allow for chaining of calls to set methods. */ public DynamicColorDialog setSelectedColor(@ColorInt int selectedColor) { this.mSelectedColor = selectedColor; @@ -316,6 +317,8 @@ public DynamicColorDialog setSelectedColor(@ColorInt int selectedColor) { } /** + * Get the shape of the color swatches. + * * @return The shape of the color swatches. */ public @DynamicColorShape int getColorShape() { @@ -327,8 +330,7 @@ public DynamicColorDialog setSelectedColor(@ColorInt int selectedColor) { * * @param colorShape The color shape to be set. * - * @return The {@link DynamicColorDialog} object to allow for - * chaining of calls to set methods. + * @return The {@link DynamicColorDialog} object to allow for chaining of calls to set methods. */ public DynamicColorDialog setColorShape(@DynamicColorShape int colorShape) { this.mColorShape = colorShape; @@ -337,19 +339,20 @@ public DynamicColorDialog setColorShape(@DynamicColorShape int colorShape) { } /** - * @return {@code true} to enable alpha for the custom color. + * Returns whether the color alpha is enabled for the picker. + * + * @return {@code true} to enable the color alpha for the picker. */ public boolean isAlpha() { return mAlpha; } /** - * Set the alpha support for the custom color. + * Set the color alpha support for the picker. * * @param alpha {@code true} to enable alpha. * - * @return The {@link DynamicColorDialog} object to allow for - * chaining of calls to set methods. + * @return The {@link DynamicColorDialog} object to allow for chaining of calls to set methods. */ public DynamicColorDialog setAlpha(boolean alpha) { this.mAlpha = alpha; @@ -358,23 +361,24 @@ public DynamicColorDialog setAlpha(boolean alpha) { } /** + * Returns the color listener for this dialog. + * * @return The color listener to get the selected color. */ - public @NonNull DynamicColorsAdapter.OnColorSelectedListener getOnColorSelectedListener() { - return mOnColorSelectedListener; + public @NonNull DynamicColorListener getDynamicColorListener() { + return mDynamicColorListener; } /** * Set the color listener to get the selected color. * - * @param onColorSelectedListener The listener to be set. + * @param dynamicColorListener The listener to be set. * - * @return The {@link DynamicColorDialog} object to allow for - * chaining of calls to set methods. + * @return The {@link DynamicColorDialog} object to allow for chaining of calls to set methods. */ - public DynamicColorDialog setOnColorSelectedListener( - @NonNull DynamicColorsAdapter.OnColorSelectedListener onColorSelectedListener) { - this.mOnColorSelectedListener = onColorSelectedListener; + public DynamicColorDialog setDynamicColorListener( + @NonNull DynamicColorListener dynamicColorListener) { + this.mDynamicColorListener = dynamicColorListener; return this; } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorPicker.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorPicker.java index ca6ffbab38..b1ff0dc22a 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorPicker.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorPicker.java @@ -18,27 +18,30 @@ import android.content.Context; import android.graphics.Color; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.text.Editable; import android.text.TextWatcher; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.Button; -import android.widget.FrameLayout; import android.widget.GridView; import android.widget.SeekBar; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.adapter.DynamicColorsAdapter; +import com.pranavpandey.android.dynamic.support.listener.DynamicColorListener; import com.pranavpandey.android.dynamic.support.picker.DynamicPickerType; import com.pranavpandey.android.dynamic.support.preference.DynamicPreferences; import com.pranavpandey.android.dynamic.support.setting.DynamicSeekBarCompact; import com.pranavpandey.android.dynamic.support.theme.DynamicColorPalette; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; -import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; +import com.pranavpandey.android.dynamic.support.view.DynamicView; import com.pranavpandey.android.dynamic.support.widget.DynamicEditText; import com.pranavpandey.android.dynamic.support.widget.WidgetDefaults; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; @@ -48,30 +51,25 @@ import java.util.List; /** - * A color picker inside a FrameLayout to display multiple grids of - * colors and their shades. It will be used internally by the + * A color picker inside a DynamicView to display multiple grids of colors and their shades. + *

It will be used internally by the * {@link com.pranavpandey.android.dynamic.support.setting.DynamicColorPreference} * but can be used by the other views also. */ -public class DynamicColorPicker extends FrameLayout { +public class DynamicColorPicker extends DynamicView { /** - * Shared preference key to save the recently selected control - * type. + * Shared preference key to save the recently selected control type. */ - private static final String ADS_PREF_COLOR_PICKER_CONTROL = - "ads_pref_color_picker_control"; + private static final String ADS_PREF_COLOR_PICKER_CONTROL = "ads_pref_color_picker_control"; /** - * Shared preference key to save the recently selected colors - * without alpha. + * Shared preference key to save the recently selected colors without alpha. */ - private static final String ADS_PREF_COLOR_PICKER_RECENTS = - "ads_pref_color_picker_recents"; + private static final String ADS_PREF_COLOR_PICKER_RECENTS = "ads_pref_color_picker_recents"; /** - * Shared preference key to save the recently selected colors - * with alpha. + * Shared preference key to save the recently selected colors with alpha. */ private static final String ADS_PREF_COLOR_PICKER_RECENTS_ALPHA = "ads_pref_color_picker_recents_alpha"; @@ -161,7 +159,7 @@ public class DynamicColorPicker extends FrameLayout { /** * Color listener to get the selected color. */ - private DynamicColorsAdapter.OnColorSelectedListener mOnColorSelectedListener; + private DynamicColorListener mDynamicColorListener; /** * Root view of the color shades. @@ -264,44 +262,42 @@ public class DynamicColorPicker extends FrameLayout { private TextWatcher mEditTextWatcher; /** - * Seek bar listener for HSV color space to update the values - * accordingly. + * Seek bar listener for HSV color space to update the values accordingly. */ private SeekBar.OnSeekBarChangeListener mHSVSeekBarListener; /** - * Seek bar listener for RGB color space to update the values - * accordingly. + * Seek bar listener for RGB color space to update the values accordingly. */ private SeekBar.OnSeekBarChangeListener mRGBSeekBarListener; /** - * {@code true} if color picker is updating the custom color. It - * will be used to disable any listeners during update process. + * {@code true} if color picker is updating the custom color. + *

It will be used to disable any listeners during update process. */ private boolean mUpdatingCustomColor; public DynamicColorPicker(@NonNull Context context) { - this(context, null); + super(context); } public DynamicColorPicker(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); - - initialize(); } - public DynamicColorPicker(Context context, AttributeSet attrs, int defStyleAttr) { + public DynamicColorPicker(@NonNull Context context, + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); + } - initialize(); + @Override + protected @LayoutRes int getLayoutRes() { + return R.layout.ads_color_picker; } - /** - * Initialize this view with default settings. - */ - private void initialize() { - inflate(getContext(), R.layout.ads_color_picker, this); + @Override + protected void onInflate() { + inflate(getContext(), getLayoutRes(), this); mShadesView = findViewById(R.id.ads_color_picker_shades_root); mColorsGridView = findViewById(R.id.ads_color_picker_colors); @@ -331,7 +327,7 @@ private void initialize() { @Override public void onClick(View v) { setSelectedColor(mPreviousColorView.getColor()); - update(); + onUpdate(); } }); @@ -455,20 +451,18 @@ public void onClick(View view) { mSeekBarBlue.setOnSeekBarControlListener(mRGBSeekBarListener); mUpdatingCustomColor = true; - mPreviousColor = DynamicColorType.UNKNOWN; + mPreviousColor = Theme.ColorType.UNKNOWN; mColorShape = DynamicColorShape.CIRCLE; mType = DynamicPickerType.PRESETS; mControl = DynamicPreferences.getInstance().loadPrefs( ADS_PREF_COLOR_PICKER_CONTROL, DynamicColorControl.HSV); - update(); + onUpdate(); } - /** - * Load this view according to the supplied parameters. - */ - public void update() { - if (mPreviousColor != DynamicColorType.UNKNOWN) { + @Override + public void onUpdate() { + if (mPreviousColor != Theme.ColorType.UNKNOWN) { mPreviousColorView.setColor(mPreviousColor); mPreviousColorView.setVisibility(VISIBLE); } else { @@ -488,10 +482,9 @@ public void update() { } mColorsGridView.setAdapter(new DynamicColorsAdapter(mColors, - mSelectedColor, mColorShape, mAlpha, - new DynamicColorsAdapter.OnColorSelectedListener() { + mSelectedColor, mColorShape, mAlpha, new DynamicColorListener() { @Override - public void onColorSelected(int position, int color) { + public void onColorSelected(@Nullable String tag, int position, int color) { if (mShades != null && position < mShades.length) { setShades(position, color); } @@ -516,8 +509,7 @@ public void onColorSelected(int position, int color) { /** * Initialize shades to find out the matching color palette. * - * @param showCustom {@code true} to show the custom color view - * if no match is found. + * @param showCustom {@code true} to show the custom color view if no match is found. */ private void initializeShades(boolean showCustom) { if (mShades != null) { @@ -536,17 +528,15 @@ private void initializeShades(boolean showCustom) { } /** - * Select the color and call - * {@link DynamicColorsAdapter.OnColorSelectedListener#onColorSelected(int, int)} - * method. + * Sets the selected color. * - * @param position Position of the parent color. + * @param position The position of the parent color. * @param color The selected color. */ protected void selectColor(int position, @ColorInt int color) { - if (mOnColorSelectedListener != null) { + if (mDynamicColorListener != null) { mSelectedColor = color; - mOnColorSelectedListener.onColorSelected(position, color); + mDynamicColorListener.onColorSelected(null, position, color); saveToRecents(color); } @@ -660,10 +650,9 @@ protected void setShades(int position, @ColorInt int color) { mShadesView.setVisibility(VISIBLE); mShadesCurrent = mShades[position]; mShadesGridView.setAdapter(new DynamicColorsAdapter(mShadesCurrent, - color, mColorShape, mAlpha, - new DynamicColorsAdapter.OnColorSelectedListener() { + color, mColorShape, mAlpha, new DynamicColorListener() { @Override - public void onColorSelected(int position, int color) { + public void onColorSelected(@Nullable String tag, int position, int color) { setCustom(color, true, true); } })); @@ -684,9 +673,10 @@ protected void setRecents(@ColorInt int color) { mRecentsGridView.setAdapter(new DynamicColorsAdapter(mRecents, color, mColorShape == DynamicColorShape.CIRCLE ? DynamicColorShape.SQUARE : DynamicColorShape.CIRCLE, mAlpha, - new DynamicColorsAdapter.OnColorSelectedListener() { + new DynamicColorListener() { @Override - public void onColorSelected(int position, int color) { + public void onColorSelected( + @Nullable String tag, int position, int color) { setCustom(color, true, true); } })); @@ -734,8 +724,8 @@ private void updateCustomControls() { } /** - * Get the root view of this picker. It will be used internally - * to add separators in the dialog. + * Get the root view of this picker. + *

It will be used internally to add separators in the dialog. * * @return The root view of this picker. */ @@ -744,6 +734,8 @@ private void updateCustomControls() { } /** + * Get the color picker view type. + * * @return The color picker view type. */ public @DynamicPickerType int getType() { @@ -760,6 +752,8 @@ public void setType(@DynamicPickerType int type) { } /** + * Get the color picker view control. + * * @return The color picker view control. */ public @DynamicColorControl int getControl() { @@ -769,8 +763,7 @@ public void setType(@DynamicPickerType int type) { /** * Set the color picker view control. * - * @param control The color picker view control to - * be set. + * @param control The color picker view control to be set. */ public void setControl(@DynamicColorControl int control) { this.mControl = control; @@ -795,6 +788,8 @@ public void setControl(@DynamicColorControl int control) { } /** + * Get the color entries used by the picker. + * * @return The color entries used by the picker. */ public Integer[] getColors() { @@ -815,12 +810,14 @@ public Integer[][] getShades() { * @param shades The shade entries to be set. */ public void setColors(@NonNull @ColorInt Integer[] colors, - @Nullable @ColorInt Integer[][] shades) { + @Nullable @ColorInt Integer[][] shades) { this.mColors = colors; this.mShades = shades; } /** + * Get the previous color. + * * @return The previous color. */ public @ColorInt int getPreviousColor() { @@ -837,6 +834,8 @@ public void setPreviousColor(@ColorInt int previousColor) { } /** + * Get the selected color. + * * @return The selected color. */ public @ColorInt int getSelectedColor() { @@ -853,6 +852,8 @@ public void setSelectedColor(@ColorInt int selectedColor) { } /** + * Ge the shape of the color swatches. + * * @return The shape of the color swatches. */ public @DynamicColorShape int getColorShape() { @@ -869,14 +870,16 @@ public void setColorShape(@DynamicColorShape int colorShape) { } /** - * @return {@code true} to enable alpha for the custom color. + * Returns whether the color alpha is enabled + * + * @return {@code true} to enable the color alpha. */ public boolean isAlpha() { return mAlpha; } /** - * Set the alpha support for the custom color. + * Set the alpha support for the color. * * @param alpha {@code true} to enable alpha. */ @@ -885,20 +888,22 @@ public void setAlpha(boolean alpha) { } /** + * Returns the color listener to get the selected color. + * * @return The color listener to get the selected color. */ - public @NonNull DynamicColorsAdapter.OnColorSelectedListener getOnColorSelectedListener() { - return mOnColorSelectedListener; + public @NonNull + DynamicColorListener getDynamicColorListener() { + return mDynamicColorListener; } /** * Set the color listener to get the selected color. * - * @param onColorSelectedListener The listener to be set. + * @param dynamicColorListener The listener to be set. */ - public void setOnColorSelectedListener( - @NonNull DynamicColorsAdapter.OnColorSelectedListener onColorSelectedListener) { - this.mOnColorSelectedListener = onColorSelectedListener; + public void setDynamicColorListener(@NonNull DynamicColorListener dynamicColorListener) { + this.mDynamicColorListener = dynamicColorListener; } /** @@ -906,12 +911,12 @@ public void setOnColorSelectedListener( * * @param color The selected color. */ - protected void saveToRecents(@ColorInt int color) { - if (color == DynamicTheme.ADS_THEME_AUTO) { + protected void saveToRecents(@ColorInt Integer color) { + if (color == Theme.AUTO) { return; } - mRecentsList = new ArrayList<>(); + mRecentsList = new ArrayList(); mRecents = getRecents(); if (mRecents != null) { @@ -921,7 +926,7 @@ protected void saveToRecents(@ColorInt int color) { if (!mRecentsList.contains(color)) { mRecentsList.add(0, color); } else { - mRecentsList.remove(mRecentsList.indexOf(color)); + mRecentsList.remove(color); mRecentsList.add(0, color); } @@ -947,6 +952,8 @@ protected void saveToRecents(@ColorInt int color) { } /** + * Returns the saved recent colors from the shared preferences. + * * @return The saved recent colors from the shared preferences. */ protected Integer[] getRecents() { diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorPopup.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorPopup.java index 48420fdcde..6f39c30ba2 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorPopup.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorPopup.java @@ -16,30 +16,34 @@ package com.pranavpandey.android.dynamic.support.picker.color; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.FragmentActivity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.GridView; import android.widget.PopupWindow; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.FragmentActivity; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.adapter.DynamicColorsAdapter; import com.pranavpandey.android.dynamic.support.dialog.DynamicDialog; +import com.pranavpandey.android.dynamic.support.listener.DynamicColorListener; import com.pranavpandey.android.dynamic.support.popup.DynamicPopup; import com.pranavpandey.android.dynamic.support.theme.DynamicColorPalette; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; +import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; import com.pranavpandey.android.dynamic.support.view.DynamicHeader; import java.util.Arrays; /** - * A {@link PopupWindow} to display a grid of colors. It will be used - * internally by the {@link com.pranavpandey.android.dynamic.support.setting.DynamicColorPreference} + * A {@link PopupWindow} to display a grid of colors. + *

It will be used internally by the + * {@link com.pranavpandey.android.dynamic.support.setting.DynamicColorPreference} * but can be used by the other views also. */ public class DynamicColorPopup extends DynamicPopup { @@ -99,7 +103,7 @@ public class DynamicColorPopup extends DynamicPopup { /** * Color listener to get the selected color. */ - private DynamicColorsAdapter.OnColorSelectedListener mOnColorSelectedListener; + private DynamicColorListener mDynamicColorListener; /** * On click listener to get the more colors callback. @@ -111,17 +115,15 @@ public class DynamicColorPopup extends DynamicPopup { * * @param anchor The anchor view for this popup. * @param entries The color entries for this popup. - * @param onColorSelectedListener The color listener to - * get the selected color. + * @param dynamicColorListener The color listener to get the selected color. */ - public DynamicColorPopup( - @NonNull View anchor, @NonNull Integer[] entries, - @NonNull DynamicColorsAdapter.OnColorSelectedListener onColorSelectedListener) { + public DynamicColorPopup(@NonNull View anchor, @NonNull Integer[] entries, + @NonNull DynamicColorListener dynamicColorListener) { this.mAnchor = anchor; this.mEntries = entries; - this.mOnColorSelectedListener = onColorSelectedListener; - this.mDefaultColor = DynamicColorType.UNKNOWN; - this.mSelectedColor = DynamicColorType.UNKNOWN; + this.mDynamicColorListener = dynamicColorListener; + this.mDefaultColor = DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE; + this.mSelectedColor = DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE; this.mColorShape = DynamicColorShape.CIRCLE; } @@ -135,13 +137,14 @@ public DynamicColorPopup( (ViewGroup) getAnchor().getRootView(), false); if (getTitle() != null) { - mHeaderView = new DynamicHeader(getAnchor().getContext()) - .setTitle(getTitle()).setShowIcon(false); + mHeaderView = new DynamicHeader(getAnchor().getContext()); + ((DynamicHeader) mHeaderView).setTitle(mTitle); + ((DynamicHeader) mHeaderView).setFillSpace(true); } final GridView gridView = mView.findViewById(R.id.ads_color_picker_presets); - if (mSelectedColor == DynamicColorType.UNKNOWN + if (mSelectedColor == DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE || Arrays.asList(mEntries).contains(mSelectedColor)) { mFooterView.findViewById(R.id.ads_color_picker_popup_footer_image) .setVisibility(View.VISIBLE); @@ -150,7 +153,8 @@ public DynamicColorPopup( R.id.ads_color_picker_popup_footer_view), mSelectedColor); } - if (mDefaultColor != DynamicColorType.UNKNOWN && mDefaultColor != mSelectedColor) { + if (mDefaultColor != DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE + && mDefaultColor != mSelectedColor) { setColorView((DynamicColorView) mFooterView.findViewById( R.id.ads_color_picker_popup_footer_view_default), mDefaultColor); } @@ -168,16 +172,18 @@ public void onClick(View view) { .setColorShape(mColorShape) .setAlpha(mAlpha) .setPreviousColor(mPreviousColor) - .setSelectedColor(mSelectedColor == DynamicTheme.ADS_THEME_AUTO - ? DynamicTheme.getInstance().getBackgroundColor() + .setSelectedColor(mSelectedColor == Theme.AUTO + ? DynamicTheme.getInstance().get().getBackgroundColor() : mSelectedColor) - .setOnColorSelectedListener( - new DynamicColorsAdapter.OnColorSelectedListener() { + .setDynamicColorListener( + new DynamicColorListener() { @Override - public void onColorSelected(int position, int color) { - if (mOnColorSelectedListener != null) { - mOnColorSelectedListener - .onColorSelected(position, color); + public void onColorSelected( + @Nullable String tag, int position, + int color) { + if (mDynamicColorListener != null) { + mDynamicColorListener.onColorSelected( + tag, position, color); } } }) @@ -191,14 +197,13 @@ public void onColorSelected(int position, int color) { }); gridView.setAdapter(new DynamicColorsAdapter(mEntries, mSelectedColor, - mColorShape, mAlpha, - new DynamicColorsAdapter.OnColorSelectedListener() { + mColorShape, mAlpha, new DynamicColorListener() { @Override - public void onColorSelected(int position, int color) { + public void onColorSelected(@Nullable String tag, int position, int color) { getPopupWindow().dismiss(); - if (mOnColorSelectedListener != null) { - mOnColorSelectedListener.onColorSelected(position, color); + if (mDynamicColorListener != null) { + mDynamicColorListener.onColorSelected(tag, position, color); } } })); @@ -226,8 +231,9 @@ public void onClick(View view) { colorView.setSelected(true); getPopupWindow().dismiss(); - if (mOnColorSelectedListener != null) { - mOnColorSelectedListener.onColorSelected(0, colorView.getColor()); + if (mDynamicColorListener != null) { + mDynamicColorListener.onColorSelected( + null, 0, colorView.getColor()); } } }); @@ -256,6 +262,8 @@ public boolean onLongClick(View view) { } /** + * Get the title used by this popup. + * * @return The title used by this popup. */ public @Nullable CharSequence getTitle() { @@ -272,6 +280,8 @@ public void setTitle(@Nullable CharSequence title) { } /** + * Get the color entries used by this popup. + * * @return The color entries used by this popup. */ public Integer[] getEntries() { @@ -288,6 +298,8 @@ public void setEntries(Integer[] entries) { } /** + * Get the default color to be shown in footer. + * * @return The default color to be shown in footer. */ public @ColorInt int getDefaultColor() { @@ -303,6 +315,15 @@ public void setDefaultColor(@ColorInt int defaultColor) { this.mDefaultColor = defaultColor; } + /** + * Get the previous color. + * + * @return The previous color. + */ + public @ColorInt int getPreviousColor() { + return mPreviousColor; + } + /** * Set the previous color. * @@ -313,6 +334,8 @@ public void setPreviousColor(@ColorInt int previousColor) { } /** + * Get the selected color. + * * @return The selected color. */ public @ColorInt int getSelectedColor() { @@ -329,6 +352,8 @@ public void setSelectedColor(@ColorInt int selectedColor) { } /** + * Get the shape of the color swatches. + * * @return The shape of the color swatches. */ public @DynamicColorShape int getColorShape() { @@ -345,14 +370,16 @@ public void setColorShape(@DynamicColorShape int colorShape) { } /** - * @return {@code true} to enable alpha for the custom color. + * Returns whether the color alpha is enabled for the picker. + * + * @return {@code true} to enable the color alpha for the picker. */ public boolean isAlpha() { return mAlpha; } /** - * Set the alpha support for the custom color. + * Set the color alpha support for the picker. * * @param alpha {@code true} to enable alpha. */ @@ -361,39 +388,38 @@ public void setAlpha(boolean alpha) { } /** + * Returns the color listener to get the selected color. + * * @return The color listener to get the selected color. */ - public @NonNull DynamicColorsAdapter.OnColorSelectedListener getOnColorSelectedListener() { - return mOnColorSelectedListener; + public @NonNull DynamicColorListener getDynamicColorListener() { + return mDynamicColorListener; } /** * Set the color listener to get the selected color. * - * @param onColorSelectedListener The listener to be set. + * @param dynamicColorListener The listener to be set. */ - public void setOnColorSelectedListener( - @NonNull DynamicColorsAdapter.OnColorSelectedListener onColorSelectedListener) { - this.mOnColorSelectedListener = onColorSelectedListener; + public void setDynamicColorListener(@NonNull DynamicColorListener dynamicColorListener) { + this.mDynamicColorListener = dynamicColorListener; } /** - * @return The on click listener to get the more colors - * callback. + * Returns the on click listener to get the more colors callback. + * + * @return The on click listener to get the more colors callback. */ public @Nullable View.OnClickListener getOnMoreColorsListener() { return mOnMoreColorsListener; } /** - * Set the on click listener to get the more colors - * callback. + * Set the on click listener to get the more colors callback. * - * @param onMoreColorsListener The on click listener - * to be set. + * @param onMoreColorsListener The on click listener to be set. */ - public void setOnMoreColorsListener( - @Nullable View.OnClickListener onMoreColorsListener) { + public void setOnMoreColorsListener(@Nullable View.OnClickListener onMoreColorsListener) { this.mOnMoreColorsListener = onMoreColorsListener; } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorShape.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorShape.java index 2b59513df1..f3d01ff6ac 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorShape.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorShape.java @@ -16,7 +16,7 @@ package com.pranavpandey.android.dynamic.support.picker.color; -import android.support.annotation.IntDef; +import androidx.annotation.IntDef; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -26,8 +26,7 @@ import static com.pranavpandey.android.dynamic.support.picker.color.DynamicColorShape.SQUARE; /** - * Interface to hold the color shape constant values to generate - * color swatches accordingly. + * Interface to hold the color shape constant values to generate color swatches accordingly. */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = { CIRCLE, SQUARE, RECTANGLE }) diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorView.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorView.java index 3bb30d0126..aaca55134a 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorView.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/picker/color/DynamicColorView.java @@ -16,51 +16,52 @@ package com.pranavpandey.android.dynamic.support.picker.color; +import android.annotation.TargetApi; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; -import android.graphics.LinearGradient; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.graphics.RadialGradient; import android.graphics.RectF; import android.graphics.Shader; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.StateListDrawable; -import android.os.Handler; -import android.support.annotation.ColorInt; -import android.support.annotation.ColorRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.content.ContextCompat; +import android.os.Build; import android.util.AttributeSet; import android.view.View; +import android.view.ViewTreeObserver; import android.widget.FrameLayout; import android.widget.Toast; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.ColorRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; import com.pranavpandey.android.dynamic.support.widget.WidgetDefaults; import com.pranavpandey.android.dynamic.toasts.DynamicHint; import com.pranavpandey.android.dynamic.utils.DynamicBitmapUtils; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; import com.pranavpandey.android.dynamic.utils.DynamicUnitUtils; +import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils; /** * A FrameLayout to display a color in different {@link DynamicColorShape}. - * It will provide various useful methods for the {@link DynamicColorPicker} + *

It will provide various useful methods for the {@link DynamicColorPicker} * to represent a set of colors and select a color from it. */ public class DynamicColorView extends FrameLayout { - /** - * Constant for color view corners, 2 dip. - */ - private static final int ADS_SQUARE_CORNERS = DynamicUnitUtils.convertDpToPixels(2); - /** * Constant for color view stroke width, 1 dip. */ @@ -123,6 +124,11 @@ public class DynamicColorView extends FrameLayout { */ private boolean mAlpha; + /** + * Corner radius for the square or rectangle shape. + */ + private int mCornerRadius; + public DynamicColorView(@NonNull Context context) { this(context, null); } @@ -134,7 +140,7 @@ public DynamicColorView(@NonNull Context context, @Nullable AttributeSet attrs) } public DynamicColorView(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -152,18 +158,18 @@ protected void loadFromAttributes(@Nullable AttributeSet attrs) { R.styleable.DynamicColorView); try { - mColorShape = a.getInt(R.styleable.DynamicColorView_ads_dynamicColorView_shape, + mColorShape = a.getInt(R.styleable.DynamicColorView_ads_shape, DynamicColorShape.CIRCLE); - mColor = a.getColor(R.styleable.DynamicColorView_ads_dynamicColorView_color, 0); - mAlpha = a.getBoolean(R.styleable.DynamicColorView_ads_dynamicColorView_alpha, + mColor = a.getColor(R.styleable.DynamicColorView_ads_color, 0); + mAlpha = a.getBoolean(R.styleable.DynamicColorView_ads_alphaEnabled, false); + mCornerRadius = a.getDimensionPixelOffset( + R.styleable.DynamicColorView_ads_cornerRadius, + getResources().getDimensionPixelOffset(R.dimen.ads_corner_radius)); } finally { a.recycle(); } - mSelectorBitmap = DynamicBitmapUtils.getBitmapFormDrawable( - DynamicResourceUtils.getDrawable(getContext(), R.drawable.ads_ic_check)); - mColorPaint = new Paint(); mColorStrokePaint = new Paint(); mSelectorPaint = new Paint(); @@ -179,26 +185,56 @@ protected void loadFromAttributes(@Nullable AttributeSet attrs) { mSelectorPaint.setAntiAlias(true); mSelectorPaint.setFilterBitmap(true); - update(mColor); + onUpdate(mColor); setWillNotDraw(false); + + getViewTreeObserver().addOnGlobalLayoutListener( + new ViewTreeObserver.OnGlobalLayoutListener() { + @TargetApi(Build.VERSION_CODES.JELLY_BEAN) + @Override + public void onGlobalLayout() { + if (DynamicVersionUtils.isJellyBean()) { + getViewTreeObserver().removeOnGlobalLayoutListener(this); + } else { + getViewTreeObserver().removeGlobalOnLayoutListener(this); + } + + setColor(mColor); + } + }); } /** * Update this color view according to the current parameters. */ - private void update(@ColorInt int color) { + private void onUpdate(@ColorInt int color) { this.mColor = color; - if (mColor == DynamicTheme.ADS_THEME_AUTO) { - mColorStrokePaint.setColor(DynamicTheme.getInstance().getTintBackgroundColor()); - mColorPaint.setShader(new LinearGradient(0, 0, - getMeasuredWidth() /2 , getMeasuredHeight() / 2, - mColorStrokePaint.getColor(), - DynamicTheme.getInstance().getBackgroundColor(), Shader.TileMode.MIRROR)); + if (mColor == Theme.AUTO) { + @ColorInt int tintColor = DynamicColorUtils.getTintColor( + DynamicTheme.getInstance().get().getBackgroundColor()); + + mSelectorBitmap = DynamicBitmapUtils.getBitmapFormDrawable( + DynamicResourceUtils.getDrawable(getContext(), R.drawable.ads_ic_play)); + mColorStrokePaint.setColor(tintColor); + mColorPaint.setColor(DynamicTheme.getInstance().get().getBackgroundColor()); + + if (getMeasuredWidth() > 0) { + RadialGradient gradient = + new RadialGradient(getMeasuredWidth() / 2f, getMeasuredWidth() / 2f, + getMeasuredWidth(), new int[] { + DynamicTheme.getInstance().get().getBackgroundColor(), + tintColor, DynamicTheme.getInstance().get().getPrimaryColor() }, + null, Shader.TileMode.CLAMP); + mColorPaint.setShader(gradient); + } } else { - mColorPaint.setShader(null); + mSelectorBitmap = DynamicBitmapUtils.getBitmapFormDrawable( + DynamicResourceUtils.getDrawable(getContext(), R.drawable.ads_ic_check)); mColorPaint.setColor(color); mColorStrokePaint.setColor(DynamicColorUtils.getTintColor(color)); + + mColorPaint.setShader(null); } mSelectorPaint.setColor(mColorStrokePaint.getColor()); @@ -229,8 +265,8 @@ protected void onDraw(Canvas canvas) { canvas.drawOval(mRectF, mColorPaint); canvas.drawOval(mRectF, mColorStrokePaint); } else { - canvas.drawRoundRect(mRectF, ADS_SQUARE_CORNERS, ADS_SQUARE_CORNERS, mColorPaint); - canvas.drawRoundRect(mRectF, ADS_SQUARE_CORNERS, ADS_SQUARE_CORNERS, mColorStrokePaint); + canvas.drawRoundRect(mRectF, mCornerRadius, mCornerRadius, mColorPaint); + canvas.drawRoundRect(mRectF, mCornerRadius, mCornerRadius, mColorStrokePaint); } if (mSelected) { @@ -238,8 +274,9 @@ protected void onDraw(Canvas canvas) { mSelectorBitmap = DynamicBitmapUtils .resizeBitmap(mSelectorBitmap, selectorSize, selectorSize); - canvas.drawBitmap(mSelectorBitmap, (getMeasuredWidth() - mSelectorBitmap.getWidth()) / 2, - (getMeasuredWidth() - mSelectorBitmap.getHeight()) / 2, mSelectorPaint); + canvas.drawBitmap(mSelectorBitmap, + (getMeasuredWidth() - mSelectorBitmap.getWidth()) / 2f, + (getMeasuredWidth() - mSelectorBitmap.getHeight()) / 2f, mSelectorPaint); } if (isClickable()) { @@ -268,9 +305,10 @@ public void setEnabled(boolean enabled) { } /** - * @return A StateListDrawable according to the {@link #mColor} - * to be used as the foreground drawable for this color - * view. + * Returns a state list drawable to use it as the foreground for this color view. + * + * @return A state list drawable according to the color to use as the foreground drawable + * for this color view. */ private StateListDrawable getForegroundDrawable() { Bitmap bitmap = Bitmap.createBitmap( @@ -283,8 +321,7 @@ private StateListDrawable getForegroundDrawable() { if (mColorShape == DynamicColorShape.CIRCLE) { canvas.drawOval(mRectF, mSelectorPaint); } else { - canvas.drawRoundRect(mRectF, ADS_SQUARE_CORNERS, - ADS_SQUARE_CORNERS, mSelectorPaint); + canvas.drawRoundRect(mRectF, mCornerRadius, mCornerRadius, mSelectorPaint); } StateListDrawable stateListDrawable = new StateListDrawable(); @@ -296,15 +333,15 @@ private StateListDrawable getForegroundDrawable() { } /** - * Show a cheat sheet around (below or above) this color view - * with hexadecimal color string according to the {@link #mColor}. + * Show a cheat sheet around (below or above) this color view with hexadecimal color string + * according to the {@link #mColor}. */ public void showHint() { final Toast toast; final @ColorInt int color; final @ColorInt int tintColor; - if (mColor == DynamicTheme.ADS_THEME_AUTO) { + if (mColor == Theme.AUTO) { color = mSelectorPaint.getColor(); tintColor = DynamicColorUtils.getTintColor(color); } else { @@ -313,18 +350,21 @@ public void showHint() { } if (mSelected) { - toast = DynamicHint.make(getContext(), getColorString(), - DynamicResourceUtils.getDrawable(getContext(), R.drawable.ads_ic_check), + toast = DynamicHint.make(DynamicTheme.getInstance().getContext(), getColorString(), + DynamicResourceUtils.getDrawable(getContext(), mColor == Theme.AUTO + ? R.drawable.ads_ic_play : R.drawable.ads_ic_check), tintColor, color); } else { - toast = DynamicHint.make(getContext(), getColorString(), - tintColor, color); + toast = DynamicHint.make(DynamicTheme.getInstance().getContext(), + getColorString(), tintColor, color); } DynamicHint.show(this, toast); } /** + * Get the color used by this color view. + * * @return The color used by this color view. */ public @ColorInt int getColor() { @@ -337,14 +377,9 @@ public void showHint() { * @param color The color to be set. */ public void setColor(final @ColorInt int color) { - new Handler().post(new Runnable() { - @Override - public void run() { - update(color); - requestLayout(); - invalidate(); - } - }); + onUpdate(color); + requestLayout(); + invalidate(); } /** @@ -367,6 +402,8 @@ public void setColorShape(@DynamicColorShape int colorShape) { } /** + * Returns whether this color view is selected. + * * @return {@code true} if this color view is selected. */ public boolean isSelected() { @@ -386,6 +423,8 @@ public void setSelected(boolean selected) { } /** + * Returns whether the alpha is enabled for the color. + * * @return {@code true} to enable alpha for the color. */ public boolean isAlpha() { @@ -405,25 +444,50 @@ public void setAlpha(boolean alpha) { } /** - * @return The hexadecimal color string according to the {@link #mColor}. - * It will return {@link R.string#ads_theme_entry_auto} - * if the color value will be {@link DynamicTheme#ADS_THEME_AUTO}. + * Get the corner radius for the square or rectangle shape. + * + * @return The corner radius for the square or rectangle shape. + */ + public int getCornerRadius() { + return mCornerRadius; + } + + /** + * Set the corner radius for the square or rectangle shape. + * + * @param cornerRadius The corner radius to be set in pixels. + */ + public void setCornerRadius(int cornerRadius) { + this.mCornerRadius = cornerRadius; + + requestLayout(); + invalidate(); + } + + /** + * Returns the hexadecimal color string according to the supplied color. + * + * @return The hexadecimal color string according to the supplied color. + *

It will return {@link R.string#ads_theme_entry_auto} if the color value is + * {@link Theme#AUTO}. */ public String getColorString() { return getColorString(getContext(), mColor, mAlpha); } /** - * @return The hexadecimal color string according to the supplied - * color. It will return {@link R.string#ads_theme_entry_auto} - * if the color value will be {@link DynamicTheme#ADS_THEME_AUTO}. + * Returns the hexadecimal color string according to the supplied color. * * @param context The context to retrieve resources. * @param color The color to be converted into string. * @param alpha {@code true} to enable alpha string. + * + * @return The hexadecimal color string according to the supplied color. + *

It will return {@link R.string#ads_theme_entry_auto} if the color value is + * {@link Theme#AUTO}. */ public static String getColorString(@NonNull Context context, int color, boolean alpha) { - return color == DynamicTheme.ADS_THEME_AUTO + return color == Theme.AUTO ? context.getString(R.string.ads_theme_entry_auto) : DynamicColorUtils.getColorString(color, alpha, true); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/popup/DynamicArrayPopup.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/popup/DynamicArrayPopup.java index 204cce340e..57e4f19e75 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/popup/DynamicArrayPopup.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/popup/DynamicArrayPopup.java @@ -16,8 +16,6 @@ package com.pranavpandey.android.dynamic.support.popup; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -26,15 +24,18 @@ import android.widget.GridView; import android.widget.PopupWindow; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.adapter.DynamicSpinnerChoiceAdapter; import com.pranavpandey.android.dynamic.support.utils.DynamicLayoutUtils; import com.pranavpandey.android.dynamic.support.view.DynamicHeader; /** - * A simple {@link PopupWindow} to display a list of items. It will be used - * internally by the {@link com.pranavpandey.android.dynamic.support.setting.DynamicSpinnerPreference} - * but it can also be used by the other views. + * A simple {@link PopupWindow} to display a list of items. It will be used internally by the + * {@link com.pranavpandey.android.dynamic.support.setting.DynamicSpinnerPreference} but it can + * be used by the other views also. */ public class DynamicArrayPopup extends DynamicPopup { @@ -64,7 +65,7 @@ public class DynamicArrayPopup extends DynamicPopup { private int mSelectedPosition; /** - * On click listener used by the list view. + * Click listener used by the list view. */ private AdapterView.OnItemClickListener mOnItemClickListener; @@ -73,11 +74,10 @@ public class DynamicArrayPopup extends DynamicPopup { * * @param anchor The anchor view used for this popup. * @param entries The list entries for this popup. - * @param onItemClickListener The on click listener - * for the list view. + * @param onItemClickListener The on click listener for the list view. */ public DynamicArrayPopup(@NonNull View anchor, @NonNull CharSequence[] entries, - @NonNull AdapterView.OnItemClickListener onItemClickListener) { + @NonNull AdapterView.OnItemClickListener onItemClickListener) { this.mAnchor = anchor; this.mEntries = entries; this.mOnItemClickListener = onItemClickListener; @@ -100,8 +100,9 @@ public DynamicArrayPopup(@NonNull View anchor, @NonNull CharSequence[] entries, } if (mTitle != null) { - mHeaderView = new DynamicHeader(getAnchor().getContext()) - .setTitle(mTitle).setShowIcon(false); + mHeaderView = new DynamicHeader(getAnchor().getContext()); + ((DynamicHeader) mHeaderView).setTitle(mTitle); + ((DynamicHeader) mHeaderView).setFillSpace(true); } listView.setAdapter(new DynamicSpinnerChoiceAdapter(mEntries, mSelectedPosition, @@ -141,6 +142,8 @@ public void onItemClick(AdapterView parent, View view, } /** + * Get the title used by this popup. + * * @return The title used by this popup. */ public @Nullable CharSequence getTitle() { @@ -157,6 +160,8 @@ public void setTitle(@Nullable CharSequence title) { } /** + * Get the list entries used by this popup. + * * @return The list entries used by this popup. */ public @Nullable CharSequence[] getEntries() { @@ -173,6 +178,8 @@ public void setEntries(@NonNull CharSequence[] entries) { } /** + * Get the selected position. + * * @return The the selected position. */ public int getSelectedPosition() { @@ -189,6 +196,8 @@ public void setSelectedPosition(int selectedPosition) { } /** + * Get the on click listener used by the list view. + * * @return The on click listener used by the list view. */ public @NonNull AdapterView.OnItemClickListener getOnItemClickListener() { diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/popup/DynamicPopup.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/popup/DynamicPopup.java index 33990cf9fd..a177cb707e 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/popup/DynamicPopup.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/popup/DynamicPopup.java @@ -19,14 +19,6 @@ import android.graphics.Color; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; -import android.support.annotation.IntDef; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.view.ViewCompat; -import android.support.v4.widget.NestedScrollView; -import android.support.v4.widget.PopupWindowCompat; -import android.support.v7.widget.CardView; -import android.support.v7.widget.RecyclerView; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; @@ -36,8 +28,16 @@ import android.widget.LinearLayout; import android.widget.PopupWindow; +import androidx.annotation.IntDef; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.cardview.widget.CardView; +import androidx.core.view.ViewCompat; +import androidx.core.widget.NestedScrollView; +import androidx.core.widget.PopupWindowCompat; +import androidx.recyclerview.widget.RecyclerView; + import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; import com.pranavpandey.android.dynamic.utils.DynamicUnitUtils; import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils; import com.pranavpandey.android.dynamic.utils.DynamicViewUtils; @@ -50,9 +50,8 @@ import static com.pranavpandey.android.dynamic.support.popup.DynamicPopup.DynamicPopupType.NONE; /** - * Base {@link PopupWindow} to provide the basic functionality to - * its descendants. Extend this class to create popup windows - * according to the need. + * Base {@link PopupWindow} to provide the basic functionality to its descendants. + *

Extend this class to create popup windows according to the need. */ public abstract class DynamicPopup { @@ -80,8 +79,7 @@ public abstract class DynamicPopup { } /** - * View root to add scroll indicators if the content - * can be scrolled. + * View root to add scroll indicators if the content can be scrolled. */ private View mViewRoot; @@ -101,11 +99,13 @@ public abstract class DynamicPopup { private PopupWindow mPopupWindow; /** + * Get the anchor view to display the popup. + * * @return The anchor view to display the popup. */ public @NonNull View getAnchor() { return mAnchor; - }; + } /** * Set the anchor view to display the popup. @@ -117,6 +117,9 @@ public void setAnchor(@NonNull View anchor) { } /** + * Returns the header view for the popup. + *

Default is {@code null} to hide the header. + * * @return The header view for the popup. */ protected @Nullable View getHeaderView() { @@ -124,11 +127,16 @@ public void setAnchor(@NonNull View anchor) { } /** + * This method will be called to return the content view for the popup. + * * @return The content view for the popup. */ protected abstract @Nullable View getView(); /** + * Returns the footer view for the popup. + *

Default is {@code null} to hide the footer. + * * @return The footer view for the popup. */ protected @Nullable View getFooterView() { @@ -136,6 +144,8 @@ public void setAnchor(@NonNull View anchor) { } /** + * Returns the popup window displayed by this class. + * * @return The popup window displayed by this class. */ public PopupWindow getPopupWindow() { @@ -143,15 +153,16 @@ public PopupWindow getPopupWindow() { } /** - * @return The view root to add scroll indicators if - * the content can be scrolled. + * Returns the root view for the popup. + * + * @return The view root to add scroll indicators if the content can be scrolled. */ public @Nullable View getViewRoot() { return mViewRoot; } /** - * Set the view root for this this popup. + * Set the view root for this the popup. * * @param viewRoot The view root to be set. */ @@ -160,14 +171,16 @@ public void setViewRoot(@NonNull View viewRoot) { } /** - * @return The view type used by this popup. + * Returns the view type for the popup. + * + * @return The view type used by the popup. */ public @DynamicPopupType int getViewType() { return mViewType; } /** - * Set the view type used by this popup. + * Set the view type used by the popup. * * @param viewType The view type to be set. */ @@ -176,17 +189,25 @@ public void setViewType(@DynamicPopupType int viewType) { } /** - * Build this popup and make it ready to show. Please call - * {@link #show()} method to show the popup. + * Build this popup and make it ready to show. Please call {@link #show()} method + * to show the popup. * - * @return The popup after building it according to the - * supplied parameters. + * @return The popup after building it according to the supplied parameters. */ protected abstract @NonNull DynamicPopup build(); /** - * Build and show {@link PopupWindow} according to the supplied - * parameters. + * Returns the maximum width for the popup. + * + * @return The maximum width for the popup. + */ + protected int getMaxWidth() { + return (int) getAnchor().getContext().getResources() + .getDimension(R.dimen.ads_popup_max_width); + } + + /** + * Build and show {@link PopupWindow} according to the supplied parameters. */ public void show() { View view = LayoutInflater.from(getAnchor().getContext()).inflate( @@ -306,9 +327,7 @@ public void run() { content.setVisibility(View.GONE); } - mPopupWindow = new PopupWindow(view, - (int) view.getContext().getResources() - .getDimension(R.dimen.ads_popup_max_width), + mPopupWindow = new PopupWindow(view, getMaxWidth(), LinearLayout.LayoutParams.WRAP_CONTENT, true); PopupWindowCompat.setWindowLayoutType(mPopupWindow, WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL); @@ -317,7 +336,6 @@ public void run() { PopupWindowCompat.setOverlapAnchor(mPopupWindow, true); mPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); - card.setCardBackgroundColor(DynamicTheme.getInstance().getBackgroundColor()); final int[] screenPos = new int[2]; final Rect displayFrame = new Rect(); diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/preference/DynamicPreferences.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/preference/DynamicPreferences.java index b246de1c18..cc0e7f20da 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/preference/DynamicPreferences.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/preference/DynamicPreferences.java @@ -19,13 +19,13 @@ import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; /** - * Helper class to handle shared preferences operations like saving or - * retrieving the values from default shared preferences. It must be - * initialized once before accessing its methods. + * Helper class to handle shared preferences operations like saving or retrieving the values from + * default shared preferences. It must be initialized once before accessing its methods. */ public class DynamicPreferences { @@ -40,8 +40,8 @@ public class DynamicPreferences { protected Context mContext; /** - * Making default constructor private so that it cannot be initialized - * without a context. Use {@link #initializeInstance(Context)} instead. + * Making default constructor private so that it cannot be initialized without a context. + *

Use {@link #initializeInstance(Context)} instead. */ private DynamicPreferences() { } @@ -56,7 +56,7 @@ private DynamicPreferences(@NonNull Context context) { /** * Initialize preferences when application starts. - * Must be initialized once. + *

Must be initialized once. * * @param context The context to retrieve resources. */ @@ -71,8 +71,7 @@ public static synchronized void initializeInstance(@Nullable Context context) { } /** - * Get instance to access public methods. Must be called before - * accessing the methods. + * Get instance to access public methods. Must be called before accessing the methods. * * @return The singleton instance of this class. */ @@ -86,6 +85,8 @@ public static synchronized DynamicPreferences getInstance() { } /** + * Returns the context used by this instance. + * * @return The context to retrieve the resources. */ public Context getContext() { @@ -94,8 +95,7 @@ public Context getContext() { /** * Set a boolean value in the supplied preferences editor and call - * {@link SharedPreferences.Editor#apply()} to apply changes - * back from this editor. + * {@link SharedPreferences.Editor#apply()} to apply changes back from this editor. * * @param preferences The preferences name to store the key. * @param key The preference key to modify. @@ -110,8 +110,7 @@ public void savePrefs(@NonNull String preferences, @NonNull String key, boolean /** * Set a boolean value in the default preferences editor and call - * {@link SharedPreferences.Editor#apply()} to apply changes - * back from this editor. + * {@link SharedPreferences.Editor#apply()} to apply changes back from this editor. * * @param key The preference key to modify. * @param value The value for the preference. @@ -125,8 +124,7 @@ public void savePrefs(@NonNull String key, boolean value) { /** * Set a integer value in the supplied preferences editor and call - * {@link SharedPreferences.Editor#apply()} to apply changes - * back from this editor. + * {@link SharedPreferences.Editor#apply()} to apply changes back from this editor. * * @param preferences The preferences name to store the key. * @param key The preference key to modify. @@ -141,8 +139,7 @@ public void savePrefs(@NonNull String preferences, @NonNull String key, int valu /** * Set an integer value in the default preferences editor and call - * {@link SharedPreferences.Editor#apply()} to apply changes - * back from this editor. + * {@link SharedPreferences.Editor#apply()} to apply changes back from this editor. * * @param key The preference key to modify. * @param value The value for the preference. @@ -156,8 +153,7 @@ public void savePrefs(@NonNull String key, int value) { /** * Set a float value in the supplied preferences editor and call - * {@link SharedPreferences.Editor#apply()} to apply changes - * back from this editor. + * {@link SharedPreferences.Editor#apply()} to apply changes back from this editor. * * @param preferences The preferences name to store the key. * @param key The preference key to modify. @@ -172,8 +168,7 @@ public void savePrefs(@NonNull String preferences, @NonNull String key, float va /** * Set a float value in the default preferences editor and call - * {@link SharedPreferences.Editor#apply()} to apply changes - * back from this editor. + * {@link SharedPreferences.Editor#apply()} to apply changes back from this editor. * * @param key The preference key to modify. * @param value The value for the preference. @@ -187,8 +182,7 @@ public void savePrefs(@NonNull String key, float value) { /** * Set a string value in the supplied preferences editor and call - * {@link SharedPreferences.Editor#apply()} to apply changes - * back from this editor. + * {@link SharedPreferences.Editor#apply()} to apply changes back from this editor. * * @param preferences The preferences name to store the key. * @param key The preference key to modify. @@ -196,16 +190,15 @@ public void savePrefs(@NonNull String key, float value) { * * @see Context#getSharedPreferences(String, int) */ - public void savePrefs(@NonNull String preferences, @NonNull String key, - @Nullable String value) { + public void savePrefs(@NonNull String preferences, + @NonNull String key, @Nullable String value) { mContext.getSharedPreferences(preferences, Context.MODE_PRIVATE) .edit().putString(key, value).apply(); } /** * Set a string value in the default preferences editor and call - * {@link SharedPreferences.Editor#apply()} to apply changes - * back from this editor. + * {@link SharedPreferences.Editor#apply()} to apply changes back from this editor. * * @param key The preference key to modify. * @param value The value for the preference. @@ -224,15 +217,15 @@ public void savePrefs(@NonNull String key, @Nullable String value) { * @param key The preference key to modify. * @param value The value for the preference. * - * @return Returns the preference value if it exists, or defValue. Throws - * ClassCastException if there is a preference with this name that - * is not a boolean. + * @return Returns the preference value if it exists, or the default value. + *

Throws {@link ClassCastException} if there is a preference with this name + * that is not a boolean. * * @see Context#getSharedPreferences(String, int) */ public boolean loadPrefs(@NonNull String preferences, @NonNull String key, boolean value) { - return mContext.getSharedPreferences( - preferences, Context.MODE_PRIVATE).getBoolean(key, value); + return mContext.getSharedPreferences(preferences, + Context.MODE_PRIVATE).getBoolean(key, value); } /** @@ -241,9 +234,9 @@ public boolean loadPrefs(@NonNull String preferences, @NonNull String key, boole * @param key The preference key to modify. * @param value The value for the preference. * - * @return Returns the preference value if it exists, or defValue. Throws - * ClassCastException if there is a preference with this name that - * is not a boolean. + * @return Returns the preference value if it exists, or the default value. + *

Throws {@link ClassCastException} if there is a preference with this name + * that is not a boolean. * * @see PreferenceManager#getDefaultSharedPreferences(Context) */ @@ -252,21 +245,21 @@ public boolean loadPrefs(@NonNull String key, boolean value) { } /** - * Retrieve a integer value from the supplied preferences. + * Retrieve an integer value from the supplied preferences. * * @param preferences The preferences name to find the key. * @param key The preference key to modify. * @param value The value for the preference. * - * @return Returns the preference value if it exists, or defValue. Throws - * ClassCastException if there is a preference with this name that - * is not a boolean. + * @return Returns the preference value if it exists, or the default value. + *

Throws {@link ClassCastException} if there is a preference with this name + * that is not an integer. * * @see Context#getSharedPreferences(String, int) */ public int loadPrefs(@NonNull String preferences, @NonNull String key, int value) { - return mContext.getSharedPreferences( - preferences, Context.MODE_PRIVATE).getInt(key, value); + return mContext.getSharedPreferences(preferences, + Context.MODE_PRIVATE).getInt(key, value); } /** @@ -275,9 +268,9 @@ public int loadPrefs(@NonNull String preferences, @NonNull String key, int value * @param key The preference key to retrieve. * @param value Value to return if this preference does not exist. * - * @return Returns the preference value if it exists, or defValue. Throws - * ClassCastException if there is a preference with this name that - * is not an integer. + * @return Returns the preference value if it exists, or the default value. + *

Throws {@link ClassCastException} if there is a preference with this name + * that is not an integer. * * @see PreferenceManager#getDefaultSharedPreferences(Context) */ @@ -292,15 +285,15 @@ public int loadPrefs(@NonNull String key, int value) { * @param key The preference key to modify. * @param value The value for the preference. * - * @return Returns the preference value if it exists, or defValue. Throws - * ClassCastException if there is a preference with this name that - * is not a boolean. + * @return Returns the preference value if it exists, or the default value. + *

Throws {@link ClassCastException} if there is a preference with this name + * that is not a float. * * @see Context#getSharedPreferences(String, int) */ public float loadPrefs(@NonNull String preferences, @NonNull String key, float value) { - return mContext.getSharedPreferences( - preferences, Context.MODE_PRIVATE).getFloat(key, value); + return mContext.getSharedPreferences(preferences, + Context.MODE_PRIVATE).getFloat(key, value); } /** @@ -309,9 +302,9 @@ public float loadPrefs(@NonNull String preferences, @NonNull String key, float v * @param key The preference key to retrieve. * @param value Value to return if this preference does not exist. * - * @return Returns the preference value if it exists, or defValue. Throws - * ClassCastException if there is a preference with this name that - * is not an integer. + * @return Returns the preference value if it exists, or the default value. + *

Throws {@link ClassCastException} if there is a preference with this name + * that is not a float. * * @see PreferenceManager#getDefaultSharedPreferences(Context) */ @@ -326,16 +319,16 @@ public float loadPrefs(@NonNull String key, float value) { * @param key The preference key to modify. * @param value The value for the preference. * - * @return Returns the preference value if it exists, or defValue. Throws - * ClassCastException if there is a preference with this name that - * is not a boolean. + * @return Returns the preference value if it exists, or the default value. + *

Throws {@link ClassCastException} if there is a preference with this name + * that is not a string. * * @see Context#getSharedPreferences(String, int) */ - public @Nullable String loadPrefs(@NonNull String preferences, @NonNull String key, - @Nullable String value) { - return mContext.getSharedPreferences( - preferences, Context.MODE_PRIVATE).getString(key, value); + public @Nullable String loadPrefs(@NonNull String preferences, + @NonNull String key, @Nullable String value) { + return mContext.getSharedPreferences(preferences, + Context.MODE_PRIVATE).getString(key, value); } /** @@ -344,9 +337,9 @@ public float loadPrefs(@NonNull String key, float value) { * @param key The preference key to retrieve. * @param value Value to return if this preference does not exist. * - * @return Returns the preference value if it exists, or defValue. Throws - * ClassCastException if there is a preference with this name that - * is not a string. + * @return Returns the preference value if it exists, or the default value. + *

Throws {@link ClassCastException} if there is a preference with this name + * that is not a string. * * @see PreferenceManager#getDefaultSharedPreferences(Context) */ @@ -355,8 +348,7 @@ public float loadPrefs(@NonNull String key, float value) { } /** - * Get default shared preferences name to perform other operations - * like backup and restore. + * Get default shared preferences name to perform other operations like backup and restore. * * @return The default shared preferences name. * @@ -375,8 +367,8 @@ public String getDefaultSharedPreferencesName() { * @see Context#getSharedPreferences(String, int) */ public void deletePrefs(@NonNull String preferences, @NonNull String key) { - mContext.getSharedPreferences( - preferences, Context.MODE_PRIVATE).edit().remove(key).apply(); + mContext.getSharedPreferences(preferences, + Context.MODE_PRIVATE).edit().remove(key).apply(); } /** diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/provider/DynamicAppWidgetProvider.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/provider/DynamicAppWidgetProvider.java index 5eff0754a3..b88f25bd37 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/provider/DynamicAppWidgetProvider.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/provider/DynamicAppWidgetProvider.java @@ -22,26 +22,72 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.res.Configuration; +import android.graphics.Bitmap; import android.os.Build; import android.os.Bundle; -import android.support.annotation.NonNull; import android.widget.RemoteViews; +import androidx.annotation.CallSuper; +import androidx.annotation.NonNull; + import com.pranavpandey.android.dynamic.support.utils.DynamicAppWidgetUtils; +import com.pranavpandey.android.dynamic.utils.DynamicBitmapUtils; +import com.pranavpandey.android.dynamic.utils.DynamicDrawableUtils; /** - * A customisable app widget provider to provide basic configuration - * functionality. Extend it and modify according to the need. + * A customisable app widget provider to provide basic configuration functionality. + *

Extend it and modify according to the need. */ +@TargetApi(Build.VERSION_CODES.JELLY_BEAN) public abstract class DynamicAppWidgetProvider extends AppWidgetProvider { + /** + * Constant size in dips for one cell. + */ + public static final int ADS_WIDGET_CELL_SIZE_ONE = 60; + + /** + * Constant size in dips for two cells. + */ + public static final int ADS_WIDGET_CELL_SIZE_TWO = ADS_WIDGET_CELL_SIZE_ONE * 2; + + /** + * Constant size in dips for three cells. + */ + public static final int ADS_WIDGET_CELL_SIZE_THREE = ADS_WIDGET_CELL_SIZE_ONE * 3; + + /** + * Constant size in dips for four cells. + */ + public static final int ADS_WIDGET_CELL_SIZE_FOUR = ADS_WIDGET_CELL_SIZE_ONE * 4; + + /** + * Constant size in dips for five cells. + */ + public static final int ADS_WIDGET_CELL_SIZE_FIVE = ADS_WIDGET_CELL_SIZE_ONE * 5; + + /** + * Constant size in dips for six cells. + */ + public static final int ADS_WIDGET_CELL_SIZE_SIX = ADS_WIDGET_CELL_SIZE_ONE * 6; + + /** + * Current width of this widget provider. + */ + private int mWidth; + + /** + * Current height of this widget provider. + */ + private int mHeight; + @Override public void onReceive(@NonNull Context context, @NonNull Intent intent) { super.onReceive(context, intent); - if (intent.getAction() != null && - (intent.getAction().equals(AppWidgetManager.ACTION_APPWIDGET_UPDATE) - || intent.getAction().equals(AppWidgetManager.ACTION_APPWIDGET_OPTIONS_CHANGED))) { + if (intent.getAction() != null && intent.getAction() + .equals(AppWidgetManager.ACTION_APPWIDGET_UPDATE)) { AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); int[] appWidgetIds = appWidgetManager.getAppWidgetIds( new ComponentName(context, getClass().getName())); @@ -50,81 +96,152 @@ public void onReceive(@NonNull Context context, @NonNull Intent intent) { } @Override - public void onUpdate(@NonNull Context context, @NonNull AppWidgetManager appWidgetManager, - @NonNull int[] appWidgetIds) { - final int N = appWidgetIds.length; - for (int i = 0; i < N; i++) { - updateAppWidget(context, appWidgetManager, appWidgetIds[i]); + public void onUpdate(@NonNull Context context, + @NonNull AppWidgetManager appWidgetManager, @NonNull int[] appWidgetIds) { + super.onUpdate(context, appWidgetManager, appWidgetIds); + + for (int appWidgetId : appWidgetIds) { + onAppWidgetOptionsChanged(context, appWidgetManager, + appWidgetId, appWidgetManager.getAppWidgetOptions(appWidgetId)); } } @Override - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) public void onAppWidgetOptionsChanged(@NonNull Context context, - @NonNull AppWidgetManager appWidgetManager, - int appWidgetId, @NonNull Bundle newOptions) { - Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId); - appWidgetManager.updateAppWidget(appWidgetId, getRemoteViews(context, - options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH), - options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT))); - + @NonNull AppWidgetManager appWidgetManager, int appWidgetId, + @NonNull Bundle newOptions) { super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions); + + appWidgetManager.updateAppWidget(appWidgetId, getRemoteViews(context)); + updateAppWidget(context, appWidgetManager, appWidgetId); } @Override - public void onDeleted(Context context, int[] appWidgetIds) { - final int N = appWidgetIds.length; - for (int i = 0; i < N; i++) { - DynamicAppWidgetUtils.deleteWidgetSettings(getPreferences(), appWidgetIds[i]); + public void onDeleted(@NonNull Context context, @NonNull int[] appWidgetIds) { + super.onDeleted(context, appWidgetIds); + + for (int appWidgetId : appWidgetIds) { + DynamicAppWidgetUtils.deleteWidgetSettings(getPreferences(), appWidgetId); } } @Override public void onDisabled(@NonNull Context context) { + super.onDisabled(context); + DynamicAppWidgetUtils.cleanupPreferences(getPreferences()); } /** - * Override this method to get a {@link RemoteViews} fo this widget - * provider. It can be according to the widget height and width to - * provide dynamic layouts. + * Override this method to get a {@link RemoteViews} fo this widget provider. + *

It can be according to the widget height and width to provide dynamic layouts. * * @param context The context associated with this widget provider. - * @param minWidth The minimum width allowed for this provider. - * @param minHeight The minimum height allowed for this provider. * * @return The remote views for this provider. */ - protected abstract RemoteViews getRemoteViews( - @NonNull Context context, int minWidth, int minHeight); + protected abstract RemoteViews getRemoteViews(@NonNull Context context); /** - * Override this method to provide a shared preferences name for - * this app widget provider. + * Override this method to provide a shared preferences name for this app widget provider. * * @return The shared preferences for this widget provider. */ protected abstract @NonNull String getPreferences(); /** - * Override this method to update a widget instance according to - * the id. It will be useful while implementing a configuration activity - * via {@link com.pranavpandey.android.dynamic.support.activity.DynamicWidgetActivity}. + * Override this method to update a widget instance according to the id. + *

It will be useful while implementing a configuration activity via + * {@link com.pranavpandey.android.dynamic.support.activity.DynamicWidgetActivity}. * * @param context The context associated with this widget provider. * @param appWidgetManager The app widget manager. * @param appWidgetId The app widget id to be updated. */ - public abstract void updateAppWidget(@NonNull Context context, - @NonNull AppWidgetManager appWidgetManager, - int appWidgetId); + @CallSuper + public void updateAppWidget(@NonNull Context context, + @NonNull AppWidgetManager appWidgetManager, int appWidgetId) { + updateWidgetDimensions(context, appWidgetManager, appWidgetId); + } + + /** + * Update widget width and height according to the current orientation. + * + * @param context The context associated with this widget provider. + * @param appWidgetManager The app widget manager. + * @param appWidgetId The app widget id to update the dimensions. + */ + protected void updateWidgetDimensions(@NonNull Context context, + @NonNull AppWidgetManager appWidgetManager, int appWidgetId) { + Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId); + if (context.getResources().getConfiguration().orientation + == Configuration.ORIENTATION_LANDSCAPE) { + mWidth = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH); + mHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT); + } else { + mWidth = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH); + mHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT); + } + } + + /** + * Returns the current width of this widget provider. + * + * @return The current width of this widget provider. + */ + public int getWidth() { + return mWidth; + } + + /** + * Sets the current width of this widget provider. + * + * @param width The width to be set. + */ + public void setWidth(int width) { + this.mWidth = width; + } + + /** + * Returns the current height of this widget provider. + * + * @return The current height of this widget provider. + */ + public int getHeight() { + return mHeight; + } /** + * Sets the current height of this widget provider. + * + * @param height The height to be set. + */ + public void setHeight(int height) { + this.mHeight = height; + } + + /** + * Converts the widget size into cells. + * * @return The number of cells according to the supplied size. * * @param size The size to be converted into cells. */ public static int getCellsForSize(int size) { - return (int) (Math.ceil(size + 30d) / 70d); + return (int) (Math.ceil(size + 30d) / ADS_WIDGET_CELL_SIZE_ONE); + } + + /** + * Get a bitmap for widget background according to the corner radius. + * + * @param width The width in dip for the bitmap. + * @param height The height in dip for the bitmap. + * @param cornerRadius The corner size in dip for the bitmap. + * + * @return The bitmap for widget background according to the supplied parameters. + */ + public static Bitmap getWidgetFrameBitmap(int width, int height, float cornerRadius) { + return DynamicBitmapUtils.getBitmapFormDrawable(DynamicDrawableUtils + .getCornerDrawable(width, height, cornerRadius)); } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/DynamicRecyclerViewFrame.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/DynamicRecyclerViewFrame.java index 2ddb4721d6..52f4e45809 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/DynamicRecyclerViewFrame.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/DynamicRecyclerViewFrame.java @@ -19,82 +19,33 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.content.Context; -import android.support.annotation.IntDef; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.ContentLoadingProgressBar; -import android.support.v4.widget.SwipeRefreshLayout; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.StaggeredGridLayoutManager; import android.util.AttributeSet; import android.view.View; import android.widget.FrameLayout; +import androidx.annotation.AttrRes; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.widget.ContentLoadingProgressBar; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.utils.DynamicLayoutUtils; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - /** - * A RecyclerView inside a FrameLayout with some built-in functionality - * like swipe refresh layout, progress bar, etc. which can be initialized - * quickly. + * A RecyclerView inside a FrameLayout with some built-in functionality like + * swipe refresh layout, progress bar, etc. which can be initialized quickly. */ public abstract class DynamicRecyclerViewFrame extends FrameLayout { /** - * Constant for the type empty view. - */ - public static final int TYPE_EMPTY_VIEW = 0; - - /** - * Constant for the type section header. - */ - public static final int TYPE_SECTION_HEADER = 1; - - /** - * Constant for the type item. - */ - public static final int TYPE_ITEM = 2; - - /** - * Constant for the type section divider. - */ - public static final int TYPE_SECTION_DIVIDER = 3; - - /** - * Valid item types for this adapter. - * - *

0. {@link #TYPE_EMPTY_VIEW} - *
1. {@link #TYPE_SECTION_HEADER} - *
2. {@link #TYPE_ITEM} - *
3. {@link #TYPE_SECTION_DIVIDER}

- */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(value = { TYPE_EMPTY_VIEW, TYPE_SECTION_HEADER, TYPE_ITEM, TYPE_SECTION_DIVIDER }) - public @interface ItemType { } - - /** - * Implement this interface in the object class to get item - * type and section header text. + * State key for the fragment super state. */ - public interface DynamicRecyclerViewItem { - - /** - * @return Item type of this object. - * @see ItemType - */ - @ItemType - int getItemViewType(); - - /** - * @return Section title for the item type {@link #TYPE_SECTION_HEADER}. - */ - String getSectionTitle(); - } + private static final String ADS_RECYCLER_VIEW_SCROLL_OFFSET = "superState"; /** * Animation duration to show or hide the progress. @@ -130,8 +81,7 @@ public interface DynamicRecyclerViewItem { private RecyclerView.LayoutManager mRecyclerViewLayoutManager; /** - * Progress bar which can be shown while the data is loading in - * the background. + * Progress bar which can be shown while the data is loading in the background. * * @see #showProgress() * @see #hideProgress() @@ -149,15 +99,17 @@ public DynamicRecyclerViewFrame(@NonNull Context context, @Nullable AttributeSet } public DynamicRecyclerViewFrame(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); initialize(); } /** - * @return The layout used by this view. Override this to supply a - * different layout. + * This method will be called to get the layout resource for this view. + *

Supply the view layout resource here to do the inflation. + * + * @return The layout used by this view. Override this to supply a different layout. */ protected @LayoutRes int getLayoutRes() { return R.layout.ads_recycler_view; @@ -181,6 +133,9 @@ private void initialize() { } /** + * This method will be called to return the layout manager for the recycler view. + *

Override this method to supply the layout manager during. + * * @return The layout manager for the recycler view. */ public abstract @Nullable RecyclerView.LayoutManager getRecyclerViewLayoutManager(); @@ -211,8 +166,6 @@ public void setRecyclerViewLayoutManager( * Set an adapter for the recycler view. * * @param adapter The recycler view adapter. - * - * @see #mRecyclerView */ public void setAdapter(@NonNull RecyclerView.Adapter adapter) { mRecyclerView.setAdapter(adapter); @@ -221,8 +174,8 @@ public void setAdapter(@NonNull RecyclerView.Adapter adapter) { } /** - * Check for the staggered grid layout manager to avoid the jumping - * of items by scrolling the recycler view to top. + * Checks for the staggered grid layout manager to avoid the jumping of items by + * scrolling the recycler view to top. */ protected void checkForStaggeredGridLayoutManager() { mRecyclerView.post(new Runnable() { @@ -237,25 +190,24 @@ public void run() { } /** - * @return Adapter used by the recycler view. + * Returns the adapter used by the recycler view. * - * @see #mRecyclerView + * @return The adapter used by the recycler view. */ public RecyclerView.Adapter getAdapter() { return mRecyclerView.getAdapter(); } /** - * Override this method to perform other operations on the - * recycler view. + * Override this method to perform other operations on the recycler view. * * @param recyclerView The recycler view inside this view. */ protected void onCreateRecyclerView(@NonNull RecyclerView recyclerView) { } /** - * Override this method to set swipe refresh layout listener - * immediately after initializing the view. + * Override this method to set swipe refresh layout listener immediately after + * initializing the view. * * @return The on refresh listener for the swipe refresh layout. * @@ -266,6 +218,8 @@ protected SwipeRefreshLayout.OnRefreshListener setOnRefreshListener() { } /** + * Get the recycler view used by this view. + * * @return The recycler view to display the data. */ public RecyclerView getRecyclerView() { @@ -273,24 +227,25 @@ public RecyclerView getRecyclerView() { } /** - * @return The swipe refresh layout to provide pull to refresh - * functionality. + * Get the swipe refresh layout used by this view. + * + * @return The swipe refresh layout used by this view. */ public SwipeRefreshLayout getSwipeRefreshLayout() { return mSwipeRefreshLayout; } /** - * @return The swipe refresh layout to provide pull ro refresh - * functionality. + * Get the swipe refresh layout listener used by this view. + * + * @return The swipe refresh layout listener used by this view. */ public SwipeRefreshLayout.OnRefreshListener getOnRefreshListener() { return mOnRefreshListener; } /** - * Set the swipe refresh layout listener to provide pull to - * refresh functionality. + * Set the swipe refresh layout listener to provide pull to efresh functionality. * * @param onRefreshListener The listener to be set. */ @@ -309,8 +264,9 @@ public void setOnRefreshListener( } /** - * @return The progress bar which can be shown while the data - * is loading in the background. + * Get the progress bar which can be shown while the data is loading in the background. + * + * @return The progress bar which can be shown while the data is loading in the background. */ public ContentLoadingProgressBar getProgressBar() { return mProgressBar; @@ -352,4 +308,28 @@ public void onAnimationEnd(Animator animation) { }); } } + + /** + * Returns the root scrollable view for this frame layout. + * + * @return The root scrollable view. + */ + public View getViewRoot() { + return getRecyclerView(); + } + + /** + * Smooth scroll the root view according to the supplied values. + * + * @param x The x position to scroll to. + * @param y The y position to scroll to. + */ + public void smoothScrollTo(final int x, final int y) { + post(new Runnable() { + @Override + public void run() { + getViewRoot().scrollTo(x, y); + } + }); + } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/DynamicRecyclerViewNested.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/DynamicRecyclerViewNested.java index 6e2f9ee4b1..c5c1000479 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/DynamicRecyclerViewNested.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/DynamicRecyclerViewNested.java @@ -17,16 +17,17 @@ package com.pranavpandey.android.dynamic.support.recyclerview; import android.content.Context; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.utils.DynamicLayoutUtils; -import com.pranavpandey.android.dynamic.support.view.DynamicInfoView; /** * A DynamicRecyclerViewFrame to display the nested content. @@ -42,7 +43,7 @@ public DynamicRecyclerViewNested(@NonNull Context context, @Nullable AttributeSe } public DynamicRecyclerViewNested(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/adapter/DynamicBinderAdapter.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/adapter/DynamicBinderAdapter.java index 8200da6f48..3736731b1e 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/adapter/DynamicBinderAdapter.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/adapter/DynamicBinderAdapter.java @@ -16,21 +16,22 @@ package com.pranavpandey.android.dynamic.support.recyclerview.adapter; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.RecyclerView; import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.RecyclerView; + import com.pranavpandey.android.dynamic.support.recyclerview.binder.DynamicRecyclerViewBinder; /** - * Simple recycler view adapter to display different types of items or views - * in a recycler view. Each section can have a header or a completely different - * item. Extend this adapter and use {@link DynamicRecyclerViewBinder} to create - * binding logic for the each type of views. + * Simple recycler view adapter to display different types of items or views in a recycler view. + *

Each section can have a header or a completely different item. + * + *

Extend this adapter and use {@link DynamicRecyclerViewBinder} to create binding logic + * for the each type of views. */ -public abstract class DynamicBinderAdapter - extends RecyclerView.Adapter { +public abstract class DynamicBinderAdapter extends RecyclerView.Adapter { /** * Recycler view displaying this adapter. @@ -38,17 +39,14 @@ public abstract class DynamicBinderAdapter private RecyclerView mRecyclerView; @Override - public RecyclerView.ViewHolder onCreateViewHolder( - @NonNull ViewGroup parent, int viewType) { + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { return getDataBinder(viewType).onCreateViewHolder(parent, viewType); } @Override - public void onBindViewHolder( - @NonNull RecyclerView.ViewHolder viewHolder, int position) { + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) { int binderPosition = getBinderPosition(position); - getDataBinder(viewHolder.getItemViewType()) - .onBindViewHolder(viewHolder, binderPosition); + getDataBinder(viewHolder.getItemViewType()).onBindViewHolder(viewHolder, binderPosition); } @Override @@ -56,11 +54,18 @@ public void onAttachedToRecyclerView(@Nullable RecyclerView recyclerView) { this.mRecyclerView = recyclerView; } + /** + * Checks whether the recycler view associated with this adapter is computing layout. + * + * @return {@code true} if the recycler view is computing layout. + */ public boolean isComputingLayout() { return mRecyclerView != null && mRecyclerView.isComputingLayout(); } /** + * Get the recycler view displaying this adapter. + * * @return The recycler view displaying this adapter. */ public RecyclerView getRecyclerView() { @@ -91,98 +96,87 @@ public RecyclerView getRecyclerView() { * @param binder The data binder inside the recycler view. * @param position The position of the data binder item. * - * @return The position of the data binder item inside the - * recycler view. + * @return The position of the data binder item inside the recycler view. */ - public abstract int getPosition( - @NonNull DynamicRecyclerViewBinder binder, int position); + public abstract int getPosition(@NonNull DynamicRecyclerViewBinder binder, int position); /** * Get the position of a data binder inside the recycler view. * * @param position The position of the data binder. * - * @return The position of the data binder inside the - * recycler view. + * @return The position of the data binder inside the recycler view. */ public abstract int getBinderPosition(int position); /** - * Called when an item has been changed in the data binder. + * This method will be called when an item has been changed in the data binder. * * @param binder The data binder inside the recycler view. - * @param position The position at which the item has - * been changed. + * @param position The position at which the item has been changed. */ - public void notifyBinderItemChanged( - @NonNull DynamicRecyclerViewBinder binder, int position) { + public void notifyBinderItemChanged(@NonNull DynamicRecyclerViewBinder binder, int position) { notifyItemChanged(getPosition(binder, position)); } /** - * Called when an item has been inserted in the data binder. + * This method will be called when an item has been inserted in the data binder. * * @param binder The data binder inside the recycler view. * @param position The position at which the item is inserted. */ - public void notifyBinderItemInserted( - @NonNull DynamicRecyclerViewBinder binder, int position) { + public void notifyBinderItemInserted(@NonNull DynamicRecyclerViewBinder binder, int position) { notifyItemInserted(getPosition(binder, position)); } /** - * Called when an item has been removed in the data binder. + * This method will be called when an item has been removed in the data binder. * * @param binder The data binder inside the recycler view. - * @param position The position at which the item has - * been removed. + * @param position The position at which the item has been removed. */ - public void notifyBinderItemRemoved( - @NonNull DynamicRecyclerViewBinder binder, int position) { + public void notifyBinderItemRemoved(@NonNull DynamicRecyclerViewBinder binder, int position) { notifyItemRemoved(getPosition(binder, position)); } /** - * Called when an item has been moved in the data binder. + * This method will be called when an item has been moved in the data binder. * * @param binder The data binder inside the recycler view. * @param fromPosition Initial position of the moved item. * @param toPosition Final position of the moved item. */ public void notifyBinderItemMoved(@NonNull DynamicRecyclerViewBinder binder, - int fromPosition, int toPosition) { + int fromPosition, int toPosition) { notifyItemMoved(getPosition(binder, fromPosition), getPosition(binder, toPosition)); } /** - * Called when the item range of a data binder has been changed. + * This method will be called when the item range of a data binder has been changed. * * @param binder The data binder inside the recycler view. - * @param position The position at which the first item has - * been changed. + * @param position The position at which the first item has been changed. * @param itemCount Total no. of items has been changed. */ public abstract void notifyBinderItemRangeChanged( @NonNull DynamicRecyclerViewBinder binder, int position, int itemCount); /** - * Called when a set of items has been inserted in a data binder. + * This method will be called when a set of items has been inserted in a data binder. * * @param binder The data binder inside the recycler view. - * @param position The position at which the first item has - * been inserted. + * @param position The position at which the first item has been inserted. * @param itemCount Total no. of items has been inserted. */ public abstract void notifyBinderItemRangeInserted( @NonNull DynamicRecyclerViewBinder binder, int position, int itemCount); /** - * Called when a set of items has been removed in a data binder. + * This method will be called when a set of items has been removed in a data binder. * * @param binder The data binder inside the recycler view. - * @param position The position at which the first item - * has been removed. + * @param position The position at which the first item has been removed. * @param itemCount Total no. of items has been removed. */ public abstract void notifyBinderItemRangeRemoved( diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/adapter/DynamicItemsAdapter.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/adapter/DynamicItemsAdapter.java index 0b6ee7b6eb..3ed30a7e63 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/adapter/DynamicItemsAdapter.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/adapter/DynamicItemsAdapter.java @@ -16,9 +16,9 @@ package com.pranavpandey.android.dynamic.support.recyclerview.adapter; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.RecyclerView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.RecyclerView; import com.pranavpandey.android.dynamic.support.model.DynamicItem; import com.pranavpandey.android.dynamic.support.recyclerview.binder.DynamicItemBinder; @@ -28,17 +28,21 @@ import java.util.List; /** - * A DynamicSimpleBinderAdapter to display the list of {@link DynamicItem} - * inside a recycler view. + * A DynamicSimpleBinderAdapter to display the list of {@link DynamicItem} inside a recycler view. */ public class DynamicItemsAdapter extends DynamicSimpleBinderAdapter { /** - * The data set used by this adapter. A list of - * {@link DynamicItem}. + * The data set used by this adapter. + *

A list of {@link DynamicItem}. */ private List mDataSet; + /** + * Constructor to initialize an object of this class. + * + * @param dataSet The data set used by this adapter. + */ public DynamicItemsAdapter(@NonNull Collection dataSet) { this.mDataSet = new ArrayList<>(dataSet); @@ -52,8 +56,7 @@ public int getItemViewType(int position) { @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) { - ((DynamicItemBinder) getDataBinder( - getItemViewType(position))).setData(getItem(position)); + ((DynamicItemBinder) getDataBinder(getItemViewType(position))).setData(getItem(position)); super.onBindViewHolder(viewHolder, position); } @@ -64,17 +67,21 @@ public int getItemCount() { } /** - * @return The data set used by this adapter. A list of - * {@link DynamicItem}. + * Get the data set used by this adapter. + * + * @return The data set used by this adapter. + *

A list of {@link DynamicItem}. */ public @NonNull List getDataSet() { return mDataSet; } /** - * @return The item according to the supplied position. + * Returns the item according to the supplied position. * * @param position The position to get the item. + * + * @return The item according to the supplied position. */ public @Nullable DynamicItem getItem(int position) { return mDataSet.get(position); diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/adapter/DynamicRecyclerViewAdapter.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/adapter/DynamicRecyclerViewAdapter.java index 5f140062d5..1aac6a995e 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/adapter/DynamicRecyclerViewAdapter.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/adapter/DynamicRecyclerViewAdapter.java @@ -16,16 +16,17 @@ package com.pranavpandey.android.dynamic.support.recyclerview.adapter; -import android.support.annotation.IntDef; -import android.support.v7.widget.RecyclerView; +import androidx.annotation.IntDef; +import androidx.recyclerview.widget.RecyclerView; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** - * Simple recycler view adapter to display items in different - * sections. Each section can have a section header also. Extend this - * adapter and implement {@link DynamicRecyclerViewItem} interface + * Simple recycler view adapter to display items in different sections. + *

Each section can have a section header also. + * + *

Extend this adapter and implement {@link DynamicRecyclerViewItem} interface * in the object class. */ public abstract class DynamicRecyclerViewAdapter @@ -64,20 +65,24 @@ public abstract class DynamicRecyclerViewAdapter public @interface ItemType { } /** - * Implement this interface in the object class to get item - * type and section header text. + * Implement this interface in the object class to get item type and section header text. */ public interface DynamicRecyclerViewItem { /** - * @return Item type of this object. + * This method will be called to return the item type of this object. + * + * @return The item type of this object. * * @see ItemType */ @ItemType int getItemViewType(); /** - * @return Section title for the item type {@link #TYPE_SECTION_HEADER}. + * This method will be called to return the section title for the item type + * {@link #TYPE_SECTION_HEADER}. + * + * @return The section title for the item type {@link #TYPE_SECTION_HEADER}. */ String getSectionTitle(); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/adapter/DynamicSimpleBinderAdapter.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/adapter/DynamicSimpleBinderAdapter.java index d58c382d0a..93a362f05c 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/adapter/DynamicSimpleBinderAdapter.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/adapter/DynamicSimpleBinderAdapter.java @@ -16,7 +16,7 @@ package com.pranavpandey.android.dynamic.support.recyclerview.adapter; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import com.pranavpandey.android.dynamic.support.recyclerview.binder.DynamicRecyclerViewBinder; @@ -96,23 +96,25 @@ public int getBinderPosition(int position) { @Override public void notifyBinderItemRangeChanged(@NonNull DynamicRecyclerViewBinder binder, - int position, int itemCount) { + int position, int itemCount) { notifyItemRangeChanged(getPosition(binder, position), itemCount); } @Override public void notifyBinderItemRangeInserted(@NonNull DynamicRecyclerViewBinder binder, - int position, int itemCount) { + int position, int itemCount) { notifyItemRangeInserted(getPosition(binder, position), itemCount); } @Override public void notifyBinderItemRangeRemoved(@NonNull DynamicRecyclerViewBinder binder, - int position, int itemCount) { + int position, int itemCount) { notifyItemRangeRemoved(getPosition(binder, position), itemCount); } /** + * Get the list of data binders displayed by this adapter. + * * @return The list of data binders displayed by this adapter. */ public List getBinderList() { @@ -131,19 +133,16 @@ public void addDataBinder(@NonNull DynamicRecyclerViewBinder binder) { /** * Add data binders to display in this adapter. * - * @param binders The array of dynamic data binders to be added - * in this adapter. + * @param binders The array of dynamic data binders to be added in this adapter. */ - public void addDataBinders( - @NonNull Collection binders) { + public void addDataBinders(@NonNull Collection binders) { mDataBinders.addAll(binders); } /** * Add data binders to display in this adapter. * - * @param binders The array of dynamic data binders to be added - * in this adapter. + * @param binders The array of dynamic data binders to be added in this adapter. */ public void addDataBinders(@NonNull DynamicRecyclerViewBinder... binders) { mDataBinders.addAll(Arrays.asList(binders)); diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/adapter/DynamicTypeBinderAdapter.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/adapter/DynamicTypeBinderAdapter.java index c5a667d9d6..7508c6aef3 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/adapter/DynamicTypeBinderAdapter.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/adapter/DynamicTypeBinderAdapter.java @@ -1,6 +1,6 @@ package com.pranavpandey.android.dynamic.support.recyclerview.adapter; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import com.pranavpandey.android.dynamic.support.recyclerview.binder.DynamicRecyclerViewBinder; @@ -8,11 +8,10 @@ import java.util.Map; /** - * A recycler view adapter to display different type of - * {@link DynamicRecyclerViewBinder} inside a recycler view. + * A recycler view adapter to display different type of {@link DynamicRecyclerViewBinder} + * inside a recycler view. */ -public abstract class DynamicTypeBinderAdapter> - extends DynamicBinderAdapter { +public abstract class DynamicTypeBinderAdapter> extends DynamicBinderAdapter { /** * Default item type {@code enums} for this adapter. @@ -97,7 +96,7 @@ public int getBinderPosition(int position) { @Override public void notifyBinderItemRangeChanged(@NonNull DynamicRecyclerViewBinder binder, - int positionStart, int itemCount) { + int positionStart, int itemCount) { for (int i = positionStart; i <= itemCount; i++) { notifyItemChanged(getPosition(binder, i)); } @@ -105,7 +104,7 @@ public void notifyBinderItemRangeChanged(@NonNull DynamicRecyclerViewBinder bind @Override public void notifyBinderItemRangeInserted(@NonNull DynamicRecyclerViewBinder binder, - int positionStart, int itemCount) { + int positionStart, int itemCount) { for (int i = positionStart; i <= itemCount; i++) { notifyItemInserted(getPosition(binder, i)); } @@ -113,7 +112,7 @@ public void notifyBinderItemRangeInserted(@NonNull DynamicRecyclerViewBinder bin @Override public void notifyBinderItemRangeRemoved(@NonNull DynamicRecyclerViewBinder binder, - int positionStart, int itemCount) { + int positionStart, int itemCount) { for (int i = positionStart; i <= itemCount; i++) { notifyItemRemoved(getPosition(binder, i)); } @@ -122,8 +121,7 @@ public void notifyBinderItemRangeRemoved(@NonNull DynamicRecyclerViewBinder bind /** * Get the item type enum associated with position the position. * - * @param position The position to get the corresponding - * {@code enum}. + * @param position The position to get the corresponding {@code enum}. * * @return The {@code enum} corresponding to the given position. */ @@ -132,11 +130,9 @@ public void notifyBinderItemRangeRemoved(@NonNull DynamicRecyclerViewBinder bind /** * Get the item type enum according to the ordinal. * - * @param ordinal The ordinal to get the corresponding - * {@code enum}. + * @param ordinal The ordinal to get the corresponding {@code enum}. * - * @return The {@code enum} corresponding to the given - * ordinal. + * @return The {@code enum} corresponding to the given ordinal. */ public abstract E getEnumFromOrdinal(int ordinal); @@ -151,17 +147,20 @@ public E getEnumFromBinder(DynamicRecyclerViewBinder binder) { } /** - * @return The dynamic data binder according to the supplied - * {@code enum}. + * Returns the dynamic data binder according to the supplied {@code enum}. * * @param e The data binder enum. * @param The dynamic recycler view binder. + * + * @return The dynamic data binder according to the supplied {@code enum}. */ public T getDataBinderBinder(E e) { return (T) mDataBinderMap.get(e); } /** + * Get the map to hold the data binders. + * * @return The map to hold the data binders. */ public Map getDataBinderMap() { @@ -173,8 +172,6 @@ public Map getDataBinderMap() { * * @param e The data binder enum. * @param binder The data binder to be added in this adapter. - * - * @see #mDataBinderMap */ public void putDataBinder(E e, DynamicRecyclerViewBinder binder) { mDataBinderMap.put(e, binder); diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/binder/DynamicInfoBigBinder.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/binder/DynamicInfoBigBinder.java index 1cbcab3026..89c000f2ba 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/binder/DynamicInfoBigBinder.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/binder/DynamicInfoBigBinder.java @@ -16,13 +16,14 @@ package com.pranavpandey.android.dynamic.support.recyclerview.binder; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.RecyclerView; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.model.DynamicInfo; import com.pranavpandey.android.dynamic.support.recyclerview.adapter.DynamicBinderAdapter; @@ -30,8 +31,7 @@ import com.pranavpandey.android.dynamic.support.view.DynamicInfoViewBig; /** - * Binder to bind the {@link DynamicInfo} which can be used with the - * {@link DynamicBinderAdapter}. + * Binder to bind the {@link DynamicInfo} which can be used with the {@link DynamicBinderAdapter}. */ public class DynamicInfoBigBinder extends DynamicRecyclerViewBinder { @@ -40,8 +40,8 @@ public class DynamicInfoBigBinder extends DynamicRecyclerViewBinder { */ private DynamicInfo mData; - public DynamicInfoBigBinder(@NonNull DynamicBinderAdapter dynamicBinderAdapter) { - super(dynamicBinderAdapter); + public DynamicInfoBigBinder(@NonNull DynamicBinderAdapter binderAdapter) { + super(binderAdapter); } @Override @@ -68,7 +68,7 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int po viewHolderInfo.getDynamicInfoViewBig().setLinksColorsId(dynamicInfo.getLinksColorsResId()); viewHolderInfo.getDynamicInfoViewBig().setLinksColors(dynamicInfo.getLinksColors()); - viewHolderInfo.getDynamicInfoViewBig().update(); + viewHolderInfo.getDynamicInfoViewBig().onUpdate(); } @Override @@ -77,6 +77,8 @@ public int getItemCount() { } /** + * Get the data used by this binder. + * * @return The data used by this binder. */ public @Nullable DynamicInfo getData() { @@ -99,7 +101,7 @@ public void setData(@Nullable DynamicInfo data) { /** * View holder to hold the dynamic info view layout. */ - protected static class ViewHolder extends RecyclerView.ViewHolder { + public static class ViewHolder extends RecyclerView.ViewHolder { /** * Dynamic info view for this view holder. @@ -118,6 +120,8 @@ public ViewHolder(View view) { } /** + * Get the dynamic info view for this view holder. + * * @return The dynamic info view for this view holder. */ public DynamicInfoView getDynamicInfoViewBig() { diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/binder/DynamicInfoBinder.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/binder/DynamicInfoBinder.java index 2cb4fe68f2..f92cd28b70 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/binder/DynamicInfoBinder.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/binder/DynamicInfoBinder.java @@ -16,21 +16,21 @@ package com.pranavpandey.android.dynamic.support.recyclerview.binder; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.RecyclerView; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.model.DynamicInfo; import com.pranavpandey.android.dynamic.support.recyclerview.adapter.DynamicBinderAdapter; import com.pranavpandey.android.dynamic.support.view.DynamicInfoView; /** - * Binder to bind the {@link DynamicInfo} which can be used with the - * {@link DynamicBinderAdapter}. + * Binder to bind the {@link DynamicInfo} which can be used with the {@link DynamicBinderAdapter}. */ public class DynamicInfoBinder extends DynamicRecyclerViewBinder { @@ -39,8 +39,8 @@ public class DynamicInfoBinder extends DynamicRecyclerViewBinder { */ private DynamicInfo mData; - public DynamicInfoBinder(@NonNull DynamicBinderAdapter dynamicBinderAdapter) { - super(dynamicBinderAdapter); + public DynamicInfoBinder(@NonNull DynamicBinderAdapter binderAdapter) { + super(binderAdapter); } @Override @@ -50,8 +50,7 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int } @Override - public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, - final int position) { + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) { ViewHolder viewHolderInfo = (ViewHolder) viewHolder; DynamicInfo dynamicInfo = getData(); @@ -68,7 +67,7 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, viewHolderInfo.getDynamicInfoView().setLinksColorsId(dynamicInfo.getLinksColorsResId()); viewHolderInfo.getDynamicInfoView().setLinksColors(dynamicInfo.getLinksColors()); - viewHolderInfo.getDynamicInfoView().update(); + viewHolderInfo.getDynamicInfoView().onUpdate(); } @Override @@ -77,6 +76,8 @@ public int getItemCount() { } /** + * Get the data used by this binder. + * * @return The data used by this binder. */ public @Nullable DynamicInfo getData() { @@ -99,7 +100,7 @@ public void setData(@Nullable DynamicInfo data) { /** * View holder to hold the dynamic info view layout. */ - protected static class ViewHolder extends RecyclerView.ViewHolder { + public static class ViewHolder extends RecyclerView.ViewHolder { /** * Dynamic info view for this view holder. @@ -118,6 +119,8 @@ public ViewHolder(View view) { } /** + * Get the dynamic info view for this view holder. + * * @return The dynamic info view for this view holder. */ public DynamicInfoView getDynamicInfoView() { diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/binder/DynamicItemBinder.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/binder/DynamicItemBinder.java index 6f963c68c7..359c4ab19f 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/binder/DynamicItemBinder.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/binder/DynamicItemBinder.java @@ -16,21 +16,21 @@ package com.pranavpandey.android.dynamic.support.recyclerview.binder; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.RecyclerView; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.model.DynamicItem; import com.pranavpandey.android.dynamic.support.recyclerview.adapter.DynamicBinderAdapter; import com.pranavpandey.android.dynamic.support.view.DynamicItemView; /** - * Binder to bind the {@link DynamicItem} which can be used with the - * {@link DynamicBinderAdapter}. + * Binder to bind the {@link DynamicItem} which can be used with the {@link DynamicBinderAdapter}. */ public class DynamicItemBinder extends DynamicRecyclerViewBinder { @@ -39,8 +39,8 @@ public class DynamicItemBinder extends DynamicRecyclerViewBinder { */ private DynamicItem mData; - public DynamicItemBinder(@NonNull DynamicBinderAdapter dynamicBinderAdapter) { - super(dynamicBinderAdapter); + public DynamicItemBinder(@NonNull DynamicBinderAdapter binderAdapter) { + super(binderAdapter); } @Override @@ -68,7 +68,7 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int po viewHolderItem.getDynamicItemView().setClickable(false); } - viewHolderItem.getDynamicItemView().update(); + viewHolderItem.getDynamicItemView().onUpdate(); } @Override @@ -77,6 +77,8 @@ public int getItemCount() { } /** + * Get the data used by this binder. + * * @return The data used by this binder. */ public @Nullable DynamicItem getData() { @@ -99,7 +101,7 @@ public void setData(@Nullable DynamicItem data) { /** * View holder to hold the dynamic item view layout. */ - protected static class ViewHolder extends RecyclerView.ViewHolder { + public static class ViewHolder extends RecyclerView.ViewHolder { /** * Dynamic item view for this view holder. @@ -118,6 +120,8 @@ public ViewHolder(View view) { } /** + * Get the dynamic info view for this view holder. + * * @return The dynamic item view for this view holder. */ public DynamicItemView getDynamicItemView() { diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/binder/DynamicRecyclerViewBinder.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/binder/DynamicRecyclerViewBinder.java index ed2764cbc3..187d445bcc 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/binder/DynamicRecyclerViewBinder.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/recyclerview/binder/DynamicRecyclerViewBinder.java @@ -16,32 +16,31 @@ package com.pranavpandey.android.dynamic.support.recyclerview.binder; -import android.support.annotation.NonNull; -import android.support.v7.widget.RecyclerView; import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + import com.pranavpandey.android.dynamic.support.recyclerview.adapter.DynamicBinderAdapter; /** - * A data binder class to bind data with the view inside the - * {@link DynamicBinderAdapter}. Extend this class to implement - * your own data binding logic. + * A data binder class to bind data with the view inside the {@link DynamicBinderAdapter}. + *

Extend this class to implement your own data binding logic. */ public abstract class DynamicRecyclerViewBinder { /** * The dynamic binder adapter for the recycler view. */ - private DynamicBinderAdapter mDataBindAdapter; + private DynamicBinderAdapter mBinderAdapter; /** * Constructor to initialize an object of this class. * - * @param dataBindAdapter The dynamic binder adapter for - * the recycler view. + * @param binderAdapter The dynamic binder adapter for the recycler view. */ - public DynamicRecyclerViewBinder(@NonNull DynamicBinderAdapter dataBindAdapter) { - mDataBindAdapter = dataBindAdapter; + public DynamicRecyclerViewBinder(@NonNull DynamicBinderAdapter binderAdapter) { + mBinderAdapter = binderAdapter; } /** @@ -60,18 +59,20 @@ public DynamicRecyclerViewBinder(@NonNull DynamicBinderAdapter dataBindAdapter) * @param viewHolder The view holder for the recycler view. * @param position Position to bind the view holder. */ - public abstract void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, - int position); + public abstract void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position); /** - * @return The recycler view adapter associated with this - * data binder. + * Get the recycler view adapter associated with this data binder. + * + * @return The recycler view adapter associated with this data binder. */ public DynamicBinderAdapter getRecyclerViewAdapter() { - return mDataBindAdapter; + return mBinderAdapter; } /** + * Returns the total no. of items in this data binder. + * * @return The total no. of items in this data binder. */ public abstract int getItemCount(); @@ -80,12 +81,11 @@ public DynamicBinderAdapter getRecyclerViewAdapter() { * Notify adapter when the data set has been changed. */ public final void notifyDataSetChanged() { - mDataBindAdapter.notifyDataSetChanged(); + mBinderAdapter.notifyDataSetChanged(); } /** - * Notify adapter when the data set has been changed in this - * data binder. + * Notify adapter when the data set has been changed in this data binder. */ public final void notifyBinderDataSetChanged() { notifyBinderItemRangeChanged(0, getItemCount()); @@ -97,7 +97,7 @@ public final void notifyBinderDataSetChanged() { * @param position Position at which the item has been changed. */ public final void notifyBinderItemChanged(int position) { - mDataBindAdapter.notifyBinderItemChanged(this, position); + mBinderAdapter.notifyBinderItemChanged(this, position); } /** @@ -106,7 +106,7 @@ public final void notifyBinderItemChanged(int position) { * @param position Position at which the item has been inserted. */ public final void notifyBinderItemInserted(int position) { - mDataBindAdapter.notifyBinderItemInserted(this, position); + mBinderAdapter.notifyBinderItemInserted(this, position); } /** @@ -116,7 +116,7 @@ public final void notifyBinderItemInserted(int position) { * @param toPosition Final position of the moved item. */ public final void notifyBinderItemMoved(int fromPosition, int toPosition) { - mDataBindAdapter.notifyBinderItemMoved(this, fromPosition, toPosition); + mBinderAdapter.notifyBinderItemMoved(this, fromPosition, toPosition); } /** @@ -125,18 +125,17 @@ public final void notifyBinderItemMoved(int fromPosition, int toPosition) { * @param position Position at which the item has been removed. */ public final void notifyBinderItemRemoved(int position) { - mDataBindAdapter.notifyBinderItemRemoved(this, position); + mBinderAdapter.notifyBinderItemRemoved(this, position); } /** - * Notify adapter when the item range of this data binder has been - * changed. + * Notify adapter when the item range of this data binder has been changed. * * @param position Position at which the first item has been changed. * @param itemCount Total no. of items has been changed. */ public final void notifyBinderItemRangeChanged(int position, int itemCount) { - mDataBindAdapter.notifyBinderItemRangeChanged(this, position, itemCount); + mBinderAdapter.notifyBinderItemRangeChanged(this, position, itemCount); } /** @@ -147,17 +146,16 @@ public final void notifyBinderItemRangeChanged(int position, int itemCount) { * @param itemCount Total no. of items has been inserted. */ public final void notifyBinderItemRangeInserted(int position, int itemCount) { - mDataBindAdapter.notifyBinderItemRangeInserted(this, position, itemCount); + mBinderAdapter.notifyBinderItemRangeInserted(this, position, itemCount); } /** - * Notify adapter when a set of items has been removed in this - * data binder. + * Notify adapter when a set of items has been removed in this data binder. * * @param position Position at which the first item has been removed. * @param itemCount Total no. of items has been removed. */ public final void notifyBinderItemRangeRemoved(int position, int itemCount) { - mDataBindAdapter.notifyBinderItemRangeRemoved(this, position, itemCount); + mBinderAdapter.notifyBinderItemRangeRemoved(this, position, itemCount); } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicCheckPreference.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicCheckPreference.java index 172524697c..34992c1808 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicCheckPreference.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicCheckPreference.java @@ -19,27 +19,24 @@ import android.content.Context; import android.content.SharedPreferences; import android.content.res.TypedArray; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.SwitchCompat; import android.util.AttributeSet; +import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; import android.widget.CompoundButton; -import android.widget.ImageView; -import android.widget.TextView; + +import androidx.annotation.AttrRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.SwitchCompat; import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.preference.DynamicPreferences; /** - * A DynamicPreference to provide the functionality of a - * {@link android.preference.SwitchPreference} with an action - * button. + * A DynamicSimplePreference to provide the functionality of a + * {@link android.preference.SwitchPreference}. */ -public class DynamicCheckPreference extends DynamicPreference { +public class DynamicCheckPreference extends DynamicSimplePreference { /** * Default value for the checked state. @@ -57,47 +54,15 @@ public class DynamicCheckPreference extends DynamicPreference { private CharSequence mSummaryUnchecked; /** - * Checked change listener to get the callback if switch - * state is changed. + * Checked change listener to get the callback if switch state is changed. */ private CompoundButton.OnCheckedChangeListener mOnCheckedChangeListener; - /** - * The preference root view. - */ - private ViewGroup mPreferenceView; - - /** - * Image view to show the icon. - */ - private ImageView mIconView; - - /** - * Text view to show the title. - */ - private TextView mTitleView; - - /** - * Text view to show the summary. - */ - private TextView mSummaryView; - - /** - * Text view to show the description. - */ - private TextView mDescriptionView; - /** * Switch compat to show the checked state. */ private SwitchCompat mSwitchCompat; - /** - * Button to provide a secondary action like permission - * request, etc. - */ - private Button mActionView; - public DynamicCheckPreference(@NonNull Context context) { super(context); } @@ -107,7 +72,7 @@ public DynamicCheckPreference(@NonNull Context context, @Nullable AttributeSet a } public DynamicCheckPreference(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); } @@ -116,42 +81,32 @@ protected void onLoadAttributes(AttributeSet attrs) { TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.DynamicPreference); try { - mChecked = a.getBoolean(R.styleable.DynamicPreference_ads_dynamicPreference_checked, + mChecked = a.getBoolean(R.styleable.DynamicPreference_ads_checked, DEFAULT_CHECK_STATE); mSummaryUnchecked = a.getString( - R.styleable.DynamicPreference_ads_dynamicPreference_unchecked); + R.styleable.DynamicPreference_ads_unchecked); } finally { a.recycle(); } } - @Override - protected @LayoutRes int getLayoutRes() { - return R.layout.ads_preference_check; - } - @Override protected void onInflate() { - inflate(getContext(), getLayoutRes(), this); + super.onInflate(); + + mSwitchCompat = LayoutInflater.from(getContext()).inflate( + R.layout.ads_preference_check, this, false) + .findViewById(R.id.ads_preference_check_switch); - mPreferenceView = findViewById(R.id.ads_preference_checked); - mIconView = findViewById(R.id.ads_preference_checked_icon); - mTitleView = findViewById(R.id.ads_preference_checked_title); - mSummaryView = findViewById(R.id.ads_preference_checked_summary); - mDescriptionView = findViewById(R.id.ads_preference_checked_description); - mSwitchCompat = findViewById(R.id.ads_preference_checked_switch); - mActionView = findViewById(R.id.ads_preference_action_button); + setViewFrame(mSwitchCompat, true); - mPreferenceView.setOnClickListener(new OnClickListener() { + setOnPreferenceClickListener(new OnClickListener() { @Override public void onClick(View v) { setChecked(!mChecked); - - if (getOnPreferenceClickListener() != null) { - getOnPreferenceClickListener().onClick(v); - } } - }); + }, false); + mChecked = DynamicPreferences.getInstance() .loadPrefs(getPreferenceKey(), mChecked); @@ -159,66 +114,34 @@ public void onClick(View v) { @Override protected void onUpdate() { - mIconView.setImageDrawable(getIcon()); - - if (getTitle() != null) { - mTitleView.setText(getTitle()); - mTitleView.setVisibility(VISIBLE); - } else { - mTitleView.setVisibility(GONE); - } - - if (getSummary() != null) { - mSummaryView.setText(getSummary()); - mSummaryView.setVisibility(VISIBLE); - } else { - mSummaryView.setVisibility(GONE); - } - - if (getDescription() != null) { - mDescriptionView.setText(getDescription()); - mDescriptionView.setVisibility(VISIBLE); - } else { - mDescriptionView.setVisibility(GONE); - } + super.onUpdate(); - if (getOnActionClickListener() != null) { - mActionView.setText(getActionString()); - mActionView.setOnClickListener(getOnActionClickListener()); - mActionView.setVisibility(VISIBLE); - } else { - mActionView.setVisibility(GONE); - } - - mSwitchCompat.post(new Runnable() { - @Override - public void run() { - mSwitchCompat.setChecked(mChecked); + if (mSwitchCompat != null) { + if (!mChecked) { + if (mSummaryUnchecked != null) { + setTextView(getSummaryView(), mSummaryUnchecked); + } } - }); - if (!mChecked) { - if (mSummaryUnchecked != null) { - mSummaryView.setText(mSummaryUnchecked); - mSummaryView.setVisibility(VISIBLE); - } + mSwitchCompat.post(new Runnable() { + @Override + public void run() { + mSwitchCompat.setChecked(mChecked); + } + }); } } @Override protected void onEnabled(boolean enabled) { - mPreferenceView.setEnabled(enabled); - mIconView.setEnabled(enabled); - mTitleView.setEnabled(enabled); - mSummaryView.setEnabled(enabled); - mDescriptionView.setEnabled(enabled); - mSwitchCompat.setEnabled(enabled); - mActionView.setEnabled(enabled); + super.onEnabled(enabled); - onUpdate(); + setViewEnabled(mSwitchCompat, enabled); } /** + * Returns whether this preference is checked. + * * @return {@code true} if this preference is checked. */ public boolean isChecked() { @@ -226,11 +149,9 @@ public boolean isChecked() { } /** - * Set the state of the switch to be checked or - * unchecked. + * Set the state of the switch to be checked or unchecked. * - * @param checked {@code true} if this preference - * is checked. + * @param checked {@code true} if this preference is checked. */ public void setChecked(boolean checked) { this.mChecked = checked; @@ -241,6 +162,8 @@ public void setChecked(boolean checked) { } /** + * Get the optional summary for the unchecked state. + * * @return The optional summary for the unchecked state. */ public @Nullable CharSequence getSummaryUnchecked() { @@ -259,16 +182,16 @@ public void setSummaryUnchecked(@Nullable String summaryUnchecked) { } /** - * @return The checked change listener to get the callback if - * switch state is changed. + * Returns the checked change listener. + * + * @return The checked change listener to get the callback if switch state is changed. */ public @Nullable CompoundButton.OnCheckedChangeListener getOnCheckedChangeListener() { return mOnCheckedChangeListener; } /** - * Set the checked change listener to get the callback if - * switch state is changed. + * Set the checked change listener to get the callback if switch state is changed. * * @param onCheckedChangeListener The listener to be set. */ @@ -277,25 +200,15 @@ public void setOnCheckedChangeListener( this.mOnCheckedChangeListener = onCheckedChangeListener; } - /** - * @return The button to provide a secondary action like - * permission request, etc. - */ - public Button getActionView() { - return mActionView; - } - @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { super.onSharedPreferenceChanged(sharedPreferences, key); if (key.equals(getPreferenceKey())) { - boolean checked = DynamicPreferences.getInstance() - .loadPrefs(key, mChecked); - mChecked = checked; + mChecked = DynamicPreferences.getInstance().loadPrefs(key, mChecked); if (mOnCheckedChangeListener != null) { - mOnCheckedChangeListener.onCheckedChanged(mSwitchCompat, checked); + mOnCheckedChangeListener.onCheckedChanged(mSwitchCompat, mChecked); } onUpdate(); diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicColorPreference.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicColorPreference.java index 61643132fa..a0cdc5962c 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicColorPreference.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicColorPreference.java @@ -17,19 +17,23 @@ package com.pranavpandey.android.dynamic.support.setting; import android.content.Context; +import android.content.SharedPreferences; import android.content.res.TypedArray; -import android.support.annotation.ArrayRes; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.FragmentActivity; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; +import androidx.annotation.ArrayRes; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.FragmentActivity; + import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.adapter.DynamicColorsAdapter; import com.pranavpandey.android.dynamic.support.dialog.DynamicDialog; +import com.pranavpandey.android.dynamic.support.listener.DynamicColorListener; +import com.pranavpandey.android.dynamic.support.listener.DynamicColorResolver; import com.pranavpandey.android.dynamic.support.picker.color.DynamicColorDialog; import com.pranavpandey.android.dynamic.support.picker.color.DynamicColorPopup; import com.pranavpandey.android.dynamic.support.picker.color.DynamicColorShape; @@ -37,16 +41,16 @@ import com.pranavpandey.android.dynamic.support.preference.DynamicPreferences; import com.pranavpandey.android.dynamic.support.theme.DynamicColorPalette; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; import com.pranavpandey.android.dynamic.support.widget.DynamicTextView; +import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; /** - * A DynamicPreference to implement the functionality of a - * color picker by using the {@link DynamicColorPopup} and - * {@link DynamicColorDialog}. + * A DynamicSimplePreference to implement the functionality of a color picker by using the + * {@link DynamicColorPopup} and {@link DynamicColorDialog}. */ -public class DynamicColorPreference extends DynamicSimplePreference - implements DynamicColorsAdapter.OnColorSelectedListener { +public class DynamicColorPreference extends DynamicSimplePreference { /** * Resource id of the primary colors array. @@ -91,14 +95,22 @@ public class DynamicColorPreference extends DynamicSimplePreference private @ColorInt int mColor; /** - * {@code true} to enable alpha component for the - * custom color. + * Default alternate color for this preference. + */ + private @ColorInt int mAltDefaultColor; + + /** + * Current alternate color value of this preference. + */ + private @ColorInt int mAltColor; + + /** + * {@code true} to enable alpha component for the custom color. */ private boolean mAlpha; /** - * {@code true} to show color popup before requesting - * for the dialog. + * {@code true} to show color popup before requesting for the dialog. * * @see DynamicColorPopup * @see DynamicColorDialog @@ -107,11 +119,30 @@ public class DynamicColorPreference extends DynamicSimplePreference private boolean mShowColorPopup; /** - * Color view used by this preference to display the - * selected color. + * Color view used by this preference to display the selected color. */ private DynamicColorView mColorView; + /** + * Dynamic color listener to listen color events. + */ + private DynamicColorListener mDynamicColorListener; + + /** + * Dynamic color listener to listen alternate color events. + */ + private DynamicColorListener mAltDynamicColorListener; + + /** + * Dynamic color resolver to resolve various colors at runtime. + */ + private DynamicColorResolver mDynamicColorResolver; + + /** + * Dynamic color resolver to resolve various alternate colors at runtime. + */ + private DynamicColorResolver mAltDynamicColorResolver; + public DynamicColorPreference(@NonNull Context context) { super(context); } @@ -121,7 +152,7 @@ public DynamicColorPreference(@NonNull Context context, @Nullable AttributeSet a } public DynamicColorPreference(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); } @@ -138,22 +169,25 @@ protected void onLoadAttributes(AttributeSet attrs) { try { mDefaultColor = a.getColor( - R.styleable.DynamicPreference_ads_dynamicPreference_color, - DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE); + R.styleable.DynamicPreference_ads_color, + Theme.AUTO); + mAltDefaultColor = a.getColor( + R.styleable.DynamicPreference_ads_altColor, + Theme.AUTO); mShowColorPopup = a.getBoolean( - R.styleable.DynamicPreference_ads_dynamicPreference_popup, + R.styleable.DynamicPreference_ads_popup, false); mColorShape = b.getInt( - R.styleable.DynamicColorView_ads_dynamicColorView_shape, + R.styleable.DynamicColorView_ads_shape, DynamicColorShape.CIRCLE); mAlpha = c.getBoolean( - R.styleable.DynamicColorPicker_ads_dynamicColorPicker_alpha, + R.styleable.DynamicColorPicker_ads_alphaEnabled, false); mColorsResId = c.getResourceId( - R.styleable.DynamicColorPicker_ads_dynamicColorPicker_colors, + R.styleable.DynamicColorPicker_ads_colors, DynamicResourceUtils.ADS_DEFAULT_RESOURCE_ID); mPopupColorsResId = c.getResourceId( - R.styleable.DynamicColorPicker_ads_dynamicColorPicker_popupColors, + R.styleable.DynamicColorPicker_ads_popupColors, DynamicResourceUtils.ADS_DEFAULT_RESOURCE_ID); } finally { a.recycle(); @@ -163,7 +197,12 @@ protected void onLoadAttributes(AttributeSet attrs) { if (getPreferenceKey() != null) { mColor = DynamicPreferences.getInstance().loadPrefs( - getPreferenceKey(), mDefaultColor); + getPreferenceKey(), getDefaultColor()); + } + + if (getAltPreferenceKey() != null) { + mAltColor = DynamicPreferences.getInstance().loadPrefs( + getAltPreferenceKey(), mAltDefaultColor); } } @@ -171,65 +210,138 @@ protected void onLoadAttributes(AttributeSet attrs) { protected void onInflate() { super.onInflate(); + final DynamicColorListener dynamicColorListener = new DynamicColorListener() { + @Override + public void onColorSelected(@Nullable String tag, int position, int color) { + setColor(color); + + if (mDynamicColorListener != null) { + mDynamicColorListener.onColorSelected(tag, position, color); + } + } + }; + + final DynamicColorListener altDynamicColorListener = new DynamicColorListener() { + @Override + public void onColorSelected(@Nullable String tag, int position, int color) { + setAltColor(color); + + if (mAltDynamicColorListener != null) { + mAltDynamicColorListener.onColorSelected(tag, position, color); + } + } + }; + mColorView = LayoutInflater.from(getContext()).inflate( R.layout.ads_preference_color, this, false) .findViewById(R.id.ads_preference_color_view); setViewFrame(mColorView, true); - getPreferenceView().setOnClickListener(new OnClickListener() { + setOnPreferenceClickListener(new OnClickListener() { @Override public void onClick(View view) { if (getOnPromptListener() != null) { if (mShowColorPopup) { if (getOnPromptListener().onPopup()) { - showColorPopup(view); + showColorPopup(view, String.valueOf(getTitle()), getDefaultColor(), + getColor(false), getColor(), dynamicColorListener); } } else { if (getOnPromptListener().onDialog()) { - showColorDialog(); + showColorDialog(String.valueOf(getTitle()), + getColor(), dynamicColorListener); } } } else { if (mShowColorPopup) { - showColorPopup(view); + showColorPopup(view, String.valueOf(getTitle()), getDefaultColor(), + getColor(false), getColor(), dynamicColorListener); } else { - showColorDialog(); + showColorDialog(String.valueOf(getTitle()), + getColor(), dynamicColorListener); } } } }); + if (getAltPreferenceKey() != null) { + getActionView().setBackgroundAware(Theme.BackgroundAware.DISABLE); + + setActionButton(getActionString(), new OnClickListener() { + @Override + public void onClick(View v) { + if (getOnPromptListener() != null) { + if (mShowColorPopup) { + if (getOnPromptListener().onPopup()) { + showColorPopup(v, getAltTitle(), getAltDefaultColor(), + getAltColor(false), getAltColor(), altDynamicColorListener); + } + } else { + if (getOnPromptListener().onDialog()) { + showColorDialog(getAltTitle(), getAltColor(), + altDynamicColorListener); + } + } + } else { + if (mShowColorPopup) { + showColorPopup(v, getAltTitle(), getAltDefaultColor(), + getAltColor(false), getAltColor(), altDynamicColorListener); + } else { + showColorDialog(getAltTitle(), getAltColor(), altDynamicColorListener); + } + } + } + }); + } + setColorShape(mColorShape); setAlpha(mAlpha, false); setColor(mColor, false); + setAltColor(mAltColor, false); + } + + @Override + protected void onUpdate() { + super.onUpdate(); + + mColorView.setColor(getColor()); + getActionView().setColor(DynamicColorUtils.removeAlpha(getAltColor())); + ((DynamicTextView) getValueView()).setColor(getColor()); } /** * Show color popup to select a color. * * @param view The anchor view for the popup. + * @param title the title for the popup. + * @param defaultColor The default color for the popup. + * @param color The color value for the popup. + * @param dynamicColorListener The listener to listen color events. * * @see DynamicColorPopup */ - private void showColorPopup(@NonNull final View view) { + private void showColorPopup(@NonNull final View view, + @Nullable final String title, @ColorInt int defaultColor, + final @ColorInt int color, final @ColorInt int resolvedColor, + @NonNull final DynamicColorListener dynamicColorListener) { DynamicColorPopup dynamicColorPopup = new DynamicColorPopup( - view, getPopupColors(), this); + view, getPopupColors(), dynamicColorListener); dynamicColorPopup.setColorShape(mColorShape); dynamicColorPopup.setAlpha(mAlpha); - dynamicColorPopup.setTitle(getTitle()); - dynamicColorPopup.setDefaultColor(mDefaultColor); - dynamicColorPopup.setPreviousColor(mColor); - dynamicColorPopup.setSelectedColor(mColor); + dynamicColorPopup.setTitle(title); + dynamicColorPopup.setDefaultColor(defaultColor); + dynamicColorPopup.setPreviousColor(color); + dynamicColorPopup.setSelectedColor(color); dynamicColorPopup.setOnMoreColorsListener(new OnClickListener() { @Override public void onClick(View v) { if (getOnPromptListener() != null) { if (getOnPromptListener().onDialog()) { - showColorDialog(); + showColorDialog(title, resolvedColor, dynamicColorListener); } } else { - showColorDialog(); + showColorDialog(title, resolvedColor, dynamicColorListener); } } }); @@ -240,30 +352,30 @@ public void onClick(View v) { /** * Show color dialog to select or create a color. * + * @param title the title for the dialog. + * @param color The color value for the dialog. + * @param dynamicColorListener The listener to listen color events. + * * @see DynamicColorDialog */ - private void showColorDialog() { - @ColorInt int color = mColor == DynamicTheme.ADS_THEME_AUTO - ? DynamicTheme.getInstance().getBackgroundColor() : mColor; + private void showColorDialog(@Nullable String title, @ColorInt int color, + @NonNull DynamicColorListener dynamicColorListener) { + color = color == Theme.AUTO + ? DynamicTheme.getInstance().get().getBackgroundColor() : color; DynamicColorDialog.newInstance().setColors(getColors(), getShades()) .setColorShape(mColorShape) .setAlpha(mAlpha) .setPreviousColor(color) .setSelectedColor(color) - .setOnColorSelectedListener(this) - .setBuilder(new DynamicDialog.Builder(getContext()).setTitle(getTitle())) + .setDynamicColorListener(dynamicColorListener) + .setBuilder(new DynamicDialog.Builder(getContext()).setTitle(title)) .showDialog((FragmentActivity) getContext()); } - @Override - protected void onUpdate() { - super.onUpdate(); - - ((DynamicTextView) getValueView()).setColor(mColor); - } - /** + * Returns the color entries used by this preference. + * * @return The color entries used by this preference. */ public @NonNull @ColorInt Integer[] getColors() { @@ -290,6 +402,8 @@ public void setColors(@Nullable @ColorInt Integer[] colors) { } /** + * Returns the popup color entries used by this preference. + * * @return The popup color entries used by this preference. */ public @NonNull @ColorInt Integer[] getPopupColors() { @@ -316,6 +430,8 @@ public void setPopupColors(@Nullable @ColorInt Integer[] popupColors) { } /** + * Returns the shade color entries used by this preference. + * * @return The shade color entries used by this preference. */ public @Nullable @ColorInt Integer[][] getShades() { @@ -336,6 +452,8 @@ public void setShades(@Nullable @ColorInt Integer[][] shades) { } /** + * Get the shape for the color view. + * * @return The shape for the color view. */ public int getColorShape() { @@ -354,12 +472,29 @@ public void setColorShape(int colorShape) { } /** + * Returns the default color for this preference. + * + * @param resolve {@code true} to resolve the auto color. + * * @return The default color for this preference. */ - public @ColorInt int getDefaultColor() { + public @ColorInt int getDefaultColor(boolean resolve) { + if (resolve && mDynamicColorResolver != null) { + return mDynamicColorResolver.getDefaultColor(getPreferenceKey()); + } + return mDefaultColor; } + /** + * Returns the default color for this preference. + * + * @return The default color for this preference. + */ + public @ColorInt int getDefaultColor() { + return getDefaultColor(true); + } + /** * Set the default color for this preference. * @@ -372,25 +507,40 @@ public void setDefaultColor(@ColorInt int defaultColor) { } /** + * Returns the current color value of this preference. + * + * @param resolve {@code true} to resolve the auto color. + * + * @return The current color value of this preference. + */ + public @ColorInt int getColor(boolean resolve) { + if (resolve && mColor == Theme.AUTO + && mDynamicColorResolver != null) { + return mDynamicColorResolver.getAutoColor(getPreferenceKey()); + } + + return mColor; + } + + /** + * Returns the current color value of this preference. + * * @return The current color value of this preference. */ public @ColorInt int getColor() { - return mColor; + return getColor(true); } /** * Set the current color value of this preference. * * @param color The color value to be set. - * @param save {@code true} to update the shared - * preferences. + * @param save {@code true} to update the shared preferences. */ public void setColor(@ColorInt int color, boolean save) { this.mColor = color; - mColorView.setColor(mColor); - setValueString(DynamicColorView.getColorString( - getContext(), color, mColorView.isAlpha())); + setValueString(getColorString()); if (getPreferenceKey() != null && save) { DynamicPreferences.getInstance().savePrefs(getPreferenceKey(), mColor); @@ -407,8 +557,94 @@ public void setColor(@ColorInt int color) { } /** - * @return {@code true} to enable alpha component for the - * custom color. + * Returns the alternate default color for this preference. + * + * @param resolve {@code true} to resolve the auto color. + * + * @return The alternate default color for this preference. + */ + public @ColorInt int getAltDefaultColor(boolean resolve) { + if (resolve && mAltDynamicColorResolver != null) { + return mAltDynamicColorResolver.getDefaultColor(getAltPreferenceKey()); + } + + return mAltDefaultColor; + } + + /** + * Returns the alternate default color for this preference. + * + * @return The alternate default color for this preference. + */ + public @ColorInt int getAltDefaultColor() { + return getAltDefaultColor(true); + } + + /** + * Set the alternate default color for this preference. + * + * @param altDefaultColor The alternate default color to be set. + */ + public void setAltDefaultColor(@ColorInt int altDefaultColor) { + this.mAltDefaultColor = altDefaultColor; + + onUpdate(); + } + + /** + * Returns the current alternate color value of this preference. + * + * @param resolve {@code true} to resolve the auto color. + * + * @return The current alternate color value of this preference. + */ + public @ColorInt int getAltColor(boolean resolve) { + if (resolve && mAltColor == Theme.AUTO + && mAltDynamicColorResolver != null) { + return mAltDynamicColorResolver.getAutoColor(getAltPreferenceKey()); + } + + return mAltColor; + } + + /** + * Returns the current alternate color value of this preference. + * + * @return The current alternate color value of this preference. + */ + public @ColorInt int getAltColor() { + return getAltColor(true); + } + + /** + * Set the current alternate color value of this preference. + * + * @param altColor The color value to be set. + * @param save {@code true} to update the shared preferences. + */ + public void setAltColor(@ColorInt int altColor, boolean save) { + this.mAltColor = altColor; + + setValueString(getColorString()); + + if (getAltPreferenceKey() != null && save) { + DynamicPreferences.getInstance().savePrefs(getAltPreferenceKey(), mAltColor); + } + } + + /** + * Set the current alternate color value of this preference. + * + * @param altColor The alternate color value to be set. + */ + public void setAltColor(@ColorInt int altColor) { + setAltColor(altColor, true); + } + + /** + * Returns whether the alpha component is enabled for custom color. + * + * @return {@code true} to enable alpha component for the custom color. */ public boolean isAlpha() { return mAlpha; @@ -427,21 +663,22 @@ public void setAlpha(boolean alpha) { * Set the alpha support for the custom color. * * @param alpha {@code true} to enable alpha. - * @param save {@code true} to update the shared - * preferences. + * @param save {@code true} to update the shared preferences. */ private void setAlpha(boolean alpha, boolean save) { this.mAlpha = alpha; mColorView.setAlpha(alpha); + if (save) { setColor(mColorView.getColor()); } } /** - * @return {@code true} to show color popup before requesting - * for the dialog. + * Returns whether to show color popup before requesting for the dialog. + * + * @return {@code true} to show color popup before requesting for the dialog. */ public boolean isShowColorPopup() { return mShowColorPopup; @@ -450,15 +687,128 @@ public boolean isShowColorPopup() { /** * Set the popup to be enabled or disabled. * - * @param showColorPopup {@code true} to show color popup - * before requesting for the dialog. + * @param showColorPopup {@code true} to show color popup before requesting for the dialog. */ public void setShowColorPopup(boolean showColorPopup) { this.mShowColorPopup = showColorPopup; } + /** + * Returns the dynamic color listener to listen color events. + * + * @return The dynamic color listener to listen color events. + */ + public @Nullable DynamicColorListener getDynamicColorListener() { + return mDynamicColorListener; + } + + /** + * Set the dynamic color listener to listen color events. + * + * @param dynamicColorListener The listener to be set. + */ + public void setDynamicColorListener(@Nullable DynamicColorListener dynamicColorListener) { + this.mDynamicColorListener = dynamicColorListener; + } + + /** + * Returns the dynamic color listener to listen alternate color events. + * + * @return The dynamic color listener to listen alternate color events. + */ + public @Nullable DynamicColorListener getAltDynamicColorListener() { + return mAltDynamicColorListener; + } + + /** + * Set the dynamic color listener to listen alternate color events. + * + * @param altDynamicColorListener The alternate listener to be set. + */ + public void setAltDynamicColorListener( + @Nullable DynamicColorListener altDynamicColorListener) { + this.mAltDynamicColorListener = altDynamicColorListener; + } + + /** + * Returns the dynamic color resolver to resolve various colors at runtime. + * + * @return The dynamic color resolver to resolve various colors at runtime. + */ + public @Nullable DynamicColorResolver getDynamicColorResolver() { + return mDynamicColorResolver; + } + + /** + * Set the dynamic color resolver to resolve various colors at runtime. + * + * @param dynamicColorResolver The resolver to be set. + */ + public void setDynamicColorResolver( + @Nullable DynamicColorResolver dynamicColorResolver) { + this.mDynamicColorResolver = dynamicColorResolver; + + update(); + } + + /** + * Returns the dynamic color resolver to resolve various alternate colors at runtime. + * + * @return The alternate dynamic color resolver to resolve various alternate colors at runtime. + */ + public @Nullable DynamicColorResolver getAltDynamicColorResolver() { + return mAltDynamicColorResolver; + } + + /** + * Set the dynamic color resolver to resolve various alternate colors at runtime. + * + * @param altDynamicColorResolver The alternate resolver to be set. + */ + public void setAltDynamicColorResolver( + @Nullable DynamicColorResolver altDynamicColorResolver) { + this.mAltDynamicColorResolver = altDynamicColorResolver; + + update(); + } + + /** + * Returns the combined title string according to the action string. + * + * @return The combined title string according to the action string. + */ + public String getAltTitle() { + return String.valueOf(getActionString()); + } + + /** + * Returns the combined title string according to the alternate color. + * + * @return The combined color string according to the alternate color. + */ + private @NonNull String getColorString() { + if (getAltPreferenceKey() == null) { + return DynamicColorView.getColorString( + getContext(), mColor, mColorView.isAlpha()); + } + + return String.format(getContext().getString(R.string.ads_format_separator), + DynamicColorView.getColorString( + getContext(), mColor, mColorView.isAlpha()), + DynamicColorView.getColorString( + getContext(), mAltColor, mColorView.isAlpha())); + } + @Override - public void onColorSelected(int position, @ColorInt int color) { - setColor(color); + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + super.onSharedPreferenceChanged(sharedPreferences, key); + + if (key.equals(getPreferenceKey())) { + setColor(DynamicPreferences.getInstance().loadPrefs( + getPreferenceKey(), getDefaultColor(false)), false); + } else if (key.equals(getAltPreferenceKey())) { + setAltColor(DynamicPreferences.getInstance().loadPrefs( + getAltPreferenceKey(), getAltDefaultColor(false)), false); + } } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicImagePreference.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicImagePreference.java index ee82b615b3..2809688ae1 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicImagePreference.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicImagePreference.java @@ -19,19 +19,22 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; -import android.support.annotation.DrawableRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.LayoutInflater; import android.widget.ImageView; +import androidx.annotation.AttrRes; +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.R; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; +import com.pranavpandey.android.dynamic.support.widget.DynamicTextView; /** - * A DynamicSimplePreference with a secondary image view to - * represent data according to the need. + * A DynamicSimplePreference with a secondary image view to represent data according to the need. */ public class DynamicImagePreference extends DynamicSimplePreference { @@ -54,7 +57,7 @@ public DynamicImagePreference(@NonNull Context context, @Nullable AttributeSet a } public DynamicImagePreference(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); } @@ -67,7 +70,7 @@ protected void onLoadAttributes(AttributeSet attrs) { try { mImageDrawable = DynamicResourceUtils.getDrawable(getContext(), a.getResourceId( - R.styleable.DynamicPreference_ads_dynamicPreference_image, + R.styleable.DynamicPreference_ads_image, DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE)); } finally { a.recycle(); @@ -81,22 +84,21 @@ protected void onInflate() { mImageView = LayoutInflater.from(getContext()).inflate( R.layout.ads_preference_image, this, false) .findViewById(R.id.ads_preference_image_big); + setViewFrame(mImageView, true); + ((DynamicTextView) getValueView()).setColorType(Theme.ColorType.NONE); } @Override protected void onUpdate() { super.onUpdate(); - if (getImageDrawable() != null) { - mImageView.setImageDrawable(getImageDrawable()); - mImageView.setVisibility(VISIBLE); - } else { - mImageView.setVisibility(GONE); - } + setImageView(mImageView, getImageDrawable()); } /** + * Get the secondary image view to show the drawable. + * * @return The secondary image view to show the drawable. */ public ImageView getImageView() { @@ -104,6 +106,8 @@ public ImageView getImageView() { } /** + * Get the drawable for the image view. + * * @return The drawable for the image view. */ public @Nullable Drawable getImageDrawable() { diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicPreference.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicPreference.java index 958cbb83bf..8b7979a24b 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicPreference.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicPreference.java @@ -21,25 +21,28 @@ import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.preference.PreferenceManager; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.View; import android.widget.AdapterView; import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.AttrRes; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.preference.DynamicPreferences; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; /** - * Base preference to provide the basic interface for the extending - * preference with a icon, title, summary, description, value and an - * action button. - *

- * It must be extended and the necessary methods should be implemented to - * create a dynamic preference.

+ * Base preference to provide the basic interface for the extending preference with an icon, + * title, summary, description, value and an action button. + * + *

It must be extended and the necessary methods should be implemented to create a + * dynamic preference. * * @see DynamicSimplePreference * @see DynamicScreenPreference @@ -53,12 +56,12 @@ public abstract class DynamicPreference extends FrameLayout implements SharedPreferences.OnSharedPreferenceChangeListener { /** - * Listener to get various callbacks related to the popup and - * dialog. It will be useful if this preference is displaying a - * popup or dialog and we have to restrict it from doing that. - *

- * Most possible situation is if we want to display the color - * picker dialog only if user has purchased this feature.

+ * Listener to get various callbacks related to the popup and dialog. + *

It will be useful if this preference is displaying a popup or dialog and we have + * to restrict it from doing that. + * + *

Most possible situation is if we want to display the color picker dialog only + * if user has purchased this feature. * * @see DynamicColorPreference * @see DynamicSpinnerPreference @@ -66,8 +69,9 @@ public abstract class DynamicPreference extends FrameLayout public interface OnPromptListener { /** - * @return {@code true} to allow this preference to show the - * corresponding popup. + * Returns whether to allow this preference to show the corresponding popup. + * + * @return {@code true} to allow this preference to show the corresponding popup. */ boolean onPopup(); @@ -76,20 +80,23 @@ public interface OnPromptListener { * * @param parent The adapter view displaying the items. * @param view The item view which has been clicked. - * @param position The position of {@code view} inside the - * {@code parent}. + * @param position The position of {@code view} inside the {@code parent}. * @param id The id of the {@code view}. */ - void onPopupItemClick(@Nullable AdapterView parent, @Nullable View view, - int position, long id); + void onPopupItemClick(@Nullable AdapterView parent, + @Nullable View view, int position, long id); /** - * @return {@code true} to allow this preference to show the - * corresponding dialog. + * Returns whether to allow this preference to show the corresponding dialog. + * + * @return {@code true} to allow this preference to show the corresponding dialog. */ boolean onDialog(); } + /** + * Default value for the enabled state. + */ public static final boolean DEFAULT_ENABLED = true; /** @@ -123,14 +130,17 @@ void onPopupItemClick(@Nullable AdapterView parent, @Nullable View view, private String mPreferenceKey; /** - * Shared preferences key on which this preference is - * dependent. + * Shared preferences key for alternate preference. + */ + private String mAltPreferenceKey; + + /** + * Shared preferences key on which this preference is dependent. */ private String mDependency; /** - * {@code true} if this preference is enabled and can accept - * click events. + * {@code true} if this preference is enabled and can accept click events. */ private boolean mEnabled; @@ -150,9 +160,7 @@ void onPopupItemClick(@Nullable AdapterView parent, @Nullable View view, private View.OnClickListener mOnActionClickListener; /** - * Listener to get various callbacks related to the popup and - * dialog. It will be useful if this preference is displaying a - * popup or dialog and we have to restrict it from doing that. + * Listener to get various callbacks related to the popup and dialog. */ private OnPromptListener mOnPromptListener; @@ -167,7 +175,7 @@ public DynamicPreference(@NonNull Context context, @Nullable AttributeSet attrs) } public DynamicPreference(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -183,16 +191,18 @@ private void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicPreference); try { - mIcon = DynamicResourceUtils.getDrawable(getContext(), a.getResourceId( - R.styleable.DynamicPreference_ads_dynamicPreference_icon, + mIcon = DynamicResourceUtils.getDrawable(getContext(), + a.getResourceId(R.styleable.DynamicPreference_ads_icon, DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE)); - mTitle = a.getString(R.styleable.DynamicPreference_ads_dynamicPreference_title); - mSummary = a.getString(R.styleable.DynamicPreference_ads_dynamicPreference_summary); - mDescription = a.getString(R.styleable.DynamicPreference_ads_dynamicPreference_description); - mValueString = a.getString(R.styleable.DynamicPreference_ads_dynamicPreference_value); - mPreferenceKey = a.getString(R.styleable.DynamicPreference_ads_dynamicPreference_key); - mDependency = a.getString(R.styleable.DynamicPreference_ads_dynamicPreference_dependency); - mEnabled = a.getBoolean(R.styleable.DynamicPreference_ads_dynamicPreference_enabled, DEFAULT_ENABLED); + mTitle = a.getString(R.styleable.DynamicPreference_ads_title); + mSummary = a.getString(R.styleable.DynamicPreference_ads_summary); + mDescription = a.getString(R.styleable.DynamicPreference_ads_description); + mValueString = a.getString(R.styleable.DynamicPreference_ads_value); + mPreferenceKey = a.getString(R.styleable.DynamicPreference_ads_key); + mAltPreferenceKey = a.getString(R.styleable.DynamicPreference_ads_altKey); + mDependency = a.getString(R.styleable.DynamicPreference_ads_dependency); + mActionString = a.getString(R.styleable.DynamicPreference_ads_action); + mEnabled = a.getBoolean(R.styleable.DynamicPreference_ads_enabled, DEFAULT_ENABLED); } finally { a.recycle(); } @@ -228,36 +238,76 @@ protected void onAttachedToWindow() { protected abstract void onLoadAttributes(@Nullable AttributeSet attrs); /** + * Returns the layout resource id for this preference. + * * @return The layout resource id for this preference. */ protected abstract @LayoutRes int getLayoutRes(); /** * This method will be called after loading the attributed. - * Initialize the preference layout here. + *

Initialize the preference layout here. */ protected abstract void onInflate(); /** - * This method will be called whenever there is a change in the - * preference attributes or parameters. It is better to do any - * real time calculation like updating the value string or checked - * state in this method. + * This method will be called whenever there is a change in the preference attributes + * or parameters. + *

It is better to do any real time calculation like updating the value string + * or checked state in this method. */ protected abstract void onUpdate(); /** - * This method will be called whenever there is a change in - * the preference view state. Either {@code enabled} or - * {@code disabled}, preference views like icon, title, value, - * etc. must be updated here to reflect the overall preference - * state. + * This method will be called whenever there is a change in the preference view state. + *

Either {@code enabled} or {@code disabled}, preference views like icon, title, value, + * etc. must be updated here to reflect the overall preference state. * - * @param enabled {@code true} if this widget is enabled and - * can receive click events. + * @param enabled {@code true} if this widget is enabled and can receive click events. */ protected abstract void onEnabled(boolean enabled); + /** + * Set drawable for a image view. + * + * @param imageView The image view to set the drawable. + * @param drawable The drawable to be set. + */ + protected void setImageView(@Nullable ImageView imageView, @Nullable Drawable drawable) { + if (imageView != null) { + imageView.setImageDrawable(drawable); + } + } + + /** + * Set text for a text view or hide it if the value is {@code null}. + * + * @param textView The text view to set the text. + * @param text The text to be set. + */ + protected void setTextView(@Nullable TextView textView, @Nullable CharSequence text) { + if (textView != null) { + if (text != null) { + textView.setText(text); + textView.setVisibility(View.VISIBLE); + } else { + textView.setVisibility(View.GONE); + } + } + } + + /** + * Set a view enabled or disabled. + * + * @param view The view to be enabled or disabled. + * @param enabled {@code true} to enable the view. + */ + protected void setViewEnabled(@Nullable View view, boolean enabled) { + if (view != null) { + view.setEnabled(enabled); + } + } + /** * Update this preference according to the dependency. */ @@ -269,6 +319,16 @@ private void updateDependency() { } /** + * Manually onUpdate this preference by calling {@link #onUpdate()} method. + *

Useful in some situations to restore the preference state. + */ + public void update() { + onUpdate(); + } + + /** + * Get the icon used by this preference. + * * @return The icon used by this preference. */ public @Nullable Drawable getIcon() { @@ -287,6 +347,8 @@ public void setIcon(@Nullable Drawable icon) { } /** + * Get the title used by this preference. + * * @return The title used by this preference. */ public @Nullable CharSequence getTitle() { @@ -305,6 +367,8 @@ public void setTitle(@Nullable String title) { } /** + * Get the summary used by this preference. + * * @return The summary used by this preference. */ public @Nullable CharSequence getSummary() { @@ -323,6 +387,8 @@ public void setSummary(@Nullable String summary) { } /** + * Get the description used by this preference. + * * @return The description used by this preference. */ public @Nullable CharSequence getDescription() { @@ -341,6 +407,8 @@ public void setDescription(@Nullable String description) { } /** + * Get the value string used by this preference. + * * @return The value string used by this preference. */ public @Nullable CharSequence getValueString() { @@ -351,14 +419,29 @@ public void setDescription(@Nullable String description) { * Set the value string used by this preference. * * @param valueString The value string to be set. + * @param update {@code true} to call {@link #onUpdate()} method after setting the + * value string. */ - public void setValueString(@Nullable CharSequence valueString) { + public void setValueString(@Nullable CharSequence valueString, boolean update) { this.mValueString = valueString; - onUpdate(); + if (update) { + onUpdate(); + } + } + + /** + * Set the value string used by this preference. + * + * @param valueString The value string to be set. + */ + public void setValueString(@Nullable CharSequence valueString) { + setValueString(valueString, true); } /** + * Get the shared preferences key used by this preference. + * * @return The shared preferences key used by this preference. */ public @Nullable String getPreferenceKey() { @@ -377,16 +460,36 @@ public void setPreferenceKey(@Nullable String preferenceKey) { } /** - * @return The shared preferences key on which this preference - * is dependent. + * Get the shared preferences key for alternate preference. + * + * @return The shared preferences key for alternate preference. + */ + public @Nullable String getAltPreferenceKey() { + return mAltPreferenceKey; + } + + /** + * Set the shared preferences key for alternate preference. + * + * @param altPreferenceKey The alternate shared preferences key to be set. + */ + public void setAltPreferenceKey(@Nullable String altPreferenceKey) { + this.mAltPreferenceKey = altPreferenceKey; + + onUpdate(); + } + + /** + * Returns the shared preferences key on which this preference is dependent. + * + * @return The shared preferences key on which this preference is dependent. */ public @Nullable String getDependency() { return mDependency; } /** - * Set the shared preferences key on which this preference - * is dependent. + * Set the shared preferences key on which this preference is dependent. * * @param dependency The shared preferences key to be set. */ @@ -399,8 +502,7 @@ public void setDependency(@Nullable String dependency) { /** * Set this preference enabled or disabled. * - * @param enabled {@code true} if this preference - * is enabled. + * @param enabled {@code true} if this preference is enabled. */ public void setEnabled(boolean enabled) { super.setEnabled(enabled); @@ -410,6 +512,8 @@ public void setEnabled(boolean enabled) { } /** + * Get the action string used by this preference. + * * @return The action string used by this preference. */ public @Nullable CharSequence getActionString() { @@ -417,38 +521,51 @@ public void setEnabled(boolean enabled) { } /** - * @return The on click listener to receive preference click - * events. + * Returns the on click listener to receive preference click events. + * + * @return The on click listener to receive preference click events. */ public @Nullable View.OnClickListener getOnPreferenceClickListener() { return mOnPreferenceClickListener; } /** - * Set the on click listener to receive preference click - * events. + * Set the on click listener to receive preference click events. * * @param onPreferenceClickListener The listener to be set. + * @param update {@code true} to call {@link #onUpdate()} method after setting the listener. */ public void setOnPreferenceClickListener( - @Nullable View.OnClickListener onPreferenceClickListener) { + @Nullable View.OnClickListener onPreferenceClickListener, boolean update) { this.mOnPreferenceClickListener = onPreferenceClickListener; - onUpdate(); + if (update) { + onUpdate(); + } } /** - * Set an action button for this preference to perform secondary - * operations like requesting a permission, reset the preference - * value etc. Extending preference should implement the functionality - * in {@link #onUpdate()} method. + * Set the on click listener to receive preference click events. + * + * @param onPreferenceClickListener The listener to be set. + */ + public void setOnPreferenceClickListener( + @Nullable View.OnClickListener onPreferenceClickListener) { + setOnPreferenceClickListener(onPreferenceClickListener, true); + } + + /** + * Set an action button for this preference to perform secondary operations like requesting + * a permission, reset the preference value etc. + * + *

Extending preference should implement the functionality in {@link #onUpdate()} + * method. * * @param actionString The string to be shown for the action. - * @param onActionClickListener The on click listener to perform the action - * when it is clicked. + * @param onActionClickListener The on click listener to perform the action when it is clicked. */ public void setActionButton(@Nullable CharSequence actionString, - @Nullable OnClickListener onActionClickListener) { + @Nullable OnClickListener onActionClickListener) { this.mActionString = actionString; this.mOnActionClickListener = onActionClickListener; @@ -456,6 +573,8 @@ public void setActionButton(@Nullable CharSequence actionString, } /** + * Returns the on click listener to receive action click events. + * * @return The on click listener to receive action click events. */ public @Nullable OnClickListener getOnActionClickListener() { @@ -463,18 +582,18 @@ public void setActionButton(@Nullable CharSequence actionString, } /** - * @return The listener to get various callbacks related to the - * popup and dialog. + * Returns the listener to get the popup and dialog dialogs. + * + * @return The llistener to get the popup and dialog dialogs. */ public @Nullable OnPromptListener getOnPromptListener() { return mOnPromptListener; } /** - * Set the listener to get various callbacks related to the - * popup and dialog. It will be useful if this preference - * is displaying a popup or dialog and we have to restrict - * it from doing that. + * Set the listener to get various callbacks related to the popup and dialog. + *

It will be useful if this preference is displaying a popup or dialog and we have + * to restrict it from doing that. * * @param onPromptListener The listener to be set. */ diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicScreenPreference.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicScreenPreference.java index bff8e909de..5b6fb014f3 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicScreenPreference.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicScreenPreference.java @@ -17,18 +17,21 @@ package com.pranavpandey.android.dynamic.support.setting; import android.content.Context; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.AttributeSet; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; +import androidx.annotation.AttrRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.widget.DynamicTextView; /** * A DynamicSimplePreference to provide the functionality of a - * {@link android.preference.PreferenceScreen} with a icon, title, - * summary, description, value and an action button. It can be - * extended to modify according to the need. + * {@link android.preference.PreferenceScreen} with an icon, title, summary, description, + * value and an action button. + * + *

It can be extended to modify according to the need. */ public class DynamicScreenPreference extends DynamicSimplePreference { @@ -41,7 +44,7 @@ public DynamicScreenPreference(@NonNull Context context, @Nullable AttributeSet } public DynamicScreenPreference(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); } @@ -49,6 +52,6 @@ public DynamicScreenPreference(@NonNull Context context, protected void onInflate() { super.onInflate(); - ((DynamicTextView) getValueView()).setColorType(DynamicColorType.ACCENT); + ((DynamicTextView) getValueView()).setColorType(Theme.ColorType.ACCENT); } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicSeekBarCompact.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicSeekBarCompact.java index 138f7f71f5..64bedf900a 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicSeekBarCompact.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicSeekBarCompact.java @@ -17,18 +17,20 @@ package com.pranavpandey.android.dynamic.support.setting; import android.content.Context; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.picker.color.DynamicColorPicker; /** - * A compact version of the DynamicSeekBarPreference for the - * {@link DynamicColorPicker}. It can also be used in other - * scenarios. + * A compact version of the DynamicSeekBarPreference for the {@link DynamicColorPicker}. + * + *

It can also be used in other scenarios. */ public class DynamicSeekBarCompact extends DynamicSeekBarPreference { @@ -41,7 +43,7 @@ public DynamicSeekBarCompact(@NonNull Context context, @Nullable AttributeSet at } public DynamicSeekBarCompact(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicSeekBarHue.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicSeekBarHue.java index f05039099f..77f3b8f40a 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicSeekBarHue.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicSeekBarHue.java @@ -17,18 +17,21 @@ package com.pranavpandey.android.dynamic.support.setting; import android.content.Context; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.picker.color.DynamicColorPicker; /** - * A compact version of the DynamicSeekBarPreference for the - * {@link DynamicColorPicker} to show the hue bar. It can - * also be used in other scenarios. + * A compact version of the DynamicSeekBarPreference for the {@link DynamicColorPicker} + * to show the hue bar. + * + *

It can also be used in other scenarios. */ public class DynamicSeekBarHue extends DynamicSeekBarCompact { @@ -41,7 +44,7 @@ public DynamicSeekBarHue(@NonNull Context context, @Nullable AttributeSet attrs) } public DynamicSeekBarHue(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicSeekBarPreference.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicSeekBarPreference.java index 42e13157a3..9d52fb637f 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicSeekBarPreference.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicSeekBarPreference.java @@ -16,34 +16,37 @@ package com.pranavpandey.android.dynamic.support.setting; +import android.animation.Animator; import android.animation.ObjectAnimator; import android.content.Context; import android.content.SharedPreferences; import android.content.res.TypedArray; import android.os.Handler; -import android.support.annotation.ColorInt; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.AppCompatSeekBar; import android.util.AttributeSet; import android.view.View; -import android.view.ViewGroup; +import android.view.animation.DecelerateInterpolator; import android.widget.Button; -import android.widget.ImageView; +import android.widget.ImageButton; import android.widget.SeekBar; import android.widget.TextView; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatSeekBar; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.preference.DynamicPreferences; import com.pranavpandey.android.dynamic.support.widget.DynamicSeekBar; import com.pranavpandey.android.dynamic.support.widget.DynamicTextView; /** - * A DynamicPreference to provide the functionality of a seek bar - * preference with control buttons to modify the value. + * A DynamicSpinnerPreference to provide the functionality of a seek bar preference with + * control buttons to modify the value. */ -public class DynamicSeekBarPreference extends DynamicPreference { +public class DynamicSeekBarPreference extends DynamicSpinnerPreference { /** * Constant for the seek bar animation duration. @@ -106,62 +109,34 @@ public class DynamicSeekBarPreference extends DynamicPreference { private CharSequence mUnit; /** - * {@code true} to show seek bar buttons to increase or - * decrease the value. + * {@code true} to show seek bar buttons to increase or decrease the value. */ private boolean mControls; /** - * Seek bar change listener to get the callback for seek - * events. + * Seek bar change listener to get the callback for seek events. */ private SeekBar.OnSeekBarChangeListener mOnSeekBarChangeListener; /** - * Seek bar change listener to get the callback for control - * events. + * Seek bar change listener to get the callback for control events. */ private SeekBar.OnSeekBarChangeListener mOnSeekBarControlListener; /** - * The preference root view. - */ - private ViewGroup mPreferenceView; - - /** - * Image view to show the icon. - */ - private ImageView mIconView; - - /** - * Text view to show the title. - */ - private TextView mTitleView; - - /** - * Text view to show the summary. + * Text view to show the seek bar value. */ - private TextView mSummaryView; - - /** - * Text view to show the description. - */ - private TextView mDescriptionView; - - /** - * Text view to show the value. - */ - private TextView mValueView; + private TextView mSeekBarView; /** * Image view to show the decrease button. */ - private ImageView mSeekLeftView; + private ImageButton mSeekBarLeftView; /** * Image view to show the increase button. */ - private ImageView mSeekRightView; + private ImageButton mSeekBarRightView; /** * Seek bar to display and modify the preference value. @@ -169,11 +144,15 @@ public class DynamicSeekBarPreference extends DynamicPreference { private AppCompatSeekBar mSeekBar; /** - * Button to provide a secondary action like permission - * request, etc. + * Button to provide a secondary action like permission request, etc. */ private Button mActionView; + /** + * {@code true} if seek bar is controls are enabled. + */ + private boolean mSeekBarEnabled; + public DynamicSeekBarPreference(@NonNull Context context) { super(context); } @@ -183,26 +162,33 @@ public DynamicSeekBarPreference(@NonNull Context context, @Nullable AttributeSet } public DynamicSeekBarPreference(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override - protected void onLoadAttributes(AttributeSet attrs) { + protected void onLoadAttributes(@Nullable AttributeSet attrs) { + super.onLoadAttributes(attrs); + TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.DynamicPreference); try { - mMaxValue = a.getInteger(R.styleable.DynamicPreference_ads_dynamicPreference_max, + mMaxValue = a.getInteger(R.styleable.DynamicPreference_ads_max, DEFAULT_MAX_VALUE); - mMinValue = a.getInteger(R.styleable.DynamicPreference_ads_dynamicPreference_min, + mMinValue = a.getInteger(R.styleable.DynamicPreference_ads_min, DEFAULT_MIN_VALUE); - mDefaultValue = a.getInteger(R.styleable.DynamicPreference_ads_dynamicPreference_progress, + mDefaultValue = a.getInteger( + R.styleable.DynamicPreference_ads_progress, DEFAULT_SEEK_VALUE); - mSeekInterval = a.getInteger(R.styleable.DynamicPreference_ads_dynamicPreference_interval, + mSeekInterval = a.getInteger( + R.styleable.DynamicPreference_ads_interval, DEFAULT_SEEK_INTERVAL); - mControls = a.getBoolean(R.styleable.DynamicPreference_ads_dynamicPreference_controls, + mControls = a.getBoolean(R.styleable.DynamicPreference_ads_controls, DEFAULT_SEEK_CONTROLS); - mUnit = a.getString(R.styleable.DynamicPreference_ads_dynamicPreference_unit); + mUnit = a.getString(R.styleable.DynamicPreference_ads_unit); + mSeekBarEnabled = a.getBoolean( + R.styleable.DynamicPreference_ads_seek_bar, + true); } finally { a.recycle(); } @@ -215,17 +201,12 @@ protected void onLoadAttributes(AttributeSet attrs) { @Override protected void onInflate() { - inflate(getContext(), getLayoutRes(), this); - - mPreferenceView = findViewById(R.id.ads_preference_seek_bar); - mIconView = findViewById(R.id.ads_preference_seek_bar_icon); - mTitleView = findViewById(R.id.ads_preference_seek_bar_title); - mSummaryView = findViewById(R.id.ads_preference_seek_bar_summary); - mDescriptionView = findViewById(R.id.ads_preference_seek_bar_description); - mValueView = findViewById(R.id.ads_preference_seek_bar_value); + super.onInflate(); + + mSeekBarView = findViewById(R.id.ads_preference_seek_bar_value); mSeekBar = findViewById(R.id.ads_preference_seek_bar_seek); - mSeekLeftView = findViewById(R.id.ads_preference_seek_bar_left); - mSeekRightView = findViewById(R.id.ads_preference_seek_bar_right); + mSeekBarLeftView = findViewById(R.id.ads_preference_seek_bar_left); + mSeekBarRightView = findViewById(R.id.ads_preference_seek_bar_right); mActionView = findViewById(R.id.ads_preference_action_button); mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @@ -234,8 +215,6 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (fromUser) { mProgress = progress; updateSeekFunctions(); - } else { - mSeekBar.setProgress(mProgress); } if (mOnSeekBarChangeListener != null) { @@ -261,14 +240,14 @@ public void onStopTrackingTouch(SeekBar seekBar) { } }); - mSeekLeftView.setOnClickListener(new OnClickListener() { + mSeekBarLeftView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { setProgressFromControl(mProgress - 1); } }); - mSeekRightView.setOnClickListener(new OnClickListener() { + mSeekBarRightView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { setProgressFromControl(mProgress + 1); @@ -280,44 +259,63 @@ public void onClick(View v) { public void onClick(View v) { final int defaultValue = getProgressFromValue(mDefaultValue); ObjectAnimator animation = ObjectAnimator.ofInt(mSeekBar, - "progress", defaultValue); + "progress", getProgress(), defaultValue); animation.setDuration(ANIMATION_DURATION); + animation.setInterpolator(new DecelerateInterpolator()); + animation.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + setProgress(defaultValue); + } + + @Override + public void onAnimationEnd(Animator animation) { } + + @Override + public void onAnimationCancel(Animator animation) { } + + @Override + public void onAnimationRepeat(Animator animation) { } + }); + animation.start(); - setProgress(defaultValue); } }); - if (getPreferenceKey() != null) { + if (super.getPreferenceKey() != null) { mProgress = getProgressFromValue(DynamicPreferences.getInstance() - .loadPrefs(getPreferenceKey(), mDefaultValue)); + .loadPrefs(super.getPreferenceKey(), mDefaultValue)); } } + @Override + public @Nullable String getPreferenceKey() { + return getAltPreferenceKey(); + } + /** - * Update seek bar functions according to the current - * parameters. + * Update seek bar functions according to the current parameters. */ private void updateSeekFunctions() { int actualValue = getValueFromProgress(); if (mUnit != null) { - mValueView.setText(String.format( + mSeekBarView.setText(String.format( getContext().getString(R.string.ads_format_blank_space), String.valueOf(actualValue), mUnit)); } else { - mValueView.setText(String.valueOf(actualValue)); + mSeekBarView.setText(String.valueOf(actualValue)); } - if (isEnabled()) { - mSeekLeftView.setEnabled(mProgress > DEFAULT_MIN_VALUE); - mSeekRightView.setEnabled(mProgress < getMax()); + if (isEnabled() && mSeekBarEnabled) { + mSeekBarLeftView.setEnabled(mProgress > DEFAULT_MIN_VALUE); + mSeekBarRightView.setEnabled(mProgress < getMax()); mActionView.setEnabled(actualValue != mDefaultValue); } } /** - * Update seek bar controls according to the current - * parameters. + * Update seek bar controls according to the current parameters. */ private void setProgressFromControl(int progress) { if (mOnSeekBarControlListener != null) { @@ -334,75 +332,73 @@ private void setProgressFromControl(int progress) { @Override protected void onUpdate() { - mIconView.setImageDrawable(getIcon()); - mSeekBar.setMax(getMax()); + super.onUpdate(); - if (mControls) { - mSeekLeftView.setVisibility(VISIBLE); - mSeekRightView.setVisibility(VISIBLE); - } else { - mSeekLeftView.setVisibility(GONE); - mSeekRightView.setVisibility(GONE); - } + if (mSeekBar != null) { + mSeekBar.setMax(getMax()); - if (getTitle() != null) { - mTitleView.setText(getTitle()); - mTitleView.setVisibility(VISIBLE); - } else { - mTitleView.setVisibility(GONE); - } - - if (getSummary() != null) { - mSummaryView.setText(getSummary()); - mSummaryView.setVisibility(VISIBLE); - } else { - mSummaryView.setVisibility(GONE); - } + if (mControls) { + mSeekBarLeftView.setVisibility(VISIBLE); + mSeekBarRightView.setVisibility(VISIBLE); + } else { + mSeekBarLeftView.setVisibility(GONE); + mSeekBarRightView.setVisibility(GONE); + } - if (getDescription() != null) { - mDescriptionView.setText(getDescription()); - mDescriptionView.setVisibility(VISIBLE); - } else { - mDescriptionView.setVisibility(GONE); - } + if (getOnActionClickListener() != null) { + mActionView.setText(getActionString()); + mActionView.setOnClickListener(getOnActionClickListener()); + mActionView.setVisibility(VISIBLE); + } else { + mActionView.setVisibility(GONE); + } - if (getOnActionClickListener() != null) { - mActionView.setText(getActionString()); - mActionView.setOnClickListener(getOnActionClickListener()); - mActionView.setVisibility(VISIBLE); - } else { - mActionView.setVisibility(GONE); + new Handler().post(new Runnable() { + @Override + public void run() { + mSeekBar.setProgress(mProgress); + updateSeekFunctions(); + } + }); } - - new Handler().post(new Runnable() { - @Override - public void run() { - mSeekBar.setProgress(mProgress); - updateSeekFunctions(); - } - }); } @Override protected void onEnabled(boolean enabled) { - mPreferenceView.setEnabled(enabled); - mIconView.setEnabled(enabled); - mTitleView.setEnabled(enabled); - mSummaryView.setEnabled(enabled); - mDescriptionView.setEnabled(enabled); - mSeekBar.setEnabled(enabled); - - if (!enabled) { - mValueView.setEnabled(enabled); - mSeekLeftView.setEnabled(enabled); - mSeekRightView.setEnabled(enabled); - mActionView.setEnabled(enabled); + super.onEnabled(enabled); + + if (mSeekBar != null) { + mSeekBar.setEnabled(enabled && mSeekBarEnabled); + mSeekBarView.setEnabled(enabled && mSeekBarEnabled); + mSeekBarLeftView.setEnabled(enabled && mSeekBarEnabled); + mSeekBarRightView.setEnabled(enabled && mSeekBarEnabled); + mActionView.setEnabled(enabled && mSeekBarEnabled); } + } - onUpdate(); + /** + * Enable or disable the seek bar. + * + * @param seekBarEnabled {@code true} to enable the seek bar. + */ + public void setSeekBarEnabled(boolean seekBarEnabled) { + this.mSeekBarEnabled = seekBarEnabled; + + onEnabled(isEnabled()); + } + + /** + * Returns whether the seek bar is enabled. + * + * {@code true} if seek bar is enabled. + */ + public boolean isSeekBarEnabled() { + return mSeekBarEnabled; } /** + * Get the default value for this preference. + * * @return The default value for this preference. */ public int getDefaultValue() { @@ -421,6 +417,8 @@ public void setDefaultValue(int defaultValue) { } /** + * Get the maximum value for this preference. + * * @return The maximum value for this preference. */ public int getMaxValue() { @@ -439,6 +437,8 @@ public void setMaxValue(int maxValue) { } /** + * Get the minimum value for this preference. + * * @return The minimum value for this preference. */ public int getMinValue() { @@ -457,6 +457,8 @@ public void setMinValue(int minValue) { } /** + * Returns the current seek bar progress. + * * @return The current seek bar progress. */ public int getProgress() { @@ -464,22 +466,24 @@ public int getProgress() { } /** - * Set the current seek bar progress. + * Get the current seek bar progress. * * @param progress The progress to be set. */ public void setProgress(int progress) { this.mProgress = progress; - if (getPreferenceKey() != null) { + if (super.getPreferenceKey() != null) { DynamicPreferences.getInstance().savePrefs( - getPreferenceKey(), getValueFromProgress()); + super.getPreferenceKey(), getValueFromProgress()); } else { onUpdate(); } } /** + * Get the seek interval for the seek bar. + * * @return The seek interval for the seek bar. */ public int getSeekInterval() { @@ -498,6 +502,8 @@ public void setSeekInterval(int seekInterval) { } /** + * Get the optional unit text for the preference value. + * * @return The optional unit text for the preference value. */ public @Nullable CharSequence getUnit() { @@ -525,8 +531,10 @@ public void setValue(int value) { } /** - * @return {@code true} to show seek bar buttons to increase - * or decrease the value. + * Returns whether the seek bar seek bar buttons to increase or decrease the value + * are enabled. + * + * @return {@code true} to show seek bar buttons to increase or decrease the value. */ public boolean isControls() { return mControls; @@ -535,8 +543,7 @@ public boolean isControls() { /** * Set the seek bar controls to be enabled or disabled. * - * @param controls {@code true} to show seek bar buttons - * to increase or decrease the value. + * @param controls {@code true} to show seek bar buttons to increase or decrease the value. */ public void setControls(boolean controls) { this.mControls = controls; @@ -545,16 +552,16 @@ public void setControls(boolean controls) { } /** - * @return The seek bar change listener to get the callback for - * seek events. + * Returns the seek bar change listener to get the callback for seek events. + * + * @return The seek bar change listener to get the callback for seek events. */ public @Nullable SeekBar.OnSeekBarChangeListener getOnSeekBarChangeListener() { return mOnSeekBarChangeListener; } /** - * Set the seek bar change listener to get the callback for - * seek events. + * Set the seek bar change listener to get the callback for seek events. * * @param onSeekBarChangeListener The listener to be set. */ @@ -564,16 +571,16 @@ public void setOnSeekBarChangeListener( } /** - * @return The seek bar change listener to get the callback for - * control events. + * Returns the seek bar change listener to get the callback for control events. + * + * @return The seek bar change listener to get the callback for control events. */ public @Nullable SeekBar.OnSeekBarChangeListener getOnSeekBarControlListener() { return mOnSeekBarControlListener; } /** - * Set the seek bar change listener to get the callback for - * control events. + * Set the seek bar change listener to get the callback for control events. * * @param onSeekBarControlListener The listener to be set. */ @@ -583,44 +590,50 @@ public void setOnSeekBarControlListener( } /** - * @return The maximum preference value according to the - * {@link #mSeekInterval}. + * Returns the maximum preference value according to the seek interval. + * + * @return The maximum preference value according to the seek interval. */ private int getMax() { return (mMaxValue - mMinValue) / mSeekInterval; } /** - * @return The seek bar progress according to the supplied - * value. + * Returns the seek bar progress according to the supplied value. * * @param value The value to converted into seek bar progress. + * + * @return The seek bar progress according to the supplied value. */ private int getProgressFromValue(int value) { return (value - mMinValue) / mSeekInterval; } /** - * @return The preference value according to the seek bar - * progress. + * Returns the preference value according to the seek bar progress. + * + * @return The preference value according to the seek bar progress. */ public int getValueFromProgress() { return mMinValue + (mProgress * mSeekInterval); } /** - * @return The seek bar to display and modify the preference - * value. + * Get the seek bar to display and modify the preference value. + * + * @return The seek bar to display and modify the preference value. */ public AppCompatSeekBar getSeekBar() { return mSeekBar; } /** + * Get the text view to show the value. + * * @return The text view to show the value. */ - public TextView getValueView() { - return mValueView; + public TextView getSeekBarValueView() { + return mSeekBarView; } /** @@ -630,16 +643,16 @@ public TextView getValueView() { */ public void setColor(@ColorInt int color) { ((DynamicSeekBar) mSeekBar).setColor(color); - ((DynamicTextView) mValueView).setColor(color); + ((DynamicTextView) mSeekBarView).setColor(color); } @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { super.onSharedPreferenceChanged(sharedPreferences, key); - if (key.equals(getPreferenceKey())) { + if (key.equals(super.getPreferenceKey())) { mProgress = getProgressFromValue(DynamicPreferences.getInstance() - .loadPrefs(getPreferenceKey(), mProgress)); + .loadPrefs(super.getPreferenceKey(), mProgress)); onUpdate(); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicSimplePreference.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicSimplePreference.java index 7a0ab9471c..e4807458df 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicSimplePreference.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicSimplePreference.java @@ -17,22 +17,26 @@ package com.pranavpandey.android.dynamic.support.setting; import android.content.Context; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import android.content.SharedPreferences; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; -import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.AttrRes; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.R; +import com.pranavpandey.android.dynamic.support.widget.DynamicButton; import com.pranavpandey.android.dynamic.utils.DynamicViewUtils; /** * A DynamicPreference to implement the basic functionality - * It can be extended to modify according to the need. + * + *

It can be extended to modify according to the need. */ public class DynamicSimplePreference extends DynamicPreference { @@ -67,16 +71,14 @@ public class DynamicSimplePreference extends DynamicPreference { private TextView mValueView; /** - * Frame to add a secondary view like another image, - * etc. + * Frame to add a secondary view like another image, etc. */ private ViewGroup mViewFrame; /** - * Button to provide a secondary action like permission - * request, etc. + * Button to provide a secondary action like permission request, etc. */ - private Button mActionView; + private DynamicButton mActionView; public DynamicSimplePreference(@NonNull Context context) { super(context); @@ -87,12 +89,12 @@ public DynamicSimplePreference(@NonNull Context context, @Nullable AttributeSet } public DynamicSimplePreference(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override - protected void onLoadAttributes(AttributeSet attrs) { } + protected void onLoadAttributes(@Nullable AttributeSet attrs) { } @Override protected @LayoutRes int getLayoutRes() { @@ -103,13 +105,13 @@ protected void onLoadAttributes(AttributeSet attrs) { } protected void onInflate() { inflate(getContext(), getLayoutRes(), this); - mPreferenceView = findViewById(R.id.ads_preference_simple); - mIconView = findViewById(R.id.ads_preference_simple_icon); - mTitleView = findViewById(R.id.ads_preference_simple_title); - mSummaryView = findViewById(R.id.ads_preference_simple_summary); - mDescriptionView = findViewById(R.id.ads_preference_simple_description); - mValueView = findViewById(R.id.ads_preference_simple_value); - mViewFrame = findViewById(R.id.ads_preference_simple_view); + mPreferenceView = findViewById(R.id.ads_preference); + mIconView = findViewById(R.id.ads_preference_icon); + mTitleView = findViewById(R.id.ads_preference_title); + mSummaryView = findViewById(R.id.ads_preference_summary); + mDescriptionView = findViewById(R.id.ads_preference_description); + mValueView = findViewById(R.id.ads_preference_value); + mViewFrame = findViewById(R.id.ads_preference_view); mActionView = findViewById(R.id.ads_preference_action_button); setViewFrame(null, true); @@ -117,67 +119,47 @@ protected void onInflate() { @Override protected void onUpdate() { - if (getOnPreferenceClickListener() != null) { + if (mPreferenceView != null) { mPreferenceView.setOnClickListener(getOnPreferenceClickListener()); } - mIconView.setImageDrawable(getIcon()); - - if (getTitle() != null) { - mTitleView.setText(getTitle()); - mTitleView.setVisibility(View.VISIBLE); - } else { - mTitleView.setVisibility(View.GONE); - } - - if (getSummary() != null) { - mSummaryView.setText(getSummary()); - mSummaryView.setVisibility(View.VISIBLE); - } else { - mSummaryView.setVisibility(View.GONE); - } - - if (getDescription() != null) { - mDescriptionView.setText(getDescription()); - mDescriptionView.setVisibility(View.VISIBLE); - } else { - mDescriptionView.setVisibility(View.GONE); - } - - if (getValueString() != null) { - mValueView.setText(getValueString()); - mValueView.setVisibility(View.VISIBLE); - } else { - mValueView.setVisibility(View.GONE); - } - - if (getOnActionClickListener() != null) { - mActionView.setText(getActionString()); - mActionView.setOnClickListener(getOnActionClickListener()); - mActionView.setVisibility(View.VISIBLE); - } else { - mActionView.setVisibility(View.GONE); + setImageView(mIconView, getIcon()); + setTextView(mTitleView, getTitle()); + setTextView(mSummaryView, getSummary()); + setTextView(mValueView, getValueString()); + setTextView(mDescriptionView, getDescription()); + + if (mActionView != null) { + if (getOnActionClickListener() != null) { + mActionView.setText(getActionString()); + mActionView.setOnClickListener(getOnActionClickListener()); + mActionView.setVisibility(View.VISIBLE); + } else { + mActionView.setVisibility(View.GONE); + } } } @Override protected void onEnabled(boolean enabled) { - mPreferenceView.setEnabled(enabled); - mIconView.setEnabled(enabled); - mTitleView.setEnabled(enabled); - mSummaryView.setEnabled(enabled); - mDescriptionView.setEnabled(enabled); - mValueView.setEnabled(enabled); - mActionView.setEnabled(enabled); - - if (mViewFrame.getChildCount() > 0) { - mViewFrame.getChildAt(0).setEnabled(enabled); + setViewEnabled(mPreferenceView, enabled); + setViewEnabled(mIconView, enabled); + setViewEnabled(mTitleView, enabled); + setViewEnabled(mSummaryView, enabled); + setViewEnabled(mDescriptionView, enabled); + setViewEnabled(mValueView, enabled); + setViewEnabled(mActionView, enabled); + + if (mViewFrame != null && mViewFrame.getChildCount() > 0) { + setViewEnabled(mViewFrame.getChildAt(0), enabled); } onUpdate(); } /** + * Get the preference root view. + * * @return The preference root view. */ public ViewGroup getPreferenceView() { @@ -185,13 +167,44 @@ public ViewGroup getPreferenceView() { } /** - * @return The image view to show the icon. + * Get the text view to show the title. + * + * @return The text view to show the title. + */ + public TextView getTitleView() { + return mTitleView; + } + + /** + * Get the text view to show the summary. + * + * @return The text view to show the summary. + */ + public TextView getSummaryView() { + return mSummaryView; + } + + /** + * Get the text view to show the value. + * + * @return The text view to show the value. */ public TextView getValueView() { return mValueView; } /** + * Get the text view to show the description. + * + * @return The text view to show the description. + */ + public TextView getDescriptionView() { + return mDescriptionView; + } + + /** + * Get the text view to show the title. + * * @return The text view to show the title. */ public ViewGroup getViewFrame() { @@ -202,15 +215,34 @@ public ViewGroup getViewFrame() { * Add a view in the view frame. * * @param view The view to be added. - * @param removePrevious {@code true} to remove all the previous - * views of the view group. + * @param removePrevious {@code true} to remove all the previous views of the view group. */ public void setViewFrame(@Nullable View view, boolean removePrevious) { - if (view != null) { - mViewFrame.setVisibility(View.VISIBLE); - DynamicViewUtils.addView(mViewFrame, view, removePrevious); - } else { - mViewFrame.setVisibility(View.GONE); + if (mViewFrame != null) { + if (view != null) { + mViewFrame.setVisibility(View.VISIBLE); + DynamicViewUtils.addView(mViewFrame, view, removePrevious); + } else { + mViewFrame.setVisibility(View.GONE); + } + } + } + + /** + * Get the button to provide a secondary action like permission request, etc. + * + * @return The button to provide a secondary action like permission request, etc. + */ + public DynamicButton getActionView() { + return mActionView; + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + super.onSharedPreferenceChanged(sharedPreferences, key); + + if (key != null && key.equals(getPreferenceKey())) { + onUpdate(); } } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicSpinnerPreference.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicSpinnerPreference.java index af33bcc111..20749490b5 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicSpinnerPreference.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicSpinnerPreference.java @@ -19,17 +19,20 @@ import android.content.Context; import android.content.SharedPreferences; import android.content.res.TypedArray; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.View; import android.widget.AdapterView; +import androidx.annotation.AttrRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.popup.DynamicArrayPopup; import com.pranavpandey.android.dynamic.support.popup.DynamicPopup; import com.pranavpandey.android.dynamic.support.preference.DynamicPreferences; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; +import com.pranavpandey.android.dynamic.support.theme.Theme; +import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; import com.pranavpandey.android.dynamic.support.widget.DynamicTextView; import java.util.Arrays; @@ -42,7 +45,7 @@ public class DynamicSpinnerPreference extends DynamicSimplePreference { /** * Popup type for this preference. - * Either {@link DynamicPopup.DynamicPopupType#LIST} + *

Either {@link DynamicPopup.DynamicPopupType#LIST} * or {@link DynamicPopup.DynamicPopupType#GRID}. */ private @DynamicPopup.DynamicPopupType int mPopupType; @@ -71,22 +74,22 @@ public DynamicSpinnerPreference(@NonNull Context context, @Nullable AttributeSet } public DynamicSpinnerPreference(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override - protected void onLoadAttributes(AttributeSet attrs) { + protected void onLoadAttributes(@Nullable AttributeSet attrs) { super.onLoadAttributes(attrs); - TypedArray a = getContext().obtainStyledAttributes( - attrs, R.styleable.DynamicPreference); + TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.DynamicPreference); try { - mEntries = a.getTextArray(R.styleable.DynamicPreference_ads_dynamicPreference_entries); - mValues = a.getTextArray(R.styleable.DynamicPreference_ads_dynamicPreference_values); - mDefaultValue = a.getInt(R.styleable.DynamicPreference_ads_dynamicPreference_value, 0); - mPopupType = a.getInt(R.styleable.DynamicPreference_ads_dynamicPreference_popupType, + mEntries = a.getTextArray(R.styleable.DynamicPreference_ads_entries); + mValues = a.getTextArray(R.styleable.DynamicPreference_ads_values); + mDefaultValue = a.getInt(R.styleable.DynamicPreference_ads_value, + DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE); + mPopupType = a.getInt(R.styleable.DynamicPreference_ads_popupType, DynamicPopup.DynamicPopupType.NONE); } finally { a.recycle(); @@ -97,7 +100,9 @@ protected void onLoadAttributes(AttributeSet attrs) { protected void onInflate() { super.onInflate(); - ((DynamicTextView) getValueView()).setColorType(DynamicColorType.ACCENT); + if (getValueView() != null) { + ((DynamicTextView) getValueView()).setColorType(Theme.ColorType.ACCENT); + } setOnPreferenceClickListener(new OnClickListener() { @Override @@ -110,9 +115,18 @@ public void onClick(View v) { showPopup(v); } } - }); + }, false); + + updateValueString(false); + } + + @Override + protected void onUpdate() { + super.onUpdate(); - updateValueString(); + if (getPreferenceView() != null) { + getPreferenceView().setClickable(mEntries != null); + } } /** @@ -143,29 +157,34 @@ public void onItemClick(AdapterView parent, View view, } /** - * Update value string according to the current preference - * value. + * Update value string according to the current preference value. + * + * @param update {@code true} to call {@link #onUpdate()} method after setting the + * value string. */ - public void updateValueString() { + public void updateValueString(boolean update) { if (mEntries != null) { - setValueString(mEntries[Arrays.asList(mValues).indexOf(getPreferenceValue())]); + setValueString(mEntries[Arrays.asList(mValues) + .indexOf(getPreferenceValue())], update); } } /** - * Set the value for this preference and save it in the - * shared preferences. + * Set the value for this preference and save it in the shared preferences. * * @param value The preference value. */ public void setPreferenceValue(@NonNull String value) { if (getPreferenceKey() != null) { DynamicPreferences.getInstance().savePrefs(getPreferenceKey(), value); - updateValueString(); } + + updateValueString(true); } /** + * Returns the current value of this preference. + * * @return The current value of this preference. */ public @Nullable String getPreferenceValue() { @@ -182,7 +201,7 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Strin super.onSharedPreferenceChanged(sharedPreferences, key); if (key.equals(getPreferenceKey())) { - updateValueString(); + updateValueString(true); } } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicThemePreference.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicThemePreference.java new file mode 100644 index 0000000000..25dff37929 --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/setting/DynamicThemePreference.java @@ -0,0 +1,255 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.setting; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.AttrRes; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.pranavpandey.android.dynamic.support.R; +import com.pranavpandey.android.dynamic.support.model.DynamicAppTheme; +import com.pranavpandey.android.dynamic.support.preference.DynamicPreferences; +import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.view.DynamicThemePreview; + +/** + * A DynamicSpinnerPreference to display and edit the dynamic theme. + */ +public class DynamicThemePreference extends DynamicSpinnerPreference { + + /** + * Default theme value for this preference. + */ + private String mDefaultTheme; + + /** + * Current theme value for this preference. + */ + private String mTheme; + + /** + * Current dynamic theme value for this preference. + */ + private DynamicAppTheme mDynamicAppTheme; + + /** + * {@code true} if theme preview is enabled. + */ + private boolean mThemeEnabled; + + /** + * Theme preview used by this preference. + */ + private DynamicThemePreview mThemePreview; + + /** + * Theme preview icon used by this preference. + */ + private ImageView mThemePreviewIcon; + + /** + * Theme preview description used by this preference. + */ + private TextView mThemePreviewDescription; + + /** + * On click listener to receive theme click events. + */ + private View.OnClickListener mOnThemeClickListener; + + public DynamicThemePreference(@NonNull Context context) { + super(context); + } + + public DynamicThemePreference(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public DynamicThemePreference(@NonNull Context context, + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onLoadAttributes(@Nullable AttributeSet attrs) { + super.onLoadAttributes(attrs); + + TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.DynamicPreference); + + try { + mDefaultTheme = a.getString( + R.styleable.DynamicPreference_ads_theme); + } finally { + a.recycle(); + } + + if (mDefaultTheme == null) { + mDefaultTheme = DynamicTheme.getInstance().get().toJsonString(); + } + + mThemeEnabled = true; + } + + @Override + protected @LayoutRes int getLayoutRes() { + return R.layout.ads_preference_theme; + } + + @Override + protected void onInflate() { + super.onInflate(); + + mThemePreview = findViewById(R.id.ads_theme_preview); + mThemePreviewIcon = findViewById(R.id.ads_theme_preview_icon); + mThemePreviewDescription = findViewById(R.id.ads_theme_preview_description); + } + + @Override + public @Nullable String getPreferenceKey() { + return getAltPreferenceKey(); + } + + @Override + protected void onUpdate() { + super.onUpdate(); + + mTheme = DynamicPreferences.getInstance() + .loadPrefs(super.getPreferenceKey(), mDefaultTheme); + mDynamicAppTheme = DynamicTheme.getInstance().getTheme(mTheme); + + if (mDynamicAppTheme != null) { + mThemePreview.setDynamicAppTheme(mDynamicAppTheme); + mThemePreviewDescription.setVisibility( + mDynamicAppTheme.isBackgroundAware() ? VISIBLE : GONE); + } + } + + @Override + protected void onEnabled(boolean enabled) { + super.onEnabled(enabled); + + mThemePreview.setEnabled(enabled && mThemeEnabled); + mThemePreviewIcon.setEnabled(enabled && mThemeEnabled); + mThemePreviewDescription.setEnabled(enabled && mThemeEnabled); + } + + /** + * Enable or disable the theme preview. + * + * @param enabled {@code true} to enable the theme preview. + */ + public void setThemeEnabled(boolean enabled) { + this.mThemeEnabled = enabled; + + setEnabled(isEnabled()); + } + + /** + * Get the default theme value for this preference. + * + * @return The default theme value for this preference. + */ + public @Nullable String getDefaultTheme() { + return mDefaultTheme; + } + + /** + * Set the default theme value for this preference. + * + * @param defaultTheme The default theme value to be set. + */ + public void setDefaultTheme(@NonNull String defaultTheme) { + this.mDefaultTheme = defaultTheme; + + onUpdate(); + } + + /** + * Get the current theme value for this preference. + * + * @return The current theme value for this preference. + */ + public @Nullable String getTheme() { + return mTheme; + } + + /** + * Set the current theme value of this preference. + * + * @param theme The theme value to be set. + * @param save {@code true} to update the shared preferences. + */ + public void setTheme(@NonNull String theme, boolean save) { + this.mTheme = theme; + + if (getPreferenceKey() != null && save) { + DynamicPreferences.getInstance().savePrefs(getPreferenceKey(), theme); + } + } + + /** + * Set the current theme value of this preference. + * + * @param theme The theme value to be set. + */ + public void setTheme(@NonNull String theme) { + setTheme(theme, true); + } + + /** + * Returns the on click listener to receive theme click events. + * + * @return The on click listener to receive theme click events. + */ + public OnClickListener getOnThemeClickListener() { + return mOnThemeClickListener; + } + + /** + * Set the on click listener for theme to receive the click events and to perform + * edit operation. + * + * @param onThemeClickListener The on click listener to be set. + */ + public void setOnThemeClickListener(@Nullable View.OnClickListener onThemeClickListener) { + this.mOnThemeClickListener = onThemeClickListener; + + mThemePreview.setOnFABClickListener(mOnThemeClickListener); + onEnabled(isEnabled()); + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + super.onSharedPreferenceChanged(sharedPreferences, key); + + if (key.equals(super.getPreferenceKey())) { + mTheme = DynamicPreferences.getInstance() + .loadPrefs(super.getPreferenceKey(), mTheme); + + onUpdate(); + } + } +} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/splash/DynamicSplashActivity.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/splash/DynamicSplashActivity.java index 83a52fd931..992651e9ea 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/splash/DynamicSplashActivity.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/splash/DynamicSplashActivity.java @@ -17,30 +17,29 @@ package com.pranavpandey.android.dynamic.support.splash; import android.os.Bundle; -import android.support.annotation.ColorInt; -import android.support.annotation.Nullable; -import android.support.design.widget.CoordinatorLayout; -import android.support.v4.app.Fragment; + +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.fragment.app.Fragment; import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.activity.DynamicSystemActivity; /** - * An activity to show a splash screen before the actual app launch. - * Its layout can be fully customised and it also provides multiple - * methods to do any background work before launching the main activity - * by running an {@link android.os.AsyncTask}. + * An activity to show a splash screen before the actual app launch. Its layout can be fully + * customised and it also provides multiple methods to do any background work before launching + * the main activity by running an {@link android.os.AsyncTask}. * - *

Just extend this activity and implement the required functions to - * show a splash screen. It should be declared as the main activity in - * the projects's manifest for best performance.

+ *

Just extend this activity and implement the required functions to show a splash screen. + * It should be declared as the main activity in the projects's manifest for best performance. */ public abstract class DynamicSplashActivity extends DynamicSystemActivity implements DynamicSplashListener { /** - * Splash fragment TAG key which will be used to find it - * during the configuration changes. + * Splash fragment TAG key which will be used to find it during the configuration changes. */ protected static final String ADS_STATE_SPLASH_FRAGMENT_TAG = "ads_state_splash_fragment_tag"; @@ -83,14 +82,11 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { mContentFragment = DynamicSplashFragment.newInstance(getLayoutRes()); } + setStatusBarColor(getStatusBarColor()); + ((DynamicSplashFragment) mContentFragment).setOnSplashListener(this); + getSupportFragmentManager().beginTransaction().replace( R.id.ads_container, mContentFragment, ADS_STATE_SPLASH_FRAGMENT_TAG).commit(); - - if (savedInstanceState == null) { - ((DynamicSplashFragment) mContentFragment).setOnSplashListener(this); - } - - setStatusBarColor(getStatusBarColor()); } @Override @@ -117,18 +113,31 @@ public long getMinSplashTime() { } @Override - public void onSaveInstanceState(@Nullable Bundle savedInstanceState) { - super.onSaveInstanceState(savedInstanceState); + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); ADS_SPLASH_MAGIC = true; } @Override - public void onDestroy() { - super.onDestroy(); + public void onPause() { + if (mContentFragment != null) { + ((DynamicSplashFragment) mContentFragment).setOnSplashListener(null); + + if (!isChangingConfigurations()) { + ((DynamicSplashFragment) mContentFragment).stop(); + } + } + super.onPause(); + } + + @Override + public void onResume() { + super.onResume(); - if (!ADS_SPLASH_MAGIC && mContentFragment != null) { - ((DynamicSplashFragment) mContentFragment).stop(); + if (!isChangingConfigurations() && ADS_SPLASH_MAGIC && mContentFragment != null) { + ((DynamicSplashFragment) mContentFragment).setOnSplashListener(this); + ((DynamicSplashFragment) mContentFragment).show(); } } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/splash/DynamicSplashFragment.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/splash/DynamicSplashFragment.java index dedc2be89b..07733d4021 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/splash/DynamicSplashFragment.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/splash/DynamicSplashFragment.java @@ -18,17 +18,18 @@ import android.os.AsyncTask; import android.os.Bundle; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + /** * A fragment to display splash before launching the main activity. - * It will be used internally by the {@link DynamicSplashActivity}. + *

It will be used internally by the {@link DynamicSplashActivity}. */ public class DynamicSplashFragment extends Fragment { @@ -38,14 +39,13 @@ public class DynamicSplashFragment extends Fragment { private static final String ADS_ARGS_SPLASH_LAYOUT_RES = "ads_args_splash_layout_res"; /** - * Async task to perform any background operation whiling showing the - * splash. + * Async task to perform any background operation whiling showing the splash. */ private SplashTask mSplashTask; /** - * Listener to implement the splash screen and to get various - * callbacks while showing the splash. + * Listener to implement the splash screen and to get various callbacks while showing + * the splash. */ private DynamicSplashListener mDynamicSplashListener; @@ -86,8 +86,8 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) { } @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, + @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { if (getArguments() != null && getArguments().getInt(ADS_ARGS_SPLASH_LAYOUT_RES) != -1) { mView = inflater.inflate(getArguments().getInt(ADS_ARGS_SPLASH_LAYOUT_RES), container, false); @@ -114,26 +114,27 @@ public void stop() { } /** - * @return The listener to implement the splash screen and to get - * various callbacks while showing the splash. + * Returns listener to implement the splash screen and to get various callbacks while + * showing the splash. + * + * @return The listener to implement the splash screen. */ - public DynamicSplashListener getOnSplashListener() { + public @Nullable DynamicSplashListener getOnSplashListener() { return mDynamicSplashListener; } /** - * Set the listener to implement the splash screen and to get - * various callbacks while showing the splash. + * Set the listener to implement the splash screen and to get various callbacks while + * showing the splash. * * @param dynamicSplashListener The listener to be set. */ - public void setOnSplashListener(DynamicSplashListener dynamicSplashListener) { + public void setOnSplashListener(@Nullable DynamicSplashListener dynamicSplashListener) { mDynamicSplashListener = dynamicSplashListener; } /** - * Async task to perform any background operation while showing - * the splash. + * Async task to perform any background operation while showing the splash. */ static class SplashTask extends AsyncTask { @@ -148,16 +149,15 @@ static class SplashTask extends AsyncTask { long taskTimeElapsed; /** - * Listener to implement the splash screen and to get various - * callbacks while showing the splash. + * Listener to implement the splash screen and to get various callbacks while + * showing the splash. */ private DynamicSplashListener dynamicSplashListener; /** * Constructor to initialize an object of this class. * - * @param dynamicSplashListener The splash listener to get the - * various callbacks. + * @param dynamicSplashListener The splash listener to get the various callbacks. */ SplashTask(@Nullable DynamicSplashListener dynamicSplashListener) { this.dynamicSplashListener = dynamicSplashListener; @@ -177,13 +177,13 @@ protected void onPreExecute() { protected Void doInBackground(Void... params) { if (dynamicSplashListener != null) { dynamicSplashListener.doBehindSplash(); - } - taskTimeElapsed = System.currentTimeMillis() - taskStartTime; - if (taskTimeElapsed < dynamicSplashListener.getMinSplashTime()) { - try { - Thread.sleep(dynamicSplashListener.getMinSplashTime() - taskTimeElapsed); - } catch (InterruptedException ignored) { + taskTimeElapsed = System.currentTimeMillis() - taskStartTime; + if (taskTimeElapsed < dynamicSplashListener.getMinSplashTime()) { + try { + Thread.sleep(dynamicSplashListener.getMinSplashTime() - taskTimeElapsed); + } catch (InterruptedException ignored) { + } } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/splash/DynamicSplashListener.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/splash/DynamicSplashListener.java index 0d4146b6aa..7ca56b4e2a 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/splash/DynamicSplashListener.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/splash/DynamicSplashListener.java @@ -16,52 +16,54 @@ package com.pranavpandey.android.dynamic.support.splash; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; import android.view.View; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; + /** - * Interface to implement the splash screen and to get various - * callbacks while showing the splash. + * Interface to implement the splash screen and to get various callbacks while showing the splash. */ public interface DynamicSplashListener { /** + * This method will be called to get the layout resource for the splash. + * * @return The splash layout resource. */ @LayoutRes int getLayoutRes(); /** - * This method will be called just after creating the splash fragment - * with the supplied layout resource. Do any modifications in - * the splash layout here. + * This method will be called just after creating the splash fragment with the supplied + * layout resource. + *

Do any modifications in the splash layout here. * * @param view The view created from the layout resource. */ void onViewCreated(@NonNull View view); /** - * @return The minimum time in milliseconds for which the splash - * must be displayed. + * This method will be called to get the minimum time in milliseconds for which the splash + * must be displayed. + * + * @return The minimum time in milliseconds for which the splash must be displayed. */ long getMinSplashTime(); /** - * This method will be called before starting the splash background - * task. + * This method will be called before starting the splash background task. */ void onPreSplash(); /** * This method will be called after starting the splash background task. - * Do any time taking operation here. Do not perform any UI related - * operation here, use {@link #onPostSplash()} here. + *

Do any time taking operation here. Do not perform any UI related operation here, + * use {@link #onPostSplash()} here. */ void doBehindSplash(); /** - * This method will be called after finishing the splash background - * task. + * This method will be called after finishing the splash background task. */ void onPostSplash(); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/strategy/ExcludeStrategy.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/strategy/ExcludeStrategy.java new file mode 100644 index 0000000000..44ef2b05f0 --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/strategy/ExcludeStrategy.java @@ -0,0 +1,37 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.strategy; + +import com.google.gson.ExclusionStrategy; +import com.google.gson.FieldAttributes; +import com.pranavpandey.android.dynamic.support.annotation.Exclude; + +/** + * A {@link com.google.gson.Gson} exclusion strategy to exclude the field from the json string. + */ +public class ExcludeStrategy implements ExclusionStrategy { + + @Override + public boolean shouldSkipField(FieldAttributes f) { + return f.getAnnotation(Exclude.class) != null; + } + + @Override + public boolean shouldSkipClass(Class clazz) { + return false; + } +} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/DynamicColorType.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/DynamicColorType.java deleted file mode 100644 index 3444cd8fd2..0000000000 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/DynamicColorType.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2018 Pranav Pandey - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.pranavpandey.android.dynamic.support.theme; - -import android.support.annotation.IntDef; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -import static com.pranavpandey.android.dynamic.support.theme.DynamicColorType.ACCENT; -import static com.pranavpandey.android.dynamic.support.theme.DynamicColorType.ACCENT_DARK; -import static com.pranavpandey.android.dynamic.support.theme.DynamicColorType.BACKGROUND; -import static com.pranavpandey.android.dynamic.support.theme.DynamicColorType.CUSTOM; -import static com.pranavpandey.android.dynamic.support.theme.DynamicColorType.NONE; -import static com.pranavpandey.android.dynamic.support.theme.DynamicColorType.PRIMARY; -import static com.pranavpandey.android.dynamic.support.theme.DynamicColorType.PRIMARY_DARK; -import static com.pranavpandey.android.dynamic.support.theme.DynamicColorType.TINT_ACCENT; -import static com.pranavpandey.android.dynamic.support.theme.DynamicColorType.TINT_ACCENT_DARK; -import static com.pranavpandey.android.dynamic.support.theme.DynamicColorType.TINT_BACKGROUND; -import static com.pranavpandey.android.dynamic.support.theme.DynamicColorType.TINT_PRIMARY; -import static com.pranavpandey.android.dynamic.support.theme.DynamicColorType.TINT_PRIMARY_DARK; - -/** - * Interface to hold the color type constant values according to the - * {@link com.pranavpandey.android.dynamic.support.R.attr#ads_colorType}. - */ -@Retention(RetentionPolicy.SOURCE) -@IntDef(value = { NONE, PRIMARY, PRIMARY_DARK, ACCENT, ACCENT_DARK, TINT_PRIMARY, - TINT_PRIMARY_DARK, TINT_ACCENT, TINT_ACCENT_DARK, CUSTOM, BACKGROUND, TINT_BACKGROUND }) -public @interface DynamicColorType { - - /** - * Constant for unknown color. - */ - int UNKNOWN = -2; - - /** - * Constant for no color. - */ - int NONE = 0; - - /** - * Constant for {@link DynamicTheme#mPrimaryColor}. - */ - int PRIMARY = 1; - - /** - * Constant for {@link DynamicTheme#mPrimaryColorDark}. - */ - int PRIMARY_DARK = 2; - - /** - * Constant for {@link DynamicTheme#mAccentColor}. - */ - int ACCENT = 3; - - /** - * Constant for {@link DynamicTheme#mAccentColorDark}. - */ - int ACCENT_DARK = 4; - - /** - * Constant for {@link DynamicTheme#mTintPrimaryColor}. - */ - int TINT_PRIMARY = 5; - - /** - * Constant for {@link DynamicTheme#mTintPrimaryColorDark}. - */ - int TINT_PRIMARY_DARK = 6; - - /** - * Constant for {@link DynamicTheme#mTintAccentColor}. - */ - int TINT_ACCENT = 7; - - /** - * Constant for {@link DynamicTheme#mTintAccentColorDark}. - */ - int TINT_ACCENT_DARK = 8; - - /** - * Constant for custom color. - */ - int CUSTOM = 9; - - /** - * Constant for {@link DynamicTheme#mBackgroundColor}. - */ - int BACKGROUND = 10; - - /** - * Constant for {@link DynamicTheme#mTintBackgroundColor}. - */ - int TINT_BACKGROUND = 11; -} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/DynamicLayoutInflater.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/DynamicLayoutInflater.java index 15d3403ee2..893b5e6abf 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/DynamicLayoutInflater.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/DynamicLayoutInflater.java @@ -19,31 +19,39 @@ import android.annotation.SuppressLint; import android.content.Context; import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; import android.os.Handler; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.RestrictTo; -import android.support.v4.view.ViewCompat; -import android.support.v7.view.menu.ListMenuItemView; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; import android.widget.ListView; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.RestrictTo; +import androidx.appcompat.view.menu.ListMenuItemView; +import androidx.cardview.widget.CardView; +import androidx.core.view.ViewCompat; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; import com.pranavpandey.android.dynamic.support.utils.DynamicScrollUtils; import com.pranavpandey.android.dynamic.support.widget.DynamicBottomNavigationView; +import com.pranavpandey.android.dynamic.support.widget.DynamicButton; import com.pranavpandey.android.dynamic.support.widget.DynamicCardView; import com.pranavpandey.android.dynamic.support.widget.DynamicCheckBox; import com.pranavpandey.android.dynamic.support.widget.DynamicDrawerLayout; import com.pranavpandey.android.dynamic.support.widget.DynamicEditText; import com.pranavpandey.android.dynamic.support.widget.DynamicFloatingActionButton; +import com.pranavpandey.android.dynamic.support.widget.DynamicImageButton; import com.pranavpandey.android.dynamic.support.widget.DynamicImageView; import com.pranavpandey.android.dynamic.support.widget.DynamicListView; import com.pranavpandey.android.dynamic.support.widget.DynamicNavigationView; import com.pranavpandey.android.dynamic.support.widget.DynamicNestedScrollView; +import com.pranavpandey.android.dynamic.support.widget.DynamicPopupBackground; import com.pranavpandey.android.dynamic.support.widget.DynamicProgressBar; import com.pranavpandey.android.dynamic.support.widget.DynamicRadioButton; import com.pranavpandey.android.dynamic.support.widget.DynamicRecyclerView; @@ -58,13 +66,15 @@ import com.pranavpandey.android.dynamic.support.widget.DynamicTextView; import com.pranavpandey.android.dynamic.support.widget.DynamicToolbar; import com.pranavpandey.android.dynamic.support.widget.DynamicViewPager; +import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; import com.pranavpandey.android.dynamic.utils.DynamicDrawableUtils; +import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils; -import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP; +import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; /** - * A layout inflater factory2 to replace original views with the - * dynamic support views during inflation. + * A layout inflater factory2 to replace original views with the dynamic support views + * during inflation. */ @RestrictTo(LIBRARY_GROUP) final class DynamicLayoutInflater implements LayoutInflater.Factory2 { @@ -75,57 +85,92 @@ final class DynamicLayoutInflater implements LayoutInflater.Factory2 { private static final String ADS_TAG_IGNORE = ":ads_ignore"; @Override - public View onCreateView(String name, @NonNull Context context, - @NonNull AttributeSet attrs) { + public View onCreateView(String name, @NonNull Context context, @NonNull AttributeSet attrs) { return onCreateView(null, name, context, attrs); } @Override @SuppressLint("RestrictedApi") public View onCreateView(@Nullable View parent, final String name, - @NonNull Context context, @NonNull AttributeSet attrs) { + final @NonNull Context context, final @NonNull AttributeSet attrs) { View view = null; switch (name) { case "android.support.v4.widget.DrawerLayout": + case "androidx.DrawerLayout.widget.DrawerLayout": view = new DynamicDrawerLayout(context, attrs); break; case "android.support.v4.widget.SwipeRefreshLayout": + case "androidx.SwipeRefreshLayout.widget.SwipeRefreshLayout": view = new DynamicSwipeRefreshLayout(context, attrs); break; case "Toolbar": case "android.support.v7.widget.Toolbar": + case "androidx.appcompat.widget.Toolbar": view = new DynamicToolbar(context, attrs); break; case "ListMenuItemView": case "android.support.v7.view.menu.ListMenuItemView": + case "androidx.appcompat.view.menu.ListMenuItemView": try { + final @ColorInt int backgroundColor = + DynamicTheme.getInstance().get().getBackgroundColor(); + final View menuItemView = LayoutInflater.from(context) .createView(name, null, attrs); - final Drawable drawable = DynamicResourceUtils.getDrawable( - context, R.drawable.ads_background); - DynamicDrawableUtils.colorizeDrawable(drawable, - DynamicTheme.getInstance().getBackgroundColor()); new Handler().post(new Runnable() { @Override public void run() { - final @ColorInt int backgroundTintColor = - DynamicTheme.getInstance().getTintBackgroundColor(); + @ColorInt int tintColor = DynamicTheme + .getInstance().get().getTintBackgroundColor(); + if (DynamicTheme.getInstance().get().isBackgroundAware()) { + tintColor = DynamicColorUtils.getContrastColor( + tintColor, backgroundColor); + } + final Drawable icon = ((ListMenuItemView) menuItemView) .getItemData().getIcon(); - try { if (icon != null) { ((ListMenuItemView) menuItemView).setIcon( - DynamicDrawableUtils.colorizeDrawable( - icon, backgroundTintColor)); + DynamicDrawableUtils.colorizeDrawable(icon, tintColor)); } - ViewCompat.setBackground( - ((View) menuItemView.getParent()), drawable); - DynamicScrollUtils.setEdgeEffectColor( - (ListView) menuItemView.getParent(), backgroundTintColor); + if (menuItemView.getParent() != null) { + ViewGroup view = (ViewGroup) menuItemView.getParent(); + ViewGroup parent = (ViewGroup) view.getParent(); + + DynamicScrollUtils.setEdgeEffectColor( + (ListView) view, tintColor); + + if (DynamicVersionUtils.isLollipop()) { + if (!(parent instanceof CardView)) { + DynamicCardView cardView = + new DynamicPopupBackground(context, attrs); + + if (parent.getBackground() instanceof GradientDrawable) { + GradientDrawable backgroundDrawable = + ((GradientDrawable) parent.getBackground()); + backgroundDrawable.setColor(backgroundColor); + backgroundDrawable.setCornerRadius(DynamicTheme + .getInstance().get().getCornerRadius()); + } + + parent.removeAllViews(); + parent.addView(cardView); + cardView.addView(view); + } else { + parent.removeAllViews(); + parent.addView(view); + } + } else { + ViewCompat.setBackground(view, DynamicDrawableUtils + .colorizeDrawable(DynamicResourceUtils.getDrawable( + context, R.drawable.ads_background), + backgroundColor)); + } + } } catch (Exception ignored) { } } @@ -135,77 +180,113 @@ public void run() { } catch (Exception ignored) { } break; - case "CardView": - case "android.support.v7.widget.CardView": - view = new DynamicCardView(context, attrs); + case "Button": + view = new Button(context, attrs); + ((Button) view).setTextColor(DynamicResourceUtils.getColorStateList( + DynamicTheme.getInstance().get().getTintBackgroundColor())); + break; + case "android.support.v7.widget.AppCompatButton": + case "androidx.appcompat.widget.AppCompatButton": + case "com.google.android.material.button.MaterialButton": + view = new DynamicButton(context, attrs); + break; + case "ImageButton": + case "android.support.v7.widget.AppCompatImageButton": + case "androidx.appcompat.widget.AppCompatImageButton": + view = new DynamicImageButton(context, attrs); break; case "ImageView": case "android.support.v7.widget.AppCompatImageView": + case "androidx.appcompat.widget.AppCompatImageView": view = new DynamicImageView(context, attrs); break; case "TextView": case "android.support.v7.widget.AppCompatTextView": + case "androidx.appcompat.widget.AppCompatTextView": view = new DynamicTextView(context, attrs); break; case "CheckBox": case "android.support.v7.widget.AppCompatCheckBox": + case "androidx.appcompat.widget.AppCompatCheckBox": view = new DynamicCheckBox(context, attrs); break; case "RadioButton": case "android.support.v7.widget.AppCompatRadioButton": + case "androidx.appcompat.widget.AppCompatRadioButton": view = new DynamicRadioButton(context, attrs); break; case "EditText": case "android.support.v7.widget.AppCompatEditText": + case "androidx.appcompat.widget.AppCompatEditText": view = new DynamicEditText(context, attrs); break; case "android.support.v7.widget.SwitchCompat": + case "androidx.appcompat.widget.SwitchCompat": view = new DynamicSwitchCompat(context, attrs); break; case "SeekBar": case "android.support.v7.widget.AppCompatSeekBar": + case "androidx.appcompat.widget.AppCompatSeekBar": view = new DynamicSeekBar(context, attrs); break; + case "Spinner": + case "android.support.v7.widget.AppCompatSpinner": + case "androidx.appcompat.widget.AppCompatSpinner": + view = new DynamicSpinner(context, attrs); + break; case "ProgressBar": + case "android.support.v4.widget.ContentLoadingProgressBar": + case "androidx.core.widget.ContentLoadingProgressBar": view = new DynamicProgressBar(context, attrs); break; case "android.support.v7.widget.RecyclerView": + case "androidx.recyclerview.widget.RecyclerView": view = new DynamicRecyclerView(context, attrs); break; case "android.support.v4.widget.NestedScrollView": + case "androidx.core.widget.NestedScrollView": view = new DynamicNestedScrollView(context, attrs); break; - case "ListView": - view = new DynamicListView(context, attrs); - break; - case "ScrollView": - view = new DynamicScrollView(context, attrs); - break; case "android.support.v4.view.ViewPager": + case "androidx.viewpager.widget.ViewPager": view = new DynamicViewPager(context, attrs); break; - case "Spinner": - case "android.support.v7.widget.AppCompatSpinner": - view = new DynamicSpinner(context, attrs); - break; - case "android.support.design.widget.TextInputLayout": - view = new DynamicTextInputLayout(context, attrs); + case "android.support.design.widget.NavigationView": + case "com.google.android.material.navigation.NavigationView": + view = new DynamicNavigationView(context, attrs); break; - case "android.support.design.widget.TextInputEditText": - view = new DynamicTextInputEditText(context, attrs); + case "android.support.design.widget.BottomNavigationView": + case "com.google.android.material.bottomnavigation.BottomNavigationView": + view = new DynamicBottomNavigationView(context, attrs); break; case "android.support.design.widget.TabLayout": + case "com.google.android.material.tabs.TabLayout": view = new DynamicTabLayout(context, attrs); break; - case "android.support.design.widget.NavigationView": - view = new DynamicNavigationView(context, attrs); + case "CardView": + case "android.support.v7.widget.CardView": + case "androidx.cardview.widget.CardView": + case "com.google.android.material.card.CardView": + view = new DynamicCardView(context, attrs); break; - case "android.support.design.widget.BottomNavigationView": - view = new DynamicBottomNavigationView(context, attrs); + case "android.support.design.widget.TextInputLayout": + case "com.google.android.material.textfield.TextInputLayout": + view = new DynamicTextInputLayout(context, attrs); + break; + case "android.support.design.widget.TextInputEditText": + case "com.google.android.material.textfield.TextInputEditText": + view = new DynamicTextInputEditText(context, attrs); break; case "android.support.design.widget.FloatingActionButton": + case "com.google.android.material.floatingactionbutton.FloatingActionButton": view = new DynamicFloatingActionButton(context, attrs); break; + case "ListView": + view = new DynamicListView(context, attrs); + break; + case "ScrollView": + view = new DynamicScrollView(context, attrs); + break; } if (view != null && view.getTag() != null && view.getTag().equals(ADS_TAG_IGNORE)) { diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/DynamicTheme.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/DynamicTheme.java index 765770b1c2..19d3d4c31e 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/DynamicTheme.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/DynamicTheme.java @@ -19,18 +19,23 @@ import android.app.Activity; import android.content.Context; import android.graphics.Color; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StyleRes; -import android.support.v4.content.ContextCompat; -import android.support.v4.view.LayoutInflaterCompat; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StyleRes; +import androidx.core.content.ContextCompat; +import androidx.core.view.LayoutInflaterCompat; + +import com.google.gson.Gson; import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.listener.DynamicListener; +import com.pranavpandey.android.dynamic.support.model.DynamicAppTheme; +import com.pranavpandey.android.dynamic.support.model.DynamicWidgetTheme; import com.pranavpandey.android.dynamic.support.preference.DynamicPreferences; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; +import com.pranavpandey.android.dynamic.utils.DynamicUnitUtils; import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils; import java.util.ArrayList; @@ -38,1800 +43,469 @@ /** * Helper class to manage theme for the whole application and its activities. - * It must be initialized before using any activity or widget as they are + *

It must be initialized before using any activity or widget as they are * heavily dependent on this class to generate colors dynamically. */ public class DynamicTheme implements DynamicListener { /** - * Dynamic theme shared preferences. - */ - public static final String ADS_PREF_THEME = "ads_dynamic_theme"; - - /** - * Key for the theme preference. - */ - public static final String ADS_PREF_THEME_KEY = "ads_theme_"; - - /** - * Constant for the auto theme. - */ - public static final int ADS_THEME_AUTO = 0; - - /** - * Default shift amount to generate the darker color. - */ - public static final float ADS_COLOR_SHIFT_DARK_DEFAULT = 0.9f; - - /** - * Default primary color used by this theme if no color is supplied. - */ - private static final @ColorInt int ADS_COLOR_PRIMARY_DEFAULT = - Color.parseColor("#3F51B5"); - - /** - * Default dark primary color used by this theme if no color is supplied. - */ - private static final @ColorInt int ADS_COLOR_PRIMARY_DARK_DEFAULT = - Color.parseColor("#303F9F"); - - /** - * Default accent color used by this theme if no color is supplied. - */ - private static final @ColorInt int ADS_COLOR_ACCENT_DEFAULT = - Color.parseColor("#E91E63"); - - /** - * Background color used by the application. - */ - private @ColorInt int mBackgroundColor; - - /** - * Primary color used by the application. - */ - private @ColorInt int mPrimaryColor; - - /** - * Dark primary color used by the application. - */ - private @ColorInt int mPrimaryColorDark; - - /** - * Accent color used by the application. - */ - private @ColorInt int mAccentColor; - - /** - * Dark accent color used by the application. - */ - private @ColorInt int mAccentColorDark; - - /** - * Tint color according to the background color. - */ - private @ColorInt int mTintBackgroundColor; - - /** - * Tint color according to the primary color. - */ - private @ColorInt int mTintPrimaryColor; - - /** - * Tint color according to the dark primary color. - */ - private @ColorInt int mTintPrimaryColorDark; - - /** - * Tint color according to the accent color. - */ - private @ColorInt int mTintAccentColor; - - /** - * Tint color according to the dark accent color. - */ - private @ColorInt int mTintAccentColorDark; - - /** - * Background color for remote views used by the application - */ - private @ColorInt int mRemoteBackgroundColor; - - /** - * Primary color for remote views used by the application. - */ - private @ColorInt int mRemotePrimaryColor; - - /** - * Accent color for remote views used by the application. - */ - private @ColorInt int mRemoteAccentColor; - - /** - * Tint color according to the remote background color. - */ - private @ColorInt int mTintRemoteBackgroundColor; - - /** - * Tint color according to the remote primary color. - */ - private @ColorInt int mTintRemotePrimaryColor; - - /** - * Tint color according to the remote accent color. - */ - private @ColorInt int mTintRemoteAccentColor; - - /** - * Background color used by the notification. - */ - private @ColorInt int mNotificationBackgroundColor; - - /** - * Primary color used by the notification. - */ - private @ColorInt int mNotificationPrimaryColor; - - /** - * Accent color used by the notification. - */ - private @ColorInt int mNotificationAccentColor; - - /** - * Tint color according to the notification background color. - */ - private @ColorInt int mTintNotificationBackgroundColor; - - /** - * Tint color according to the notification primary color. - */ - private @ColorInt int mTintNotificationPrimaryColor; - - /** - * Tint color according to the notification accent color. - */ - private @ColorInt int mTintNotificationAccentColor; - - /** - * Background color used by the widget. - */ - private @ColorInt int mWidgetBackgroundColor; - - /** - * Primary color used by the widget. - */ - private @ColorInt int mWidgetPrimaryColor; - - /** - * Accent color used by the widget. - */ - private @ColorInt int mWidgetAccentColor; - - /** - * Tint color according to the widget background color. - */ - private @ColorInt int mTintWidgetBackgroundColor; - - /** - * Tint color according to the widget primary color. - */ - private @ColorInt int mTintWidgetPrimaryColor; - - /** - * Tint color according to the widget accent color. - */ - private @ColorInt int mTintWidgetAccentColor; - - /** - * Theme resource used by the local context. - */ - private @ColorInt int mLocalThemeRes; - - /** - * Background color used by the local context. - */ - private @ColorInt int mLocalBackgroundColor; - - /** - * Primary color used by the local context. - */ - private @ColorInt int mLocalPrimaryColor; - - /** - * Dark primary color used by the local context. - */ - private @ColorInt int mLocalPrimaryColorDark; - - /** - * Accent color used by the local context. - */ - private @ColorInt int mLocalAccentColor; - - /** - * Dark accent color used by the local context. - */ - private @ColorInt int mLocalAccentColorDark; - - /** - * Tint color according to the local background color. - */ - private @ColorInt int mTintLocalBackgroundColor; - - /** - * Tint color according to the local primary color. - */ - private @ColorInt int mTintLocalPrimaryColor; - - /** - * Tint color according to the local dark primary color. - */ - private @ColorInt int mTintLocalPrimaryColorDark; - - /** - * Tint color according to the local accent color. - */ - private @ColorInt int mTintLocalAccentColor; - - /** - * Tint color according to the local dark accent color. - */ - private @ColorInt int mTintLocalAccentColorDark; - - /** - * Singleton instance of {@link DynamicTheme}. - */ - private static DynamicTheme sInstance; - - /** - * Application context used by this theme instance. - */ - private Context mContext; - - /** - * Local activity context used by this theme instance. - */ - private Context mLocalContext; - - /** - * Collection of dynamic listeners to send them event callback. - */ - private List mDynamicListeners; - - /** - * Making default constructor private so that it cannot be initialized - * without a context. Use {@link #initializeInstance(Context)} instead. - */ - private DynamicTheme() { } - - /** - * Constructor to initialize an object of this class. - * - * @param context The application context to be attached - * with this theme. - */ - private DynamicTheme(@NonNull Context context) { - this.mContext = context; - this.mPrimaryColor = ADS_COLOR_PRIMARY_DEFAULT; - this.mPrimaryColorDark = ADS_COLOR_PRIMARY_DARK_DEFAULT; - this.mAccentColor = ADS_COLOR_ACCENT_DEFAULT; - this.mDynamicListeners = new ArrayList<>(); - } - - /** - * Attach a local context to this theme. It can be an activity in - * case different themes are required for different activities. - * - * @param localContext The context to be attached with this theme. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - */ - public DynamicTheme attach(@NonNull Context localContext) { - this.mLocalContext = localContext; - this.mLocalPrimaryColor = ADS_COLOR_PRIMARY_DEFAULT; - this.mLocalPrimaryColorDark = ADS_COLOR_PRIMARY_DARK_DEFAULT; - this.mLocalAccentColor = ADS_COLOR_ACCENT_DEFAULT; - - if (localContext instanceof Activity && ((Activity) localContext) - .getLayoutInflater().getFactory2() == null) { - LayoutInflaterCompat.setFactory2(((Activity) localContext) - .getLayoutInflater(), new DynamicLayoutInflater()); - } - return this; - } - - /** - * Initialize theme when application starts. - * Must be initialized once. - * - * @param context The context to retrieve resources. - */ - public static synchronized void initializeInstance(@Nullable Context context) { - if (context == null) { - throw new NullPointerException("Context should not be null"); - } - - if (sInstance == null) { - sInstance = new DynamicTheme(context); - } - } - - /** - * Get instance to access public methods. Must be called before - * accessing methods. - * - * @return The singleton instance of this class. - */ - public static synchronized DynamicTheme getInstance() { - if (sInstance == null) { - throw new IllegalStateException(DynamicTheme.class.getSimpleName() + - " is not initialized, call initializeInstance(..) method first."); - } - - return sInstance; - } - - /** - * Initialize colors form the supplied theme resource. - * - * @param theme The theme resource to initialize colors. - * @param initializeRemoteColors {@code true} to initialize remote - * colors also. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - */ - public DynamicTheme setTheme(@StyleRes int theme, boolean initializeRemoteColors) { - mContext.getTheme().applyStyle(theme, true); - - this.mBackgroundColor = DynamicResourceUtils.resolveColor(mContext, - android.R.attr.windowBackground, DynamicColorType.NONE); - this.mPrimaryColor = DynamicResourceUtils.resolveColor(mContext, - android.support.v7.appcompat.R.attr.colorPrimary, mPrimaryColor); - this.mPrimaryColorDark = DynamicResourceUtils.resolveColor(mContext, - android.support.v7.appcompat.R.attr.colorPrimaryDark, mPrimaryColorDark); - this.mAccentColor = DynamicResourceUtils.resolveColor(mContext, - android.support.v7.appcompat.R.attr.colorAccent, mAccentColor); - initializeColors(); - - if (initializeRemoteColors) { - initializeRemoteColors(true); - } - - return this; - } - - /** - * Initialize colors form the supplied local theme resource. - * - * @param localTheme The local theme resource to initialize colors. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - */ - public DynamicTheme setLocalTheme(@StyleRes int localTheme) { - if (mLocalContext == null) { - throw new IllegalStateException("Not attached to a local mContext."); - } - - this.mLocalThemeRes = localTheme; - mLocalContext.getTheme().applyStyle(localTheme, true); - this.mLocalBackgroundColor = DynamicResourceUtils.resolveColor(mLocalContext, - android.R.attr.windowBackground, DynamicColorType.NONE); - this.mLocalPrimaryColor = DynamicResourceUtils.resolveColor(mLocalContext, - android.support.v7.appcompat.R.attr.colorPrimary, mLocalPrimaryColor); - this.mLocalPrimaryColorDark = DynamicResourceUtils.resolveColor(mLocalContext, - android.support.v7.appcompat.R.attr.colorPrimaryDark, mLocalPrimaryColorDark); - this.mLocalAccentColor = DynamicResourceUtils.resolveColor(mLocalContext, - android.support.v7.appcompat.R.attr.colorAccent, mLocalAccentColor); - initializeLocalColors(); - - addDynamicListener(mLocalContext); - return this; - } - - /** - * Initialize other colors according to the base colors. They can - * be set individually by calling the appropriate functions. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - */ - public DynamicTheme initializeColors() { - this.mAccentColorDark = mAccentColor; - setTintBackgroundColor(DynamicColorUtils.getTintColor(mBackgroundColor)); - setTintPrimaryColor(DynamicColorUtils.getTintColor(mPrimaryColor)); - setTintPrimaryColorDark(DynamicColorUtils.getTintColor(mPrimaryColorDark)); - setTintAccentColor(DynamicColorUtils.getTintColor(mAccentColor)); - setTintAccentColorDark(DynamicColorUtils.getTintColor(mAccentColorDark)); - - return this; - } - - /** - * Initialize other local colors according to the base local colors. - * They can be set individually by calling the appropriate functions. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - */ - public DynamicTheme initializeLocalColors() { - this.mLocalAccentColorDark = mLocalAccentColor; - setTintLocalBackgroundColor(DynamicColorUtils.getTintColor(mLocalBackgroundColor)); - setTintLocalPrimaryColor(DynamicColorUtils.getTintColor(mLocalPrimaryColor)); - setTintLocalPrimaryColorDark(DynamicColorUtils.getTintColor(mLocalPrimaryColorDark)); - setTintLocalAccentColor(DynamicColorUtils.getTintColor(mLocalAccentColor)); - setTintLocalAccentColorDark(DynamicColorUtils.getTintColor(mLocalAccentColorDark)); - - return this; - } - - /** - * Initialize remote colors according to the base colors. They can - * be set individually by calling the appropriate functions. - * - * @param reset {@code true} to reset the previously set remote colors. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - */ - public DynamicTheme initializeRemoteColors(boolean reset) { - if (reset) { - this.mRemoteBackgroundColor = ContextCompat.getColor(getResolvedContext(), - !DynamicVersionUtils.isLollipop() ? R.color.notification_background - : R.color.notification_background_light); - this.mRemotePrimaryColor = mPrimaryColor; - this.mRemoteAccentColor = mAccentColor; - this.mNotificationBackgroundColor = mRemoteBackgroundColor; - this.mNotificationPrimaryColor = mPrimaryColor; - this.mNotificationAccentColor = mAccentColor; - this.mWidgetBackgroundColor = mRemoteBackgroundColor; - this.mWidgetPrimaryColor = mPrimaryColor; - this.mWidgetAccentColor = mAccentColor; - } - - setTintRemoteBackgroundColor(DynamicColorUtils.getTintColor(mRemoteBackgroundColor)); - setTintRemotePrimaryColor(DynamicColorUtils.getTintColor(mRemotePrimaryColor)); - setTintRemoteAccentColor(DynamicColorUtils.getTintColor(mRemoteAccentColor)); - setTintNotificationBackgroundColor(DynamicColorUtils.getTintColor(mNotificationBackgroundColor)); - setTintNotificationPrimaryColor(DynamicColorUtils.getTintColor(mNotificationPrimaryColor)); - setTintNotificationAccentColor(DynamicColorUtils.getTintColor(mNotificationAccentColor)); - setTintWidgetBackgroundColor(DynamicColorUtils.getTintColor(mWidgetBackgroundColor)); - setTintWidgetPrimaryColor(DynamicColorUtils.getTintColor(mWidgetPrimaryColor)); - setTintWidgetAccentColor(DynamicColorUtils.getTintColor(mWidgetAccentColor)); - - return this; - } - - /** - * Get color according to the dynamic color type. - * - * @param colorType The color type to be retrieved. - * - * @return The color according to the type. - * - * @see DynamicColorType - */ - public @ColorInt int getColorFromType(@DynamicColorType int colorType) { - switch (colorType) { - default: return DynamicColorType.NONE; - case DynamicColorType.PRIMARY: return getPrimaryColor(); - case DynamicColorType.PRIMARY_DARK: return getPrimaryColorDark(); - case DynamicColorType.ACCENT: return getAccentColor(); - case DynamicColorType.ACCENT_DARK: return getAccentColorDark(); - case DynamicColorType.TINT_PRIMARY: return getTintPrimaryColor(); - case DynamicColorType.TINT_PRIMARY_DARK: return getTintPrimaryColorDark(); - case DynamicColorType.TINT_ACCENT: return getTintAccentColor(); - case DynamicColorType.TINT_ACCENT_DARK: return getTintAccentColorDark(); - case DynamicColorType.BACKGROUND: return getBackgroundColor(); - case DynamicColorType.TINT_BACKGROUND: return getTintBackgroundColor(); - } - } - - /** - * @return The application context. - */ - public @NonNull Context getContext() { - return mContext; - } - - /** - * Set the application context for this theme. - * - * @param context The application context to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - */ - public DynamicTheme setContext(@NonNull Context context) { - this.mContext = context; - - return this; - } - - /** - * @return The background color used by the application. - */ - public @ColorInt int getBackgroundColor() { - return mLocalContext != null ? mLocalBackgroundColor : mBackgroundColor; - } - - /** - * Set the background color used by the application. - * - * @param backgroundColor The background color to be set. - * @param generateTint {@code true} to automatically generate - * the tint color also. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setTintBackgroundColor(int) - */ - public DynamicTheme setBackgroundColor(@ColorInt int backgroundColor, - boolean generateTint) { - this.mBackgroundColor = backgroundColor; - if (generateTint) { - setTintBackgroundColor(DynamicColorUtils.getTintColor(backgroundColor)); - } - - return this; - } - - /** - * Set the background color used by the application. - * It will automatically generate the tint color also. - * - * @param backgroundColor The background color to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setBackgroundColor(int, boolean) - * @see #setTintBackgroundColor(int) - */ - public DynamicTheme setBackgroundColor(@ColorInt int backgroundColor) { - return setBackgroundColor(backgroundColor, true); - } - - /** - * @return The primary color used by the application. - */ - public @ColorInt int getPrimaryColor() { - return mLocalContext != null ? mLocalPrimaryColor : mPrimaryColor; - } - - /** - * Set the primary color used by the application. - * - * @param primaryColor The primary color to be set. - * @param generateTint {@code true} to automatically generate - * the tint color also. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setTintPrimaryColor(int) - */ - public DynamicTheme setPrimaryColor(@ColorInt int primaryColor, boolean generateTint) { - this.mPrimaryColor = primaryColor; - if (generateTint) { - setTintPrimaryColor(DynamicColorUtils.getTintColor(primaryColor)); - } - - return this; - } - - /** - * Set the primary color used by the application. - * It will automatically generate the tint color also. - * - * @param primaryColor The primary color to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setPrimaryColor(int, boolean) - * @see #setTintPrimaryColor(int) - */ - public DynamicTheme setPrimaryColor(@ColorInt int primaryColor) { - return setPrimaryColor(primaryColor, true); - } - - /** - * @return The dark primary color used by the application. - */ - public @ColorInt int getPrimaryColorDark() { - return mLocalContext != null ? mLocalPrimaryColorDark : mPrimaryColorDark; - } - - /** - * Set the dark primary color used by the application. - * - * @param primaryColorDark The dark primary color to be set. - * @param generateTint {@code true} to automatically generate - * the tint color also. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setTintPrimaryColorDark(int) - */ - public DynamicTheme setPrimaryColorDark(@ColorInt int primaryColorDark, - boolean generateTint) { - this.mPrimaryColorDark = primaryColorDark; - if (generateTint) { - setTintPrimaryColorDark(DynamicColorUtils.getTintColor(primaryColorDark)); - } - - return this; - } - - /** - * Set the dark primary color used by the application. - * It will automatically generate the tint color also. - * - * @param primaryColorDark The dark primary color to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setPrimaryColorDark(int, boolean) - * @see #setTintPrimaryColorDark(int) - */ - public DynamicTheme setPrimaryColorDark(@ColorInt int primaryColorDark) { - return setPrimaryColorDark(primaryColorDark, true); - } - - /** - * @return The accent color used by the application. - */ - public @ColorInt int getAccentColor() { - return mLocalContext != null ? mLocalAccentColor : mAccentColor; - } - - /** - * Set the accent color used by the application. - * - * @param accentColor The accent color to be set. - * @param generateTint {@code true} to automatically generate - * the tint color also. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setTintAccentColor(int) - */ - public DynamicTheme setAccentColor(@ColorInt int accentColor, boolean generateTint) { - this.mAccentColor = accentColor; - if (generateTint) { - setTintAccentColor(DynamicColorUtils.getTintColor(accentColor)); - } - - return this; - } - - /** - * Set the accent color used by the application. - * It will automatically generate the tint color also. - * - * @param accentColor The accent color to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setAccentColor(int, boolean) - * @see #setTintAccentColor(int) - */ - public DynamicTheme setAccentColor(@ColorInt int accentColor) { - return setAccentColor(accentColor, true); - } - - /** - * @return The dark accent color used by the application. - */ - public @ColorInt int getAccentColorDark() { - return mLocalContext != null ? mLocalAccentColorDark : mAccentColorDark; - } - - /** - * Set the dark accent color used by the application. - * - * @param accentColorDark The dark accent color to be set. - * @param generateTint {@code true} to automatically generate - * the tint color also. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setTintAccentColorDark(int) - */ - public DynamicTheme setAccentColorDark(@ColorInt int accentColorDark, - boolean generateTint) { - this.mAccentColorDark = accentColorDark; - if (generateTint) { - setTintAccentColorDark(DynamicColorUtils.getTintColor(accentColorDark)); - } - - return this; - } - - /** - * Set the dark accent color used by the application. - * It will automatically generate the tint color also. - * - * @param accentColorDark The dark accent color to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setAccentColorDark(int, boolean) - * @see #setTintAccentColorDark(int) - */ - public DynamicTheme setAccentColorDark(@ColorInt int accentColorDark) { - return setAccentColorDark(accentColorDark, true); - } - - /** - * @return The background tint color used by the application. - */ - public @ColorInt int getTintBackgroundColor() { - return mLocalContext != null ? mTintLocalBackgroundColor : mTintBackgroundColor; - } - - /** - * Set the background tint color used by the application. - * - * @param tintBackgroundColor The background tint color to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - */ - public DynamicTheme setTintBackgroundColor(@ColorInt int tintBackgroundColor) { - this.mTintBackgroundColor = tintBackgroundColor; - - return this; - } - - /** - * @return The primary tint color used by the application. - */ - public @ColorInt int getTintPrimaryColor() { - return mLocalContext != null ? mTintLocalPrimaryColor : mTintPrimaryColor; - } - - /** - * Set the primary tint color used by the application. - * - * @param tintPrimaryColor The primary tint color to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - */ - public DynamicTheme setTintPrimaryColor(@ColorInt int tintPrimaryColor) { - this.mTintPrimaryColor = tintPrimaryColor; - - return this; - } - - /** - * @return The dark primary tint color used by the application. - */ - public @ColorInt int getTintPrimaryColorDark() { - return mLocalContext != null ? mTintLocalPrimaryColorDark : mTintPrimaryColorDark; - } - - /** - * Set the dark primary tint color used by the application. - * - * @param tintPrimaryColorDark The dark primary tint color to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - */ - public DynamicTheme setTintPrimaryColorDark(@ColorInt int tintPrimaryColorDark) { - this.mTintPrimaryColorDark = tintPrimaryColorDark; - - return this; - } - - /** - * @return The accent tint color used by the application. - */ - public @ColorInt int getTintAccentColor() { - return mLocalContext != null ? mTintLocalAccentColor : mTintAccentColor; - } - - /** - * Set the accent tint color used by the application. - * - * @param tintAccentColor The accent tint color to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - */ - public DynamicTheme setTintAccentColor(@ColorInt int tintAccentColor) { - this.mTintAccentColor = tintAccentColor; - - return this; - } - - /** - * @return The dark accent tint color used by the application. - */ - public @ColorInt int getTintAccentColorDark() { - return mLocalContext != null ? mTintLocalAccentColorDark : mTintAccentColorDark; - } - - - /** - * Set the dark accent tint color used by the application. - * - * @param tintAccentColorDark The dark accent tint color to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - */ - public DynamicTheme setTintAccentColorDark(@ColorInt int tintAccentColorDark) { - this.mTintAccentColorDark = tintAccentColorDark; - - return this; - } - - /** - * @return The remote background color used by the application. - */ - public @ColorInt int getRemoteBackgroundColor() { - return mRemoteBackgroundColor; - } - - /** - * Set the remote background color used by the application. - * - * @param remoteBackgroundColor The remote background color - * to be set. - * @param generateTint {@code true} to automatically generate - * the tint color also. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setTintRemoteBackgroundColor(int) - */ - public DynamicTheme setRemoteBackgroundColor(@ColorInt int remoteBackgroundColor, - boolean generateTint) { - this.mRemoteBackgroundColor = remoteBackgroundColor; - if (generateTint) { - setTintRemoteBackgroundColor(DynamicColorUtils.getTintColor(remoteBackgroundColor)); - } - - return this; - } - - /** - * Set the remote background color used by the application. - * It will automatically generate the tint color also. - * - * @param remoteBackgroundColor The remote background color to - * be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setRemoteBackgroundColor(int, boolean) - * @see #setTintRemoteBackgroundColor(int) - */ - public DynamicTheme setRemoteBackgroundColor(@ColorInt int remoteBackgroundColor) { - return setRemoteBackgroundColor(remoteBackgroundColor, true); - } - - /** - * @return The remote primary color used by the application. - */ - public @ColorInt int getRemotePrimaryColor() { - return mRemotePrimaryColor; - } - - /** - * Set the remote primary color used by the application. - * - * @param remotePrimaryColor The remote primary color to be set. - * @param generateTint {@code true} to automatically generate - * the tint color also. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setTintRemotePrimaryColor(int) - */ - public DynamicTheme setRemotePrimaryColor( - @ColorInt int remotePrimaryColor, boolean generateTint) { - this.mRemotePrimaryColor = remotePrimaryColor; - if (generateTint) { - setTintRemotePrimaryColor(DynamicColorUtils.getTintColor(remotePrimaryColor)); - } - - return this; - } - - /** - * Set the remote primary color used by the application. - * It will automatically generate the tint color also. - * - * @param remotePrimaryColor The remote primary color to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setRemotePrimaryColor(int, boolean) - * @see #setTintRemotePrimaryColor(int) - */ - public DynamicTheme setRemotePrimaryColor(@ColorInt int remotePrimaryColor) { - return setRemotePrimaryColor(remotePrimaryColor, true); - } - - /** - * @return The remote accent color used by the application. - */ - public @ColorInt int getRemoteAccentColor() { - return mRemoteAccentColor; - } - - /** - * Set the remote accent color used by the application. - * - * @param remoteAccentColor The remote accent color to be set. - * @param generateTint {@code true} to automatically generate - * the tint color also. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setTintRemoteAccentColor(int) - */ - public DynamicTheme setRemoteAccentColor(@ColorInt int remoteAccentColor, - boolean generateTint) { - this.mRemoteAccentColor = remoteAccentColor; - if (generateTint) { - setTintRemoteAccentColor(DynamicColorUtils.getTintColor(remoteAccentColor)); - } - - return this; - } - - /** - * Set the remote accent color used by the application. - * It will automatically generate the tint color also. - * - * @param remoteAccentColor The remote accent color to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setRemoteAccentColor(int, boolean) - * @see #setTintRemoteAccentColor(int) - */ - public DynamicTheme setRemoteAccentColor(@ColorInt int remoteAccentColor) { - return setRemoteAccentColor(remoteAccentColor, true); - } - - /** - * @return The remote background tint color used by the application. - */ - public @ColorInt int getTintRemoteBackgroundColor() { - return mTintRemoteBackgroundColor; - } - - /** - * Set the remote background tint color used by the application. - * - * @param tintRemoteBackgroundColor The remote background tint - * color to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - */ - public DynamicTheme setTintRemoteBackgroundColor(@ColorInt int tintRemoteBackgroundColor) { - this.mTintRemoteBackgroundColor = tintRemoteBackgroundColor; - - return this; - } - - /** - * @return The remote primary tint color used by the application. - */ - public @ColorInt int getTintRemotePrimaryColor() { - return mTintRemotePrimaryColor; - } - - /** - * Set the remote primary tint color used by the application. - * - * @param tintRemotePrimaryColor The remote primary tint color - * to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - */ - public DynamicTheme setTintRemotePrimaryColor(@ColorInt int tintRemotePrimaryColor) { - this.mTintRemotePrimaryColor = tintRemotePrimaryColor; - - return this; - } - - /** - * @return The remote accent tint color used by the application. - */ - public @ColorInt int getTintRemoteAccentColor() { - return mTintRemoteAccentColor; - } - - /** - * Set the remote accent tint color used by the application. - * - * @param tintRemoteAccentColor The remote accent tint color - * to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - */ - public DynamicTheme setTintRemoteAccentColor(@ColorInt int tintRemoteAccentColor) { - this.mTintRemoteAccentColor = tintRemoteAccentColor; - - return this; - } - - /** - * @return The background color used by the notification. - */ - public @ColorInt int getNotificationBackgroundColor() { - return mNotificationBackgroundColor; - } - - /** - * Set the background color used by the notification. - * - * @param notificationBackgroundColor The notification background - * color to be set. - * @param generateTint {@code true} to automatically generate - * the tint color also. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setTintNotificationBackgroundColor(int) - */ - public DynamicTheme setNotificationBackgroundColor( - @ColorInt int notificationBackgroundColor, boolean generateTint) { - this.mNotificationBackgroundColor = notificationBackgroundColor; - if (generateTint) { - setTintNotificationBackgroundColor( - DynamicColorUtils.getTintColor(notificationBackgroundColor)); - } - - return this; - } - - /** - * Set the background color used by the notification. - * It will automatically generate the tint color also. - * - * @param notificationBackgroundColor The notification background - * color to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setNotificationBackgroundColor(int, boolean) - * @see #setTintNotificationBackgroundColor(int) - */ - public DynamicTheme setNotificationBackgroundColor( - @ColorInt int notificationBackgroundColor) { - return setNotificationBackgroundColor( - notificationBackgroundColor, true); - } - - /** - * @return The primary color used by the notification. - */ - public @ColorInt int getNotificationPrimaryColor() { - return mNotificationPrimaryColor; - } - - /** - * Set the primary color used by the notification. - * - * @param notificationPrimaryColor The notification primary - * color to be set. - * @param generateTint {@code true} to automatically generate - * the tint color also. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setTintNotificationPrimaryColor(int) - */ - public DynamicTheme setNotificationPrimaryColor(@ColorInt int notificationPrimaryColor, - boolean generateTint) { - this.mNotificationPrimaryColor = notificationPrimaryColor; - if (generateTint) { - this.mTintNotificationPrimaryColor = - DynamicColorUtils.getTintColor(notificationPrimaryColor); - } - - return this; - } - - /** - * Set the primary color used by the notification. - * It will automatically generate the tint color also. - * - * @param notificationPrimaryColor The notification primary - * color to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setNotificationPrimaryColor(int, boolean) - * @see #setTintNotificationPrimaryColor(int) - */ - public DynamicTheme setNotificationPrimaryColor(@ColorInt int notificationPrimaryColor) { - return setNotificationPrimaryColor(notificationPrimaryColor, true); - } - - /** - * @return The accent color used by the notification. + * Normal delay for updating the views. */ - public @ColorInt int getNotificationAccentColor() { - return mNotificationAccentColor; - } + public static final int ADS_DELAY_NORMAL = 250; /** - * Set the accent color used by the notification. - * - * @param notificationAccentColor The notification accent - * color to be set. - * @param generateTint {@code true} to automatically generate - * the tint color also. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setTintNotificationAccentColor(int) + * Theme change delay which will be useful in some situations like changing the app theme, + * updating the widgets, etc. */ - public DynamicTheme setNotificationAccentColor(@ColorInt int notificationAccentColor, - boolean generateTint) { - this.mNotificationAccentColor = notificationAccentColor; - if (generateTint) { - this.mTintNotificationAccentColor = - DynamicColorUtils.getTintColor(notificationAccentColor); - } - - return this; - } + public static final int ADS_DELAY_THEME_CHANGE = 100; /** - * Set the accent color used by the notification. - * It will automatically generate the tint color also. - * - * @param notificationAccentColor The notification accent - * color to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setNotificationAccentColor(int, boolean) - * @see #setTintNotificationAccentColor(int) + * Dynamic theme shared preferences. */ - public DynamicTheme setNotificationAccentColor(@ColorInt int notificationAccentColor) { - return setNotificationAccentColor(notificationAccentColor, true); - } + public static final String ADS_PREF_THEME = "ads_dynamic_theme"; /** - * @return The background tint color used by the notification. + * Key for the theme preference. */ - public @ColorInt int getTintNotificationBackgroundColor() { - return mTintNotificationBackgroundColor; - } + public static final String ADS_PREF_THEME_KEY = "ads_theme_"; /** - * Sets background tint color used by the notification. - * - * @param tintNotificationBackgroundColor The background tint color - * to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. + * Default shift amount to generate the darker color. */ - public DynamicTheme setTintNotificationBackgroundColor( - @ColorInt int tintNotificationBackgroundColor) { - this.mTintNotificationBackgroundColor = tintNotificationBackgroundColor; - - return this; - } + public static final float ADS_COLOR_SHIFT_DARK_DEFAULT = 0.863f; /** - * @return The primary tint color used by the notification. + * Default primary color used by this theme if no color is supplied. */ - public @ColorInt int getTintNotificationPrimaryColor() { - return mTintNotificationPrimaryColor; - } + private static final @ColorInt int ADS_COLOR_PRIMARY_DEFAULT = + Color.parseColor("#3F51B5"); /** - * Sets primary tint color used by the notification. - * - * @param tintNotificationPrimaryColor The primary tint color - * to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. + * Default dark primary color used by this theme if no color is supplied. */ - public DynamicTheme setTintNotificationPrimaryColor( - @ColorInt int tintNotificationPrimaryColor) { - this.mTintNotificationPrimaryColor = tintNotificationPrimaryColor; - - return this; - } + private static final @ColorInt int ADS_COLOR_PRIMARY_DARK_DEFAULT = + Color.parseColor("#303F9F"); /** - * @return The accent tint color used by the notification. + * Default accent color used by this theme if no color is supplied. */ - public @ColorInt int getTintNotificationAccentColor() { - return mTintNotificationAccentColor; - } + private static final @ColorInt int ADS_COLOR_ACCENT_DEFAULT = + Color.parseColor("#E91E63"); /** - * Sets accent tint color used by the notification. - * - * @param tintNotificationAccentColor The accent tint color - * to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. + * Default corner size for the theme. */ - public DynamicTheme setTintNotificationAccentColor( - @ColorInt int tintNotificationAccentColor) { - this.mTintNotificationAccentColor = tintNotificationAccentColor; - - return this; - } + private static final int ADS_CORNER_SIZE_DEFAULT = DynamicUnitUtils.convertDpToPixels(2); /** - * @return The background color used by the widget. + * Default theme used by the application. */ - public @ColorInt int getWidgetBackgroundColor() { - return mWidgetBackgroundColor; - } + private DynamicAppTheme mDefaultApplicationTheme; /** - * Set the background color used by the widget. - * - * @param widgetBackgroundColor The widget background color - * to be set. - * @param generateTint {@code true} to automatically generate - * the tint color also. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setTintWidgetBackgroundColor(int) + * Default theme used by the local context. */ - public DynamicTheme setWidgetBackgroundColor(@ColorInt int widgetBackgroundColor, - boolean generateTint) { - this.mWidgetBackgroundColor = widgetBackgroundColor; - if (generateTint) { - setTintWidgetBackgroundColor(DynamicColorUtils.getTintColor(widgetBackgroundColor)); - } - - return this; - } + private DynamicAppTheme mDefaultLocalTheme; /** - * Set the background color used by the widget. - * It will automatically generate the tint color also. - * - * @param widgetBackgroundColor The widget background color to - * be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setWidgetBackgroundColor(int, boolean) - * @see #setTintWidgetBackgroundColor(int) + * Theme used by the application. */ - public DynamicTheme setWidgetBackgroundColor(@ColorInt int widgetBackgroundColor) { - return setWidgetBackgroundColor(widgetBackgroundColor, true); - } + private DynamicAppTheme mApplicationTheme; /** - * @return The primary color used by the widget. + * Theme used by the local context. */ - public @ColorInt int getWidgetPrimaryColor() { - return mWidgetPrimaryColor; - } + private DynamicAppTheme mLocalTheme; /** - * Set the primary color used by the widget. - * - * @param widgetPrimaryColor The widget primary color - * to be set. - * @param generateTint {@code true} to automatically generate - * the tint color also. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setTintWidgetPrimaryColor(int) + * Theme used by the remote elements. */ - public DynamicTheme setWidgetPrimaryColor(@ColorInt int widgetPrimaryColor, - boolean generateTint) { - this.mWidgetPrimaryColor = widgetPrimaryColor; - if (generateTint) { - setTintWidgetPrimaryColor(DynamicColorUtils.getTintColor(widgetPrimaryColor)); - } - - return this; - } + private DynamicWidgetTheme mRemoteTheme; /** - * Set the primary color used by the widget. - * It will automatically generate the tint color also. - * - * @param widgetPrimaryColor The widget primary color to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setWidgetPrimaryColor(int, boolean) - * @see #setTintWidgetPrimaryColor(int) + * Singleton instance of {@link DynamicTheme}. */ - public DynamicTheme setWidgetPrimaryColor(@ColorInt int widgetPrimaryColor) { - return setWidgetPrimaryColor(widgetPrimaryColor, true); - } + private static DynamicTheme sInstance; /** - * @return The accent color used by the widget. + * Application context used by this theme instance. */ - public @ColorInt int getWidgetAccentColor() { - return mWidgetAccentColor; - } + private Context mContext; /** - * Set the accent color used by the widget. - * - * @param widgetAccentColor The widget accent color to be set. - * @param generateTint {@code true} to automatically generate - * the tint color also. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setTintWidgetAccentColor(int) + * Local activity context used by this theme instance. */ - public DynamicTheme setWidgetAccentColor(@ColorInt int widgetAccentColor, - boolean generateTint) { - this.mWidgetAccentColor = widgetAccentColor; - if (generateTint) { - setTintWidgetAccentColor(DynamicColorUtils.getTintColor(widgetAccentColor)); - } - - return this; - } + private Context mLocalContext; /** - * Set the accent color used by the widget. - * It will automatically generate the tint color also. - * - * @param widgetAccentColor The widget accent color to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setWidgetAccentColor(int, boolean) - * @see #setTintWidgetAccentColor(int) + * Collection of dynamic listeners to send them event callback. */ - public DynamicTheme setWidgetAccentColor(@ColorInt int widgetAccentColor) { - return setWidgetAccentColor(widgetAccentColor, true); - } + private List mDynamicListeners; /** - * @return The background tint color used by the widget. + * Making default constructor private so that it cannot be initialized without a context. + *

Use {@link #initializeInstance(Context)} instead. */ - public @ColorInt int getTintWidgetBackgroundColor() { - return mTintWidgetBackgroundColor; - } + private DynamicTheme() { } /** - * Sets background tint color used by the widget. - * - * @param tintWidgetBackgroundColor The background tint color - * to be set. + * Constructor to initialize an object of this class. * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - */ - public DynamicTheme setTintWidgetBackgroundColor(@ColorInt int tintWidgetBackgroundColor) { - this.mTintWidgetBackgroundColor = tintWidgetBackgroundColor; - - return this; - } - - /** - * @return The primary tint color used by the widget. + * @param context The application context to be attached with this theme. */ - public @ColorInt int getTintWidgetPrimaryColor() { - return mTintWidgetPrimaryColor; + private DynamicTheme(@NonNull Context context) { + this.mContext = context; + this.mDynamicListeners = new ArrayList<>(); + this.mDefaultApplicationTheme = new DynamicAppTheme(ADS_COLOR_PRIMARY_DEFAULT, + ADS_COLOR_PRIMARY_DARK_DEFAULT, ADS_COLOR_ACCENT_DEFAULT, + ADS_CORNER_SIZE_DEFAULT, Theme.BackgroundAware.ENABLE); + this.mApplicationTheme = new DynamicAppTheme(); + this.mRemoteTheme = new DynamicWidgetTheme(); } /** - * Sets primary tint color used by the widget. + * Attach a local context to this theme. + *

It can be an activity in case different themes are required for different activities. * - * @param tintWidgetPrimaryColor The primary tint color - * to be set. + * @param localContext The context to be attached with this theme. * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. + * @return The {@link DynamicTheme} object to allow for chaining of calls to set methods. */ - public DynamicTheme setTintWidgetPrimaryColor(@ColorInt int tintWidgetPrimaryColor) { - this.mTintWidgetPrimaryColor = tintWidgetPrimaryColor; + public DynamicTheme attach(@NonNull Context localContext) { + this.mLocalContext = localContext; + this.mDefaultLocalTheme = new DynamicAppTheme(ADS_COLOR_PRIMARY_DEFAULT, + ADS_COLOR_PRIMARY_DARK_DEFAULT, ADS_COLOR_ACCENT_DEFAULT, + ADS_CORNER_SIZE_DEFAULT, Theme.BackgroundAware.ENABLE); + this.mLocalTheme = new DynamicAppTheme(); - return this; - } + if (localContext instanceof Activity && ((Activity) localContext) + .getLayoutInflater().getFactory2() == null) { + LayoutInflaterCompat.setFactory2(((Activity) localContext) + .getLayoutInflater(), new DynamicLayoutInflater()); + } - /** - * @return The accent tint color used by the widget. - */ - public @ColorInt int getTintWidgetAccentColor() { - return mTintWidgetAccentColor; + return this; } /** - * Sets accent tint color used by the widget. - * - * @param tintWidgetAccentColor The accent tint color - * to be set. + * Initialize theme when application starts. + *

Must be initialized once. * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. + * @param context The context to retrieve resources. */ - public DynamicTheme setTintWidgetAccentColor(@ColorInt int tintWidgetAccentColor) { - this.mTintWidgetAccentColor = tintWidgetAccentColor; - - return this; - } + public static synchronized void initializeInstance(@Nullable Context context) { + if (context == null) { + throw new NullPointerException("Context should not be null"); + } - /** - * @return The background color used by the local context. - */ - public @ColorInt int getLocalBackgroundColor() { - return mLocalBackgroundColor; + if (sInstance == null) { + sInstance = new DynamicTheme(context); + } } /** - * Set the background color used by the local context. - * - * @param localBackgroundColor The background color to be set. - * @param generateTint {@code true} to automatically generate - * the tint color also. + * Get instance to access public methods. + *

Must be called before accessing methods. * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setTintLocalBackgroundColor(int) + * @return The singleton instance of this class. */ - public DynamicTheme setLocalBackgroundColor(@ColorInt int localBackgroundColor, - boolean generateTint) { - this.mLocalBackgroundColor = localBackgroundColor; - if (generateTint) { - this.mTintLocalBackgroundColor = - DynamicColorUtils.getTintColor(localBackgroundColor); + public static synchronized DynamicTheme getInstance() { + if (sInstance == null) { + throw new IllegalStateException(DynamicTheme.class.getSimpleName() + + " is not initialized, call initializeInstance(..) method first."); } - return this; + return sInstance; } /** - * Set the background color used by the local context. - * It will automatically generate the tint color also. - * - * @param localBackgroundColor The background color to be set. + * Initialize colors form the supplied theme resource. * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. + * @param theme The theme resource to initialize colors. + * @param initializeRemoteColors {@code true} to initialize remote colors also. * - * @see #setLocalBackgroundColor(int, boolean) - * @see #setTintLocalBackgroundColor(int) + * @return The {@link DynamicTheme} object to allow for chaining of calls to set methods. */ - public DynamicTheme setLocalBackgroundColor(@ColorInt int localBackgroundColor) { - return setLocalBackgroundColor(localBackgroundColor, true); - } + public @NonNull DynamicTheme setThemeRes(@StyleRes int theme, boolean initializeRemoteColors) { + if (theme != DynamicResourceUtils.ADS_DEFAULT_RESOURCE_ID) { + mContext.getTheme().applyStyle(theme, true); - /** - * @return The primary color used by the local context. - */ - public @ColorInt int getLocalPrimaryColor() { - return mLocalPrimaryColor; - } + mDefaultApplicationTheme.setThemeRes(theme) + .setBackgroundColor(DynamicResourceUtils.resolveColor( + mContext, theme, android.R.attr.windowBackground, + DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE)) + .setPrimaryColor(DynamicResourceUtils.resolveColor( + mContext, theme, R.attr.colorPrimary, + mDefaultApplicationTheme.getPrimaryColor())) + .setPrimaryColorDark(DynamicResourceUtils.resolveColor( + mContext, theme, R.attr.colorPrimaryDark, + mDefaultApplicationTheme.getPrimaryColorDark())) + .setAccentColor(DynamicResourceUtils.resolveColor( + mContext, theme, R.attr.colorAccent, + mDefaultApplicationTheme.getAccentColor())) + .setAccentColorDark(mApplicationTheme.getAccentColor()) + .setTextPrimaryColor(DynamicResourceUtils.resolveColor( + mContext, theme, android.R.attr.textColorPrimary, + DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE)) + .setTextSecondaryColor(DynamicResourceUtils.resolveColor( + mContext, theme, android.R.attr.textColorSecondary, + DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE)) + .setTextPrimaryColorInverse(DynamicResourceUtils.resolveColor( + mContext, theme, android.R.attr.textColorPrimaryInverse, + DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE)) + .setTextSecondaryColorInverse(DynamicResourceUtils.resolveColor( + mContext, theme, android.R.attr.textColorSecondaryInverse, + DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE)) + .setCornerRadius(DynamicResourceUtils.resolveDimensionPixelOffSet( + mContext, theme, R.attr.ads_cornerRadius, + mDefaultApplicationTheme.getCornerRadius())) + .setBackgroundAware(DynamicResourceUtils.resolveInteger( + mContext, theme, R.attr.ads_backgroundAware, + mDefaultApplicationTheme.getBackgroundAware())); - /** - * Set the primary color used by the local context. - * - * @param localPrimaryColor The primary color to be set. - * @param generateTint {@code true} to automatically generate - * the tint color also. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setTintLocalPrimaryColor(int) - */ - public DynamicTheme setLocalPrimaryColor(@ColorInt int localPrimaryColor, - boolean generateTint) { - this.mLocalPrimaryColor = localPrimaryColor; - if (generateTint) { - this.mTintLocalPrimaryColor = DynamicColorUtils.getTintColor(localPrimaryColor); + mApplicationTheme = mDefaultApplicationTheme; + + if (initializeRemoteColors) { + initializeRemoteColors(); + } } return this; } /** - * Set the primary color used by the local context. - * It will automatically generate the tint color also. - * - * @param localPrimaryColor The primary color to be set. + * Initialize colors form the supplied dynamic app theme. * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. + * @param dynamicTheme The dynamic app theme to initialize colors. + * @param initializeRemoteColors {@code true} to initialize remote colors also. * - * @see #setLocalPrimaryColor(int, boolean) - * @see #setTintLocalPrimaryColor(int) + * @return The {@link DynamicTheme} object to allow for chaining of calls to set methods. */ - public DynamicTheme setLocalPrimaryColor(@ColorInt int localPrimaryColor) { - return setLocalPrimaryColor(localPrimaryColor, true); - } + public @NonNull DynamicTheme setTheme(@Nullable DynamicAppTheme dynamicTheme, + boolean initializeRemoteColors) { + if (dynamicTheme != null) { + if (dynamicTheme.getThemeRes() == DynamicResourceUtils.ADS_DEFAULT_RESOURCE_ID) { + throw new IllegalStateException("Dynamic app theme style resource " + + "id is not found for the application theme."); + } - /** - * @return The dark primary color used by the local context. - */ - public @ColorInt int getLocalPrimaryColorDark() { - return mLocalPrimaryColorDark; - } + setThemeRes(dynamicTheme.getThemeRes(), false); + mApplicationTheme = dynamicTheme; - /** - * Set the dark primary color used by the local context. - * - * @param localPrimaryColorDark The dark primary color to be set. - * @param generateTint {@code true} to automatically generate - * the tint color also. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setTintLocalPrimaryColorDark(int) - */ - public DynamicTheme setLocalPrimaryColorDark(@ColorInt int localPrimaryColorDark, - boolean generateTint) { - this.mLocalPrimaryColorDark = localPrimaryColorDark; - if (generateTint) { - this.mTintLocalPrimaryColorDark = - DynamicColorUtils.getTintColor(localPrimaryColorDark); + if (initializeRemoteColors) { + initializeRemoteColors(); + } } return this; } /** - * Set the dark primary color used by the local context. - * It will automatically generate the tint color also. - * - * @param localPrimaryColorDark The dark primary color to be set. + * Initialize colors form the supplied local theme resource. * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. + * @param localTheme The local theme resource to initialize colors. * - * @see #setLocalPrimaryColorDark(int, boolean) - * @see #setTintLocalPrimaryColorDark(int) + * @return The {@link DynamicTheme} object to allow for chaining of calls to set methods. */ - public DynamicTheme setLocalPrimaryColorDark(@ColorInt int localPrimaryColorDark) { - return setLocalPrimaryColorDark(localPrimaryColorDark, true); - } + public @NonNull DynamicTheme setLocalThemeRes(@StyleRes int localTheme) { + if (mLocalContext == null) { + throw new IllegalStateException("Not attached to a local context."); + } - /** - * @return The accent color used by the local context. - */ - public @ColorInt int getLocalAccentColor() { - return mLocalAccentColor; - } + if (localTheme != DynamicResourceUtils.ADS_DEFAULT_RESOURCE_ID) { + mLocalContext.getTheme().applyStyle(localTheme, true); - /** - * Set the accent color used by the local context. - * - * @param localAccentColor The accent color to be set. - * @param generateTint {@code true} to automatically generate - * the tint color also. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setTintLocalAccentColor(int) - */ - public DynamicTheme setLocalAccentColor(@ColorInt int localAccentColor, - boolean generateTint) { - this.mLocalAccentColor = localAccentColor; - if (generateTint) { - this.mTintLocalAccentColor = DynamicColorUtils.getTintColor(localAccentColor); + mDefaultLocalTheme.setThemeRes(localTheme) + .setBackgroundColor(DynamicResourceUtils.resolveColor( + mContext, localTheme, android.R.attr.windowBackground, + DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE)) + .setPrimaryColor(DynamicResourceUtils.resolveColor( + mContext, localTheme, R.attr.colorPrimary, + mDefaultLocalTheme.getPrimaryColor())) + .setPrimaryColorDark(DynamicResourceUtils.resolveColor( + mContext, localTheme, R.attr.colorPrimaryDark, + mDefaultLocalTheme.getPrimaryColorDark())) + .setAccentColor(DynamicResourceUtils.resolveColor( + mContext, localTheme, R.attr.colorAccent, + mDefaultLocalTheme.getAccentColor())) + .setAccentColorDark(mLocalTheme.getAccentColor()) + .setTextPrimaryColor(DynamicResourceUtils.resolveColor( + mContext, localTheme, android.R.attr.textColorPrimary, + DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE)) + .setTextSecondaryColor(DynamicResourceUtils.resolveColor( + mContext, localTheme, android.R.attr.textColorSecondary, + DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE)) + .setTextPrimaryColorInverse(DynamicResourceUtils.resolveColor( + mContext, localTheme, android.R.attr.textColorPrimaryInverse, + DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE)) + .setTextSecondaryColorInverse(DynamicResourceUtils.resolveColor( + mContext, localTheme, android.R.attr.textColorSecondaryInverse, + DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE)) + .setCornerRadius(DynamicResourceUtils.resolveDimensionPixelOffSet( + mContext, localTheme, R.attr.ads_cornerRadius, + mDefaultLocalTheme.getCornerRadius())) + .setBackgroundAware(DynamicResourceUtils.resolveInteger( + mContext, localTheme, R.attr.ads_backgroundAware, + mDefaultLocalTheme.getBackgroundAware())); + + mLocalTheme = mDefaultLocalTheme; + addDynamicListener(mLocalContext); } return this; } /** - * Set the accent color used by the local context. - * It will automatically generate the tint color also. + * Initialize colors form the supplied local dynamic app theme. * - * @param localAccentColor The accent color to be set. + * @param dynamicLocalTheme The local dynamic app theme to initialize colors. * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setLocalAccentColor(int, boolean) - * @see #setTintLocalAccentColor(int) + * @return The {@link DynamicTheme} object to allow for chaining of calls to set methods. */ - public DynamicTheme setLocalAccentColor(@ColorInt int localAccentColor) { - return setLocalAccentColor(localAccentColor, true); - } + public @NonNull DynamicTheme setLocalTheme(@Nullable DynamicAppTheme dynamicLocalTheme) { + if (dynamicLocalTheme != null) { + if (dynamicLocalTheme.getThemeRes() == DynamicResourceUtils.ADS_DEFAULT_RESOURCE_ID) { + throw new IllegalStateException("Dynamic app theme style resource " + + "id is not found for the application theme."); + } - /** - * @return The dark accent color used by the local context. - */ - public @ColorInt int getLocalAccentColorDark() { - return mLocalAccentColorDark; + setLocalThemeRes(dynamicLocalTheme.getThemeRes()); + mLocalTheme = dynamicLocalTheme; + } + + return this; } /** - * Set the dark accent color used by the local context. - * - * @param localAccentColorDark The dark accent color to be set. - * @param generateTint {@code true} to automatically generate - * the tint color also. + * Initialize remote colors according to the base colors. + *

They can be set individually by calling the appropriate functions. * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - * - * @see #setTintLocalAccentColorDark(int) + * @return The {@link DynamicTheme} object to allow for chaining of calls to set methods. */ - public DynamicTheme setLocalAccentColorDark(@ColorInt int localAccentColorDark, - boolean generateTint) { - this.mLocalAccentColorDark = localAccentColorDark; - if (generateTint) { - this.mTintLocalAccentColorDark = - DynamicColorUtils.getTintColor(localAccentColorDark); - } + public @NonNull DynamicTheme initializeRemoteColors() { + mRemoteTheme = (DynamicWidgetTheme) new DynamicWidgetTheme(mApplicationTheme) + .setBackgroundColor(ContextCompat.getColor(getResolvedContext(), + !DynamicVersionUtils.isLollipop() + ? R.color.notification_background + : R.color.notification_background_light)); return this; } /** - * Set the dark accent color used by the local context. - * It will automatically generate the tint color also. + * Resolve background aware according to the constant value. * - * @param localAccentColorDark The dark accent color to be set. + * @param backgroundAware The background aware to be resolved. * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. + * @return The resolved background aware value. + *

Either {@link Theme.BackgroundAware#ENABLE} + * or {@link Theme.BackgroundAware#DISABLE}. * - * @see #setLocalAccentColorDark(int, boolean) - * @see #setTintLocalAccentColorDark(int) + * @see Theme.BackgroundAware */ - public DynamicTheme setLocalAccentColorDark(@ColorInt int localAccentColorDark) { - return setLocalAccentColorDark(localAccentColorDark, true); - } + public @Theme.BackgroundAware int resolveBackgroundAware( + @Theme.BackgroundAware int backgroundAware) { + if (backgroundAware == Theme.BackgroundAware.AUTO) { + return DynamicTheme.getInstance().get().getBackgroundAware(); + } - /** - * @return The background tint color used by the local context. - */ - public @ColorInt int getTintLocalBackgroundColor() { - return mTintLocalBackgroundColor; + return backgroundAware; } /** - * Set the background tint color used by the local context. + * Resolve color according to the color type. * - * @param tintLocalBackgroundColor The background tint color to be set. + * @param colorType The color type to be resolved. * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. + * @return The resolved color value. + * + * @see Theme.ColorType */ - public DynamicTheme setTintLocalBackgroundColor(@ColorInt int tintLocalBackgroundColor) { - this.mTintLocalBackgroundColor = tintLocalBackgroundColor; - - return this; + public @ColorInt int resolveColorType(@Theme.ColorType int colorType) { + switch (colorType) { + default: return Theme.ColorType.NONE; + case Theme.ColorType.PRIMARY: return get().getPrimaryColor(); + case Theme.ColorType.PRIMARY_DARK: return get().getPrimaryColorDark(); + case Theme.ColorType.ACCENT: return get().getAccentColor(); + case Theme.ColorType.ACCENT_DARK: return get().getAccentColorDark(); + case Theme.ColorType.TINT_PRIMARY: return get().getTintPrimaryColor(); + case Theme.ColorType.TINT_PRIMARY_DARK: return get().getTintPrimaryColorDark(); + case Theme.ColorType.TINT_ACCENT: return get().getTintAccentColor(); + case Theme.ColorType.TINT_ACCENT_DARK: return get().getTintAccentColorDark(); + case Theme.ColorType.BACKGROUND: return get().getBackgroundColor(); + case Theme.ColorType.TINT_BACKGROUND: return get().getTintBackgroundColor(); + case Theme.ColorType.TEXT_PRIMARY: return get().getTextPrimaryColor(); + case Theme.ColorType.TEXT_SECONDARY: return get().getTextSecondaryColor(); + case Theme.ColorType.TEXT_PRIMARY_INVERSE: return get().getTextPrimaryColorInverse(); + case Theme.ColorType.TEXT_SECONDARY_INVERSE: return get().getTextSecondaryColorInverse(); + } } /** - * @return The primary tint color used by the local context. + * Get the application context. + * + * @return The application context. */ - public @ColorInt int getTintLocalPrimaryColor() { - return mTintLocalPrimaryColor; + public @NonNull Context getContext() { + return mContext; } /** - * Set the primary tint color used by the local context. + * Set the application context for this theme. * - * @param tintLocalPrimaryColor The primary tint color to be set. + * @param context The application context to be set. * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. + * @return The {@link DynamicTheme} object to allow for chaining of calls to set methods. */ - public DynamicTheme setTintLocalPrimaryColor(@ColorInt int tintLocalPrimaryColor) { - this.mTintLocalPrimaryColor = tintLocalPrimaryColor; + public @NonNull DynamicTheme setContext(@NonNull Context context) { + this.mContext = context; return this; } /** - * @return The dark primary tint color used by the local context. + * Get the theme used by the application. + * + * @return The theme used by the application. */ - public @ColorInt int getTintLocalPrimaryColorDark() { - return mTintLocalPrimaryColorDark; + public DynamicAppTheme getApplication() { + return mApplicationTheme; } /** - * Set the dark primary tint color used by the local context. - * - * @param tintLocalPrimaryColorDark The dark primary tint color - * to be set. + * Get the theme used by the local context. * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. + * @return The theme used by the local context. */ - public DynamicTheme setTintLocalPrimaryColorDark(@ColorInt int tintLocalPrimaryColorDark) { - this.mTintLocalPrimaryColorDark = tintLocalPrimaryColorDark; - - return this; + public DynamicAppTheme getLocal() { + return mLocalTheme; } /** - * @return The accent tint color used by the local context. + * @return The theme used by the remote views. */ - public @ColorInt int getTintLocalAccentColor() { - return mTintLocalAccentColor; + public DynamicWidgetTheme getRemote() { + return mRemoteTheme; } /** - * Set the accent tint color used by the local context. + * Get the theme according to the current state. + *

Either application theme or local theme. * - * @param tintLocalAccentColor The accent tint color to be set. - * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. - */ - public DynamicTheme setTintLocalAccentColor(@ColorInt int tintLocalAccentColor) { - this.mTintLocalAccentColor = tintLocalAccentColor; - - return this; - } - - /** - * @return The dark accent tint color used by the local context. + * @return The theme according to the current state. */ - public @ColorInt int getTintLocalAccentColorDark() { - return mTintLocalAccentColorDark; + public DynamicAppTheme get() { + return mLocalContext != null ? mLocalTheme : mApplicationTheme; } /** - * Set the dark accent tint color used by the local context. - * - * @param tintLocalAccentColorDark The dark accent tint color - * to be set. + * Get the default theme according to the current state. + *

Either default application theme or default local theme. * - * @return The {@link DynamicTheme} object to allow for chaining - * of calls to set methods. + * @return The default theme according to the current state. */ - public DynamicTheme setTintLocalAccentColorDark(@ColorInt int tintLocalAccentColorDark) { - this.mTintLocalAccentColorDark = tintLocalAccentColorDark; - - return this; + public DynamicAppTheme getDefault() { + return mLocalContext != null ? mDefaultLocalTheme : mDefaultApplicationTheme; } /** @@ -1850,8 +524,8 @@ public void recreateLocal() { } /** - * Set the initialized instance to {@code null} when app - * terminates for better theme results when theme is changed. + * Set the initialized instance to {@code null} when app terminates for better theme + * results when theme is changed. */ public void onDestroy() { if (sInstance == null) { @@ -1860,41 +534,77 @@ public void onDestroy() { mContext = null; mLocalContext = null; + mDefaultApplicationTheme = null; + mApplicationTheme = null; + mDefaultLocalTheme = null; + mLocalTheme = null; + mRemoteTheme = null; sInstance.mContext = null; + sInstance.mApplicationTheme = null; + sInstance.mDefaultApplicationTheme = null; + sInstance.mDefaultLocalTheme = null; sInstance.mLocalContext = null; + sInstance.mLocalTheme = null; + sInstance.mRemoteTheme = null; sInstance = null; clearDynamicListeners(); } /** - * Set the initialized instance to {@code null} when local - * destroys for better theme results when theme is changed. + * Set the initialized instance to {@code null} when local destroys for better theme + * results when theme is changed. */ public void onLocalDestroy() { if (sInstance == null) { return; } - saveLocalTheme(); removeDynamicListener(mLocalContext); + saveLocalTheme(); + mLocalContext = null; + mLocalTheme = null; + } + + /** + * Generates default theme according to the current settings. + * + * @return The generated default theme. + */ + public @NonNull DynamicAppTheme generateDefaultTheme() { + return new DynamicAppTheme().setBackgroundColor( + getDefault().getBackgroundColor(), false); } /** - * @return The currently used context. Generally either the - * application or an activity + * Generates dark variant of the supplied color. + * + * @param color The color to generate the dark variant. + * + * @return The generated dark variant. + */ + public @ColorInt int generateDarkColor(@ColorInt int color) { + return DynamicColorUtils.shiftColor(color, DynamicTheme.ADS_COLOR_SHIFT_DARK_DEFAULT); + } + + /** + * Returns the currently used context. + *

Generally, either application or an activity. + * + * @return The currently used context. */ private Context getResolvedContext() { return mLocalContext != null ? mLocalContext : mContext; } /** - * @return The default contrast with color to tint the background - * aware views accordingly. + * Returns the default contrast with color to tint the background aware views accordingly. + * + * @return The default contrast with color. */ public @ColorInt int getDefaultContrastWith() { - return mLocalContext != null ? mLocalBackgroundColor : mBackgroundColor; + return get().getBackgroundColor(); } /** @@ -1924,6 +634,21 @@ public void removeDynamicListener(@Nullable Context dynamicListener) { } } + /** + * Checks whether a dynamic listener is already registered. + * + * @param dynamicListener The dynamic listener to be checked. + * + * @see DynamicListener + */ + public boolean isDynamicListener(@Nullable Context dynamicListener) { + if (!(dynamicListener instanceof DynamicListener)) { + return false; + } + + return mDynamicListeners.contains(dynamicListener); + } + /** * Remove all the dynamic listeners. */ @@ -1948,45 +673,20 @@ public void onDynamicChange(boolean context, boolean recreate) { } @Override - public String toString() { - return "DynamicTheme{" + - "mBackgroundColor=" + mBackgroundColor + - ", mPrimaryColor=" + mPrimaryColor + - ", mPrimaryColorDark=" + mPrimaryColorDark + - ", mAccentColor=" + mAccentColor + - ", mAccentColorDark=" + mAccentColorDark + - ", mTintBackgroundColor=" + mTintBackgroundColor + - ", mTintPrimaryColor=" + mTintPrimaryColor + - ", mTintPrimaryColorDark=" + mTintPrimaryColorDark + - ", mTintAccentColor=" + mTintAccentColor + - ", mTintAccentColorDark=" + mTintAccentColorDark + - ", mRemoteBackgroundColor=" + mRemoteBackgroundColor + - ", mRemotePrimaryColor=" + mRemotePrimaryColor + - ", mRemoteAccentColor=" + mRemoteAccentColor + - ", mTintRemotePrimaryColor=" + mTintRemotePrimaryColor + - ", mTintRemoteAccentColor=" + mTintRemoteAccentColor + - ", mNotificationBackgroundColor=" + mNotificationBackgroundColor + - ", mNotificationPrimaryColor=" + mNotificationPrimaryColor + - ", mNotificationAccentColor=" + mNotificationAccentColor + - ", mTintNotificationPrimaryColor=" + mTintNotificationPrimaryColor + - ", mTintNotificationAccentColor=" + mTintNotificationAccentColor + - ", mWidgetBackgroundColor=" + mWidgetBackgroundColor + - ", mWidgetPrimaryColor=" + mWidgetPrimaryColor + - ", mWidgetAccentColor=" + mWidgetAccentColor + - ", mTintWidgetPrimaryColor=" + mTintWidgetPrimaryColor + - ", mTintWidgetAccentColor=" + mTintWidgetAccentColor + - ", mLocalThemeRes=" + mLocalThemeRes + - ", mLocalBackgroundColor=" + mLocalBackgroundColor + - ", mLocalPrimaryColor=" + mLocalPrimaryColor + - ", mLocalPrimaryColorDark=" + mLocalPrimaryColorDark + - ", mLocalAccentColor=" + mLocalAccentColor + - ", mLocalAccentColorDark=" + mLocalAccentColorDark + - ", mTintLocalBackgroundColor=" + mTintLocalBackgroundColor + - ", mTintLocalPrimaryColor=" + mTintLocalPrimaryColor + - ", mTintLocalPrimaryColorDark=" + mTintLocalPrimaryColorDark + - ", mTintLocalAccentColor=" + mTintLocalAccentColor + - ", mTintLocalAccentColorDark=" + mTintLocalAccentColorDark + - '}'; + public @NonNull String toString() { + StringBuilder theme = new StringBuilder(); + + if (mApplicationTheme != null) { + theme.append(mApplicationTheme.toString()); + } + if (mLocalTheme != null) { + theme.append(mLocalTheme.toString()); + } + if (mRemoteTheme != null) { + theme.append(mRemoteTheme.toString()); + } + + return theme.toString(); } /** @@ -2000,9 +700,11 @@ public void saveLocalTheme() { } /** - * @return The supplied context theme from shared preferences. + * Returns the supplied context theme from the shared preferences. * * @param context The context to retrieve the theme. + * + * @return The supplied context theme from shared preferences. */ public @Nullable String getLocalTheme(@NonNull Context context) { return DynamicPreferences.getInstance().loadPrefs(ADS_PREF_THEME, @@ -2015,7 +717,21 @@ public void saveLocalTheme() { * @param context The context to delete the theme. */ public void deleteLocalTheme(@NonNull Context context) { - DynamicPreferences.getInstance().deletePrefs(ADS_PREF_THEME, - ADS_PREF_THEME_KEY + context.getClass().getName()); + try { + DynamicPreferences.getInstance().deletePrefs(ADS_PREF_THEME, + ADS_PREF_THEME_KEY + context.getClass().getName()); + } catch (Exception ignored) { + } + } + + /** + * Returns the dynamic app theme from the Json string. + * + * @param theme The dynamic app theme Json string to be converted. + * + * @return The dynamic app theme from the Json string. + */ + public @Nullable DynamicAppTheme getTheme(@Nullable String theme) { + return new Gson().fromJson(theme, DynamicAppTheme.class); } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/Theme.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/Theme.java new file mode 100644 index 0000000000..b921bf614b --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/Theme.java @@ -0,0 +1,252 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.theme; + +import androidx.annotation.IntDef; +import androidx.annotation.StringDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Constant values for the dynamic theme. + */ +@Retention(RetentionPolicy.SOURCE) +@IntDef(value = { Theme.AUTO, Theme.CUSTOM }) +public @interface Theme { + + /** + * Constant for the automatic theme. + */ + int AUTO = -3; + + /** + * Constant for the custom theme. + */ + int CUSTOM = -2; + + /** + * String constant values for the dynamic theme. + */ + @Retention(RetentionPolicy.SOURCE) + @StringDef(value = { ToString.AUTO, ToString.CUSTOM }) + @interface ToString { + + /** + * String constant for the automatic theme. + */ + String AUTO = "-3"; + + /** + * String constant for the custom theme. + */ + String CUSTOM = "-2"; + } + + /** + * Constant values for the visibility. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { Visibility.AUTO, Visibility.HIDE, Visibility.SHOW }) + @interface Visibility { + + /** + * Constant for the automatic visibility. + */ + int AUTO = Theme.AUTO; + + /** + * Constant for the always hide visibility. + */ + int HIDE = 0; + + /** + * Constant for the always show visibility. + */ + int SHOW = 1; + + /** + * String constant values for the visibility. + */ + @Retention(RetentionPolicy.SOURCE) + @StringDef(value = { Theme.Visibility.ToString.AUTO, + Theme.Visibility.ToString.HIDE, Theme.Visibility.ToString.SHOW }) + @interface ToString { + + /** + * String constant for the automatic visibility. + */ + String AUTO = Theme.ToString.AUTO; + + /** + * String constant for the always hide visibility. + */ + String HIDE = "0"; + + /** + * String constant for the always show visibility. + */ + String SHOW = "1"; + } + } + + /** + * Constant values for the background aware functionality. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { BackgroundAware.AUTO, BackgroundAware.DISABLE, BackgroundAware.ENABLE}) + @interface BackgroundAware { + + /** + * Constant for the automatic background aware. + */ + int AUTO = Theme.AUTO; + + /** + * Constant to disable the background aware. + */ + int DISABLE = 0; + + /** + * Constant to enable the background aware. + */ + int ENABLE = 1; + + /** + * String constant values for the background aware functionality. + */ + @Retention(RetentionPolicy.SOURCE) + @StringDef(value = { Theme.BackgroundAware.ToString.AUTO, + Theme.BackgroundAware.ToString.DISABLE, Theme.BackgroundAware.ToString.ENABLE}) + @interface ToString { + + /** + * String constant for the automatic background aware. + */ + String AUTO = Theme.ToString.AUTO; + + /** + * String constant to disable the background aware. + */ + String DISABLE = "0"; + + /** + * String constant to enable the background aware. + */ + String ENABLE = "1"; + } + } + + /** + * Interface to hold the color type constant values according to the + * {@link com.pranavpandey.android.dynamic.support.R.attr#ads_colorType}. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { ColorType.NONE, ColorType.PRIMARY, ColorType.PRIMARY_DARK, + ColorType.ACCENT, ColorType.ACCENT_DARK, ColorType.TINT_PRIMARY, + ColorType.TINT_PRIMARY_DARK, ColorType.TINT_ACCENT, ColorType.TINT_ACCENT_DARK, + ColorType.CUSTOM, ColorType.BACKGROUND, ColorType.TINT_BACKGROUND, + ColorType.TEXT_PRIMARY, ColorType.TEXT_SECONDARY, ColorType.TEXT_PRIMARY_INVERSE, + ColorType.TEXT_SECONDARY_INVERSE }) + @interface ColorType { + + /** + * Constant for the unknown color. + */ + int UNKNOWN = -2; + + /** + * Constant for the no color. + */ + int NONE = 0; + + /** + * Constant for the primary color. + */ + int PRIMARY = 1; + + /** + * Constant for the dark primary color. + */ + int PRIMARY_DARK = 2; + + /** + * Constant for the accent color. + */ + int ACCENT = 3; + + /** + * Constant for the dark accent color. + */ + int ACCENT_DARK = 4; + + /** + * Constant for the tint primary color. + */ + int TINT_PRIMARY = 5; + + /** + * Constant for the tint dark primary color. + */ + int TINT_PRIMARY_DARK = 6; + + /** + * Constant for the tint accent color. + */ + int TINT_ACCENT = 7; + + /** + * Constant for the tint dark accent color. + */ + int TINT_ACCENT_DARK = 8; + + /** + * Constant for the custom color. + */ + int CUSTOM = 9; + + /** + * Constant for the background color. + */ + int BACKGROUND = 10; + + /** + * Constant for the tint background color. + */ + int TINT_BACKGROUND = 11; + + /** + * Constant for the text primary color. + */ + int TEXT_PRIMARY = 12; + + /** + * Constant for the text secondary color. + */ + int TEXT_SECONDARY = 13; + + /** + * Constant for the inverse text primary color. + */ + int TEXT_PRIMARY_INVERSE = 14; + + /** + * Constant for the inverse text secondary color. + */ + int TEXT_SECONDARY_INVERSE = 15; + } +} \ No newline at end of file diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/dialog/DynamicThemeDialog.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/dialog/DynamicThemeDialog.java new file mode 100644 index 0000000000..45792c4933 --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/dialog/DynamicThemeDialog.java @@ -0,0 +1,244 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.theme.dialog; + +import android.content.DialogInterface; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.IntDef; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.pranavpandey.android.dynamic.support.R; +import com.pranavpandey.android.dynamic.support.dialog.DynamicDialog; +import com.pranavpandey.android.dynamic.support.dialog.fragment.DynamicDialogFragment; +import com.pranavpandey.android.dynamic.support.utils.DynamicInputUtils; +import com.pranavpandey.android.dynamic.support.utils.DynamicThemeUtils; + +import static com.pranavpandey.android.dynamic.support.theme.dialog.DynamicThemeDialog.Type.THEME_IMPORT; +import static com.pranavpandey.android.dynamic.support.theme.dialog.DynamicThemeDialog.Type.THEME_INVALID; + +/** + * A dialog fragment to import a dynamic theme. + */ +public class DynamicThemeDialog extends DynamicDialogFragment { + + /** + * Interface to listen theme import events. + */ + public interface OnThemeImportListener { + + /** + * This method will be called on importing the theme. + * + * @param theme The theme string to be imported. + */ + void onImportTheme(@NonNull String theme); + } + + /** + * Dialog type to show the layout accordingly. + */ + @IntDef(value = { THEME_IMPORT, THEME_INVALID }) + public @interface Type { + + /** + * Constant for the import theme dialog. + */ + int THEME_IMPORT = 0; + + /** + * Constant for the invalid theme dialog. + */ + int THEME_INVALID = 1; + } + + /** + * Key for dialog type to maintain its state. + */ + private static final String ADS_STATE_DIALOG_TYPE = "ads_state_dialog_type"; + + /** + * Key for edit text string to maintain its state. + */ + private static final String ADS_STATE_EDIT_TEXT_STRING = "state_edit_text_string"; + + /** + * Dialog type to show the layout accordingly. + */ + private @Type int mType; + + /** + * Interface to listen theme import events. + */ + private OnThemeImportListener mOnThemeImportListener; + + + private EditText mEditText; + + /** + * Initialize the new instance of this fragment. + * + * @return An instance of {@link DynamicThemeDialog}. + */ + public static DynamicThemeDialog newInstance() { + return new DynamicThemeDialog(); + } + + @Override + protected @NonNull DynamicDialog.Builder onCustomiseBuilder( + @NonNull DynamicDialog.Builder dialogBuilder, + @Nullable final Bundle savedInstanceState) { + View view; + + if (savedInstanceState != null) { + mType = savedInstanceState.getInt(ADS_STATE_DIALOG_TYPE); + } + + if (mType == THEME_INVALID) { + view = LayoutInflater.from(getContext()).inflate( + R.layout.ads_dialog_general, new LinearLayout(getContext()), false); + + ((TextView) view.findViewById(R.id.ads_dialog_general_message)) + .setText(R.string.ads_theme_invalid); + ((TextView) view.findViewById(R.id.ads_dialog_general_desc)) + .setText(R.string.ads_theme_invalid_desc); + } else { + view = LayoutInflater.from(getContext()).inflate( + R.layout.ads_dialog_theme, new LinearLayout(getContext()), false); + mEditText = view.findViewById(R.id.ads_dialog_theme_edit_text); + + mEditText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + updatePositiveButton(charSequence); + } + + @Override + public void afterTextChanged(Editable editable) { } + }); + + dialogBuilder.setPositiveButton( + R.string.ads_backup_import, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (mOnThemeImportListener != null && mEditText.getText() != null) { + mEditText.getText().clearSpans(); + mOnThemeImportListener.onImportTheme( + mEditText.getText().toString()); + } + } + }); + + + setOnShowListener(new DialogInterface.OnShowListener() { + @Override + public void onShow(DialogInterface dialog) { + if (savedInstanceState != null) { + mEditText.setText(savedInstanceState.getString(ADS_STATE_EDIT_TEXT_STRING)); + } else { + updatePositiveButton(mEditText.getText().toString()); + } + + DynamicInputUtils.showSoftInput(mEditText); + } + }); + } + + dialogBuilder.setTitle(R.string.ads_theme) + .setNegativeButton(R.string.ads_cancel, null) + .setView(view).setViewRoot(view.findViewById(R.id.ads_dialog_theme)); + + return dialogBuilder; + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + + outState.putInt(ADS_STATE_DIALOG_TYPE, mType); + + if (mEditText != null) { + outState.putString(ADS_STATE_EDIT_TEXT_STRING, mEditText.getText().toString()); + } + } + + private void updatePositiveButton(@Nullable CharSequence charSequence) { + if (getDynamicDialog() != null) { + getDynamicDialog().getButton(DynamicDialog.BUTTON_POSITIVE) + .setEnabled(charSequence != null + && DynamicThemeUtils.isValidJson(charSequence.toString())); + } + } + + /** + * Get the dialog type. + * + * @return The current dialog type. + */ + public @Type int getType() { + return mType; + } + + /** + * Set the dialog type. + * + * @param type The dialog type to be set. + * + * @return The {@link DynamicThemeDialog} object to allow for chaining of calls to + * set methods. + */ + public DynamicThemeDialog setType(@Type int type) { + this.mType = type; + + return this; + } + + /** + * Get the theme import listener. + * + * @return The theme import listener. + */ + public @Nullable OnThemeImportListener getOnImportThemeListener() { + return mOnThemeImportListener; + } + + /** + * Set the theme import listener. + * + * @param onThemeImportListener The theme import listener to be set. + * + * @return The {@link DynamicThemeDialog} object to allow for chaining of calls to + * set methods. + */ + public DynamicThemeDialog setOnImportThemeListener( + @Nullable OnThemeImportListener onThemeImportListener) { + this.mOnThemeImportListener = onThemeImportListener; + + return this; + } +} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/fragment/DynamicThemeFragment.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/fragment/DynamicThemeFragment.java new file mode 100644 index 0000000000..ab6ba99d07 --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/fragment/DynamicThemeFragment.java @@ -0,0 +1,677 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package com.pranavpandey.android.dynamic.support.theme.fragment; + +import android.app.Activity; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.pranavpandey.android.dynamic.support.R; +import com.pranavpandey.android.dynamic.support.dialog.DynamicDialog; +import com.pranavpandey.android.dynamic.support.fragment.DynamicFragment; +import com.pranavpandey.android.dynamic.support.intent.DynamicIntent; +import com.pranavpandey.android.dynamic.support.listener.DynamicColorResolver; +import com.pranavpandey.android.dynamic.support.model.DynamicAppTheme; +import com.pranavpandey.android.dynamic.support.setting.DynamicColorPreference; +import com.pranavpandey.android.dynamic.support.setting.DynamicSeekBarPreference; +import com.pranavpandey.android.dynamic.support.setting.DynamicSpinnerPreference; +import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; +import com.pranavpandey.android.dynamic.support.theme.dialog.DynamicThemeDialog; +import com.pranavpandey.android.dynamic.support.theme.view.DynamicThemePreview; +import com.pranavpandey.android.dynamic.support.utils.DynamicMenuUtils; +import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; +import com.pranavpandey.android.dynamic.utils.DynamicLinkUtils; + +/** + * Base theme fragment to provide theme editing functionality. + *

Extend this fragment to implement theme attributes according to the need. + */ +public class DynamicThemeFragment extends DynamicFragment { + + /** + * Key for background color preference. + */ + private static final String ADS_PREF_THEME_COLOR_BACKGROUND = + "ads_pref_settings_theme_color_background"; + + /** + * Key for tint background color preference. + */ + private static final String ADS_PREF_THEME_COLOR_TINT_BACKGROUND = + "ads_pref_settings_theme_color_tint_background"; + + /** + * Key for primary color preference. + */ + private static final String ADS_PREF_THEME_COLOR_PRIMARY = + "ads_pref_settings_theme_color_primary"; + + /** + * Key for tint primary color preference. + */ + private static final String ADS_PREF_THEME_COLOR_TINT_PRIMARY = + "ads_pref_settings_theme_color_tint_primary"; + + /** + * Key for dark primary color preference. + */ + private static final String ADS_PREF_THEME_COLOR_PRIMARY_DARK = + "ads_pref_settings_theme_color_primary_dark"; + + /** + * Key for accent color preference. + */ + private static final String ADS_PREF_THEME_COLOR_ACCENT = + "ads_pref_settings_theme_color_accent"; + + /** + * Key for tint accent color preference. + */ + private static final String ADS_PREF_THEME_COLOR_TINT_ACCENT = + "ads_pref_settings_theme_color_tint_accent"; + + /** + * Key for primary text color preference. + */ + private static final String ADS_PREF_THEME_TEXT_PRIMARY = + "ads_pref_settings_theme_text_primary"; + + /** + * Key for inverse primary text color preference. + */ + private static final String ADS_PREF_THEME_TEXT_INVERSE_PRIMARY = + "ads_pref_settings_theme_text_inverse_primary"; + + /** + * Key for secondary text color preference. + */ + private static final String ADS_PREF_THEME_TEXT_SECONDARY = + "ads_pref_settings_theme_text_secondary"; + + /** + * Key for inverse secondary text color preference. + */ + private static final String ADS_PREF_THEME_TEXT_INVERSE_SECONDARY = + "ads_pref_settings_theme_text_inverse_secondary"; + + /** + * Key for corner size preference. + */ + private static final String ADS_PREF_THEME_CORNER_SIZE = + "ads_pref_settings_theme_corner_size"; + + /** + * Key for corner size alternate preference. + */ + private static final String ADS_PREF_THEME_CORNER_SIZE_ALT = + "ads_pref_settings_theme_corner_size_alt"; + + /** + * Key for background aware preference. + */ + private static final String ADS_PREF_THEME_BACKGROUND_AWARE = + "ads_pref_settings_theme_background_aware"; + + /** + * Dynamic app theme used by this fragment. + */ + private DynamicAppTheme mDynamicAppTheme; + + /** + * Default dynamic app theme used by this fragment. + */ + private DynamicAppTheme mDynamicAppThemeDefault; + + /** + * {@code true} if the settings has been changed. + */ + private boolean mSettingsChanged; + + /** + * Theme preview used by this fragment. + */ + private DynamicThemePreview mThemePreview; + + /** + * Dynamic color preference to control the background color. + */ + private DynamicColorPreference mColorBackgroundPreference; + + /** + * Dynamic color preference to control the primary color. + */ + private DynamicColorPreference mColorPrimaryPreference; + + /** + * Dynamic color preference to control the dark primary color. + */ + private DynamicColorPreference mColorPrimaryDarkPreference; + + /** + * Dynamic color preference to control the accent color. + */ + private DynamicColorPreference mColorAccentPreference; + + /** + * Dynamic color preference to control the primary text color. + */ + private DynamicColorPreference mTextPrimaryPreference; + + /** + * Dynamic color preference to control the secondary text color. + */ + private DynamicColorPreference mTextSecondaryPreference; + + /** + * Dynamic seek bar preference to control the corner radius. + */ + private DynamicSeekBarPreference mCornerSizePreference; + + /** + * Dynamic spinner preference to control the background aware functionality. + */ + private DynamicSpinnerPreference mBackgroundAwarePreference; + + /** + * Initialize the new instance of this fragment. + * + * @param dynamicAppTheme The dynamic app theme. + * + * @return An instance of {@link DynamicThemeFragment}. + */ + public static Fragment newInstance(@Nullable String dynamicAppTheme, + @Nullable String dynamicAppThemeDefault) { + DynamicThemeFragment fragment = new DynamicThemeFragment(); + Bundle args = new Bundle(); + args.putString(DynamicIntent.EXTRA_THEME, dynamicAppTheme); + args.putString(DynamicIntent.EXTRA_THEME_DEFAULT, dynamicAppThemeDefault); + fragment.setArguments(args); + + return fragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setResult(Activity.RESULT_CANCELED, null, false); + + setRetainInstance(true); + setHasOptionsMenu(true); + + if (savedInstanceState == null) { + mSettingsChanged = false; + } + + mDynamicAppTheme = getThemeFromArguments(DynamicIntent.EXTRA_THEME); + mDynamicAppThemeDefault = getThemeFromArguments(DynamicIntent.EXTRA_THEME_DEFAULT); + + if (mDynamicAppTheme == null) { + mDynamicAppTheme = DynamicTheme.getInstance().generateDefaultTheme(); + } + + if (mDynamicAppThemeDefault == null) { + mDynamicAppThemeDefault = mDynamicAppTheme; + } + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, + @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.ads_fragment_theme, container, false); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + mThemePreview = view.findViewById(R.id.ads_theme_preview); + mColorBackgroundPreference = view.findViewById(R.id.ads_pref_theme_color_background); + mColorPrimaryPreference = view.findViewById(R.id.ads_pref_theme_color_primary); + mColorPrimaryDarkPreference = view.findViewById(R.id.ads_pref_theme_color_primary_dark); + mColorAccentPreference = view.findViewById(R.id.ads_pref_theme_color_accent); + mTextPrimaryPreference = view.findViewById(R.id.ads_pref_theme_text_primary); + mTextSecondaryPreference = view.findViewById(R.id.ads_pref_theme_text_secondary); + mCornerSizePreference = view.findViewById(R.id.ads_pref_theme_corner_size); + mBackgroundAwarePreference = view.findViewById(R.id.ads_pref_theme_background_aware); + + mThemePreview.getFAB().setImageResource(R.drawable.ads_ic_preview); + + mColorBackgroundPreference.setDynamicColorResolver(new DynamicColorResolver() { + @Override + public int getDefaultColor(@Nullable String tag) { + return mDynamicAppThemeDefault.getBackgroundColor(); + } + + @Override + public int getAutoColor(@Nullable String tag) { + return DynamicTheme.getInstance().getDefault().getBackgroundColor(); + } + }); + mColorBackgroundPreference.setAltDynamicColorResolver(new DynamicColorResolver() { + @Override + public int getDefaultColor(@Nullable String tag) { + return Theme.AUTO; + } + + @Override + public int getAutoColor(@Nullable String tag) { + return DynamicColorUtils.getTintColor( + mThemePreview.getDynamicAppTheme().getBackgroundColor()); + } + }); + + mColorPrimaryPreference.setDynamicColorResolver(new DynamicColorResolver() { + @Override + public int getDefaultColor(@Nullable String tag) { + return Theme.AUTO; + } + + @Override + public int getAutoColor(@Nullable String tag) { + return DynamicTheme.getInstance().getDefault().getPrimaryColor(); + } + }); + mColorPrimaryPreference.setAltDynamicColorResolver(new DynamicColorResolver() { + @Override + public int getDefaultColor(@Nullable String tag) { + return Theme.AUTO; + } + + @Override + public int getAutoColor(@Nullable String tag) { + return DynamicColorUtils.getTintColor( + mThemePreview.getDynamicAppTheme().getPrimaryColor()); + } + }); + + mColorPrimaryDarkPreference.setDynamicColorResolver(new DynamicColorResolver() { + @Override + public int getDefaultColor(@Nullable String tag) { + return Theme.AUTO; + } + + @Override + public int getAutoColor(@Nullable String tag) { + return DynamicTheme.getInstance().generateDarkColor( + mThemePreview.getDynamicAppTheme().getPrimaryColor()); + } + }); + + mColorAccentPreference.setDynamicColorResolver(new DynamicColorResolver() { + @Override + public int getDefaultColor(@Nullable String tag) { + return Theme.AUTO; + } + + @Override + public int getAutoColor(@Nullable String tag) { + return DynamicTheme.getInstance().getDefault().getAccentColor(); + } + }); + mColorAccentPreference.setAltDynamicColorResolver(new DynamicColorResolver() { + @Override + public int getDefaultColor(@Nullable String tag) { + return Theme.AUTO; + } + + @Override + public int getAutoColor(@Nullable String tag) { + return DynamicColorUtils.getTintColor( + mThemePreview.getDynamicAppTheme().getAccentColor()); + } + }); + + mTextPrimaryPreference.setDynamicColorResolver(new DynamicColorResolver() { + @Override + public int getDefaultColor(@Nullable String tag) { + return Theme.AUTO; + } + + @Override + public int getAutoColor(@Nullable String tag) { + if (DynamicColorUtils.getContrastColor( + DynamicTheme.getInstance().getDefault().getTextPrimaryColor(), + mThemePreview.getDynamicAppTheme().getBackgroundColor()) + != DynamicTheme.getInstance().getDefault().getTextPrimaryColor()) { + return DynamicTheme.getInstance().getDefault().getTextPrimaryColorInverse(); + } + + return DynamicTheme.getInstance().getDefault().getTextPrimaryColor(); + } + }); + mTextPrimaryPreference.setAltDynamicColorResolver(new DynamicColorResolver() { + @Override + public int getDefaultColor(@Nullable String tag) { + return DynamicColorUtils.getTintColor(mTextPrimaryPreference.getColor()); + } + + @Override + public int getAutoColor(@Nullable String tag) { + if (DynamicColorUtils.getContrastColor( + DynamicTheme.getInstance().getDefault().getTextPrimaryColorInverse(), + mThemePreview.getDynamicAppTheme().getBackgroundColor()) + == DynamicTheme.getInstance().getDefault().getTextPrimaryColorInverse()) { + return DynamicColorUtils.getTintColor( + DynamicTheme.getInstance().getDefault().getTextPrimaryColorInverse()); + } + + return DynamicTheme.getInstance().getDefault().getTextPrimaryColorInverse(); + } + }); + + mTextSecondaryPreference.setDynamicColorResolver(new DynamicColorResolver() { + @Override + public int getDefaultColor(@Nullable String tag) { + return Theme.AUTO; + } + + @Override + public int getAutoColor(@Nullable String tag) { + if (DynamicColorUtils.getContrastColor( + DynamicTheme.getInstance().getDefault().getTextSecondaryColor(), + mThemePreview.getDynamicAppTheme().getBackgroundColor()) + != DynamicTheme.getInstance().getDefault().getTextSecondaryColor()) { + return DynamicTheme.getInstance().getDefault().getTextSecondaryColorInverse(); + } + + return DynamicTheme.getInstance().getDefault().getTextSecondaryColor(); + } + }); + mTextSecondaryPreference.setAltDynamicColorResolver(new DynamicColorResolver() { + @Override + public int getDefaultColor(@Nullable String tag) { + return DynamicColorUtils.getTintColor(mTextSecondaryPreference.getColor()); + } + + @Override + public int getAutoColor(@Nullable String tag) { + if (DynamicColorUtils.getContrastColor( + DynamicTheme.getInstance().getDefault().getTextSecondaryColorInverse(), + mThemePreview.getDynamicAppTheme().getBackgroundColor()) + == DynamicTheme.getInstance().getDefault().getTextSecondaryColorInverse()) { + return DynamicColorUtils.getTintColor( + DynamicTheme.getInstance().getDefault().getTextSecondaryColorInverse()); + } + + return DynamicTheme.getInstance().getDefault().getTextSecondaryColorInverse(); + } + }); + + getDynamicActivity().setFAB(R.drawable.ads_ic_save, + getDynamicActivity().getFABVisibility(), + new View.OnClickListener() { + @Override + public void onClick(View v) { + saveThemeSettings(); + } + }); + + loadTheme(mDynamicAppTheme); + } + + @Override + public void onPrepareOptionsMenu(@Nullable Menu menu) { + super.onPrepareOptionsMenu(menu); + + DynamicMenuUtils.forceMenuIcons(menu); + } + + @Override + public void onCreateOptionsMenu(@Nullable Menu menu, @Nullable MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + + inflater.inflate(R.menu.ads_menu_theme, menu); + } + + @Override + public boolean onOptionsItemSelected(@Nullable MenuItem item) { + if (item != null) { + int i = item.getItemId(); + if (i == R.id.ads_menu_theme_copy) { + DynamicLinkUtils.copyToClipboard(getContext(), getString(R.string.ads_theme), + mThemePreview.getDynamicAppTheme().toDynamicString()); + + getDynamicActivity().getSnackBar(R.string.ads_theme_copy_done).show(); + } else if (i == R.id.ads_menu_theme_share) { + DynamicLinkUtils.share(getContext(), null, + mThemePreview.getDynamicAppTheme().toDynamicString()); + } else if (i == R.id.ads_menu_theme_import) { + importTheme(); + } else if (i == R.id.ads_menu_refresh) { + mSettingsChanged = false; + loadTheme(mDynamicAppTheme); + } else if (i == R.id.ads_menu_default) { + mSettingsChanged = false; + mDynamicAppTheme = new DynamicAppTheme(mDynamicAppThemeDefault); + loadTheme(mDynamicAppTheme); + + getDynamicActivity().getSnackBar(R.string.ads_theme_reset_desc).show(); + } + } + + return super.onOptionsItemSelected(item); + } + + /** + * Show dialog to import the theme. + * + * @see DynamicThemeDialog + * @see DynamicThemeDialog.Type#THEME_IMPORT + */ + private void importTheme() { + DynamicThemeDialog.newInstance() + .setType(DynamicThemeDialog.Type.THEME_IMPORT) + .setOnImportThemeListener( + new DynamicThemeDialog.OnThemeImportListener() { + @Override + public void onImportTheme(@NonNull String theme) { + try { + DynamicAppTheme dynamicAppTheme = new DynamicAppTheme(theme); + mSettingsChanged = false; + loadTheme(dynamicAppTheme); + + getDynamicActivity().getSnackBar( + R.string.ads_theme_import_done).show(); + } catch (Exception ignored) { + invalidTheme(); + } + } + }).showDialog(getActivity()); + } + + /** + * Show dialog for the invalid theme. + * + * @see DynamicThemeDialog + * @see DynamicThemeDialog.Type#THEME_INVALID + */ + private void invalidTheme() { + DynamicThemeDialog.newInstance() + .setType(DynamicThemeDialog.Type.THEME_INVALID) + .setBuilder(new DynamicDialog.Builder(getContext()) + .setPositiveButton(R.string.ads_backup_import, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + importTheme(); + } + })).showDialog(getActivity()); + } + + @Override + public void onResume() { + super.onResume(); + + updateThemePreview(); + updatePreferences(); + } + + /** + * Retrieves the theme from the supplies arguments + * + * @param key The key to be retrieved. + * + * @return The dynamic theme from the supplied arguments. + */ + public @Nullable DynamicAppTheme getThemeFromArguments(@NonNull String key) { + return DynamicTheme.getInstance().getTheme(getStringFromArguments(key)); + } + + /** + * Update settings according to the supplied theme. + */ + private void loadTheme(@NonNull DynamicAppTheme dynamicAppTheme) { + if (!mSettingsChanged) { + mColorBackgroundPreference.setColor(dynamicAppTheme.getBackgroundColor(false)); + mColorBackgroundPreference.setAltColor(dynamicAppTheme.getTintBackgroundColor(false)); + mColorPrimaryPreference.setColor(dynamicAppTheme.getPrimaryColor(false)); + mColorPrimaryPreference.setAltColor(dynamicAppTheme.getTintPrimaryColor(false)); + mColorPrimaryDarkPreference.setColor(dynamicAppTheme.getPrimaryColorDark(false)); + mColorAccentPreference.setColor(dynamicAppTheme.getAccentColor(false)); + mColorAccentPreference.setAltColor(dynamicAppTheme.getTintAccentColor(false)); + mTextPrimaryPreference.setColor(dynamicAppTheme.getTextPrimaryColor(false)); + mTextPrimaryPreference.setAltColor(dynamicAppTheme.getTextPrimaryColorInverse(false)); + mTextSecondaryPreference.setColor(dynamicAppTheme.getTextSecondaryColor(false)); + mTextSecondaryPreference.setAltColor(dynamicAppTheme.getTextSecondaryColorInverse(false)); + + if (dynamicAppTheme.getCornerRadius(false) != Theme.AUTO) { + mCornerSizePreference.setPreferenceValue(Theme.ToString.CUSTOM); + mCornerSizePreference.setValue(dynamicAppTheme.getCornerSizeDp()); + } else { + mCornerSizePreference.setPreferenceValue(Theme.ToString.AUTO); + } + + mBackgroundAwarePreference.setPreferenceValue( + String.valueOf(dynamicAppTheme.getBackgroundAware(false))); + } + + updateThemePreview(); + updatePreferences(); + } + + /** + * Get the resolved corner size from the preference. + */ + private int getCornerSize() { + return mCornerSizePreference.getPreferenceValue().equals(Theme.ToString.AUTO) + ? Theme.AUTO : mCornerSizePreference.getValueFromProgress(); + } + + /** + * Get the resolved background aware from the preference. + */ + private @Theme.BackgroundAware int getBackgroundAware() { + if (mBackgroundAwarePreference.getPreferenceValue() != null) { + return Integer.valueOf(mBackgroundAwarePreference.getPreferenceValue()); + } + + return Theme.BackgroundAware.AUTO; + } + + /** + * Update all the preferences. + */ + private void updatePreferences() { + mColorBackgroundPreference.update(); + mColorPrimaryPreference.update(); + mColorPrimaryDarkPreference.update(); + mColorAccentPreference.update(); + mTextPrimaryPreference.update(); + mTextSecondaryPreference.update(); + mCornerSizePreference.setSeekBarEnabled(getCornerSize() != Theme.AUTO); + mBackgroundAwarePreference.update(); + } + + /** + * Update the theme preview. + */ + private void updateThemePreview() { + mThemePreview.setDynamicAppTheme( + new DynamicAppTheme(mDynamicAppTheme) + .setBackgroundColor(mColorBackgroundPreference.getColor(false)) + .setTintBackgroundColor(mColorBackgroundPreference.getAltColor(false)) + .setPrimaryColor(mColorPrimaryPreference.getColor(false)) + .setTintPrimaryColor(mColorPrimaryPreference.getAltColor(false)) + .setPrimaryColorDark(mColorPrimaryDarkPreference.getColor(false)) + .setTintPrimaryColorDark(Theme.AUTO) + .setAccentColor(mColorAccentPreference.getColor(false)) + .setTintAccentColor(mColorAccentPreference.getAltColor(false)) + .setTextPrimaryColor(mTextPrimaryPreference.getColor(false)) + .setTextPrimaryColorInverse(mTextPrimaryPreference.getAltColor(false)) + .setTextSecondaryColor(mTextSecondaryPreference.getColor(false)) + .setTextSecondaryColorInverse(mTextSecondaryPreference.getAltColor(false)) + .setCornerRadiusDp(getCornerSize()) + .setBackgroundAware(getBackgroundAware())); + + mSettingsChanged = true; + } + + /** + * Set the theme and finish this activity. + */ + public void saveThemeSettings() { + Intent intent = new Intent(); + intent.putExtra(DynamicIntent.EXTRA_THEME, + mThemePreview.getDynamicAppTheme().toJsonString()); + setResult(Activity.RESULT_OK, intent); + + finishActivity(); + } + + @Override + protected boolean setSharedPreferenceChangeListener() { + return true; + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + switch (key) { + case ADS_PREF_THEME_COLOR_BACKGROUND: + case ADS_PREF_THEME_COLOR_TINT_BACKGROUND: + case ADS_PREF_THEME_COLOR_PRIMARY: + case ADS_PREF_THEME_COLOR_TINT_PRIMARY: + case ADS_PREF_THEME_COLOR_PRIMARY_DARK: + case ADS_PREF_THEME_COLOR_ACCENT: + case ADS_PREF_THEME_COLOR_TINT_ACCENT: + case ADS_PREF_THEME_TEXT_PRIMARY: + case ADS_PREF_THEME_TEXT_INVERSE_PRIMARY: + case ADS_PREF_THEME_TEXT_SECONDARY: + case ADS_PREF_THEME_TEXT_INVERSE_SECONDARY: + case ADS_PREF_THEME_CORNER_SIZE: + case ADS_PREF_THEME_CORNER_SIZE_ALT: + case ADS_PREF_THEME_BACKGROUND_AWARE: + updateThemePreview(); + updatePreferences(); + break; + } + } +} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/view/DynamicThemePreview.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/view/DynamicThemePreview.java new file mode 100644 index 0000000000..284633556f --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/view/DynamicThemePreview.java @@ -0,0 +1,350 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.theme.view; + +import android.content.Context; +import android.graphics.RadialGradient; +import android.graphics.Shader; +import android.graphics.drawable.ShapeDrawable; +import android.graphics.drawable.shapes.RectShape; +import android.os.Handler; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import androidx.annotation.AttrRes; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.pranavpandey.android.dynamic.support.R; +import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; +import com.pranavpandey.android.dynamic.support.widget.DynamicCardView; +import com.pranavpandey.android.dynamic.support.widget.DynamicFloatingActionButton; +import com.pranavpandey.android.dynamic.support.widget.DynamicImageView; +import com.pranavpandey.android.dynamic.utils.DynamicDrawableUtils; +import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils; + +/** + * A ThemePreview to show the dynamic app theme preview according to the selected values. + */ +public class DynamicThemePreview extends ThemePreview { + + /** + * Status bar used by this preview. + */ + private ImageView mStatusBar; + + /** + * Background card used by this preview. + */ + private DynamicCardView mBackgroundCard; + + /** + * Header background used by this preview. + */ + private ViewGroup mHeader; + + /** + * Header icon used by this preview. + */ + private DynamicImageView mHeaderIcon; + + /** + * Header title used by this preview. + */ + private DynamicImageView mHeaderTitle; + + /** + * Header menu used by this preview. + */ + private DynamicImageView mHeaderMenu; + + /** + * Content parent view used by this preview. + */ + private ViewGroup mContent; + + /** + * Icon used by this preview. + */ + private DynamicImageView mIcon; + + /** + * Primary text used by this preview. + */ + private DynamicImageView mTextPrimary; + + /** + * Secondary text used by this preview. + */ + private DynamicImageView mTextSecondary; + + /** + * Background tint text used by this preview. + */ + private DynamicImageView mTextTintBackground; + + /** + * FAB used by this preview. + */ + private DynamicFloatingActionButton mFAB; + + /** + * On click listener to receive FAB click events. + */ + private View.OnClickListener mOnFABClickListener; + + public DynamicThemePreview(@NonNull Context context) { + this(context, null); + } + + public DynamicThemePreview(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public DynamicThemePreview(@NonNull Context context, + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onLoadAttributes(@Nullable AttributeSet attrs) { + super.onLoadAttributes(attrs); + } + + @Override + protected @LayoutRes int getLayoutRes() { + return R.layout.ads_layout_theme_preview; + } + + @Override + protected void onInflate() { + inflate(getContext(), getLayoutRes(), this); + + mStatusBar = findViewById(R.id.ads_theme_status_bar); + mBackgroundCard = findViewById(R.id.ads_theme_background); + mHeader = findViewById(R.id.ads_theme_header); + mHeaderIcon = findViewById(R.id.ads_theme_header_icon); + mHeaderTitle = findViewById(R.id.ads_theme_header_title); + mHeaderMenu = findViewById(R.id.ads_theme_header_menu); + mContent = findViewById(R.id.ads_theme_content); + mIcon = findViewById(R.id.ads_theme_icon); + mTextPrimary = findViewById(R.id.ads_theme_text_primary); + mTextSecondary = findViewById(R.id.ads_theme_text_secondary); + mTextTintBackground = findViewById(R.id.ads_theme_text_tint_background); + mFAB = findViewById(R.id.ads_theme_fab); + } + + @Override + protected void onUpdate() { + mStatusBar.setBackgroundColor(getDynamicAppTheme().getPrimaryColorDark()); + mBackgroundCard.setRadius(getDynamicAppTheme().getCornerRadius()); + mHeader.setBackgroundColor(getDynamicAppTheme().getPrimaryColor()); + mBackgroundCard.setColor(getDynamicAppTheme().getBackgroundColor()); + + new Handler().post(new Runnable() { + @Override + public void run() { + if (getDynamicAppTheme().getBackgroundColor(false) == Theme.AUTO + && getMeasuredWidth() > 0 && getMeasuredHeight() > 0) { + + RadialGradient gradient = + new RadialGradient(mContent.getMeasuredWidth() / 2f, + mContent.getMeasuredHeight() / 2f, + getMeasuredWidth() / 2f, + new int[] { DynamicTheme.getInstance().generateDarkColor( + getDynamicAppTheme().getTintBackgroundColor()), + getDynamicAppTheme().getBackgroundColor() }, + null, Shader.TileMode.CLAMP); + ShapeDrawable shape = new ShapeDrawable(new RectShape()); + shape.getPaint().setShader(gradient); + DynamicDrawableUtils.setBackground(mContent, shape); + } else { + DynamicDrawableUtils.setBackground(mContent, null); + } + } + }); + + mHeaderIcon.setBackgroundAware(getDynamicAppTheme().getBackgroundAware()); + mHeaderTitle.setBackgroundAware(getDynamicAppTheme().getBackgroundAware()); + mHeaderMenu.setBackgroundAware(getDynamicAppTheme().getBackgroundAware()); + mIcon.setBackgroundAware(getDynamicAppTheme().getBackgroundAware()); + mTextPrimary.setBackgroundAware(getDynamicAppTheme().getBackgroundAware()); + mTextSecondary.setBackgroundAware(getDynamicAppTheme().getBackgroundAware()); + mTextTintBackground.setBackgroundAware(getDynamicAppTheme().getBackgroundAware()); + mFAB.setBackgroundAware(getDynamicAppTheme().getBackgroundAware()); + + mHeaderIcon.setContrastWithColor(getDynamicAppTheme().getPrimaryColor()); + mHeaderTitle.setContrastWithColor(getDynamicAppTheme().getPrimaryColor()); + mHeaderMenu.setContrastWithColor(getDynamicAppTheme().getPrimaryColor()); + mIcon.setContrastWithColor(getDynamicAppTheme().getBackgroundColor()); + mTextPrimary.setContrastWithColor(getDynamicAppTheme().getBackgroundColor()); + mTextSecondary.setContrastWithColor(getDynamicAppTheme().getBackgroundColor()); + mTextTintBackground.setContrastWithColor(getDynamicAppTheme().getBackgroundColor()); + mFAB.setContrastWithColor(getDynamicAppTheme().getBackgroundColor()); + + mHeaderIcon.setColor(getDynamicAppTheme().getTintPrimaryColor()); + mHeaderTitle.setColor(getDynamicAppTheme().getTintPrimaryColor()); + mHeaderMenu.setColor(getDynamicAppTheme().getTintPrimaryColor()); + mIcon.setColor(getDynamicAppTheme().getPrimaryColor()); + mTextPrimary.setColor(getDynamicAppTheme().getTextPrimaryColor()); + mTextSecondary.setColor(getDynamicAppTheme().getTextSecondaryColor()); + mTextTintBackground.setColor(getDynamicAppTheme().getTintBackgroundColor()); + mFAB.setColor(getDynamicAppTheme().getAccentColor()); + + if (!DynamicVersionUtils.isLollipop()) { + DynamicDrawableUtils.setBackground(mStatusBar, DynamicDrawableUtils + .getCornerDrawable(Math.max(0f, + (float) (getDynamicAppTheme().getCornerSizeDp() - 1)), + getDynamicAppTheme().getPrimaryColorDark())); + } + } + + @Override + protected void onEnabled(boolean enabled) { + super.onEnabled(enabled); + + mFAB.setEnabled(enabled); + mFAB.setOnClickListener(enabled ? mOnFABClickListener : null); + mFAB.setClickable(enabled && mOnFABClickListener != null); + } + + /** + * Get the on click listener to receive FAB click events. + * + * @return The on click listener to receive FAB click events. + */ + public OnClickListener getOnFABClickListener() { + return mOnFABClickListener; + } + + /** + * Set the on click listener for FAB to receive the click events and to perform edit + * operation. + * + * @param onFABClickListener The on click listener to be set. + */ + public void setOnFABClickListener( + @Nullable View.OnClickListener onFABClickListener) { + this.mOnFABClickListener = onFABClickListener; + + mFAB.setOnClickListener(mOnFABClickListener); + onEnabled(isEnabled()); + } + + /** + * Get the status bar used by this preview. + * + * @return The status bar used by this preview. + */ + public ImageView getStatusBar() { + return mStatusBar; + } + + /** + * Get the background card used by this preview. + * + * @return The background card used by this preview. + */ + public DynamicCardView getBackgroundCard() { + return mBackgroundCard; + } + + /** + * Get the header background used by this preview. + * + * @return The header background used by this preview. + */ + public ViewGroup getHeader() { + return mHeader; + } + + /** + * Get the header icon used by this preview. + * + * @return The header title used by this preview. + */ + public DynamicImageView getHeaderIcon() { + return mHeaderIcon; + } + + /** + * Get the header title used by this preview. + * + * @return The header title used by this preview. + */ + public DynamicImageView getHeaderTitle() { + return mHeaderTitle; + } + + /** + * Get the header menu used by this preview. + * + * @return The header menu used by this preview. + */ + public DynamicImageView getHeaderMenu() { + return mHeaderMenu; + } + + /** + * Get the icon used by this preview. + * + * @return The icon used by this preview. + */ + public DynamicImageView getIcon() { + return mIcon; + } + + /** + * Get the primary text used by this preview. + * + * @return The primary text used by this preview. + */ + public DynamicImageView getTextPrimary() { + return mTextPrimary; + } + + /** + * Ge the secondary text used by this preview. + * + * @return The secondary text used by this preview. + */ + public DynamicImageView getTextSecondary() { + return mTextSecondary; + } + + /** + * Get the background tint text used by this preview. + * + * @return The background tint text used by this preview. + */ + public DynamicImageView getTextTintBackground() { + return mTextTintBackground; + } + + /** + * Get the FAB used by this preview. + * + * @return The FAB used by this preview. + */ + public DynamicFloatingActionButton getFAB() { + return mFAB; + } +} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/view/ThemePreview.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/view/ThemePreview.java new file mode 100644 index 0000000000..3d91e6dbdc --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/theme/view/ThemePreview.java @@ -0,0 +1,83 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.theme.view; + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.annotation.AttrRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.pranavpandey.android.dynamic.support.model.DynamicAppTheme; +import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.view.DynamicView; +import com.pranavpandey.android.dynamic.support.widget.WidgetDefaults; + +/** + * A DynamicView to show the theme preview according to the selected values. + */ +public abstract class ThemePreview extends DynamicView { + + /** + * Dynamic app theme used by this preview. + */ + private DynamicAppTheme mDynamicAppTheme; + + public ThemePreview(@NonNull Context context) { + super(context); + } + + public ThemePreview(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public ThemePreview(@NonNull Context context, + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onLoadAttributes(@Nullable AttributeSet attrs) { + this.mDynamicAppTheme = DynamicTheme.getInstance().get(); + } + + @Override + protected void onEnabled(boolean enabled) { + setAlpha(enabled ? WidgetDefaults.ADS_ALPHA_ENABLED : WidgetDefaults.ADS_ALPHA_DISABLED); + } + + /** + * Get the dynamic app theme used by this preview. + * + * @return The dynamic app theme used by this preview. + */ + public @NonNull DynamicAppTheme getDynamicAppTheme() { + return mDynamicAppTheme; + } + + /** + * Set the dynamic app theme used by this preview. + * + * @param dynamicAppTheme The dynamic app theme to be set. + */ + public void setDynamicAppTheme(@NonNull DynamicAppTheme dynamicAppTheme) { + this.mDynamicAppTheme = dynamicAppTheme; + + onUpdate(); + } +} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/DynamicSimpleTutorial.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/DynamicSimpleTutorial.java index bafec5d62c..368f6b5345 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/DynamicSimpleTutorial.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/DynamicSimpleTutorial.java @@ -18,17 +18,17 @@ import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.ColorInt; -import android.support.annotation.DrawableRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; + +import androidx.annotation.ColorInt; +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.pranavpandey.android.dynamic.support.tutorial.fragment.DynamicSimpleTutorialFragment; /** - * A simple tutorial item to display a title, subtitle and description - * along with an image which can be tinted according to the background - * color. + * A simple tutorial item to display a title, subtitle and description along with an image + * which can be tinted according to the background color. */ public class DynamicSimpleTutorial implements Parcelable { @@ -63,8 +63,7 @@ public class DynamicSimpleTutorial implements Parcelable { private @DrawableRes int imageRes; /** - * {@code true} to tint the image according to the - * background color. + * {@code true} to tint the image according to the background color. */ private boolean tintImage; @@ -77,8 +76,8 @@ public class DynamicSimpleTutorial implements Parcelable { * @param description The description for this tutorial. * @param imageRes The image resource for this tutorial. */ - public DynamicSimpleTutorial(int id, @ColorInt int backgroundColor, @Nullable String title, - @Nullable String description, @DrawableRes int imageRes) { + public DynamicSimpleTutorial(int id, @ColorInt int backgroundColor, + @Nullable String title, @Nullable String description, @DrawableRes int imageRes) { this(id, backgroundColor, title, null, description, imageRes); } @@ -92,9 +91,9 @@ public DynamicSimpleTutorial(int id, @ColorInt int backgroundColor, @Nullable St * @param description The description for this tutorial. * @param imageRes The image resource for this tutorial. */ - public DynamicSimpleTutorial(int id, @ColorInt int backgroundColor, @Nullable String title, - @Nullable String subtitle, @Nullable String description, - @DrawableRes int imageRes) { + public DynamicSimpleTutorial(int id, @ColorInt int backgroundColor, + @Nullable String title, @Nullable String subtitle, + @Nullable String description, @DrawableRes int imageRes) { this(id, backgroundColor, title, subtitle, description, imageRes, false); } @@ -107,12 +106,11 @@ public DynamicSimpleTutorial(int id, @ColorInt int backgroundColor, @Nullable St * @param subtitle The subtitle for this tutorial. * @param description The description for this tutorial. * @param imageRes The image resource for this tutorial. - * @param tintImage {@code true} to tint the image according - * to the background color. + * @param tintImage {@code true} to tint the image according to the background color. */ - public DynamicSimpleTutorial(int id, @ColorInt int backgroundColor, @Nullable String title, - @Nullable String subtitle, @Nullable String description, - @DrawableRes int imageRes, boolean tintImage) { + public DynamicSimpleTutorial(int id, @ColorInt int backgroundColor, + @Nullable String title, @Nullable String subtitle, @Nullable String description, + @DrawableRes int imageRes, boolean tintImage) { this.id = id; this.backgroundColor = backgroundColor; this.title = title; @@ -122,37 +120,24 @@ public DynamicSimpleTutorial(int id, @ColorInt int backgroundColor, @Nullable St this.tintImage = tintImage; } - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(id); - dest.writeInt(backgroundColor); - dest.writeString(title); - dest.writeString(subtitle); - dest.writeString(description); - dest.writeInt(imageRes); - dest.writeByte((byte) (tintImage ? 1 : 0)); - } - /** * Parcelable creator to create from parcel. */ - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override public DynamicSimpleTutorial createFromParcel(Parcel in) { return new DynamicSimpleTutorial(in); } + @Override public DynamicSimpleTutorial[] newArray(int size) { return new DynamicSimpleTutorial[size]; } }; /** - * De-parcel {@link DynamicSimpleTutorial} object. + * Read {@link DynamicSimpleTutorial} object from the parcel. * * @param in The parcel to read the values. */ @@ -166,7 +151,25 @@ public DynamicSimpleTutorial(Parcel in) { this.tintImage = in.readByte() != 0; } + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(id); + dest.writeInt(backgroundColor); + dest.writeString(title); + dest.writeString(subtitle); + dest.writeString(description); + dest.writeInt(imageRes); + dest.writeByte((byte) (tintImage ? 1 : 0)); + } + /** + * Returns the id to uniquely identify this tutorial. + * * @return The id to uniquely identify this tutorial. */ public int getId() { @@ -178,8 +181,8 @@ public int getId() { * * @param id The id to be set. * - * @return The {@link DynamicSimpleTutorial} object to allow - * for chaining of calls to set methods. + * @return The {@link DynamicSimpleTutorial} object to allow for chaining of calls to + * set methods. */ public DynamicSimpleTutorial setId(int id) { this.id = id; @@ -188,6 +191,8 @@ public DynamicSimpleTutorial setId(int id) { } /** + * Get the background color used by this tutorial. + * * @return The background color used by this tutorial. */ public @ColorInt int getBackgroundColor() { @@ -199,8 +204,8 @@ public DynamicSimpleTutorial setId(int id) { * * @param backgroundColor The background color to be set. * - * @return The {@link DynamicSimpleTutorial} object to allow - * for chaining of calls to set methods. + * @return The {@link DynamicSimpleTutorial} object to allow for chaining of calls to + * set methods. */ public DynamicSimpleTutorial setBackgroundColor(@ColorInt int backgroundColor) { this.backgroundColor = backgroundColor; @@ -209,6 +214,8 @@ public DynamicSimpleTutorial setBackgroundColor(@ColorInt int backgroundColor) { } /** + * Get the title used by this tutorial. + * * @return The title used by this tutorial. */ public @Nullable String getTitle() { @@ -220,8 +227,8 @@ public DynamicSimpleTutorial setBackgroundColor(@ColorInt int backgroundColor) { * * @param title The subtitle to be set. * - * @return The {@link DynamicSimpleTutorial} object to allow - * for chaining of calls to set methods. + * @return The {@link DynamicSimpleTutorial} object to allow for chaining of calls to + * set methods. */ public DynamicSimpleTutorial setTitle(@Nullable String title) { this.title = title; @@ -230,6 +237,8 @@ public DynamicSimpleTutorial setTitle(@Nullable String title) { } /** + * Get the subtitle used by this tutorial. + * * @return The subtitle used by this tutorial. */ public @Nullable String getSubtitle() { @@ -241,8 +250,8 @@ public DynamicSimpleTutorial setTitle(@Nullable String title) { * * @param subtitle The subtitle to be set. * - * @return The {@link DynamicSimpleTutorial} object to allow - * for chaining of calls to set methods. + * @return The {@link DynamicSimpleTutorial} object to allow for chaining of calls to + * set methods. */ public DynamicSimpleTutorial setSubtitle(@Nullable String subtitle) { this.subtitle = subtitle; @@ -251,6 +260,8 @@ public DynamicSimpleTutorial setSubtitle(@Nullable String subtitle) { } /** + * Get the description used by this tutorial. + * * @return The description used by this tutorial. */ public @Nullable String getDescription() { @@ -262,8 +273,8 @@ public DynamicSimpleTutorial setSubtitle(@Nullable String subtitle) { * * @param description The description to be set. * - * @return The {@link DynamicSimpleTutorial} object to allow - * for chaining of calls to set methods. + * @return The {@link DynamicSimpleTutorial} object to allow for chaining of calls to + * set methods. */ public DynamicSimpleTutorial setDescription(@Nullable String description) { this.description = description; @@ -272,6 +283,8 @@ public DynamicSimpleTutorial setDescription(@Nullable String description) { } /** + * Get the image resource used by this tutorial. + * * @return The image resource used by this tutorial. */ public @DrawableRes int getImageRes() { @@ -283,8 +296,8 @@ public DynamicSimpleTutorial setDescription(@Nullable String description) { * * @param imageRes The image resource to be set. * - * @return The {@link DynamicSimpleTutorial} object to allow - * for chaining of calls to set methods. + * @return The {@link DynamicSimpleTutorial} object to allow for chaining of calls to + * set methods. */ public DynamicSimpleTutorial setImageRes(@DrawableRes int imageRes) { this.imageRes = imageRes; @@ -293,8 +306,9 @@ public DynamicSimpleTutorial setImageRes(@DrawableRes int imageRes) { } /** - * @return {@code true} to tint the image according to the - * background color. + * Returns whether to tint the image according to the background color. + * + * @return {@code true} to tint the image according to the background color. */ public boolean isTintImage() { return tintImage; @@ -305,8 +319,8 @@ public boolean isTintImage() { * * @param tintImage {@code true} to tint the image. * - * @return The {@link DynamicSimpleTutorial} object to allow - * for chaining of calls to set methods. + * @return The {@link DynamicSimpleTutorial} object to allow for chaining of calls to + * set methods. */ public DynamicSimpleTutorial setTintImage(boolean tintImage) { this.tintImage = tintImage; @@ -315,8 +329,9 @@ public DynamicSimpleTutorial setTintImage(boolean tintImage) { } /** - * @return Build this simple tutorial and return a dynamic tutorial - * to show it in the view pager. + * Build the simple tutorial according to the supplied parameters. + * + * @return The dynamic tutorial fragment to show it in the view pager. * * @see DynamicSimpleTutorialFragment */ diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/DynamicTutorial.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/DynamicTutorial.java index fd3f1e54e4..1c84b64a8a 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/DynamicTutorial.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/DynamicTutorial.java @@ -16,37 +16,42 @@ package com.pranavpandey.android.dynamic.support.tutorial; -import android.support.annotation.ColorInt; -import android.support.v4.view.ViewPager; +import androidx.annotation.ColorInt; +import androidx.viewpager.widget.ViewPager; /** - * Interface for the dynamic tutorial having useful functions which - * will be called by the {@link DynamicTutorialActivity} to perform - * color transitions. - *

Any child view or fragment must implement this - * interface to support any color transitions.

+ * Interface for the dynamic tutorial having useful functions which will be called by the + * {@link DynamicTutorialActivity} to perform color transitions. + * + *

Any child view or fragment must implement this interface to support any color + * transitions. */ public interface DynamicTutorial extends ViewPager.OnPageChangeListener { /** + * Returns the tutorial object. + * * @return The tutorial object. */ Object getTutorial(); /** + * Returns the id for this tutorial. + * * @return The id of this tutorial. */ int getTutorialId(); /** + * Returns the background color for this tutorial. + * * @return The background color used by this tutorial. */ @ColorInt int getBackgroundColor(); /** - * This method will be called when there is a change in the - * background color of the activity. Implement this method to - * update any views during the transition. + * This method will be called when there is a change in the background color of the activity. + *

Implement this method to update any views during the transition. * * @param color The color of the background. */ diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/DynamicTutorialActivity.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/DynamicTutorialActivity.java index 4415224d71..7ff7642e9d 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/DynamicTutorialActivity.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/DynamicTutorialActivity.java @@ -19,31 +19,35 @@ import android.animation.ArgbEvaluator; import android.os.Bundle; import android.os.Handler; -import android.support.annotation.ColorInt; -import android.support.annotation.Nullable; -import android.support.design.widget.CoordinatorLayout; -import android.support.v4.view.ViewPager; import android.view.View; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.viewpager.widget.ViewPager; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.activity.DynamicSystemActivity; +import com.pranavpandey.android.dynamic.support.listener.DynamicWindowResolver; +import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; import com.pranavpandey.android.dynamic.support.tutorial.adapter.DynamicTutorialsAdapter; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; +import com.pranavpandey.android.dynamic.support.utils.DynamicTintUtils; import com.pranavpandey.android.dynamic.support.widget.DynamicButton; import com.pranavpandey.android.dynamic.support.widget.DynamicImageButton; import com.pranavpandey.android.dynamic.support.widget.DynamicPageIndicator; import com.pranavpandey.android.dynamic.support.widget.DynamicViewPager; -import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; import com.pranavpandey.android.dynamic.support.widget.WidgetDefaults; +import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; import com.pranavpandey.android.dynamic.toasts.DynamicHint; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; import java.util.ArrayList; /** - * Base activity with a view pager to show the supplied tutorials. Extend - * this activity and supply tutorials or dataSet by using the provided - * methods. + * Base activity with a view pager to show the supplied tutorials. + *

Extend this activity and supply tutorials or dataSet by using the provided methods. */ public abstract class DynamicTutorialActivity extends DynamicSystemActivity { @@ -87,6 +91,11 @@ public abstract class DynamicTutorialActivity extends DynamicSystemActivity { */ private ArgbEvaluator mArgbEvaluator; + /** + * Resolver to resolve the status and navigation bar color. + */ + private DynamicWindowResolver mDynamicWindowResolver; + @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -152,7 +161,7 @@ public void onClick(View v) { mActionPrevious.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { - DynamicHint.show(v, DynamicHint.make(DynamicTutorialActivity.this, + DynamicHint.show(v, DynamicHint.make(DynamicTheme.getInstance().getContext(), v.getContentDescription(), mActionCustom.getCurrentTextColor(), ((DynamicWidget) v).getColor())); return true; @@ -172,14 +181,14 @@ public void onClick(View v) { mActionNext.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { - DynamicHint.show(v, DynamicHint.make(DynamicTutorialActivity.this, + DynamicHint.show(v, DynamicHint.make(DynamicTheme.getInstance().getContext(), v.getContentDescription(), mActionCustom.getCurrentTextColor(), ((DynamicWidget) v).getColor())); return true; } }); - setViewPagerAdapter(); + setTutorials(); // A hack to retain the status bar color. if (savedInstanceState == null) { @@ -197,39 +206,81 @@ public void setStatusBarColor(@ColorInt int color) { } /** - * @return A list of {@link DynamicTutorial} to be shown by this - * activity. + * Returns the list of {@link DynamicTutorial} to be shown by this activity. + * + * @return The list of {@link DynamicTutorial} to be shown by this activity. */ - protected ArrayList getTutorials() { + protected @NonNull ArrayList getTutorials() { return new ArrayList<>(); } + /** + * Returns the listener to resolve the status and navigation bar color. + * + * @return The listener to resolve the status and navigation bar color. + */ + public @Nullable DynamicWindowResolver getDynamicWindowResolver() { + return mDynamicWindowResolver; + } + + /** + * Set resolver to resolve the status and navigation bar. + * + * @param dynamicWindowResolver The resolver to be set + */ + public void setDynamicWindowResolver(@Nullable DynamicWindowResolver dynamicWindowResolver) { + this.mDynamicWindowResolver = dynamicWindowResolver; + + setTutorials(); + } + /** * Set view pager adapter according to the tutorials list. + * + * @param page The current page for to be set. */ - private void setViewPagerAdapter() { + protected void setTutorials(int page) { mAdapter = new DynamicTutorialsAdapter(getSupportFragmentManager()); mAdapter.setTutorials(getTutorials()); mViewPager.setOffscreenPageLimit(mAdapter.getCount()); mViewPager.setAdapter(mAdapter); mPageIndicator.setViewPager(mViewPager); - mAdapter.notifyDataSetChanged(); + + mViewPager.setCurrentItem(page); } /** - * Update activity background and system UI according to the - * supplied color. + * Set view pager adapter according to the tutorials list. + */ + protected void setTutorials() { + setTutorials(mViewPager.getCurrentItem()); + } + + /** + * Update activity background and system UI according to the supplied color. * * @param color The activity color to be applied. */ private void setColor(int position, @ColorInt int color) { - setStatusBarColor(color); - setNavigationBarColor(color); - mCoordinatorLayout.setBackgroundColor(color); + @ColorInt int systemUIColor = color; + @ColorInt int tintColor = DynamicColorUtils.getTintColor(color); + + if (mDynamicWindowResolver != null) { + systemUIColor = mDynamicWindowResolver.getSystemUIColor(color); + } else { + systemUIColor = DynamicTheme.getInstance().get().getPrimaryColor() + != DynamicTheme.getInstance().get().getPrimaryColorDark() + ? DynamicTheme.getInstance().generateDarkColor(systemUIColor) + : systemUIColor; + } + + updateTaskDescription(color); + setStatusBarColor(systemUIColor); + setNavigationBarColor(systemUIColor); mCoordinatorLayout.setStatusBarBackgroundColor(getStatusBarColor()); + mCoordinatorLayout.setBackgroundColor(color); - final @ColorInt int tintColor = DynamicColorUtils.getTintColor(color); mViewPager.setColor(color); mActionPrevious.setColor(tintColor); mActionNext.setColor(tintColor); @@ -238,6 +289,10 @@ private void setColor(int position, @ColorInt int color) { mPageIndicator.setSelectedColour(tintColor); mPageIndicator.setUnselectedColour(DynamicColorUtils.adjustAlpha( tintColor, WidgetDefaults.ADS_ALPHA_UNCHECKED)); + DynamicTintUtils.setViewBackgroundTint(mActionPrevious, + color, tintColor, true, false); + DynamicTintUtils.setViewBackgroundTint(mActionNext, color, + tintColor, true, false); if (hasTutorialPrevious()) { mActionPrevious.setVisibility(View.VISIBLE); @@ -259,16 +314,18 @@ private void setColor(int position, @ColorInt int color) { } /** - * @return {@code true} if view pager can be moved to the - * previous tutorial or item. + * Checks whether the view pager can be moved to the previous tutorial or item. + * + * @return {@code true} if view pager can be moved to the previous tutorial or item. */ private boolean hasTutorialPrevious() { return mViewPager.getCurrentItem() != 0; } /** - * @return {@code true} if view pager can be moved to the - * next tutorial or item. + * Checks whether the view pager can be moved to the next tutorial or item. + * + * @return {@code true} if view pager can be moved to the next tutorial or item. */ private boolean hasTutorialNext() { return mAdapter != null && mViewPager.getCurrentItem() < mAdapter.getCount() - 1; @@ -281,7 +338,7 @@ private boolean hasTutorialNext() { * @param onClickListener The on click listener for the action button. */ protected void setAction(final @Nullable String text, - final @Nullable View.OnClickListener onClickListener) { + final @Nullable View.OnClickListener onClickListener) { new Handler().post(new Runnable() { @Override public void run() { @@ -297,6 +354,8 @@ public void run() { } /** + * Get the view pager used by this activity. + * * @return The view pager used by this activity. */ protected DynamicViewPager getViewPager() { @@ -304,6 +363,8 @@ protected DynamicViewPager getViewPager() { } /** + * Get the view pager adapter used by this activity. + * * @return The view pager adapter used by this activity. */ protected DynamicTutorialsAdapter getViewPagerAdapter() { diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/adapter/DynamicTutorialsAdapter.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/adapter/DynamicTutorialsAdapter.java index 2b12d545d0..bae9d8df98 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/adapter/DynamicTutorialsAdapter.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/adapter/DynamicTutorialsAdapter.java @@ -16,12 +16,14 @@ package com.pranavpandey.android.dynamic.support.tutorial.adapter; -import android.support.annotation.NonNull; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentPagerAdapter; import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentPagerAdapter; + import com.pranavpandey.android.dynamic.support.tutorial.DynamicTutorial; import java.util.ArrayList; @@ -45,10 +47,16 @@ public class DynamicTutorialsAdapter extends FragmentPagerAdapter { */ private List mDataSet; + /** + * Constructor to initialize an object of this class. + * + * @param fragmentManager The fragment manager to do the transactions. + */ public DynamicTutorialsAdapter(@NonNull FragmentManager fragmentManager) { super(fragmentManager); this.mFragmentManager = fragmentManager; + this.mDataSet = new ArrayList<>(); } @Override @@ -68,7 +76,7 @@ public int getItemPosition(@NonNull Object object) { } @Override - public @NonNull Object instantiateItem(ViewGroup container, int position) { + public @NonNull Object instantiateItem(@NonNull ViewGroup container, int position) { Fragment fragment = getItem(position); if (fragment.isAdded()) { return fragment; @@ -81,7 +89,7 @@ public int getItemPosition(@NonNull Object object) { } @Override - public void destroyItem(ViewGroup container, int position, Object object) { + public void destroyItem(@NonNull ViewGroup container, int position, @Nullable Object object) { if (object == null) { return; } @@ -93,13 +101,27 @@ public int getCount() { return mDataSet.size(); } - public void addTutorial(int location, DynamicTutorial dynamicTutorial) { - if (!mDataSet.contains(dynamicTutorial)) { - mDataSet.add(location, dynamicTutorial); - } + /** + * Set tutorials for this adapter. + * + * @param dynamicTutorials The collection of tutorials to be set. + */ + public void setTutorials(@NonNull Collection dynamicTutorials) { + removeTutorialFragments(mDataSet); + mDataSet = new ArrayList<>(dynamicTutorials); + + notifyDataSetChanged(); } - public boolean addTutorial(DynamicTutorial dynamicTutorial) { + /** + * Add tutorial to this adapter. + * + * @param location The index at which to add. + * @param dynamicTutorial The tutorial to be added. + * + * @return {@code true} if the tutorial added successfully. + */ + public boolean addTutorial(int location, @NonNull DynamicTutorial dynamicTutorial) { if (mDataSet.contains(dynamicTutorial)) { return false; } @@ -112,8 +134,27 @@ public boolean addTutorial(DynamicTutorial dynamicTutorial) { return modified; } - public boolean addTutorials( - int location, @NonNull Collection dynamicTutorials) { + /** + * Add tutorial to this adapter. + * + * @param dynamicTutorial The tutorial to be added. + * + * @return {@code true} if the tutorial added successfully. + */ + public boolean addTutorial(@NonNull DynamicTutorial dynamicTutorial) { + return addTutorial(mDataSet.size(), dynamicTutorial); + } + + /** + * Add a collection of tutorials to this adapter. + * + * @param location The index at which to add. + * @param dynamicTutorials The collection of tutorials to be added. + * + * @return {@code true} if the tutorials added successfully. + */ + public boolean addTutorials(int location, + @NonNull Collection dynamicTutorials) { boolean modified = false; int i = 0; for (DynamicTutorial dynamicTutorial : dynamicTutorials) { @@ -130,64 +171,104 @@ public boolean addTutorials( return modified; } - public boolean addTutorials( - @NonNull Collection dynamicTutorials) { - boolean modified = false; - for (DynamicTutorial dynamicTutorial : dynamicTutorials) { - if (!mDataSet.contains(dynamicTutorial)) { - mDataSet.add(dynamicTutorial); - modified = true; - } - } - - if (modified) { - notifyDataSetChanged(); - } - return modified; + /** + * Add a collection of tutorials to this adapter. + * + * @param dynamicTutorials The collection of tutorials to be added. + * + * @return {@code true} if the tutorials added successfully. + */ + public boolean addTutorials(@NonNull Collection dynamicTutorials) { + return addTutorials(mDataSet.size(), dynamicTutorials); } + /** + * Remove all the tutorials from this adapter. + * + * @return {@code true} if the tutorials removed successfully. + */ public boolean clearTutorials() { if (!mDataSet.isEmpty()) { mDataSet.clear(); + + notifyDataSetChanged(); return true; } return false; } + /** + * Checks whether this adapter contains the supplied object. + * + * @return {@code true} if this adapter contains the supplied object. + */ public boolean containsTutorial(Object object) { return object instanceof DynamicTutorial && mDataSet.contains(object); } + /** + * Checks whether this adapter contains the supplied collection. + * + * @return {@code true} if this adapter contains the supplied collection. + */ public boolean containsTutorials( @NonNull Collection dynamicTutorials) { return mDataSet.containsAll(dynamicTutorials); } - public List getTutorials() { + /** + * Get the tutorials shown by this adapter. + */ + public @NonNull List getTutorials() { return mDataSet; } + /** + * Returns the tutorial for a particular position. + * + * @param position The position to get the tutorial. + * + * @return The tutorial at the supplied position. + */ public DynamicTutorial getTutorial(int position) { return mDataSet.get(position); } - public boolean removeTutorial(DynamicTutorial dynamicTutorial) { + /** + * Remove tutorial from this adapter. + * + * @param dynamicTutorial The tutorial to be removed. + * + * @return {@code true} if the tutorial removed successfully. + */ + public boolean removeTutorial(@NonNull DynamicTutorial dynamicTutorial) { int locationToRemove = mDataSet.indexOf(dynamicTutorial); if (locationToRemove >= 0) { mDataSet.remove(locationToRemove); + removeTutorialFragment(dynamicTutorial); + + notifyDataSetChanged(); return true; } return false; } + /** + * Remove a collection of tutorials from this adapter. + * + * @param dynamicTutorials The collection of tutorials to be removed. + * + * @return {@code true} if the tutorials removed successfully. + */ public boolean removeTutorials( @NonNull Collection dynamicTutorials) { boolean modified = false; for (DynamicTutorial dynamicTutorial : dynamicTutorials) { int locationToRemove = mDataSet.indexOf(dynamicTutorial); if (locationToRemove >= 0) { + removeTutorialFragment(dynamicTutorial); mDataSet.remove(locationToRemove); modified = true; } @@ -196,40 +277,52 @@ public boolean removeTutorials( return modified; } + /** + * Retain a collection of tutorials to this adapter. + * + * @param dynamicTutorials The collection of tutorials to be retained. + * + * @return {@code true} if the tutorials retained successfully. + */ public boolean retainTutorials( @NonNull Collection dynamicTutorials) { boolean modified = false; for (int i = mDataSet.size() - 1; i >= 0; i--) { if (!dynamicTutorials.contains(mDataSet.get(i))) { + removeTutorialFragment(mDataSet.get(i)); mDataSet.remove(i); modified = true; i--; } } + if (modified) { + notifyDataSetChanged(); + } + return modified; } - public DynamicTutorial setTutorial(int location, DynamicTutorial dynamicTutorial) { - if (!mDataSet.contains(dynamicTutorial)) { - return mDataSet.set(location, dynamicTutorial); + /** + * Remove a tutorial fragments from the activity. + * + * @param dynamicTutorial The tutorial to be removed. + */ + public void removeTutorialFragment(@NonNull DynamicTutorial dynamicTutorial) { + if (((Fragment) dynamicTutorial).isAdded()) { + mFragmentManager.beginTransaction().remove((Fragment) dynamicTutorial).commit(); } - - return mDataSet.set(location, dynamicTutorial); } - public @NonNull List setTutorials( - Collection dynamicTutorials) { - List oldList = new ArrayList<>(); - if (mDataSet != null) { - oldList = new ArrayList<>(mDataSet); - for (DynamicTutorial fragment : oldList) { - mFragmentManager.beginTransaction().remove((Fragment) fragment).commit(); - } + /** + * Remove a collection of tutorial fragments from the activity. + * + * @param dynamicTutorials The collection of tutorials to be removed. + */ + public void removeTutorialFragments( + @NonNull Collection dynamicTutorials) { + for (DynamicTutorial dynamicTutorial : dynamicTutorials) { + removeTutorialFragment(dynamicTutorial); } - - mDataSet = new ArrayList<>(dynamicTutorials); - notifyDataSetChanged(); - return oldList; } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/fragment/DynamicSimpleTutorialFragment.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/fragment/DynamicSimpleTutorialFragment.java index fb84ffce04..3205bf85f7 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/fragment/DynamicSimpleTutorialFragment.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/fragment/DynamicSimpleTutorialFragment.java @@ -17,13 +17,14 @@ package com.pranavpandey.android.dynamic.support.tutorial.fragment; import android.os.Bundle; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.tutorial.DynamicSimpleTutorial; import com.pranavpandey.android.dynamic.support.tutorial.DynamicTutorial; @@ -35,9 +36,8 @@ import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; /** - * A intro fragment which will be used with the {@link DynamicTutorialActivity} - * to display a list of fragments in the view pager. Extend this provide any - * extra functionality according to the need. + * A DynamicTutorialFragment fragment with an image, title, subtitle and description which + * will be used with the {@link DynamicTutorialActivity}. */ public class DynamicSimpleTutorialFragment extends DynamicTutorialFragment { @@ -84,8 +84,7 @@ public class DynamicSimpleTutorialFragment extends DynamicTutorialFragment { /** * Function to initialize this fragment. * - * @param dynamicSimpleTutorial The dynamic simple tutorial for this - * fragment. + * @param dynamicSimpleTutorial The dynamic simple tutorial for this fragment. * * @return An instance of {@link DynamicSimpleTutorialFragment}. */ @@ -140,8 +139,8 @@ public void onCreate(@Nullable Bundle savedInstanceState) { } @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, + @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.ads_fragment_tutorial_simple, container, false); } @@ -177,10 +176,9 @@ public void onSaveInstanceState(@NonNull Bundle outState) { } /** - * Tint the widgets according to the supplied background - * color. + * Tint the widgets according to the supplied background color. * - * @param color Color to generate the tint. + * @param color The color to generate the tint. */ private void tintWidgets(@ColorInt int color) { final @ColorInt int tintColor = DynamicColorUtils.getTintColor(color); diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/fragment/DynamicTutorialFragment.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/fragment/DynamicTutorialFragment.java index cc51b4814a..fb4d77bc52 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/fragment/DynamicTutorialFragment.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/tutorial/fragment/DynamicTutorialFragment.java @@ -17,12 +17,13 @@ package com.pranavpandey.android.dynamic.support.tutorial.fragment; import android.graphics.drawable.Drawable; -import android.support.annotation.ColorInt; -import android.support.annotation.Nullable; import android.view.View; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.ColorInt; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.fragment.DynamicFragment; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; import com.pranavpandey.android.dynamic.support.tutorial.DynamicTutorial; @@ -30,15 +31,14 @@ import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; /** - * A tutorial fragment which will be used with the {@link DynamicTutorialActivity} - * to display a list of fragments in the view pager. Extend this provide any - * extra functionality according to the need. + * A tutorial fragment which will be used with the {@link DynamicTutorialActivity} to display + * a list of fragments in the view pager. + *

Extend this to provide any extra functionality according to the need. */ public abstract class DynamicTutorialFragment extends DynamicFragment implements DynamicTutorial { @Override - public void onPageScrolled(int position, float positionOffset, - int positionOffsetPixels) { } + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { @@ -55,15 +55,14 @@ public int getTutorialId() { @Override public int getBackgroundColor() { - return DynamicTheme.getInstance().getPrimaryColor(); + return DynamicTheme.getInstance().get().getPrimaryColor(); } @Override public void onBackgroundColorChanged(int color) { } /** - * Set drawable for the tutorial image view and mange its visibility - * according to the data. + * Set drawable for the tutorial image view and mange its visibility according to the data. * * @param imageView The image view to set the drawable. * @param drawable The drawable for the image view. @@ -80,8 +79,7 @@ protected void setTutorialImage(@Nullable ImageView imageView, @Nullable Drawabl } /** - * Set text for the tutorial text view and mange its visibility - * according to the data. + * Set text for the tutorial text view and mange its visibility according to the data. * * @param textView The text view to set the text. * @param text The text for the text view. @@ -98,8 +96,7 @@ protected void setTutorialText(@Nullable TextView textView, @Nullable String tex } /** - * Tint dynamic widgets used by the tutorial according to the - * supplied color. + * Tint dynamic widgets used by the tutorial according to the supplied color. * * @param dynamicWidget The dynamic widget to be tinted. * @param color The color to tint the widget. diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicAppWidgetUtils.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicAppWidgetUtils.java index a6b0ad80d8..c22d74015e 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicAppWidgetUtils.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicAppWidgetUtils.java @@ -16,18 +16,11 @@ package com.pranavpandey.android.dynamic.support.utils; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringDef; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.pranavpandey.android.dynamic.support.preference.DynamicPreferences; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -import static com.pranavpandey.android.dynamic.support.utils.DynamicAppWidgetUtils.Theme.THEME_AUTO; -import static com.pranavpandey.android.dynamic.support.utils.DynamicAppWidgetUtils.Theme.THEME_CUSTOM; - /** * Helper class to perform various app widget operations. It will be used internally * by the {@link com.pranavpandey.android.dynamic.support.provider.DynamicAppWidgetProvider} @@ -35,26 +28,6 @@ */ public class DynamicAppWidgetUtils { - /** - * Intent extra if updating the widget. - */ - public static final String ADS_EXTRA_WIDGET_UPDATE = "ads_extra_widget_update"; - - @Retention(RetentionPolicy.SOURCE) - @StringDef(value = { THEME_AUTO, THEME_CUSTOM }) - public @interface Theme { - - /** - * Constant for automatic widget theme. - */ - String THEME_AUTO = "0"; - - /** - * Constant for custom widget theme. - */ - String THEME_CUSTOM = "1"; - } - /** * Default alpha value for enabled or active views. */ @@ -66,41 +39,37 @@ public class DynamicAppWidgetUtils { public static final int ALPHA_ACTION_DISABLED = 125; /** - * Save a string preference for an app widget widget provider according - * to the widget id. + * Save a string preference for an app widget widget provider according to the widget id. * * @param preferences The preference name to store the key. - * @param appWidgetId The app widget id to create or find the - * preference key. + * @param appWidgetId The app widget id to create or find the preference key. * @param value The value for the preference. */ public static void saveWidgetSettings(@NonNull String preferences, - int appWidgetId, @Nullable String value) { + int appWidgetId, @Nullable String value) { DynamicPreferences.getInstance().savePrefs( preferences, String.valueOf(appWidgetId), value); } /** - * Load a string preference for an app widget widget provider according - * to the widget id. + * Load a string preference for an app widget widget provider according to the widget id. * * @param preferences The preference name to store the key. * @param appWidgetId The app widget id to find the preference key. * @param value The default value for the preference. * - * @return Returns the preference value if it exists, or defValue. Throws - * ClassCastException if there is a preference with this name that - * is not a string. + * @return Returns the preference value if it exists, or the default value. + *

Throws {@link ClassCastException} if there is a preference with this name + * that is not a string. */ public static @Nullable String loadWidgetSettings(@NonNull String preferences, - int appWidgetId, @Nullable String value) { + int appWidgetId, @Nullable String value) { return DynamicPreferences.getInstance().loadPrefs( preferences, String.valueOf(appWidgetId), value); } /** - * Remove a preference for an app widget widget provider according - * to the widget id. + * Remove a preference for an app widget widget provider according to the widget id. * * @param preferences The preference name to remove the key. * @param appWidgetId The app widget id to find the preference key. @@ -110,8 +79,8 @@ public static void deleteWidgetSettings(@NonNull String preferences, int appWidg } /** - * Cleanup preferences for an app widget provider when all of its widget - * instances has been deleted. + * Cleanup preferences for an app widget provider when all of its widget instances has been + * deleted. * * @param preferences The preference name to cleanup the preferences. */ diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicDialogUtils.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicDialogUtils.java index a742eca387..5b0f6ae927 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicDialogUtils.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicDialogUtils.java @@ -18,12 +18,12 @@ import android.app.Dialog; import android.content.Context; -import android.os.IBinder; -import android.support.annotation.NonNull; import android.view.View; import android.view.Window; import android.view.WindowManager; +import androidx.annotation.NonNull; + import com.pranavpandey.android.dynamic.support.dialog.DynamicDialog; /** @@ -32,16 +32,15 @@ public class DynamicDialogUtils { /** - * Set custom view to a dialog with top padding to maintain - * uniform layout on all Android versions. + * Set custom view to a dialog with top padding to maintain uniform layout on all + * Android versions. * - * @param alertDialog AlertDialog to set the custom view. - * @param view View to be used as the custom view. + * @param alertDialog The alert dialog to set the custom view. + * @param view The view to be used as the custom view. * * @return The alert dialog after setting the custom view. */ - public static DynamicDialog setView(@NonNull DynamicDialog alertDialog, - @NonNull View view) { + public static DynamicDialog setView(@NonNull DynamicDialog alertDialog, @NonNull View view) { alertDialog.setView(view, 0, getDialogTopPadding( alertDialog.getContext()), 0, 0); @@ -49,38 +48,31 @@ public static DynamicDialog setView(@NonNull DynamicDialog alertDialog, } /** - * Get top padding of the dialog to maintain uniform layout on all - * Android versions. Generally, it is required in case of custom view - * in the dialog. + * Get top padding of the dialog to maintain uniform layout on all Android versions. + *

Generally, it is required in case of custom view in the dialog. * * @param context The context to get the resources. * - * @return Top padding of the dialog. + * @return The top padding of the dialog. */ public static int getDialogTopPadding(@NonNull Context context) { return (int) (14 * context.getResources().getDisplayMetrics().density); } /** - * Bind the dialog with a window token. Useful to display it - * from a service. + * Bind the dialog with a window token. Useful to display it from a service. * - * @param view View to extract the window token. - * @param dialog Dialog to be displayed. + * @param dialog The dialog to be displayed. * @param type The dialog type. * * @return The bound dialog with the supplied view. */ - public static Dialog bindDialog(@NonNull View view, @NonNull Dialog dialog, int type) { - IBinder windowToken = view.getWindowToken(); + public static Dialog bindDialog(@NonNull Dialog dialog, int type) { Window window = dialog.getWindow(); if (window != null) { - WindowManager.LayoutParams lp = window.getAttributes(); - lp.token = windowToken; - lp.windowAnimations = android.R.style.Animation_InputMethod; - lp.type = type; - window.setAttributes(lp); + window.setType(type); + window.setWindowAnimations(android.R.style.Animation_InputMethod); window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicFABUtils.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicFABUtils.java index 10221c08de..a41dffcf97 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicFABUtils.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicFABUtils.java @@ -16,8 +16,9 @@ package com.pranavpandey.android.dynamic.support.utils; -import android.support.annotation.NonNull; -import android.support.design.widget.FloatingActionButton; +import androidx.annotation.NonNull; + +import com.google.android.material.floatingactionbutton.FloatingActionButton; /** * Helper class to perform various {@link FloatingActionButton} operations. @@ -25,20 +26,20 @@ public class DynamicFABUtils { /** - * Same animation that FloatingActionButton.Behavior uses to hide the - * FAB when the AppBarLayout exits. + * Same animation that FloatingActionButton.Behavior uses to hide the FAB when the + * AppBarLayout exits. * - * @param fab FAB to set hide animation. + * @param fab The FAB to set hide animation. */ public static void hide(@NonNull FloatingActionButton fab) { fab.hide(); } /** - * Same animation that FloatingActionButton.Behavior uses to show the - * FAB when the AppBarLayout enters. + * Same animation that FloatingActionButton.Behavior uses to show the FAB when the + * AppBarLayout enters. * - * @param fab FAB to set show animation. + * @param fab The FAB to set show animation. */ public static void show(@NonNull FloatingActionButton fab) { fab.show(); diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicHintUtils.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicHintUtils.java index f1c4b18408..33918aaf0e 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicHintUtils.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicHintUtils.java @@ -19,108 +19,113 @@ import android.annotation.SuppressLint; import android.content.Context; import android.graphics.drawable.Drawable; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.Snackbar; import android.view.View; import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.google.android.material.snackbar.Snackbar; +import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; import com.pranavpandey.android.dynamic.toasts.DynamicToast; +import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; +import com.pranavpandey.android.dynamic.utils.DynamicDrawableUtils; /** - * A collection of useful functions to display hints throughout the - * app by using {@link DynamicToast} and {@link Snackbar}. + * A collection of useful functions to display hints throughout the app. */ public class DynamicHintUtils { /** - * Make a themed toast with text and icon. Background will be primary - * color from the theme and it will automatically use its tint color for - * the text and icon to provide best visibility. + * Make a themed snack bar with text and action. Background will be accent color from the + * theme and it will automatically use its tint color for the text and icon to provide + * best visibility. * - * @param context The context to use. Usually the - * {@link android.app.Application} or - * {@link android.app.Activity} object. + * @param context The context to use. * @param text The text to show. Can be formatted text. * @param icon The toast icon to show. * - * @return Toast with the supplied parameters. Use {@link Toast#show()} - * to display the toast. + * @return The toast with the supplied parameters. + *

Use {@link Toast#show()} to display the toast. */ - public static @NonNull Toast getToast(@NonNull Context context, @Nullable CharSequence text, - @Nullable Drawable icon) { + public static @NonNull Toast getToast(@NonNull Context context, + @Nullable CharSequence text, @Nullable Drawable icon) { return DynamicToast.make(context, text, icon, - DynamicTheme.getInstance().getTintAccentColor(), - DynamicTheme.getInstance().getAccentColor(), Toast.LENGTH_SHORT); + DynamicTheme.getInstance().get().getTintAccentColor(), + DynamicTheme.getInstance().get().getAccentColor(), Toast.LENGTH_SHORT); } /** - * Make a themed snack bar with text and action. Background will be primary - * color from the theme and it will automatically use its tint color for - * the text and action to provide best visibility. + * Make a themed snack bar with text and action. Background will be primary color from the + * theme and it will automatically use its tint color for the text and action to provide + * best visibility. * - * @param view View to show the snack bar. + * @param view The view to show the snack bar. * @param text The text to show. Can be formatted text. * - * @return Snack bar with the supplied parameters. - * Use {@link Snackbar#show()} to display the snack bar. + * @return The snack bar with the supplied parameters. + *

Use {@link Snackbar#show()} to display the snack bar. */ @SuppressLint("Range") - public static @NonNull Snackbar getSnackBar( - @NonNull View view, @NonNull CharSequence text) { - return getSnackBar(view, text, DynamicTheme.getInstance().getPrimaryColor(), - DynamicTheme.getInstance().getTintPrimaryColor(), Snackbar.LENGTH_LONG); + public static @NonNull Snackbar getSnackBar(@NonNull View view, @NonNull CharSequence text) { + return getSnackBar(view, text, DynamicTheme.getInstance().get().getPrimaryColor(), + DynamicTheme.getInstance().get().getTintPrimaryColor(), Snackbar.LENGTH_LONG); } /** - * Make a themed snack bar with text and action. Background will be primary - * color from the theme and it will automatically use its tint color for - * the text and action to provide best visibility. + * Make a themed snack bar with text and action. Background will be primary color from the + * theme and it will automatically use its tint color for the text and action to provide + * best visibility. * - * @param view View to show the snack bar. + * @param view The view to show the snack bar. * @param text The text to show. Can be formatted text. - * @param duration The duration of the snack bar. Can be - * {@link Snackbar#LENGTH_SHORT}, - * {@link Snackbar#LENGTH_LONG} or - * {@link Snackbar#LENGTH_INDEFINITE}. + * @param duration The duration of the snack bar. + *

Can be {@link Snackbar#LENGTH_SHORT}, {@link Snackbar#LENGTH_LONG} + * or {@link Snackbar#LENGTH_INDEFINITE}. * - * @return Snack bar with the supplied parameters. - * Use {@link Snackbar#show()} to display the snack bar. + * @return The snack bar with the supplied parameters. + *

Use {@link Snackbar#show()} to display the snack bar. */ - public static @NonNull Snackbar getSnackBar(@NonNull View view, @NonNull CharSequence text, - @Snackbar.Duration int duration) { - return getSnackBar(view, text, DynamicTheme.getInstance().getPrimaryColor(), - DynamicTheme.getInstance().getTintPrimaryColor(), duration); + public static @NonNull Snackbar getSnackBar(@NonNull View view, + @NonNull CharSequence text, @Snackbar.Duration int duration) { + return getSnackBar(view, text, DynamicTheme.getInstance().get().getPrimaryColor(), + DynamicTheme.getInstance().get().getTintPrimaryColor(), duration); } /** * Make a themed snack bar with text and action. * - * @param view View to show the snack bar. + * @param view The view to show the snack bar. * @param text The text to show. Can be formatted text. * @param backgroundColor The snack bar background color. - * @param tintColor The snack bar tint color based on the - * background. It will automatically check - * for the contrast to provide bes visibility. - * @param duration The duration of the snack bar. Can be - * {@link Snackbar#LENGTH_SHORT}, - * {@link Snackbar#LENGTH_LONG} or - * {@link Snackbar#LENGTH_INDEFINITE}. + * @param tintColor The snack bar tint color based on the background. It will automatically + * check for the contrast to provide bes visibility. + * @param duration The duration of the snack bar. + *

Can be {@link Snackbar#LENGTH_SHORT}, {@link Snackbar#LENGTH_LONG} + * or {@link Snackbar#LENGTH_INDEFINITE}. * - * @return Snack bar with the supplied parameters. - * Use {@link Snackbar#show()} to display the snack bar. + * @return The snack bar with the supplied parameters. + *

Use {@link Snackbar#show()} to display the snack bar. */ - public static @NonNull Snackbar getSnackBar(@NonNull View view, @NonNull CharSequence text, - @ColorInt int backgroundColor, - @ColorInt int tintColor, - @Snackbar.Duration int duration) { + public static @NonNull Snackbar getSnackBar(@NonNull View view, + @NonNull CharSequence text, @ColorInt int backgroundColor, + @ColorInt int tintColor, @Snackbar.Duration int duration) { + if (DynamicTheme.getInstance().get().isBackgroundAware()) { + tintColor = DynamicColorUtils.getContrastColor(tintColor, backgroundColor); + } + Snackbar snackbar = Snackbar.make(view, text, duration); - snackbar.getView().setBackgroundColor(backgroundColor); + + DynamicDrawableUtils.setBackground(snackbar.getView(), + DynamicDrawableUtils.getCornerDrawable(DynamicTheme.getInstance() + .get().getCornerSizeDp(), backgroundColor)); + ((TextView) snackbar.getView().findViewById( + R.id.snackbar_text)).setTextColor(tintColor); ((TextView) snackbar.getView().findViewById( - android.support.design.R.id.snackbar_text)).setTextColor(tintColor); + R.id.snackbar_text)).setMaxLines(Integer.MAX_VALUE); snackbar.setActionTextColor(tintColor); return snackbar; diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicInputUtils.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicInputUtils.java index 1865b56a7b..e6bfcd1876 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicInputUtils.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicInputUtils.java @@ -21,17 +21,17 @@ import android.content.res.ColorStateList; import android.graphics.drawable.Drawable; import android.os.Build; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.RestrictTo; -import android.support.design.widget.TextInputLayout; -import android.support.v4.view.TintableBackgroundView; -import android.support.v4.view.ViewCompat; -import android.support.v7.widget.AppCompatEditText; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.TextView; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.RestrictTo; +import androidx.core.view.TintableBackgroundView; +import androidx.core.view.ViewCompat; + +import com.google.android.material.textfield.TextInputLayout; import com.pranavpandey.android.dynamic.support.widget.WidgetDefaults; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; import com.pranavpandey.android.dynamic.utils.DynamicDrawableUtils; @@ -41,12 +41,11 @@ import java.lang.reflect.Method; import java.util.Arrays; -import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP; +import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; /** - * Helper class to tint the various input widgets like {@link EditText}, etc. - * dynamically by using reflection. It will be used to match the color with - * the app's theme. + * Helper class to tint the various input widgets like {@link EditText}, etc. dynamically + * by using reflection. It will be used to match the color with the app's theme. */ @RestrictTo(LIBRARY_GROUP) @TargetApi(Build.VERSION_CODES.LOLLIPOP) @@ -55,13 +54,12 @@ public final class DynamicInputUtils { /** * Set cursor color for the supplied {@link EditText}. * - * @param editText The EditText to set the cursor color. + * @param editText The edit text to set the cursor color. * @param color The color for the cursor. */ - private static void setCursorColor(final @NonNull EditText editText, - @ColorInt final int color) { + private static void setCursorColor(final @NonNull EditText editText, @ColorInt int color) { @ColorInt int hintColor = DynamicColorUtils.adjustAlpha( - color, WidgetDefaults.ADS_ALPHA_UNCHECKED); + color, WidgetDefaults.ADS_ALPHA_HINT); editText.setHintTextColor(hintColor); editText.setHighlightColor(DynamicColorUtils.getContrastColor( hintColor, editText.getCurrentTextColor())); @@ -115,18 +113,16 @@ private static void setCursorColor(final @NonNull EditText editText, } /** - * Tint an {@link EditText} by changing its cursor, hint, etc. colors - * according to the supplied color. + * Tint an {@link EditText} by changing its cursor, hint, etc. colors according to the + * supplied color. * - * @param editText The EditText to be colorized. + * @param editText The edit text to be colorized. * @param color The color to be used. */ public static void setColor(@NonNull EditText editText, @ColorInt int color) { - final ColorStateList editTextColorStateList = - DynamicResourceUtils.getColorStateListWithStates(color); + ColorStateList editTextColorStateList = DynamicResourceUtils.getColorStateList(color); - if (editText instanceof AppCompatEditText - || editText instanceof TintableBackgroundView) { + if (editText instanceof TintableBackgroundView) { ViewCompat.setBackgroundTintList(editText, editTextColorStateList); } else if (DynamicVersionUtils.isLollipop()) { editText.setBackgroundTintList(editTextColorStateList); @@ -138,7 +134,7 @@ public static void setColor(@NonNull EditText editText, @ColorInt int color) { /** * Set hint color for the supplied {@link TextInputLayout}. * - * @param textInputLayout The TextInputLayout to set the hint color. + * @param textInputLayout The text input layout to set the hint color. * @param color The color to be used. */ public static void setHint(@NonNull TextInputLayout textInputLayout, @ColorInt int color) { @@ -152,35 +148,28 @@ public static void setHint(@NonNull TextInputLayout textInputLayout, @ColorInt i "updateLabelState", boolean.class, boolean.class); updateLabelStateMethod.setAccessible(true); updateLabelStateMethod.invoke(textInputLayout, false, true); - } catch (Throwable t) { - throw new IllegalStateException( - "Unable to set the TextInputLayout hint (collapsed) color: " - + t.getLocalizedMessage(), t); + } catch (Exception ignored) { } } /** - * Tint an {@link TextInputLayout} by changing its label and focus - * colors according to the supplied color. + * Tint an {@link TextInputLayout} by changing its label and focus colors according to the + * supplied color. * - * @param textInputLayout The TextInputLayout to be colorized. + * @param textInputLayout The text input layout to be colorized. * @param color The color to be used. */ public static void setColor(@NonNull TextInputLayout textInputLayout, @ColorInt int color) { try { - final Field focusedTextColorField = + Field focusedTextColorField = TextInputLayout.class.getDeclaredField("focusedTextColor"); focusedTextColorField.setAccessible(true); focusedTextColorField.set(textInputLayout, ColorStateList.valueOf(color)); - final Method updateLabelStateMethod = - TextInputLayout.class.getDeclaredMethod( - "updateLabelState", boolean.class, boolean.class); + Method updateLabelStateMethod = TextInputLayout.class.getDeclaredMethod( + "updateLabelState", boolean.class, boolean.class); updateLabelStateMethod.setAccessible(true); updateLabelStateMethod.invoke(textInputLayout, false, true); - } catch (Throwable t) { - throw new IllegalStateException( - "Unable to set the TextInputLayout hint (expanded) color: " - + t.getLocalizedMessage(), t); + } catch (Exception ignored) { } if (textInputLayout.getEditText() != null) { @@ -190,10 +179,9 @@ public static void setColor(@NonNull TextInputLayout textInputLayout, @ColorInt } /** - * Show the soft input keyboard and focus it on the supplied - * {@link EditText}. + * Show the soft input keyboard and focus it on the supplied {@link EditText}. * - * @param editText The EditText to show the soft input. + * @param editText The edit text to show the soft input. */ public static void showSoftInput(final @NonNull EditText editText) { editText.requestFocus(); @@ -212,10 +200,9 @@ public void run() { } /** - * Hide the soft input keyboard and remove focus from the supplied - * {@link EditText}. + * Hide the soft input keyboard and remove focus from the supplied {@link EditText}. * - * @param editText The EditText to clear the focus. + * @param editText The edit text to clear the focus. */ public static void hideSoftInput(final @NonNull EditText editText) { editText.clearFocus(); diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicLayoutUtils.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicLayoutUtils.java index dc7db6dd96..0829dc6dd2 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicLayoutUtils.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicLayoutUtils.java @@ -21,41 +21,36 @@ import android.content.Context; import android.content.res.Configuration; import android.os.Build; -import android.support.annotation.NonNull; -import android.support.v7.widget.GridLayoutManager; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.StaggeredGridLayoutManager; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.recyclerview.DynamicRecyclerViewFrame; +import com.pranavpandey.android.dynamic.support.recyclerview.adapter.DynamicRecyclerViewAdapter; import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils; /** - * Helper class to perform layout operations like detecting the - * column count at runtime. + * Helper class to perform layout operations like detecting the column count at runtime. */ public class DynamicLayoutUtils { /** - * Get the column count according to the current configuration. - * It will also consider multi-window mode on {@link Build.VERSION_CODES#N} - * or above devices. + * Get the column count according to the current configuration. It will also consider + * multi-window mode on {@link Build.VERSION_CODES#N} or above devices. * - *

It is not recommended to do this calculation at runtime. - * So, please define all the span counts in xml.

+ *

It is not recommended to do this calculation at runtime. So, please define all the + * span counts in xml. * * @param context The context to get configuration. * @param defaultCount The default column count. - * @param maxCount The maximum column count up to which we can - * scale. - * @param compact {@code true} if the layout is compact and - * disable the auto increase of columns in - * multi-window mode. - * - * @return The column count according to the current device - * configurations. + * @param maxCount The maximum column count up to which we can scale. + * @param compact {@code true} if the layout is compact and disable the auto increase of + * columns in multi-window mode. * + * @return The column count according to the current device configurations. */ @TargetApi(Build.VERSION_CODES.N) public static int getLayoutColumns(@NonNull Context context, int defaultCount, @@ -95,9 +90,11 @@ public static int getLayoutColumns(@NonNull Context context, int defaultCount, } /** - * @return {@code true} if the app is in multi-window mode. + * Checks whether the app is in multi-window mode. * * @param context The context to get configuration. + * + * @return {@code true} if the app is in multi-window mode. */ @TargetApi(Build.VERSION_CODES.N) public static boolean isInMultiWindowMode(@NonNull Context context) { @@ -110,9 +107,12 @@ public static boolean isInMultiWindowMode(@NonNull Context context) { } /** - * @return The screen size category for the supplied context. + * + * Get the screen size category for the supplied context. * * @param context The context to get configuration. + * + * @return The screen size category for the supplied context. */ public static int getScreenSizeCategory(@NonNull Context context){ return context.getResources().getConfiguration().screenLayout @@ -120,48 +120,51 @@ public static int getScreenSizeCategory(@NonNull Context context){ } /** - * @return The grid count for the supplied context with default - * count 1 and max count 2. + * Get the grid count for the supplied context. * * @param context The context to get the span count. + * + * @return The grid count for the supplied context with default count 1 and max count 2. */ public static int getGridCount(@NonNull Context context) { return context.getResources().getInteger(R.integer.ads_span_normal); } /** - * @return The grid count for the supplied context with default - * count 1 and max count 3. + * Get the grid count for the supplied context suitable for no drawer activity. * * @param context The context to get the span count. + * + * @return The grid count for the supplied context with default count 1 and max count 3. */ public static int getGridCountNoDrawer(@NonNull Context context) { return context.getResources().getInteger(R.integer.ads_span_no_drawer); } /** - * @return The grid count for the supplied context with default - * count 1 or 2 and max count 3. + * Get the grid count for the supplied context suitable for a compact layout. * * @param context The context to get the span count. + * + * @return The grid count for the supplied context with default ount 1 or 2 and max count 3. */ public static int getGridCountCompact(@NonNull Context context) { return context.getResources().getInteger(R.integer.ads_span_compact); } /** - * @return The grid count for the supplied context with default - * count 1 or 2 and max count 3. + * Get the grid count for the supplied context suitable for a dialog. * * @param context The context to get the span count. + * + * @return The grid count for the supplied context with default count 1 or 2 and max count 3. */ public static int getGridCountCompactDialog(@NonNull Context context) { return context.getResources().getInteger(R.integer.ads_span_compact_dialog); } /** - * @return The {@link LinearLayoutManager} object for a given - * context. + * @return The {@link LinearLayoutManager} object for a given context. * * @param context The context to instantiate layout manager. * @param orientation The orientation of the layout manager. @@ -174,8 +177,7 @@ public static LinearLayoutManager getLinearLayoutManager( } /** - * @return The {@link GridLayoutManager} object for a given - * context. + * @return The {@link GridLayoutManager} object for a given context. * * @param context The context to instantiate layout manager. * @param count The column count for the grid layout. @@ -186,11 +188,9 @@ public static GridLayoutManager getGridLayoutManager( } /** - * @return The {@link StaggeredGridLayoutManager} object for a given - * context. + * @return The {@link StaggeredGridLayoutManager} object for a given context. * - * @param count The no. of rows or columns count according to the - * orientation. + * @param count The no. of rows or columns count according to the orientation. * @param orientation The orientation of the layout manager. * {@link StaggeredGridLayoutManager#VERTICAL} or * {@link StaggeredGridLayoutManager#HORIZONTAL} @@ -201,14 +201,13 @@ public static StaggeredGridLayoutManager getStaggeredGridLayoutManager( } /** - * Set full span for the header and empty view in case of a - * {@link GridLayoutManager}. This method must be called - * after setting a adapter for the recycler view. + * Set full span for the header and empty view in case of a {@link GridLayoutManager}. + * This method must be called after setting a adapter for the recycler view. * * @param recyclerView The recycler view to set the span size. * - * @see DynamicRecyclerViewFrame.ItemType - * @see GridLayoutManager#setSpanSizeLookup(GridLayoutManager.SpanSizeLookup) + * @see DynamicRecyclerViewAdapter.ItemType + * @see GridLayoutManager#setSpanSizeLookup( GridLayoutManager.SpanSizeLookup) */ public static void setFullSpanForHeader(final RecyclerView recyclerView) { if (recyclerView != null && recyclerView.getAdapter() != null) { @@ -218,11 +217,11 @@ public static void setFullSpanForHeader(final RecyclerView recyclerView) { @Override public int getSpanSize(int position) { switch (recyclerView.getAdapter().getItemViewType(position)) { - case DynamicRecyclerViewFrame.TYPE_EMPTY_VIEW: - case DynamicRecyclerViewFrame.TYPE_SECTION_HEADER: + case DynamicRecyclerViewAdapter.TYPE_EMPTY_VIEW: + case DynamicRecyclerViewAdapter.TYPE_SECTION_HEADER: return ((GridLayoutManager) recyclerView.getLayoutManager()).getSpanCount(); - case DynamicRecyclerViewFrame.TYPE_ITEM: + case DynamicRecyclerViewAdapter.TYPE_ITEM: return 1; default: return -1; diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicMenuUtils.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicMenuUtils.java index abc7e79c89..f2564dea85 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicMenuUtils.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicMenuUtils.java @@ -22,11 +22,6 @@ import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; import android.os.Build; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.v7.view.menu.ActionMenuItemView; -import android.support.v7.view.menu.MenuView; -import android.support.v7.widget.ActionMenuView; import android.text.TextUtils; import android.view.Menu; import android.view.View; @@ -37,6 +32,14 @@ import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.view.menu.ActionMenuItemView; +import androidx.appcompat.view.menu.MenuView; +import androidx.appcompat.widget.ActionMenuView; + +import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; import com.pranavpandey.android.dynamic.toasts.DynamicHint; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; import com.pranavpandey.android.dynamic.utils.DynamicDrawableUtils; @@ -53,19 +56,16 @@ */ public class DynamicMenuUtils { - /** - * The estimated height of a toast, in dips (density-independent pixels). - * This is used to determine whether or not the toast should appear above - * or below the UI element. - */ - private static final int ADS_HINT_OFFSET_DIPS = 64; - /** * Set the menu to show MenuItem icons in the overflow window. * * @param menu The menu to force icons to show. */ - public static void forceMenuIcons(@NonNull Menu menu) { + public static void forceMenuIcons(@Nullable Menu menu) { + if (menu == null) { + return; + } + try { Class MenuBuilder = menu.getClass(); Method setOptionalIconsVisible = @@ -80,8 +80,8 @@ public static void forceMenuIcons(@NonNull Menu menu) { /** * Set other items color of this view according to the supplied values. - * Generally, it should be a tint color so that items will be visible on - * this view background. + *

Generally, it should be a tint color so that items will be visible on this view + * background. * * @param view The view to set its items color. * @param color The tint color to be applied. @@ -92,19 +92,21 @@ public static void setViewItemsTint(@NonNull final View view, @ColorInt final in = new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN); if (view instanceof ViewGroup){ - for (int lli = 0; lli < ((ViewGroup) view).getChildCount(); lli++){ - setViewItemsTint(((ViewGroup) view).getChildAt(lli), color); + for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++){ + setViewItemsTint(((ViewGroup) view).getChildAt(i), color); } } if (view instanceof ImageButton) { ((ImageButton) view).getDrawable().setAlpha(255); ((ImageButton) view).getDrawable().setColorFilter(colorFilter); + DynamicTintUtils.setViewBackgroundTint(view, color, true); } if (view instanceof ImageView) { ((ImageView) view).getDrawable().setAlpha(255); ((ImageView) view).getDrawable().setColorFilter(colorFilter); + DynamicTintUtils.setViewBackgroundTint(view, color, true); if (!TextUtils.isEmpty(view.getContentDescription())) { new android.os.Handler().post(new Runnable() { @@ -114,10 +116,10 @@ public void run() { view.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { - DynamicHint.show(v, DynamicHint.make(v.getContext(), + DynamicHint.show(v, DynamicHint.make( + DynamicTheme.getInstance().getContext(), v.getContentDescription(), - DynamicColorUtils.getTintColor(color), color), - ADS_HINT_OFFSET_DIPS); + DynamicColorUtils.getTintColor(color), color)); return true; } }); @@ -134,6 +136,7 @@ public boolean onLongClick(View v) { if (view instanceof TextView) { ((TextView) view).setTextColor(color); + DynamicTintUtils.setViewBackgroundTint(view, color, true); } if (view instanceof EditText) { @@ -160,6 +163,8 @@ public boolean onLongClick(View v) { } if (innerView instanceof MenuView.ItemView) { + DynamicTintUtils.setViewBackgroundTint(view, color, true); + new android.os.Handler().post(new Runnable() { @Override public void run() { @@ -168,11 +173,11 @@ public void run() { @SuppressLint("RestrictedApi") @Override public boolean onLongClick(View v) { - DynamicHint.show(v, DynamicHint.make(v.getContext(), + DynamicHint.show(v, DynamicHint.make( + DynamicTheme.getInstance().getContext(), ((MenuView.ItemView) innerView) .getItemData().getTitle(), - DynamicColorUtils.getTintColor(color), color), - ADS_HINT_OFFSET_DIPS); + DynamicColorUtils.getTintColor(color), color)); return true; } }); diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissionUtils.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicPermissionUtils.java similarity index 77% rename from dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissionUtils.java rename to dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicPermissionUtils.java index ba1a5b6559..bc4f655d22 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/permission/DynamicPermissionUtils.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicPermissionUtils.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.pranavpandey.android.dynamic.support.permission; +package com.pranavpandey.android.dynamic.support.utils; import android.Manifest; import android.content.ActivityNotFoundException; @@ -22,11 +22,14 @@ import android.content.Intent; import android.net.Uri; import android.provider.Settings; -import android.support.annotation.DrawableRes; -import android.support.annotation.NonNull; -import android.support.annotation.StringRes; + +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.StringRes; import com.pranavpandey.android.dynamic.support.R; +import com.pranavpandey.android.dynamic.support.intent.DynamicIntent; +import com.pranavpandey.android.dynamic.support.model.DynamicPermission; /** * Helper class to work with permissions and {@link DynamicPermission}. @@ -39,20 +42,19 @@ public class DynamicPermissionUtils { private static final String SCHEME = "package"; /** - * Open the settings activity according to the permission - * name. + * Open the settings activity according to the permission name. * * @param context The context to start the activity. * @param permission The permission name. * - * @return {@code true} if permissions settings activity can - * be opened successfully. Otherwise, {@code false}. + * @return {@code true} if permissions settings activity can be opened successfully. + * Otherwise, {@code false}. */ - public static boolean openPermissionSettings( - @NonNull Context context, @NonNull String permission) { + public static boolean openPermissionSettings(@NonNull Context context, + @NonNull String permission) { Intent intent = new Intent(getPermissionSettingsAction(permission)); if (!getPermissionSettingsAction(permission) - .equals(DynamicPermissions.ADS_ACTION_USAGE_ACCESS_SETTINGS)) { + .equals(DynamicIntent.ACTION_USAGE_ACCESS_SETTINGS)) { Uri uri = Uri.fromParts(SCHEME, context.getPackageName(), null); intent.setData(uri); } @@ -67,13 +69,12 @@ public static boolean openPermissionSettings( } /** - * Launch app info by extracting the package name from the - * supplied context. + * Launch app info by extracting the package name from the supplied context. * * @param context The context to start the activity. * - * @return {@code true} if application info activity can - * be opened successfully. Otherwise, {@code false}. + * @return {@code true} if permissions settings activity can be opened successfully. + * Otherwise, {@code false}. */ public static boolean launchAppInfo(@NonNull Context context) { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); @@ -90,8 +91,7 @@ public static boolean launchAppInfo(@NonNull Context context) { } /** - * Get permission icon drawable resource according to the - * permission name. + * Get permission icon drawable resource according to the permission name. * * @param permission The permission name. * @@ -101,13 +101,11 @@ public static boolean launchAppInfo(@NonNull Context context) { switch (permission) { default: return R.drawable.ads_ic_settings; - } } /** - * Get permission title string resource according to the - * permission name. + * Get permission title string resource according to the permission name. * * @param permission The permission name. * @@ -128,8 +126,7 @@ public static boolean launchAppInfo(@NonNull Context context) { } /** - * Get permission subtitle string resource according to the - * permission name. + * Get permission subtitle string resource according to the permission name. * * @param permission The permission name. * @@ -149,8 +146,7 @@ public static boolean launchAppInfo(@NonNull Context context) { } /** - * Get permission settings action according to the permission - * name. + * Get permission settings action according to the permission name. * * @param permission The permission name. * @@ -159,11 +155,11 @@ public static boolean launchAppInfo(@NonNull Context context) { public static @NonNull String getPermissionSettingsAction(@NonNull String permission) { switch (permission) { case Manifest.permission.SYSTEM_ALERT_WINDOW: - return DynamicPermissions.ADS_ACTION_OVERLAY_SETTINGS; + return DynamicIntent.ACTION_OVERLAY_SETTINGS; case Manifest.permission.PACKAGE_USAGE_STATS: - return DynamicPermissions.ADS_ACTION_USAGE_ACCESS_SETTINGS; + return DynamicIntent.ACTION_USAGE_ACCESS_SETTINGS; case Manifest.permission.WRITE_SETTINGS: - return DynamicPermissions.ADS_ACTION_WRITE_SYSTEM_SETTINGS; + return DynamicIntent.ACTION_WRITE_SYSTEM_SETTINGS; default: return Settings.ACTION_APPLICATION_DETAILS_SETTINGS; diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicResourceUtils.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicResourceUtils.java index 0f15a3ba9c..74e40a6b9b 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicResourceUtils.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicResourceUtils.java @@ -24,26 +24,31 @@ import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.PorterDuff; +import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; -import android.support.annotation.ArrayRes; -import android.support.annotation.AttrRes; -import android.support.annotation.ColorInt; -import android.support.annotation.ColorRes; -import android.support.annotation.DrawableRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.content.ContextCompat; -import android.support.v4.graphics.drawable.DrawableCompat; -import android.support.v7.content.res.AppCompatResources; +import android.graphics.drawable.StateListDrawable; import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.text.style.ForegroundColorSpan; import android.text.style.StyleSpan; +import android.util.AttributeSet; import android.util.TypedValue; import android.widget.TextView; -import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import androidx.annotation.ArrayRes; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.ColorRes; +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StyleRes; +import androidx.appcompat.content.res.AppCompatResources; +import androidx.core.content.ContextCompat; +import androidx.core.graphics.drawable.DrawableCompat; + +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; import com.pranavpandey.android.dynamic.utils.DynamicDrawableUtils; import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils; @@ -51,8 +56,8 @@ import java.util.Calendar; /** - * Helper class to perform resource operations. Context and App compat - * is used to provide backward compatibility. + * Helper class to perform resource operations. Context and App compat is used to provide + * backward compatibility. * * @see ContextCompat * @see AppCompatResources @@ -69,52 +74,141 @@ public class DynamicResourceUtils { */ public static final int ADS_DEFAULT_RESOURCE_VALUE = 0; + /** + * Extract the supplied attribute value resource id from the theme. + * + * @param context The context to retrieve resources. + * @param attr The attribute whose value resource id to be extracted. + * + * @return The value resource id of the supplied attribute. + */ + public static int getAttributeResId(@NonNull Context context, @AttrRes int attr) { + TypedValue outValue = new TypedValue(); + context.getTheme().resolveAttribute(attr, outValue, true); + + return outValue.resourceId; + } + + /** + * Extract the supplied integer attribute value from the theme. + * + * @param theme The theme to get the styled attributes. + * @param attr The integer attribute whose value should be extracted. + * @param defaultValue The value to return if the attribute is not defined or not a resource. + * + * @return The value of the supplied attribute. + */ + public static int resolveInteger(@NonNull Context context, + @StyleRes int theme, @AttrRes int attr, int defaultValue) { + TypedArray a = context.getTheme().obtainStyledAttributes(theme, new int[] { attr }); + + try { + return a.getInteger(0, defaultValue); + } catch (Exception e) { + return defaultValue; + } finally { + a.recycle(); + } + } + /** * Extract the supplied color attribute value from the theme. * + * @param theme The theme to get the styled attributes. * @param context The context to retrieve resources. - * @param attr The color attribute whose value should be extracted. - * @param defValue The value to return if the attribute is not - * defined or not a resource. + * @param attr The color attribute whose value to be extracted. + * @param defaultValue The value to return if the attribute is not defined or not a resource. * * @return The value of the supplied attribute. */ public static @ColorInt int resolveColor(@NonNull Context context, - @AttrRes int attr, int defValue) { - TypedValue outValue = new TypedValue(); - context.getTheme().resolveAttribute(attr, outValue, true); + @StyleRes int theme, @AttrRes int attr, int defaultValue) { + TypedArray a = context.getTheme().obtainStyledAttributes(theme, new int[] { attr }); - return ContextCompat.getColor(context, outValue.resourceId); + try { + return a.getColor(0, defaultValue); + } catch (Exception e) { + return defaultValue; + } finally { + a.recycle(); + } } /** * Extract the supplied drawable attribute value from the theme. * + * @param theme The theme to get the styled attributes. * @param context The context to retrieve resources. - * @param attr The drawable attribute whose value should be - * extracted. + * @param attr The drawable attribute whose value to be extracted. * * @return The value of the supplied attribute. */ - public static @Nullable Drawable resolveDrawable( - @NonNull Context context, @AttrRes int attr) { - TypedValue outValue = new TypedValue(); - context.getTheme().resolveAttribute(attr, outValue, true); + public static @Nullable Drawable resolveDrawable(@NonNull Context context, + @StyleRes int theme, @AttrRes int attr) { + TypedArray a = context.getTheme().obtainStyledAttributes(theme, new int[] { attr }); - return ContextCompat.getDrawable(context, outValue.resourceId); + try { + return a.getDrawable(0); + } finally { + a.recycle(); + } + } + + /** + * Extract the supplied dimension attribute value from the theme. + * + * @param theme The theme to get the styled attributes. + * @param attr The dimension attribute whose value should be extracted. + * @param defaultValue The value to return if the attribute is not defined or not a resource. + * + * @return The value of the supplied attribute. + */ + public static float resolveDimension(@NonNull Context context, + @StyleRes int theme, @AttrRes int attr, float defaultValue) { + TypedArray a = context.getTheme().obtainStyledAttributes(theme, new int[] { attr }); + + try { + return a.getDimension(0, defaultValue); + } catch (Exception e) { + return defaultValue; + } finally { + a.recycle(); + } + } + + /** + * Extract the supplied dimension attribute value from the theme. + *

The extracted value will be converted into the integer pixels. + * + * @param theme The theme to get the styled attributes. + * @param attr The dimension attribute whose value to be extracted. + * @param defaultValue The value to return if the attribute is not defined or not a resource. + * + * @return The value of the supplied attribute. + */ + public static int resolveDimensionPixelOffSet(@NonNull Context context, + @StyleRes int theme, @AttrRes int attr, int defaultValue) { + TypedArray a = context.getTheme().obtainStyledAttributes(theme, new int[] { attr }); + + try { + return a.getDimensionPixelOffset(0, defaultValue); + } catch (Exception e) { + return defaultValue; + } finally { + a.recycle(); + } } /** * Get the drawable from the supplied resource. * * @param context The context to retrieve resources. - * @param drawableRes The drawable resource to get the - * drawable. + * @param drawableRes The drawable resource to get the drawable. * * @return The drawable retrieved from the resource. */ public static @Nullable Drawable getDrawable(@NonNull Context context, - @DrawableRes int drawableRes) { + @DrawableRes int drawableRes) { try { return AppCompatResources.getDrawable(context, drawableRes); } catch (Exception e) { @@ -125,16 +219,11 @@ public class DynamicResourceUtils { /** * Get the bitmap from the vector drawable. * - * @param drawable The instance of vector drawable to - * be converted into bitmap. + * @param drawable The instance of vector drawable to be converted into bitmap. * * @return The bitmap converted from the vector drawable. */ - public static @Nullable Bitmap getBitmapFromVectorDrawable(@Nullable Drawable drawable) { - if (drawable == null) { - return null; - } - + public static @NonNull Bitmap getBitmapFromVectorDrawable(@NonNull Drawable drawable) { if (DynamicVersionUtils.isLollipop()) { drawable = (DrawableCompat.wrap(drawable)).mutate(); } else { @@ -153,27 +242,28 @@ public class DynamicResourceUtils { /** * Get the bitmap drawable from the drawable. * - * @param drawable The drawable to be converted into - * bitmap drawable. + * @param drawable The drawable to be converted into bitmap drawable. * * @return The bitmap drawable converted from the drawable. */ public static @Nullable Bitmap getBitmap(@Nullable Drawable drawable) { + if (drawable == null) { + return null; + } + return getBitmapFromVectorDrawable(drawable); } /** - * Colorize and return the mutated drawable so that, all other - * references do not change. + * Colorize and return the mutated drawable so that, all other references do not change. * * @param drawable The drawable to be colorized. - * @param colorFilter The color filter to be applied - * on the drawable. + * @param colorFilter The color filter to be applied on the drawable. * * @return The colorized drawable. */ - public static @Nullable Drawable colorizeDrawable( - @Nullable Drawable drawable, @NonNull ColorFilter colorFilter) { + public static @Nullable Drawable colorizeDrawable(@Nullable Drawable drawable, + @NonNull ColorFilter colorFilter) { if (drawable != null) { return DynamicDrawableUtils.colorizeDrawable(drawable, colorFilter); } @@ -182,25 +272,21 @@ public class DynamicResourceUtils { } /** - * Colorize and return the mutated drawable so that, all other - * references do not change. + * Colorize and return the mutated drawable so that, all other references do not change. * * @param context The context to retrieve drawable resource. * @param drawableRes The drawable resource to be colorized. - * @param colorFilter The color filter to be applied on the - * drawable. + * @param colorFilter The color filter to be applied on the drawable. * * @return The colorized drawable. */ - public static @Nullable Drawable colorizeDrawableRes( - @NonNull Context context, @DrawableRes int drawableRes, - @NonNull ColorFilter colorFilter) { + public static @Nullable Drawable colorizeDrawableRes(@NonNull Context context, + @DrawableRes int drawableRes, @NonNull ColorFilter colorFilter) { return colorizeDrawable(getDrawable(context, drawableRes), colorFilter); } /** - * Colorize and return the mutated drawable so that, all other - * references do not change. + * Colorize and return the mutated drawable so that, all other references do not change. * * @param drawable The drawable to be colorized. * @param color The color to colorize the drawable. @@ -208,8 +294,8 @@ public class DynamicResourceUtils { * * @return The colorized drawable. */ - public static @Nullable Drawable colorizeDrawable( - @Nullable Drawable drawable, @ColorInt int color, @Nullable PorterDuff.Mode mode) { + public static @Nullable Drawable colorizeDrawable(@Nullable Drawable drawable, + @ColorInt int color, @Nullable PorterDuff.Mode mode) { if (drawable != null) { return DynamicDrawableUtils.colorizeDrawable(drawable, color, mode); } @@ -218,8 +304,7 @@ public class DynamicResourceUtils { } /** - * Colorize and return the mutated drawable so that, all other references - * do not change. + * Colorize and return the mutated drawable so that, all other references do not change. * * @param context The context to retrieve drawable resource. * @param drawableRes The drawable resource to be colorized. @@ -228,15 +313,13 @@ public class DynamicResourceUtils { * * @return The colorized drawable. */ - public static @Nullable Drawable colorizeDrawableRes( - @NonNull Context context, @DrawableRes int drawableRes, - @ColorInt int color, @Nullable PorterDuff.Mode mode) { + public static @Nullable Drawable colorizeDrawableRes( @NonNull Context context, + @DrawableRes int drawableRes, @ColorInt int color, @Nullable PorterDuff.Mode mode) { return colorizeDrawable(getDrawable(context, drawableRes), color, mode); } /** - * Colorize and return the mutated drawable so that, all other references - * do not change. + * Colorize and return the mutated drawable so that, all other references do not change. * * @param context The context to retrieve drawable resource. * @param drawableId Id of the drawable to be colorized. @@ -244,17 +327,15 @@ public class DynamicResourceUtils { * * @return The colorized drawable. */ - public static @Nullable Drawable colorizeDrawableRes( - @NonNull Context context, @DrawableRes int drawableId, @ColorInt int color) { - return colorizeDrawable(getDrawable( - context, drawableId), color, PorterDuff.Mode.SRC_IN); + public static @Nullable Drawable colorizeDrawableRes(@NonNull Context context, + @DrawableRes int drawableId, @ColorInt int color) { + return colorizeDrawable(getDrawable(context, drawableId), color, PorterDuff.Mode.SRC_IN); } /** - * Highlight the query text within a text view. Suitable for notifying - * user about the searched query found in the adapter. TextView should - * not be empty. Please set your default text first then, highlight the - * query text by using this method. + * Highlight the query text within a text view. Suitable for notifying user about the + * searched query found in the adapter. TextView should not be empty. Please set your default + * text first then, highlight the query text by using this method. * * @param query The string to be highlighted. * @param textView The text view to set the highlighted text. @@ -262,9 +343,9 @@ public class DynamicResourceUtils { * * @see Spannable */ - public static void highlightQueryTextColor( - @NonNull String query, @NonNull TextView textView, @ColorInt int color) { - final String stringText = textView.getText().toString().toLowerCase(); + public static void highlightQueryTextColor(@NonNull String query, + @NonNull TextView textView, @ColorInt int color) { + String stringText = textView.getText().toString().toLowerCase(); if (!TextUtils.isEmpty(query) && stringText.contains(query)) { final int startPos = stringText.indexOf(query); final int endPos = startPos + query.length(); @@ -280,10 +361,9 @@ public static void highlightQueryTextColor( } /** - * Highlight the query text within a text view. Suitable for notifying - * user about the searched query found in the adapter. TextView should - * not be empty. Please set your default text first then, highlight the - * query text by using this method. + * Highlight the query text within a text view. Suitable for notifying user about the + * searched query found in the adapter. TextView should not be empty. Please set your default + * text first then, highlight the query text by using this method. * * @param query The string to be highlighted. * @param textView The text view to set the highlighted text. @@ -291,18 +371,16 @@ public static void highlightQueryTextColor( * * @see Spannable */ - public static void highlightQueryTextColorRes( - @NonNull String query, @NonNull TextView textView, @ColorRes int colorRes) { + public static void highlightQueryTextColorRes(@NonNull String query, + @NonNull TextView textView, @ColorRes int colorRes) { highlightQueryTextColor(query, textView, ContextCompat.getColor(textView.getContext(), colorRes)); } /** - * Create a new color state list from the supplied one by - * changing its normal and tint colors. + * Create a new color state list from the supplied one by changing its normal and tint colors. * - * @param colorStateList The state list drawable to - * be converted. + * @param colorStateList The state list drawable to be converted. * @param normalColor The normal color to be applied. * @param tintColor The color to be applied. * @@ -332,15 +410,12 @@ public static void highlightQueryTextColorRes( } /** - * Create a new color state list from the supplied one by - * changing its normal and tint colors. + * Create a new color state list from the supplied one by changing its normal and tint colors. * - * @param colorStateList The state list drawable to - * be converted. + * @param colorStateList The state list drawable to be converted. * @param normalColor The normal color to be applied. * @param tintColor The color to be applied. - * @param contrastWith The contrast color to make sure - * that it will always be visible on + * @param contrastWith The contrast color to make sure that it will always be visible on * this background. * * @return The new color state list with the applied color. @@ -354,11 +429,9 @@ public static void highlightQueryTextColorRes( } /** - * Create a new color state list from the supplied one by - * changing its tint color. + * Create a new color state list from the supplied one by changing its tint color. * - * @param colorStateList The state list drawable to - * be converted. + * @param colorStateList The state list drawable to be converted. * @param color The color to be applied. * * @return The new color state list with the applied color. @@ -390,14 +463,11 @@ public static void highlightQueryTextColorRes( } /** - * Create a new color state list from the supplied one by - * changing its tint color. + * Create a new color state list from the supplied one by changing its tint color. * - * @param colorStateList The state list drawable to - * be converted. + * @param colorStateList The state list drawable to be converted. * @param color The color to be applied. - * @param contrastWith The contrast color to make sure - * that it will always be visible on + * @param contrastWith The contrast color to make sure that it will always be visible on * this background. * * @return The new color state list with the applied color. @@ -411,11 +481,11 @@ public static void highlightQueryTextColorRes( /** * Create a new color state list from the supplied tint color. - * Tint color will be applied on all the states. + *

Tint color will be applied on all the states. * * @param color The tint color to be applied. * - * @return The new color state list with the applied tint color. + * @return The color state list with the applied tint color. */ public static @NonNull ColorStateList getColorStateList(@ColorInt int color) { return new ColorStateList( @@ -427,82 +497,200 @@ public static void highlightQueryTextColorRes( } /** - * Create a new color state list from the supplied normal and - * tint colors. Tint color will be applied on the states like - * checked, enabled, etc. + * Create a new color state list from the supplied disabled, normal and tint colors. + *

Tint color will be applied on the states like checked, enabled, etc. * - * @param normal The normal color to be applied. + * @param disabled The color for the disabled state. + * @param normal The color for the normal state. + * @param pressed The color for the pressed state. * @param color The tint color to be applied. + * @param checkable {@code true} if the view is checkable. * - * @return The new color state list with the applied normal - * and tint colors. + * @return The color state list with the applied normal and tint colors. */ - public static @NonNull ColorStateList getColorStateList( - @ColorInt int normal, @ColorInt int color) { - return new ColorStateList( - new int[][] { - new int[] { -android.R.attr.state_enabled, - -android.R.attr.state_activated, - -android.R.attr.state_checked }, - new int[] { android.R.attr.state_enabled, - -android.R.attr.state_activated, - -android.R.attr.state_checked - }, - new int[] { android.R.attr.state_activated }, - new int[] { android.R.attr.state_checked } - }, - new int[] { normal, normal, color, color }); + public static @NonNull ColorStateList getColorStateList(@ColorInt int disabled, + @ColorInt int normal, @ColorInt int pressed, @ColorInt int color, boolean checkable) { + if (checkable) { + return new ColorStateList( + new int[][] { + new int[] { -android.R.attr.state_enabled, + -android.R.attr.state_activated, + -android.R.attr.state_checked, + -android.R.attr.state_pressed }, + new int[] { android.R.attr.state_enabled, + -android.R.attr.state_activated, + -android.R.attr.state_checked, + -android.R.attr.state_pressed }, + new int[] { android.R.attr.state_enabled, + -android.R.attr.state_activated, + -android.R.attr.state_checked, + android.R.attr.state_pressed }, + new int[] { android.R.attr.state_activated }, + new int[] { android.R.attr.state_checked }, + new int[] { } + }, + new int[] { disabled, normal, pressed, color, color, normal }); + } else { + return new ColorStateList( + new int[][]{ + new int[] { -android.R.attr.state_enabled, + -android.R.attr.state_pressed }, + new int[] { android.R.attr.state_enabled, + -android.R.attr.state_pressed }, + new int[] { android.R.attr.state_pressed }, + new int[] { } + }, + new int[]{ disabled, normal, color, normal }); + } } /** - * Create a new color state list buttons from the supplied normal - * and tint colors. Tint color will be applied on the states like - * pressed, focused, etc. + * Create a new color state list from the supplied normal and tint colors. + *

Tint color will be applied on the states like checked, enabled, etc. + * + * @param disabled The color for the disabled state. + * @param normal The color for the normal state. + * @param color The tint color to be applied. + * @param checkable {@code true} if the view is checkable. + * + * @return The color state list with the applied normal and tint colors. + */ + public static @NonNull ColorStateList getColorStateList(@ColorInt int disabled, + @ColorInt int normal, @ColorInt int color, boolean checkable) { + return getColorStateList(disabled, normal, normal, color, checkable); + } + + /** + * Create a new color state list from the supplied normal and tint colors. + *

Tint color will be applied on the states like checked, enabled, etc. * * @param normal The normal color to be applied. - * @param pressed The pressed color to be applied. + * @param color The tint color to be applied. + * @param checkable {@code true} if the view is checkable. * - * @return The new color state list with the applied normal - * and tint colors. + * @return The color state list with the applied normal and tint colors. */ - public static @NonNull ColorStateList getColorStateListButton( - @ColorInt int normal, @ColorInt int pressed) { - return new ColorStateList( - new int[][] { - new int[] { android.R.attr.state_pressed }, - new int[] { android.R.attr.state_focused }, - new int[] {} - }, - new int[] { pressed, pressed, normal }); + public static @NonNull ColorStateList getColorStateList(@ColorInt int normal, + @ColorInt int color, boolean checkable) { + return getColorStateList(normal, normal, color, checkable); } /** - * Create a new color state list from the supplied tint color. - * Tint color will be applied on all the states. + * Create a new state list drawable from the supplied disabled, normal and tint colors. + *

Tint color will be applied on the states like checked, enabled, etc. * + * @param disabled The color for the disabled state. + * @param normal The color for the normal state. + * @param pressed The color for the pressed state. * @param color The tint color to be applied. + * @param checkable {@code true} if the view is checkable. * - * @return The new color state list with the applied tint color. + * @return The state list drawable with the applied normal and tint colors. */ - public static @NonNull ColorStateList getColorStateListWithStates(@ColorInt int color) { - final @ColorInt int normalColor = DynamicTheme.getInstance().getTintBackgroundColor(); + public static @NonNull StateListDrawable getStateListDrawable(@ColorInt int disabled, + @ColorInt int normal, @ColorInt int pressed, @ColorInt int color, boolean checkable) { + StateListDrawable drawable = new StateListDrawable(); + + if (checkable) { + drawable.addState( + new int[] { -android.R.attr.state_enabled, + -android.R.attr.state_activated, + -android.R.attr.state_checked, + -android.R.attr.state_pressed }, + new ColorDrawable(disabled)); + drawable.addState( + new int[] { android.R.attr.state_enabled, + -android.R.attr.state_activated, + -android.R.attr.state_checked, + -android.R.attr.state_pressed }, + new ColorDrawable(normal)); + drawable.addState( + new int[] { android.R.attr.state_enabled, + -android.R.attr.state_activated, + -android.R.attr.state_checked, + android.R.attr.state_pressed }, + new ColorDrawable(pressed)); + drawable.addState( + new int[] { android.R.attr.state_checked, + android.R.attr.state_pressed }, + new ColorDrawable(color)); + drawable.addState( + new int[] { android.R.attr.state_checked, + android.R.attr.state_pressed }, + new ColorDrawable(color)); + drawable.addState(new int[] { }, + new ColorDrawable(normal)); + } else { + drawable.addState( + new int[] { -android.R.attr.state_enabled, + -android.R.attr.state_pressed }, + new ColorDrawable(disabled)); + drawable.addState( + new int[] { android.R.attr.state_enabled, + -android.R.attr.state_pressed }, + new ColorDrawable(normal)); + drawable.addState( + new int[] { android.R.attr.state_pressed }, + new ColorDrawable(color)); + drawable.addState( + new int[] { }, + new ColorDrawable(normal)); + } - return new ColorStateList( - new int[][] { - new int[] { -android.R.attr.state_enabled }, - new int[] { android.R.attr.state_enabled, - -android.R.attr.state_pressed, - -android.R.attr.state_focused - }, - new int[] {} - }, - new int[] { - normalColor, - normalColor, - color - }); + return drawable; + } + + /** + * Create a new state list drawable from the supplied disabled, normal and tint colors. + *

Tint color will be applied on the states like checked, enabled, etc. + * + * @param normal The color for the normal state. + * @param pressed The color for the pressed state. + * @param color The tint color to be applied. + * @param checkable {@code true} if the view is checkable. + * + * @return The state list drawable with the applied normal and tint colors. + */ + public static @NonNull StateListDrawable getStateListDrawable(@ColorInt int normal, + @ColorInt int pressed, @ColorInt int color, boolean checkable) { + return getStateListDrawable(normal, normal, pressed, color, checkable); + } + + /** + * Get the value resource id of a given attribute. + * + * @param context The context to retrieve resources. + * @param attrRes The resource id of the attribute. + * + * @return The value resource id of the supplied attribute. + */ + public static int getResourceId(@NonNull Context context, @AttrRes int attrRes) { + TypedArray a = context.getTheme().obtainStyledAttributes(new int[] { attrRes }); + try { + return a.getResourceId(0, ADS_DEFAULT_RESOURCE_VALUE); + } finally { + a.recycle(); + } + } + + /** + * Get the value resource id of a given attribute. + * + * @param context The context to retrieve resources. + * @param attrRes The resource id of the attribute. + * + * @return The value resource id of the supplied attribute. + */ + public static int getResourceIdFromAttributes(@NonNull Context context, + @NonNull AttributeSet attrs, @AttrRes int attrRes) { + TypedArray a = context.obtainStyledAttributes(attrs, new int[] { attrRes }); + try { + return a.getResourceId(0, ADS_DEFAULT_RESOURCE_VALUE); + } finally { + a.recycle(); + } } /** @@ -523,7 +711,7 @@ public static void highlightQueryTextColorRes( for (int i = 0; i < drawableArray.length(); i++) { try { - drawables[i] = DynamicResourceUtils.getDrawable(context, + drawables[i] = getDrawable(context, drawableArray.getResourceId(i, ADS_DEFAULT_RESOURCE_VALUE)); } catch (Exception e) { drawables[i] = null; @@ -554,7 +742,11 @@ public static void highlightQueryTextColorRes( for (int i = 0; i < colorArray.length(); i++) { try { - colors[i] = colorArray.getColor(i, ADS_DEFAULT_RESOURCE_VALUE); + if (colorArray.getInteger(i, Theme.AUTO) != Theme.AUTO) { + colors[i] = colorArray.getColor(i, ADS_DEFAULT_RESOURCE_VALUE); + } else { + colors[i] = Theme.AUTO; + } } catch (Exception e) { colors[i] = ADS_DEFAULT_RESOURCE_VALUE; } @@ -567,8 +759,10 @@ public static void highlightQueryTextColorRes( } /** - * @return {@code true} if it is night. Useful to - * apply themes based on the day and night. + * Checks for the night time. + *

Useful to apply themes based on the day and night. + * + * @return {@code true} if it is night. */ @SuppressLint("WrongConstant") public static boolean isNight() { diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicScrollUtils.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicScrollUtils.java index a4f6ff5d4b..0e705ac148 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicScrollUtils.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicScrollUtils.java @@ -20,134 +20,133 @@ import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.os.Build; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.RestrictTo; -import android.support.design.internal.NavigationMenuPresenter; -import android.support.design.internal.NavigationMenuView; -import android.support.design.widget.NavigationView; -import android.support.v4.view.ViewPager; -import android.support.v4.widget.EdgeEffectCompat; -import android.support.v4.widget.NestedScrollView; -import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.AbsListView; import android.widget.EdgeEffect; import android.widget.ScrollView; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.RestrictTo; +import androidx.core.widget.EdgeEffectCompat; +import androidx.core.widget.NestedScrollView; +import androidx.recyclerview.widget.RecyclerView; +import androidx.viewpager.widget.ViewPager; + +import com.google.android.material.internal.NavigationMenuPresenter; +import com.google.android.material.internal.NavigationMenuView; +import com.google.android.material.navigation.NavigationView; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; import com.pranavpandey.android.dynamic.utils.DynamicDrawableUtils; import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils; import java.lang.reflect.Field; -import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP; +import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; /** - * Helper class to set {@link EdgeEffect} or glow color and scroll bar - * color for the supported views dynamically by using reflection. It - * will be used to match the color with the app's theme. + * Helper class to set {@link EdgeEffect} or glow color and scroll bar color for the supported + * views dynamically by using reflection. It will be used to match the color with the app's theme. */ @RestrictTo(LIBRARY_GROUP) public final class DynamicScrollUtils { /** - * {@link EdgeEffect} field constant for edge. + * {@link EdgeEffect} field constant for the edge. */ private static Field ADS_EDGE_EFFECT_FIELD_EDGE; /** - * {@link EdgeEffect} field constant for glow. + * {@link EdgeEffect} field constant for the glow. */ private static Field ADS_EDGE_EFFECT_FIELD_GLOW; /** - * {@link EdgeEffectCompat} field constant for edge effect. + * {@link EdgeEffectCompat} field constant for the edge effect. */ private static Field ADS_EDGE_EFFECT_COMPAT_FIELD_EDGE_EFFECT; /** - * {@link AbsListView} field constant for top glow. + * {@link AbsListView} field constant for the top glow. */ private static Field ADS_LIST_VIEW_FIELD_EDGE_GLOW_TOP; /** - * {@link AbsListView} field constant for bottom glow. + * {@link AbsListView} field constant for the bottom glow. */ private static Field ADS_LIST_VIEW_FIELD_EDGE_GLOW_BOTTOM; /** - * {@link RecyclerView} field constant for top glow. + * {@link RecyclerView} field constant for the top glow. */ private static Field ADS_RECYCLER_VIEW_FIELD_EDGE_GLOW_TOP; /** - * {@link RecyclerView} field constant for left glow. + * {@link RecyclerView} field constant for the left glow. */ private static Field ADS_RECYCLER_VIEW_FIELD_EDGE_GLOW_LEFT; /** - * {@link RecyclerView} field constant for right glow. + * {@link RecyclerView} field constant for the right glow. */ private static Field ADS_RECYCLER_VIEW_FIELD_EDGE_GLOW_RIGHT; /** - * {@link RecyclerView} field constant for bottom glow. + * {@link RecyclerView} field constant for the bottom glow. */ private static Field ADS_RECYCLER_VIEW_FIELD_EDGE_GLOW_BOTTOM; /** - * {@link ScrollView} field constant for top glow. + * {@link ScrollView} field constant for the top glow. */ private static Field ADS_SCROLL_VIEW_FIELD_EDGE_GLOW_TOP; /** - * {@link ScrollView} field constant for bottom glow. + * {@link ScrollView} field constant for the bottom glow. */ private static Field ADS_SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM; /** - * {@link NestedScrollView} field constant for top glow. + * {@link NestedScrollView} field constant for the top glow. */ private static Field ADS_NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_TOP; /** - * {@link NestedScrollView} field constant for bottom glow. + * {@link NestedScrollView} field constant for the bottom glow. */ private static Field ADS_NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_BOTTOM; /** - * {@link ViewPager} field constant for left glow. + * {@link ViewPager} field constant for the left glow. */ private static Field ADS_VIEW_PAGER_FIELD_EDGE_GLOW_LEFT; /** - * {@link ViewPager} field constant for right glow. + * {@link ViewPager} field constant for the right glow. */ private static Field ADS_VIEW_PAGER_FIELD_EDGE_GLOW_RIGHT; /** - * {@link NavigationView} field constant for presenter. + * {@link NavigationView} field constant for the presenter. */ private static Field ADS_NAVIGATION_VIEW_FIELD_PRESENTER; /** - * {@link NavigationView} field constant for recycler view. + * {@link NavigationView} field constant for the recycler view. */ private static Field ADS_NAVIGATION_VIEW_FIELD_RECYCLER_VIEW; /** - * Scroll bar field constant for view. + * Scroll bar field constant for the view. */ private static Field ADS_VIEW_SCROLL_BAR_FIELD; /** - * Scroll bar cache constant for view. + * Scroll bar cache constant for the view. */ private static Field ADS_VIEW_SCROLL_BAR_FIELD_CACHE; /** - * Scroll bar vertical thumb constant for view. + * Scroll bar vertical thumb constant for the view. */ private static Field ADS_VIEW_SCROLL_BAR_VERTICAL_THUMB; /** - * Scroll bar horizontal thumb constant for view. + * Scroll bar horizontal thumb constant for the view. */ private static Field ADS_VIEW_SCROLL_BAR_HORIZONTAL_THUMB; /** - * Initialize edge effect or glow fields so that we can access them - * via reflection. + * Initialize edge effect or glow fields so that we can access them via reflection. */ @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) private static void initializeEdgeEffectFields() { @@ -193,8 +192,7 @@ private static void initializeEdgeEffectFields() { } /** - * Initialize recycler view fields so that we can access them via - * reflection. + * Initialize recycler view fields so that we can access them via reflection. */ private static void initializeRecyclerViewFields() { if (ADS_RECYCLER_VIEW_FIELD_EDGE_GLOW_TOP != null @@ -233,8 +231,7 @@ private static void initializeRecyclerViewFields() { } /** - * Initialize abs list view fields so that we can access them via - * reflection. + * Initialize abs list view fields so that we can access them via reflection. */ private static void initializeListViewFields() { if (ADS_LIST_VIEW_FIELD_EDGE_GLOW_TOP != null @@ -261,8 +258,7 @@ private static void initializeListViewFields() { } /** - * Initialize scroll view fields so that we can access them via - * reflection. + * Initialize scroll view fields so that we can access them via reflection. */ private static void initializeScrollViewFields() { if (ADS_SCROLL_VIEW_FIELD_EDGE_GLOW_TOP != null @@ -289,8 +285,7 @@ private static void initializeScrollViewFields() { } /** - * Initialize nested scroll view fields so that we can access them - * via reflection. + * Initialize nested scroll view fields so that we can access them via reflection. */ private static void initializeNestedScrollViewFields() { if (ADS_NESTED_SCROLL_VIEW_FIELD_EDGE_GLOW_TOP != null @@ -317,8 +312,7 @@ private static void initializeNestedScrollViewFields() { } /** - * Initialize view pager fields so that we can access them via - * reflection. + * Initialize view pager fields so that we can access them via reflection. */ private static void initializeViewPagerFields() { if (ADS_VIEW_PAGER_FIELD_EDGE_GLOW_LEFT != null @@ -345,8 +339,7 @@ private static void initializeViewPagerFields() { } /** - * Initialize navigation view fields so that we can access them via - * reflection. + * Initialize navigation view fields so that we can access them via reflection. */ private static void initializeNavigationViewFields() { if (ADS_NAVIGATION_VIEW_FIELD_PRESENTER != null @@ -379,8 +372,7 @@ private static void initializeNavigationViewFields() { } /** - * Initialize scroll bar fields so that we can access them via - * reflection. + * Initialize scroll bar fields so that we can access them via reflection. */ private static void initializeScrollBarFields(@NonNull View view) { try { @@ -393,13 +385,12 @@ private static void initializeScrollBarFields(@NonNull View view) { } /** - * Set edge effect or glow color dynamically. + * Set edge effect or glow color for list view. * - * @param listView List view to set the edge effect color. - * @param color The edge effect color. + * @param listView The list view to set the edge effect color. + * @param color The edge effect color to be set. */ - public static void setEdgeEffectColor( - @NonNull AbsListView listView, @ColorInt int color) { + public static void setEdgeEffectColor(@NonNull AbsListView listView, @ColorInt int color) { initializeListViewFields(); try { @@ -412,13 +403,12 @@ public static void setEdgeEffectColor( } /** - * Set edge effect or glow color dynamically. + * Set edge effect or glow color for recycler view. * - * @param recyclerView Recycler view to set the edge effect color. - * @param color The edge effect color. + * @param recyclerView The recycler view to set the edge effect color. + * @param color The edge effect color to be set. */ - public static void setEdgeEffectColor( - @NonNull RecyclerView recyclerView, final @ColorInt int color) { + public static void setEdgeEffectColor(@NonNull RecyclerView recyclerView, @ColorInt int color) { initializeRecyclerViewFields(); try { @@ -435,21 +425,20 @@ public static void setEdgeEffectColor( } /** - * Set edge effect or glow color dynamically. + * Set edge effect or glow color for recycler view. * - * @param recyclerView Recycler view to set the edge effect color. - * @param color The edge effect color. + * @param recyclerView The recycler view to set the edge effect color. + * @param color The edge effect color to be set. * @param scrollListener Scroll listener to set color on over scroll. */ - private static void setEdgeEffectColor( - @NonNull RecyclerView recyclerView, final @ColorInt int color, - @Nullable RecyclerView.OnScrollListener scrollListener) { + private static void setEdgeEffectColor(@NonNull RecyclerView recyclerView, + final @ColorInt int color, @Nullable RecyclerView.OnScrollListener scrollListener) { if (scrollListener == null) { scrollListener = new RecyclerView.OnScrollListener() { @Override - public void onScrollStateChanged( - RecyclerView recyclerView, int newState) { + public void onScrollStateChanged(@NonNull RecyclerView recyclerView, + int newState) { super.onScrollStateChanged(recyclerView, newState); setEdgeEffectColor(recyclerView, color); @@ -462,13 +451,12 @@ public void onScrollStateChanged( } /** - * Set edge effect or glow color dynamically. + * Set edge effect or glow color for scroll view. * - * @param scrollView Scroll view to set the edge effect color. - * @param color The edge effect color. + * @param scrollView The scroll view to set the edge effect color. + * @param color The edge effect color to be set. */ - public static void setEdgeEffectColor( - @NonNull ScrollView scrollView, @ColorInt int color) { + public static void setEdgeEffectColor(@NonNull ScrollView scrollView, @ColorInt int color) { initializeScrollViewFields(); try { @@ -481,10 +469,10 @@ public static void setEdgeEffectColor( } /** - * Set edge effect or glow color dynamically. + * Set edge effect or glow color for nested scroll view. * - * @param nestedScrollView Nested scroll view to set the edge effect color. - * @param color The edge effect color. + * @param nestedScrollView The nested scroll view to set the edge effect color. + * @param color The edge effect color to be set. */ public static void setEdgeEffectColor( @NonNull NestedScrollView nestedScrollView, @ColorInt int color) { @@ -502,13 +490,12 @@ public static void setEdgeEffectColor( } /** - * Set edge effect or glow color dynamically. + * Set edge effect or glow color for view pager. * - * @param viewPager View pager to set the edge effect color. - * @param color The edge effect color. + * @param viewPager The view pager to set the edge effect color. + * @param color The edge effect color to be set. */ - public static void setEdgeEffectColor( - @NonNull ViewPager viewPager, @ColorInt int color) { + public static void setEdgeEffectColor(@NonNull ViewPager viewPager, @ColorInt int color) { initializeViewPagerFields(); try { @@ -521,10 +508,10 @@ public static void setEdgeEffectColor( } /** - * Set edge effect or glow color dynamically. + * Set edge effect or glow color for navigation view. * - * @param navigationView Navigation view to set the edge effect color. - * @param color The edge effect color. + * @param navigationView The navigation view to set the edge effect color. + * @param color The edge effect color to be set. */ public static void setEdgeEffectColor( @NonNull NavigationView navigationView, @ColorInt int color) { @@ -543,8 +530,8 @@ public static void setEdgeEffectColor( /** * Set color of the supplied edge effect object. * - * @param edgeEffect Edge effect object to set the color. - * @param color The edge effect color. + * @param edgeEffect The edge effect object to set the color. + * @param color The edge effect color to be set. */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) public static void setEdgeEffectColor(@Nullable Object edgeEffect, @ColorInt int color) { @@ -581,10 +568,10 @@ public static void setEdgeEffectColor(@Nullable Object edgeEffect, @ColorInt int } /** - * Set scroll bar color dynamically. + * Set scroll bar color for navigation view. * - * @param navigationView Navigation view to set the scroll bar color. - * @param color The edge effect color. + * @param navigationView The navigation view to set the scroll bar color. + * @param color The edge effect color to be set. */ public static void setScrollBarColor( @NonNull NavigationView navigationView, @ColorInt int color) { @@ -601,9 +588,9 @@ public static void setScrollBarColor( } /** - * Set scroll bar color dynamically. + * Set scroll bar color for view. * - * @param view View to set the scroll bar color. + * @param view The view to set the scroll bar color. * @param color The scroll bar color. */ public static void setScrollBarColor(@NonNull View view, @ColorInt int color) { diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicSeekBarUtils.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicSeekBarUtils.java index 57a6d1694c..04356dddca 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicSeekBarUtils.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicSeekBarUtils.java @@ -23,9 +23,10 @@ import android.graphics.drawable.ShapeDrawable; import android.graphics.drawable.shapes.RectShape; import android.os.Build; -import android.support.annotation.NonNull; import android.widget.SeekBar; +import androidx.annotation.NonNull; + import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils; /** @@ -45,7 +46,7 @@ public static void setHueDrawable(@NonNull SeekBar seekBar) { } LinearGradient gradient = - new LinearGradient(0.0f, 0.0f, ((float) seekBar.getWidth()), 0.0f, + new LinearGradient(0.0f, 0.0f, (float) seekBar.getWidth(), 0.0f, new int[] { 0xFFFF0000, 0xFFFFFF00, 0xFF00FF00, 0xFF00FFFF, 0xFF0000FF, 0xFFFF00FF, 0xFFFF0000 }, null, Shader.TileMode.CLAMP); diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicThemeUtils.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicThemeUtils.java new file mode 100644 index 0000000000..f48e8b0a2f --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicThemeUtils.java @@ -0,0 +1,403 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.utils; + +import android.graphics.Color; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.pranavpandey.android.dynamic.support.model.DynamicAppTheme; +import com.pranavpandey.android.dynamic.support.model.DynamicWidgetTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; +import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; +import com.pranavpandey.android.dynamic.utils.DynamicUnitUtils; + +import org.json.JSONObject; + +/** + * Helper class to perform theme operations. + */ +public class DynamicThemeUtils { + + public static final String ADS_PATTERN_QUOTES = "[\"\\\"][\\s+][\\\"\"]"; + public static final String ADS_PATTERN_SPACE = "[\\s+]"; + + /** + * Serialized name for the theme resource. + */ + public static final String ADS_NAME_THEME_RES = "themeRes"; + + /** + * Serialized name for the background color. + */ + public static final String ADS_NAME_BACKGROUND_COLOR = "backgroundColor"; + + /** + * Serialized name for the tint background color. + */ + public static final String ADS_NAME_TINT_BACKGROUND_COLOR = "tintBackgroundColor"; + + /** + * Serialized name for the primary color. + */ + public static final String ADS_NAME_PRIMARY_COLOR = "primaryColor"; + + /** + * Serialized name for the tint primary color. + */ + public static final String ADS_NAME_TINT_PRIMARY_COLOR = "tintPrimaryColor"; + + /** + * Serialized name for the primary color dark. + */ + public static final String ADS_NAME_PRIMARY_COLOR_DARK = "primaryColorDark"; + + /** + * Serialized name for the tint primary color dark. + */ + public static final String ADS_NAME_TINT_PRIMARY_COLOR_DARK = "tintPrimaryColorDark"; + + /** + * Serialized name for the accent color. + */ + public static final String ADS_NAME_ACCENT_COLOR = "accentColor"; + + /** + * Serialized name for the tint accent color. + */ + public static final String ADS_NAME_TINT_ACCENT_COLOR = "tintAccentColor"; + + /** + * Serialized name for the accent color dark. + */ + public static final String ADS_NAME_ACCENT_COLOR_DARK = "accentColorDark"; + + /** + * Serialized name for the tint accent color dark. + */ + public static final String ADS_NAME_TINT_ACCENT_COLOR_DARK = "tintAccentColorDark"; + + /** + * Serialized name for the text primary color. + */ + public static final String ADS_NAME_TEXT_PRIMARY_COLOR = "textPrimaryColor"; + + /** + * Serialized name for the text primary color inverse. + */ + public static final String ADS_NAME_TEXT_PRIMARY_COLOR_INVERSE = "textPrimaryColorInverse"; + + /** + * Serialized name for the text secondary color. + */ + public static final String ADS_NAME_TEXT_SECONDARY_COLOR = "textSecondaryColor"; + + /** + * Serialized name for the text secondary color inverse. + */ + public static final String ADS_NAME_TEXT_SECONDARY_COLOR_INVERSE = "textSecondaryColorInverse"; + + /** + * Serialized name for the corner radius. + */ + public static final String ADS_NAME_CORNER_RADIUS = "cornerRadius"; + + /** + * Serialized name for the background aware. + */ + public static final String ADS_NAME_BACKGROUND_AWARE = "backgroundAware"; + + /** + * Serialized name for the widget id. + */ + public static final String ADS_NAME_WIDGET_ID = "widgetId"; + + /** + * Serialized name for the header. + */ + public static final String ADS_NAME_HEADER = "header"; + + /** + * Serialized name for the opacity. + */ + public static final String ADS_NAME_OPACITY = "opacity"; + + /** + * Constant for the auto value. + */ + public static final String ADS_VALUE_AUTO = "auto"; + + /** + * Constant for the disable value. + */ + public static final String ADS_VALUE_DISABLE = "disable"; + + /** + * Constant for the enable value. + */ + public static final String ADS_VALUE_ENABLE = "enable"; + + /** + * Constant for the hide value. + */ + public static final String ADS_VALUE_HIDE = "hide"; + + /** + * Constant for the show value. + */ + public static final String ADS_VALUE_SHOW = "show"; + + /** + * Checks whether the string is a valid JSON. + * + * @param string The string to be checked. + * + * @return {@code true} if the supplied string is a valid JSON. + */ + public static boolean isValidJson(@Nullable String string) { + boolean isValidJson = false; + + try { + if (string != null) { + new JSONObject(string); + isValidJson = true; + } + } catch (Exception ignored) { + } + + return isValidJson; + } + + /** + * Format the dynamic theme string and remove extra double quotes and white spaces. + * + * @param string The dynamic theme string to be formatted. + * + * @return The formatted dynamic theme string. + */ + public static @NonNull String formatDynamicTheme(@NonNull String string) { + return string.trim().replaceAll(ADS_PATTERN_SPACE, "") + .replaceAll(ADS_PATTERN_QUOTES, "\""); + } + + /** + * Generates an app theme from the dynamic string. + * + * @param dynamicTheme The dynamic string to generate the theme. + * + * @return The generated dynamic app theme. + */ + public static @NonNull DynamicAppTheme getAppTheme(@NonNull String dynamicTheme) + throws Exception { + DynamicAppTheme dynamicAppTheme = new DynamicAppTheme(); + JSONObject jsonObject = new JSONObject(formatDynamicTheme(dynamicTheme)); + + dynamicAppTheme.setBackgroundColor(getValueFromColor( + jsonObject.getString(ADS_NAME_BACKGROUND_COLOR)), false); + dynamicAppTheme.setTintBackgroundColor(getValueFromColor( + jsonObject.getString(ADS_NAME_TINT_BACKGROUND_COLOR))); + dynamicAppTheme.setPrimaryColor(getValueFromColor( + jsonObject.getString(ADS_NAME_PRIMARY_COLOR)), false); + dynamicAppTheme.setTintPrimaryColor(getValueFromColor( + jsonObject.getString(ADS_NAME_TINT_PRIMARY_COLOR))); + dynamicAppTheme.setPrimaryColorDark(getValueFromColor( + jsonObject.getString(ADS_NAME_PRIMARY_COLOR_DARK)), false); + dynamicAppTheme.setTintPrimaryColorDark(getValueFromColor( + jsonObject.getString(ADS_NAME_TINT_PRIMARY_COLOR_DARK))); + dynamicAppTheme.setAccentColor(getValueFromColor( + jsonObject.getString(ADS_NAME_ACCENT_COLOR)), false); + dynamicAppTheme.setTintAccentColor(getValueFromColor( + jsonObject.getString(ADS_NAME_TINT_ACCENT_COLOR))); + dynamicAppTheme.setAccentColorDark(getValueFromColor( + jsonObject.getString(ADS_NAME_ACCENT_COLOR_DARK)), false); + dynamicAppTheme.setTintAccentColorDark(getValueFromColor( + jsonObject.getString(ADS_NAME_TINT_ACCENT_COLOR_DARK))); + dynamicAppTheme.setTextPrimaryColor(getValueFromColor( + jsonObject.getString(ADS_NAME_TEXT_PRIMARY_COLOR)), false); + dynamicAppTheme.setTextPrimaryColorInverse(getValueFromColor( + jsonObject.getString(ADS_NAME_TEXT_PRIMARY_COLOR_INVERSE))); + dynamicAppTheme.setTextSecondaryColor(getValueFromColor( + jsonObject.getString(ADS_NAME_TEXT_SECONDARY_COLOR)), false); + dynamicAppTheme.setTextSecondaryColorInverse(getValueFromColor( + jsonObject.getString(ADS_NAME_TEXT_SECONDARY_COLOR_INVERSE))); + dynamicAppTheme.setCornerRadius(getValueFromCornerRadius( + jsonObject.getString(ADS_NAME_CORNER_RADIUS))); + dynamicAppTheme.setBackgroundAware(getValueFromBackgroundAware( + jsonObject.getString(ADS_NAME_BACKGROUND_AWARE))); + + return dynamicAppTheme; + } + + /** + * Generates an widget theme from the dynamic string. + * + * @param dynamicTheme The dynamic string to generate the theme. + * + * @return The generated dynamic widget theme. + */ + public static @NonNull DynamicWidgetTheme getWidgetTheme(@NonNull String dynamicTheme) + throws Exception { + DynamicWidgetTheme dynamicWidgetTheme = new DynamicWidgetTheme(getAppTheme(dynamicTheme)); + JSONObject jsonObject = new JSONObject(formatDynamicTheme(dynamicTheme)); + + dynamicWidgetTheme.setHeader(getValueFromVisibility( + jsonObject.getString(ADS_NAME_HEADER))); + dynamicWidgetTheme.setCornerRadius(jsonObject.getInt(ADS_NAME_CORNER_RADIUS)); + + return dynamicWidgetTheme; + } + + /** + * Converts color integer into its string equivalent. + * + * @param color The color to be converted. + * + * @return The string equivalent of the color. + */ + public static @NonNull String getValueFromColor(int color) { + if (color == Theme.AUTO) { + return ADS_VALUE_AUTO; + } else { + return DynamicColorUtils.getColorString(color, + DynamicColorUtils.isAlpha(color), true); + } + } + + /** + * Converts color string into its integer equivalent. + * + * @param color The color to be converted. + * + * @return The integer equivalent of the color. + */ + public static int getValueFromColor(@NonNull String color) { + if (color.equals(ADS_VALUE_AUTO)) { + return Theme.AUTO; + } else { + return Color.parseColor(color); + } + } + + /** + * Converts corner radius into its string equivalent. + * + * @param cornerRadius The corner radius to be converted. + * + * @return The string equivalent of the corner radius. + */ + public static @NonNull String getValueFromCornerRadius(int cornerRadius) { + if (cornerRadius == Theme.AUTO) { + return ADS_VALUE_AUTO; + } else { + return String.valueOf(DynamicUnitUtils.convertPixelsToDp(cornerRadius)); + } + } + + /** + * Converts corner radius string into its integer equivalent. + * + * @param cornerRadius The corner radius to be converted. + * + * @return The integer equivalent of the corner radius. + */ + public static int getValueFromCornerRadius(@NonNull String cornerRadius) { + if (cornerRadius.equals(ADS_VALUE_AUTO)) { + return Theme.AUTO; + } else { + return Integer.valueOf(cornerRadius); + } + } + + /** + * Converts background aware into its string equivalent. + * + * @param backgroundAware The background aware to be converted. + * + * @return The string equivalent of the background aware. + */ + public static @NonNull String getValueFromBackgroundAware( + @Theme.BackgroundAware int backgroundAware) { + switch (backgroundAware) { + default: + case Theme.BackgroundAware.AUTO: + return ADS_VALUE_AUTO; + case Theme.BackgroundAware.DISABLE: + return ADS_VALUE_DISABLE; + case Theme.BackgroundAware.ENABLE: + return ADS_VALUE_ENABLE; + } + } + + /** + * Converts background aware string into its integer equivalent. + * + * @param backgroundAware The background aware to be converted. + * + * @return The integer equivalent of the background aware. + */ + public static @Theme.BackgroundAware int getValueFromBackgroundAware( + @NonNull String backgroundAware) { + switch (backgroundAware) { + default: + case ADS_VALUE_AUTO: + return Theme.BackgroundAware.AUTO; + case ADS_VALUE_DISABLE: + return Theme.BackgroundAware.DISABLE; + case ADS_VALUE_ENABLE: + return Theme.BackgroundAware.ENABLE; + } + } + + /** + * Converts visibility into its string equivalent. + * + * @param visibility The visibility to be converted. + * + * @return The string equivalent of the visibility. + */ + public static @NonNull String getValueFromVisibility(@Theme.Visibility int visibility) { + switch (visibility) { + default: + case Theme.Visibility.AUTO: + return ADS_VALUE_AUTO; + case Theme.Visibility.HIDE: + return ADS_VALUE_HIDE; + case Theme.Visibility.SHOW: + return ADS_VALUE_SHOW; + } + } + + /** + * Converts visibility string into its integer equivalent. + * + * @param visibility The visibility to be converted. + * + * @return The integer equivalent of the visibility. + */ + public static @Theme.Visibility int getValueFromVisibility(@NonNull String visibility) { + switch (visibility) { + default: + case ADS_VALUE_AUTO: + return Theme.Visibility.AUTO; + case ADS_VALUE_HIDE: + return Theme.Visibility.HIDE; + case ADS_VALUE_SHOW: + return Theme.Visibility.SHOW; + } + } +} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicTintUtils.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicTintUtils.java index 7abdf1bfcf..4b9dc64052 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicTintUtils.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/utils/DynamicTintUtils.java @@ -18,18 +18,28 @@ import android.annotation.TargetApi; import android.content.res.ColorStateList; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.RippleDrawable; import android.os.Build; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.design.widget.FloatingActionButton; -import android.support.v4.view.TintableBackgroundView; import android.view.View; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.core.view.TintableBackgroundView; + +import com.google.android.material.button.MaterialButton; +import com.google.android.material.internal.ScrimInsetsFrameLayout; +import com.google.android.material.navigation.NavigationView; +import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.widget.DynamicCheckedTextView; import com.pranavpandey.android.dynamic.support.widget.WidgetDefaults; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; +import com.pranavpandey.android.dynamic.utils.DynamicDrawableUtils; import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils; +import java.lang.reflect.Field; + /** * Helper class to perform various tint operations on views. */ @@ -39,28 +49,118 @@ public class DynamicTintUtils { * Set a view background tint according to the supplied color. * * @param view The view to set the background tint. + * @param background The background color to calculate the default color. * @param color The tint color to be used. + * @param borderless {@code true} if the view is borderless. + * @param checkable {@code true} if the view is checkable. */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public static void setViewBackgroundTint(@NonNull View view, @ColorInt int color) { - @ColorInt int pressedColor = DynamicColorUtils.getStateColor(color, - WidgetDefaults.ADS_STATE_PRESSED, WidgetDefaults.ADS_STATE_PRESSED); + public static void setViewBackgroundTint(@NonNull View view, @ColorInt int background, + @ColorInt int color, boolean borderless, boolean checkable) { + @ColorInt int pressedColor = DynamicColorUtils.shiftColor(color, + WidgetDefaults.ADS_SHIFT_LIGHT, WidgetDefaults.ADS_SHIFT_DARK); + + if (view instanceof MaterialButton) { + if (borderless) { + if (!DynamicVersionUtils.isLollipop()) { + pressedColor = DynamicColorUtils.getStateColor(DynamicColorUtils.adjustAlpha( + pressedColor, WidgetDefaults.ADS_STATE_PRESSED), + WidgetDefaults.ADS_STATE_LIGHT, WidgetDefaults.ADS_STATE_DARK); + } - if (view instanceof FloatingActionButton) { - ((FloatingActionButton) view).setBackgroundTintList( - DynamicResourceUtils.getColorStateListButton(color, pressedColor)); + ((MaterialButton) view).setRippleColor( + DynamicResourceUtils.getColorStateList( + Color.TRANSPARENT, pressedColor, checkable)); + } else { + ((TintableBackgroundView) view).setSupportBackgroundTintList( + DynamicResourceUtils.getColorStateList( + DynamicColorUtils.getTintColor(background), + color, pressedColor, checkable)); + } } else if (view instanceof TintableBackgroundView) { - ((TintableBackgroundView) view).setSupportBackgroundTintList( - DynamicResourceUtils.getColorStateListButton(color, pressedColor)); + if (borderless) { + ((TintableBackgroundView) view).setSupportBackgroundTintList( + DynamicResourceUtils.getColorStateList( + Color.TRANSPARENT, pressedColor, checkable)); + } else { + ((TintableBackgroundView) view).setSupportBackgroundTintList( + DynamicResourceUtils.getColorStateList( + DynamicColorUtils.getTintColor(background), + color, pressedColor, checkable)); + } + } else { + if (!DynamicVersionUtils.isLollipop()) { + background = DynamicColorUtils.getStateColor( + DynamicColorUtils.adjustAlpha(DynamicColorUtils.getTintColor(background), + WidgetDefaults.ADS_STATE_PRESSED), + WidgetDefaults.ADS_STATE_LIGHT, WidgetDefaults.ADS_STATE_DARK); + pressedColor = DynamicColorUtils.getStateColor( + DynamicColorUtils.adjustAlpha(color, WidgetDefaults.ADS_STATE_PRESSED), + WidgetDefaults.ADS_STATE_LIGHT, WidgetDefaults.ADS_STATE_DARK); + + if (borderless) { + DynamicDrawableUtils.setBackground(view, + DynamicResourceUtils.getStateListDrawable(Color.TRANSPARENT, + background, pressedColor, checkable)); + } else { + // TODO: + } + } } if (DynamicVersionUtils.isLollipop() && view.getBackground() instanceof RippleDrawable) { + if (borderless) { + pressedColor = DynamicColorUtils.adjustAlpha( + color, WidgetDefaults.ADS_STATE_PRESSED); + } + + pressedColor = DynamicColorUtils.getStateColor(pressedColor, + WidgetDefaults.ADS_STATE_LIGHT, WidgetDefaults.ADS_STATE_DARK); + RippleDrawable rippleDrawable = (RippleDrawable) view.getBackground(); - rippleDrawable.setColor(ColorStateList.valueOf( - DynamicColorUtils.getStateColor(pressedColor, - WidgetDefaults.ADS_STATE_PRESSED, - WidgetDefaults.ADS_STATE_PRESSED))); + if (checkable && !(view instanceof DynamicCheckedTextView)) { + background = DynamicColorUtils.getStateColor( + DynamicColorUtils.adjustAlpha( + DynamicColorUtils.getTintColor(background), + WidgetDefaults.ADS_STATE_PRESSED), + WidgetDefaults.ADS_STATE_LIGHT, WidgetDefaults.ADS_STATE_DARK); + + rippleDrawable.setColor(DynamicResourceUtils.getColorStateList( + Color.TRANSPARENT, background, pressedColor, true)); + } else { + rippleDrawable.setColor(ColorStateList.valueOf(pressedColor)); + } + } + } + + /** + * Set a view background tint according to the supplied color. + * + * @param view The view to set the background tint. + * @param color The tint color to be used. + */ + public static void setViewBackgroundTint(@NonNull View view, + @ColorInt int color, boolean borderless) { + setViewBackgroundTint(view, DynamicTheme.getInstance().get() + .getTintBackgroundColor(), color, borderless, false); + } + + /** + * Try to set the top scrim color for the navigation view. + * + * @param color The scrim color to be set. + */ + public static void setNavigationViewScrimColor( + @NonNull NavigationView navigationView, @ColorInt int color) { + try { + final Field insetForeground = + ScrimInsetsFrameLayout.class.getDeclaredField("insetForeground"); + insetForeground.setAccessible(true); + insetForeground.set(navigationView, new ColorDrawable(DynamicColorUtils + .adjustAlpha(color, WidgetDefaults.ADS_ALPHA_SCRIM))); + navigationView.invalidate(); + } catch (Exception ignored) { } } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/view/DynamicHeader.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/view/DynamicHeader.java index c16a5fafbb..e979a912b0 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/view/DynamicHeader.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/view/DynamicHeader.java @@ -33,221 +33,36 @@ package com.pranavpandey.android.dynamic.support.view; import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.AttributeSet; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.TextView; + +import androidx.annotation.AttrRes; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.pranavpandey.android.dynamic.support.R; /** - * A FrameLayout to provide the header view with a icon, title - * and subtitle. It will be used at various locations like for - * settings category header, popup title, etc. + * A DynamicItemView to provide the header view with an icon, title and subtitle. + *

It will be used at various locations like for settings category header, popup title, etc. */ -public class DynamicHeader extends FrameLayout { - - /** - * Icon used by this view. - */ - private Drawable mIcon; - - /** - * Title used by this view. - */ - private CharSequence mTitle; - - /** - * Subtitle used by this view. - */ - private CharSequence mSubtitle; - - /** - * {@code true} to show the icon. - */ - private boolean mShowIcon; - - /** - * Image view to show the icon. - */ - private ImageView mIconView; - - /** - * Text view to show the title. - */ - private TextView mTitleView; - - /** - * Text view to show the subtitle. - */ - private TextView mSubtitleView; +public class DynamicHeader extends DynamicItemView { public DynamicHeader(@NonNull Context context) { - this(context, null); + super(context); } public DynamicHeader(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); - - loadFromAttributes(attrs); } public DynamicHeader(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); - - loadFromAttributes(attrs); } - /** - * Load values from the supplied attribute set. - * - * @param attrs The supplied attribute set to load the values. - */ - protected void loadFromAttributes(@Nullable AttributeSet attrs) { - TypedArray a = getContext().obtainStyledAttributes( - attrs, R.styleable.DynamicHeader); - - try { - mIcon = a.getDrawable(R.styleable.DynamicHeader_ads_dynamicHeader_icon); - mTitle = a.getString(R.styleable.DynamicHeader_ads_dynamicHeader_title); - mSubtitle = a.getString(R.styleable.DynamicHeader_ads_dynamicHeader_subtitle); - mShowIcon = a.getBoolean(R.styleable.DynamicHeader_ads_dynamicHeader_showIcon, true); - } finally { - a.recycle(); - } - - initialize(); - } - - /** - * @return The layout used by this view. Override this to supply a - * different layout. - */ + @Override protected @LayoutRes int getLayoutRes() { return R.layout.ads_header; } - - /** - * Initialize the layout for this view. - */ - private void initialize() { - inflate(getContext(), getLayoutRes(), this); - - mIconView = findViewById(R.id.ads_header_icon); - mTitleView = findViewById(R.id.ads_header_title); - mSubtitleView = findViewById(R.id.ads_header_subtitle); - - update(); - } - - /** - * Load this view according to the supplied parameters. - */ - public void update() { - mIconView.setImageDrawable(mIcon); - mTitleView.setText(mTitle); - - if (mSubtitle != null) { - mSubtitleView.setText(mSubtitle); - mSubtitleView.setVisibility(VISIBLE); - } else { - mSubtitleView.setVisibility(GONE); - } - - mIconView.setVisibility(mShowIcon ? VISIBLE : GONE); - } - - /** - * @return The icon used by this view. - */ - public Drawable getIcon() { - return mIcon; - } - - /** - * Set the icon for this view. - * - * @param icon The icon to be set. - * - * @return The {@link DynamicHeader} object to allow for - * chaining of calls to set methods. - */ - public DynamicHeader setIcon(@Nullable Drawable icon) { - this.mIcon = icon; - - update(); - return this; - } - - /** - * @return The title used by this view. - */ - public CharSequence getTitle() { - return mTitle; - } - - /** - * Set the title for this view. - * - * @param title The title to be set. - * - * @return The {@link DynamicHeader} object to allow for - * chaining of calls to set methods.* - */ - public DynamicHeader setTitle(@Nullable CharSequence title) { - this.mTitle = title; - - update(); - return this; - } - - /** - * @return The subtitle used by this view. - */ - public CharSequence getSubtitle() { - return mSubtitle; - } - - /** - * Set the subtitle for this view. - * - * @param subtitle The subtitle to be set. - * - * @return The {@link DynamicHeader} object to allow for - * chaining of calls to set methods. - */ - public DynamicHeader setSubtitle(@Nullable CharSequence subtitle) { - this.mSubtitle = subtitle; - - update(); - return this; - } - - /** - * @return {@code true} to show the icon. - */ - public boolean isShowIcon() { - return mShowIcon; - } - - /** - * Set the icon visibility for this view. - * - * @param showIcon {@code true} to show the icon. - * - * @return The {@link DynamicHeader} object to allow for - * chaining of calls to set methods. - */ - public DynamicHeader setShowIcon(boolean showIcon) { - this.mShowIcon = showIcon; - - update(); - return this; - } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/view/DynamicInfoView.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/view/DynamicInfoView.java index b1842321e7..3333aa36e9 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/view/DynamicInfoView.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/view/DynamicInfoView.java @@ -19,23 +19,24 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; -import android.support.annotation.ArrayRes; -import android.support.annotation.ColorInt; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.View; -import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.ArrayRes; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.model.DynamicItem; import com.pranavpandey.android.dynamic.support.recyclerview.DynamicRecyclerViewFrame; import com.pranavpandey.android.dynamic.support.recyclerview.DynamicRecyclerViewNested; import com.pranavpandey.android.dynamic.support.recyclerview.adapter.DynamicItemsAdapter; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; import com.pranavpandey.android.dynamic.support.widget.WidgetDefaults; import com.pranavpandey.android.dynamic.utils.DynamicLinkUtils; @@ -44,12 +45,11 @@ import java.util.List; /** - * A FrameLayout with a icon, title and subtitle, description and - * links functionality which can be used to show various information - * according to the requirement. Links can be clickable or pass - * {@code null} url to just show or completely hide them. + * A DynamicView with an icon, title and subtitle, description and links functionality which + * can be used to show various information according to the requirement. + *

Links can be clickable or pass {@code null} url to just show or completely hide them. */ -public class DynamicInfoView extends FrameLayout { +public class DynamicInfoView extends DynamicView { /** * Icon used by this view. @@ -92,14 +92,12 @@ public class DynamicInfoView extends FrameLayout { private CharSequence[] mLinksUrls; /** - * Icon drawables array resource for the links - * used by this view. + * Icon drawables array resource for the links used by this view. */ private @ArrayRes int mLinksIconsResId; /** - * Icon tint colors array resource for the links - * used by this view. + * Icon tint colors array resource for the links used by this view. */ private @ArrayRes int mLinksColorsResId; @@ -139,8 +137,7 @@ public class DynamicInfoView extends FrameLayout { private TextView mDescriptionView; /** - * Recycler view to show the links associated with - * this view. + * Recycler view to show the links associated with this view. */ private DynamicRecyclerViewNested mLinksView; @@ -150,68 +147,53 @@ public class DynamicInfoView extends FrameLayout { private List mDynamicItems; public DynamicInfoView(@NonNull Context context) { - this(context, null); + super(context); } public DynamicInfoView(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); - - loadFromAttributes(attrs); } - public DynamicInfoView(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + public DynamicInfoView(@NonNull Context context, + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); - - loadFromAttributes(attrs); } - /** - * Load values from the supplied attribute set. - * - * @param attrs The supplied attribute set to load the values. - */ - protected void loadFromAttributes(@Nullable AttributeSet attrs) { + @Override + protected void onLoadAttributes(@Nullable AttributeSet attrs) { TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.DynamicInfo); try { mIcon = DynamicResourceUtils.getDrawable(getContext(), a.getResourceId( - R.styleable.DynamicInfo_ads_dynamicInfo_icon, + R.styleable.DynamicInfo_ads_icon, DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE)); - mTitle = a.getString(R.styleable.DynamicInfo_ads_dynamicInfo_title); - mSubtitle = a.getString(R.styleable.DynamicInfo_ads_dynamicInfo_subtitle); - mDescription = a.getString(R.styleable.DynamicInfo_ads_dynamicInfo_description); + mTitle = a.getString(R.styleable.DynamicInfo_ads_title); + mSubtitle = a.getString(R.styleable.DynamicInfo_ads_subtitle); + mDescription = a.getString(R.styleable.DynamicInfo_ads_description); mIconBig = DynamicResourceUtils.getDrawable(getContext(), a.getResourceId( - R.styleable.DynamicInfo_ads_dynamicInfo_iconBig, + R.styleable.DynamicInfo_ads_iconBig, DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE)); - mLinks = a.getTextArray(R.styleable.DynamicInfo_ads_dynamicInfo_links); - mLinksSubtitles = a.getTextArray(R.styleable.DynamicInfo_ads_dynamicInfo_linksSubtitles); - mLinksUrls = a.getTextArray(R.styleable.DynamicInfo_ads_dynamicInfo_linksUrls); + mLinks = a.getTextArray(R.styleable.DynamicInfo_ads_links); + mLinksSubtitles = a.getTextArray(R.styleable.DynamicInfo_ads_subtitles); + mLinksUrls = a.getTextArray(R.styleable.DynamicInfo_ads_urls); mLinksIconsResId = a.getResourceId( - R.styleable.DynamicInfo_ads_dynamicInfo_linksIcons, + R.styleable.DynamicInfo_ads_icons, DynamicResourceUtils.ADS_DEFAULT_RESOURCE_ID); mLinksColorsResId = a.getResourceId( - R.styleable.DynamicInfo_ads_dynamicInfo_linksColors, + R.styleable.DynamicInfo_ads_colors, DynamicResourceUtils.ADS_DEFAULT_RESOURCE_ID); } finally { a.recycle(); } - - initialize(); } - /** - * @return The layout used by this view. Override this to supply a - * different layout. - */ + @Override protected @LayoutRes int getLayoutRes() { return R.layout.ads_info_view; } - /** - * Initialize the layout for this view. - */ - private void initialize() { + @Override + protected void onInflate() { inflate(getContext(), getLayoutRes(), this); mIconView = findViewById(R.id.ads_info_view_icon); @@ -223,13 +205,12 @@ private void initialize() { mLinksView.getRecyclerView().setNestedScrollingEnabled(false); mDynamicItems = new ArrayList<>(); - update(); + + onUpdate(); } - /** - * Load this view according to the supplied parameters. - */ - public void update() { + @Override + public void onUpdate() { if (mIcon != null) { mIconView.setImageDrawable(mIcon); mIconView.setVisibility(VISIBLE); @@ -286,7 +267,7 @@ public void update() { final Drawable icon; final @ColorInt int color; - if (mLinks != null && mLinks[i] != null) { + if (mLinks[i] != null) { title = mLinks[i].toString(); } else { title = null; @@ -318,7 +299,7 @@ public void update() { } DynamicItem dynamicItem = new DynamicItem(icon, title, subtitle, color, - DynamicColorType.CUSTOM, false); + Theme.ColorType.CUSTOM, false); if (url != null) { dynamicItem.setOnClickListener(new OnClickListener() { @@ -339,6 +320,8 @@ public void onClick(View v) { } /** + * Get the icon used by this view. + * * @return The icon used by this view. */ public @Nullable Drawable getIcon() { @@ -353,10 +336,12 @@ public void onClick(View v) { public void setIcon(@Nullable Drawable icon) { this.mIcon = icon; - update(); + onUpdate(); } /** + * Ge the big fallback icon used by this view. + * * @return The big fallback icon used by this view. */ public @Nullable Drawable getIconBig() { @@ -371,10 +356,12 @@ public void setIcon(@Nullable Drawable icon) { public void setIconBig(@Nullable Drawable iconBig) { this.mIconBig = iconBig; - update(); + onUpdate(); } /** + * Get the title used by this view. + * * @return The title used by this view. */ public @Nullable CharSequence getTitle() { @@ -389,10 +376,12 @@ public void setIconBig(@Nullable Drawable iconBig) { public void setTitle(@Nullable CharSequence title) { this.mTitle = title; - update(); + onUpdate(); } /** + * Get the subtitle used by this view. + * * @return The subtitle used by this view. */ public @Nullable CharSequence getSubtitle() { @@ -407,10 +396,12 @@ public void setTitle(@Nullable CharSequence title) { public void setSubtitle(@Nullable CharSequence subtitle) { this.mSubtitle = subtitle; - update(); + onUpdate(); } /** + * Get the description used by this view. + * * @return The description used by this view. */ public @Nullable CharSequence getDescription() { @@ -425,10 +416,12 @@ public void setSubtitle(@Nullable CharSequence subtitle) { public void setDescription(@Nullable CharSequence description) { this.mDescription = description; - update(); + onUpdate(); } /** + * Get the title for the links used by this view. + * * @return The title for the links used by this view. */ public @Nullable CharSequence[] getLinks() { @@ -437,9 +430,9 @@ public void setDescription(@Nullable CharSequence description) { /** * Set the title for the links used by this view. - * Automatic refresh is disabled due to the stability - * reasons. Please call {@link #update()} to refresh - * the view. + * + *

Automatic refresh is disabled due to the stability reasons. + *

Please call {@link #onUpdate()} to refresh the view. * * @param links The titles for the links to be set. */ @@ -448,6 +441,8 @@ public void setLinks(@Nullable CharSequence[] links) { } /** + * Get the subtitle for the links used by this view. + * * @return The subtitle for the links used by this view. */ public @Nullable CharSequence[] getLinksSubtitles() { @@ -456,9 +451,9 @@ public void setLinks(@Nullable CharSequence[] links) { /** * Set the subtitle for the links used by this view. - * Automatic refresh is disabled due to the stability - * reasons. Please call {@link #update()} to refresh - * the view. + * + *

Automatic refresh is disabled due to the stability reasons. + *

Please call {@link #onUpdate()} to refresh the view. * * @param linksSubtitles The subtitles for the links to be set. */ @@ -467,6 +462,8 @@ public void setLinksSubtitles(@Nullable CharSequence[] linksSubtitles) { } /** + * Get the url for the links used by this view. + * * @return The url for the links used by this view. */ public @Nullable CharSequence[] getLinksUrls() { @@ -475,9 +472,9 @@ public void setLinksSubtitles(@Nullable CharSequence[] linksSubtitles) { /** * Set the url for the links used by this view. - * Automatic refresh is disabled due to the stability - * reasons. Please call {@link #update()} to refresh - * the view. + * + *

Automatic refresh is disabled due to the stability reasons. + *

Please call {@link #onUpdate()} to refresh the view. * * @param linksUrls The urls for the links to be set. */ @@ -486,48 +483,50 @@ public void setLinksUrls(@Nullable CharSequence[] linksUrls) { } /** - * @return The icons array resource for the links - * used by this view. + * Get the icons array resource for the links used by this view. + * + * @return The icons array resource for the links used by this view. */ public @ArrayRes int getLinksIconsId() { return mLinksIconsResId; } /** - * Set the icons array resource for the links used by - * this view. Automatic refresh is disabled due to the - * stability reasons. Please call {@link #update()} to - * refresh the view. + * Set the icons array resource for the links used by this view. + * + *

Automatic refresh is disabled due to the stability reasons. + *

Please call {@link #onUpdate()} to refresh the view. * - * @param linksIconsResId The icon drawables array resource for - * the links to be set. + * @param linksIconsResId The icon drawables array resource for the links to be set. */ public void setLinksIconsId(@ArrayRes int linksIconsResId) { this.mLinksIconsResId = linksIconsResId; } /** - * @return The icon tint colors array resource for the links - * used by this view. + * Get the icon tint colors array resource for the links used by this view. + * + * @return The icon tint colors array resource for the links used by this view. */ public @ArrayRes int getLinksColorsId() { return mLinksColorsResId; } /** - * Set the icon tint colors array resource for the links - * used by this view. Automatic refresh is disabled due to - * the stability reasons. Please call {@link #update()} to - * refresh the view. + * Set the icon tint colors array resource for the links used by this view. * - * @param linksColorsResId The icon tint colors array resource for - * the links to be set. + *

Automatic refresh is disabled due to the stability reasons. + *

Please call {@link #onUpdate()} to refresh the view. + * + * @param linksColorsResId The icon tint colors array resource for the links to be set. */ public void setLinksColorsId(@ArrayRes int linksColorsResId) { this.mLinksColorsResId = linksColorsResId; } /** + * Get the icon for the links used by this view. + * * @return The icon for the links used by this view. */ public @Nullable Drawable[] getLinksDrawables() { @@ -536,18 +535,19 @@ public void setLinksColorsId(@ArrayRes int linksColorsResId) { /** * Set the icon for the links used by this view. - * Automatic refresh is disabled due to the stability - * reasons. Please call {@link #update()} to refresh - * the view. * - * @param linksDrawables The icon drawables for the links - * to be set. + *

Automatic refresh is disabled due to the stability reasons. + *

Please call {@link #onUpdate()} to refresh the view. + * + * @param linksDrawables The icon drawables for the links to be set. */ public void setLinksDrawables(@Nullable Drawable[] linksDrawables) { this.mLinksDrawables = linksDrawables; } /** + * Get the icon tint color for the links used by this view. + * * @return The icon tint color for the links used by this view. */ public @Nullable @ColorInt Integer[] getLinksColors() { @@ -555,19 +555,20 @@ public void setLinksDrawables(@Nullable Drawable[] linksDrawables) { } /** - * Set the icon tint color for the links used by this - * view. Automatic refresh is disabled due to the stability - * reasons. Please call {@link #update()} to refresh - * the view. + * Set the icon tint color for the links used by this view. + * + *

Automatic refresh is disabled due to the stability reasons. + *

Please call {@link #onUpdate()} to refresh the view. * - * @param linksColors The icon tint color for the links - * to be set. + * @param linksColors The icon tint color for the links to be set. */ public void setLinksColors(@Nullable @ColorInt Integer[] linksColors) { this.mLinksColors = linksColors; } /** + * Get the image view to show the icon. + * * @return The image view to show the icon. */ public ImageView getIconView() { @@ -575,6 +576,8 @@ public ImageView getIconView() { } /** + * Get the image view to show big fallback icon. + * * @return The image view to show big fallback icon. */ public ImageView getIconBigView() { @@ -582,6 +585,8 @@ public ImageView getIconBigView() { } /** + * Get the text view to show the title. + * * @return The text view to show the title. */ public TextView getTitleView() { @@ -589,6 +594,8 @@ public TextView getTitleView() { } /** + * Get the text view to show the subtitle. + * * @return The text view to show the subtitle. */ public TextView getSubtitleView() { @@ -596,6 +603,8 @@ public TextView getSubtitleView() { } /** + * Get the text view to show the description. + * * @return The text view to show the description. */ public TextView getDescriptionView() { @@ -603,8 +612,9 @@ public TextView getDescriptionView() { } /** - * @return The recycler view to show the links associated - * with this view. + * Get the recycler view to show the links associated with this view. + * + * @return The recycler view to show the links associated with this view. */ public DynamicRecyclerViewFrame getLinksView() { return mLinksView; diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/view/DynamicInfoViewBig.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/view/DynamicInfoViewBig.java index 01083c50f8..e92ccfb99e 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/view/DynamicInfoViewBig.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/view/DynamicInfoViewBig.java @@ -17,16 +17,18 @@ package com.pranavpandey.android.dynamic.support.view; import android.content.Context; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.R; /** - * A DynamicInfoView with bigger fallback icon. Useful for - * showing app info like about, author, etc. + * A DynamicInfoView with bigger fallback icon. + *

Useful for showing the app info like about, author, etc. */ public class DynamicInfoViewBig extends DynamicInfoView { @@ -39,7 +41,7 @@ public DynamicInfoViewBig(@NonNull Context context, @Nullable AttributeSet attrs } public DynamicInfoViewBig(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/view/DynamicItemView.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/view/DynamicItemView.java index 7f44f31f38..7eec72032e 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/view/DynamicItemView.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/view/DynamicItemView.java @@ -19,30 +19,31 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; -import android.support.annotation.ColorInt; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; -import android.widget.FrameLayout; import android.widget.TextView; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; import com.pranavpandey.android.dynamic.support.widget.DynamicImageView; import com.pranavpandey.android.dynamic.support.widget.WidgetDefaults; /** - * A FrameLayout with a icon, title and subtitle functionality which - * can be used to show various informations according to the requirement. - * Use {@link #getItemView()} method to set click listeners or to perform - * other operations. + * A DynamicView with an icon, title and subtitle functionality which can be used to show various + * information according to the requirement. + * + *

Use {@link #getItemView()} method to set click listeners or to perform other operations. */ -public class DynamicItemView extends FrameLayout { +public class DynamicItemView extends DynamicView { /** * Icon used by this view. @@ -62,7 +63,7 @@ public class DynamicItemView extends FrameLayout { /** * Icon tint color type used by this view. */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** * Icon tint color used by this view. @@ -71,10 +72,15 @@ public class DynamicItemView extends FrameLayout { /** * {@code true} to show horizontal divider. - * Useful to display in a list view. + *

Useful to display in a list view. */ private boolean mShowDivider; + /** + * {@code true} to fill the empty icon space if applicable. + */ + private boolean mFillSpace; + /** * Root element of this view. */ @@ -101,48 +107,16 @@ public class DynamicItemView extends FrameLayout { private View mDivider; public DynamicItemView(@NonNull Context context) { - this(context, null); + super(context); } public DynamicItemView(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); - - loadFromAttributes(attrs); } public DynamicItemView(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); - - loadFromAttributes(attrs); - } - - /** - * Load values from the supplied attribute set. - * - * @param attrs The supplied attribute set to load the values. - */ - protected void loadFromAttributes(@Nullable AttributeSet attrs) { - TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.DynamicInfo); - - try { - mIcon = DynamicResourceUtils.getDrawable(getContext(), a.getResourceId( - R.styleable.DynamicInfo_ads_dynamicInfo_icon, - DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE)); - mTitle = a.getString(R.styleable.DynamicInfo_ads_dynamicInfo_title); - mSubtitle = a.getString(R.styleable.DynamicInfo_ads_dynamicInfo_subtitle); - mColor = a.getColor(R.styleable.DynamicInfo_ads_dynamicInfo_color, - WidgetDefaults.ADS_COLOR_UNKNOWN); - mColorType = a.getInt( - R.styleable.DynamicInfo_ads_dynamicInfo_colorType, - DynamicColorType.NONE); - mShowDivider = a.getBoolean(R.styleable.DynamicInfo_ads_dynamicInfo_showDivider, - WidgetDefaults.ADS_SHOW_DIVIDER); - } finally { - a.recycle(); - } - - initialize(); } /** @@ -156,8 +130,8 @@ protected void loadFromAttributes(@Nullable AttributeSet attrs) { * @param showDivider {@code true} to show horizontal divider. */ public DynamicItemView(@NonNull Context context, @Nullable Drawable icon, - @Nullable CharSequence title, @Nullable CharSequence subtitle, - @ColorInt int color, boolean showDivider) { + @Nullable CharSequence title, @Nullable CharSequence subtitle, + @ColorInt int color, boolean showDivider) { super(context); this.mIcon = icon; @@ -166,21 +140,39 @@ public DynamicItemView(@NonNull Context context, @Nullable Drawable icon, this.mColor = color; this.mShowDivider = showDivider; - initialize(); + onUpdate(); } - /** - * @return The layout used by this view. Override this method to - * supply a different layout. - */ + @Override + protected void onLoadAttributes(@Nullable AttributeSet attrs) { + TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.DynamicInfo); + + try { + mIcon = DynamicResourceUtils.getDrawable(getContext(), a.getResourceId( + R.styleable.DynamicInfo_ads_icon, + DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE)); + mTitle = a.getString(R.styleable.DynamicInfo_ads_title); + mSubtitle = a.getString(R.styleable.DynamicInfo_ads_subtitle); + mColor = a.getColor(R.styleable.DynamicInfo_ads_color, + WidgetDefaults.ADS_COLOR_UNKNOWN); + mColorType = a.getInt(R.styleable.DynamicInfo_ads_colorType, + Theme.ColorType.NONE); + mShowDivider = a.getBoolean(R.styleable.DynamicInfo_ads_showDivider, + WidgetDefaults.ADS_SHOW_DIVIDER); + mFillSpace = a.getBoolean(R.styleable.DynamicInfo_ads_fillSpace, + WidgetDefaults.ADS_FILL_SPACE); + } finally { + a.recycle(); + } + } + + @Override protected @LayoutRes int getLayoutRes() { return R.layout.ads_item_view; } - /** - * Initialize the layout for this view. - */ - private void initialize() { + @Override + protected void onInflate() { inflate(getContext(), getLayoutRes(), this); mItemView = findViewById(R.id.ads_item_view); @@ -189,26 +181,30 @@ private void initialize() { mSubtitleView = findViewById(R.id.ads_item_view_subtitle); mDivider = findViewById(R.id.ads_item_view_divider); - update(); + onUpdate(); } - /** - * Load this view according to the supplied parameters. - */ - public void update() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + @Override + public void onUpdate() { + if (mColorType != Theme.ColorType.NONE && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } if (mIcon != null) { mIconView.setImageDrawable(mIcon); + mIconView.setVisibility(VISIBLE); + } else { + if (mFillSpace) { + mIconView.setVisibility(GONE); + } } - if (mColor != DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE) { - mIconView.setColor(mColor); - } else { - mIconView.clearColorFilter(); + if (mIconView != null) { + if (mColor != DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE) { + mIconView.setColor(mColor); + } else { + mIconView.clearColorFilter(); + } } if (mTitle != null) { @@ -225,10 +221,22 @@ public void update() { mSubtitleView.setVisibility(GONE); } - mDivider.setVisibility(mShowDivider ? VISIBLE : GONE); + if (mDivider != null) { + mDivider.setVisibility(mShowDivider ? VISIBLE : GONE); + } + } + + @Override + protected void onEnabled(boolean enabled) { + mItemView.setEnabled(enabled); + mIconView.setEnabled(enabled); + mTitleView.setEnabled(enabled); + mSubtitleView.setEnabled(enabled); } /** + * Get the icon used by this view. + * * @return The icon used by this view. */ public @Nullable Drawable getIcon() { @@ -243,10 +251,12 @@ public void update() { public void setIcon(@Nullable Drawable icon) { this.mIcon = icon; - update(); + onUpdate(); } /** + * Get the title used by this view. + * * @return The title used by this view. */ public @Nullable CharSequence getTitle() { @@ -261,10 +271,12 @@ public void setIcon(@Nullable Drawable icon) { public void setTitle(@Nullable CharSequence title) { this.mTitle = title; - update(); + onUpdate(); } /** + * Get the subtitle used by this view. + * * @return The subtitle used by this view. */ public @Nullable CharSequence getSubtitle() { @@ -279,13 +291,15 @@ public void setTitle(@Nullable CharSequence title) { public void setSubtitle(@Nullable CharSequence subtitle) { this.mSubtitle = subtitle; - update(); + onUpdate(); } /** + * Get the icon tint color type used by this view. + * * @return The icon tint color type used by this view. */ - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @@ -294,15 +308,17 @@ public void setSubtitle(@Nullable CharSequence subtitle) { * * @param colorType The icon tint color type to be set. * - * @see DynamicColorType + * @see Theme.ColorType */ - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; - update(); + onUpdate(); } /** + * Get the icon tint color used by this view. + * * @return The icon tint color used by this view. */ public @ColorInt int getColor() { @@ -315,15 +331,17 @@ public void setColorType(@DynamicColorType int colorType) { * @param color The icon tint color to be set. */ public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; - update(); + onUpdate(); } /** - * @return {@code true} to show horizontal divider. - * Useful to display in a list view. + * Returns whether to show the horizontal divider. + *

Useful to display in a list view. + * + * @return {@code true} to show the horizontal divider. */ public boolean isShowDivider() { return mShowDivider; @@ -331,18 +349,39 @@ public boolean isShowDivider() { /** * Set the horizontal divider fro this view. - * Useful to display in a list view. + *

Useful to display in a list view. * - * @param showDivider {@code true} to show horizontal - * divider. + * @param showDivider {@code true} to show the horizontal divider. */ public void setShowDivider(boolean showDivider) { this.mShowDivider = showDivider; - update(); + onUpdate(); } /** + * Returns whether to fill the empty icon space if applicable. + * + * @return {@code true} to fill the empty icon space if applicable. + */ + public boolean isFillSpace() { + return mFillSpace; + } + + /** + * Controls the fill empty space behavior for this view. + * + * @param fillSpace {@code true} to fill the empty icon space. + */ + public void setFillSpace(boolean fillSpace) { + this.mFillSpace = fillSpace; + + onUpdate(); + } + + /** + * Get the root element of this view. + * * @return The root element of this view. */ public ViewGroup getItemView() { @@ -350,6 +389,8 @@ public ViewGroup getItemView() { } /** + * Get the image view to show the icon. + * * @return The image view to show the icon. */ public DynamicImageView getIconView() { @@ -357,6 +398,8 @@ public DynamicImageView getIconView() { } /** + * Get the text view to show the title. + * * @return The text view to show the title. */ public TextView getTitleView() { @@ -364,6 +407,8 @@ public TextView getTitleView() { } /** + * Get the text view to show the subtitle. + * * @return The text view to show the subtitle. */ public TextView getSubtitleView() { @@ -371,6 +416,8 @@ public TextView getSubtitleView() { } /** + * Get the view to show the divider. + * * @return The view to show the divider. */ public View getDivider() { diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/view/DynamicView.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/view/DynamicView.java new file mode 100644 index 0000000000..e461a68343 --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/view/DynamicView.java @@ -0,0 +1,107 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.FrameLayout; + +import androidx.annotation.AttrRes; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +/** + * A FrameLayout with basic functionality to create views according to the need. + */ +public abstract class DynamicView extends FrameLayout { + + public DynamicView(@NonNull Context context) { + this(context, null); + } + + public DynamicView(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + + loadFromAttributes(attrs); + } + + public DynamicView(@NonNull Context context, + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { + super(context, attrs, defStyleAttr); + + loadFromAttributes(attrs); + } + + /** + * Load values from the supplied attribute set. + * + * @param attrs The supplied attribute set to load the values. + */ + private void loadFromAttributes(@Nullable AttributeSet attrs) { + onLoadAttributes(attrs); + onInflate(); + } + + /** + * Load values from the supplied attribute set. + * + * @param attrs The attribute set to load the values. + */ + protected void onLoadAttributes(@Nullable AttributeSet attrs) { }; + + /** + * This method will be called to get the layout resource for this view. + *

Supply the view layout resource here to do the inflation. + * + * @return The layout resource for this view. + */ + protected abstract @LayoutRes int getLayoutRes(); + + /** + * This method will be called after loading the attributed. + *

Initialize the view layout here. + */ + protected abstract void onInflate(); + + /** + * This method will be called whenever there is a change in the view attributes or parameters. + *

It is better to do any real time calculation like updating the value string or checked + * state in this method. + */ + protected abstract void onUpdate(); + + /** + * This method will be called whenever there is a change in the view state. + *

Either {@code enabled} or {@code disabled}, other views like icon, title, color, etc. + * must be updated here to reflect the overall view state. + * + * @param enabled {@code true} if this view is enabled and can receive click events. + */ + protected void onEnabled(boolean enabled) { }; + + /** + * Set this view enabled or disabled. + * + * @param enabled {@code true} if this view is enabled. + */ + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + + onEnabled(enabled); + } +} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicAppBarLayout.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicAppBarLayout.java index 82b01d6bd4..fa74aee44e 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicAppBarLayout.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicAppBarLayout.java @@ -18,36 +18,36 @@ import android.content.Context; import android.content.res.TypedArray; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.AppBarLayout; import android.util.AttributeSet; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.google.android.material.appbar.AppBarLayout; import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; /** - * An AppBarLayout to apply color filter according to the - * supplied parameters. + * An AppBarLayout to apply color filter according to the supplied parameters. */ public class DynamicAppBarLayout extends AppBarLayout implements DynamicWidget { /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -55,24 +55,24 @@ public class DynamicAppBarLayout extends AppBarLayout implements DynamicWidget { private @ColorInt int mColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; public DynamicAppBarLayout(@NonNull Context context) { this(context, null); @@ -90,19 +90,21 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.PRIMARY); + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, + Theme.ColorType.PRIMARY); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); mContrastWithColor = a.getColor( R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -112,39 +114,39 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } setColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -157,7 +159,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -170,22 +172,28 @@ public void setColor(@ColorInt int color) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override @@ -198,7 +206,7 @@ public void setEnabled(boolean enabled) { @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicBottomNavigationView.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicBottomNavigationView.java index 3f3a5df9ab..67d61ea589 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicBottomNavigationView.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicBottomNavigationView.java @@ -18,22 +18,24 @@ import android.content.Context; import android.content.res.TypedArray; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.BottomNavigationView; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.google.android.material.bottomnavigation.BottomNavigationView; import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; import com.pranavpandey.android.dynamic.support.widget.base.DynamicTextWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; /** - * A BottomNavigationView to change its text and indicator - * color according to the supplied parameters. + * A BottomNavigationView to change its text and indicator color according to the + * supplied parameters. */ public class DynamicBottomNavigationView extends BottomNavigationView implements DynamicTextWidget { @@ -41,22 +43,22 @@ public class DynamicBottomNavigationView extends BottomNavigationView /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** * Text color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mTextColorType; + private @Theme.ColorType int mTextColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -69,24 +71,24 @@ public class DynamicBottomNavigationView extends BottomNavigationView private @ColorInt int mTextColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; public DynamicBottomNavigationView(@NonNull Context context) { this(context, null); @@ -99,7 +101,7 @@ public DynamicBottomNavigationView(@NonNull Context context, @Nullable Attribute } public DynamicBottomNavigationView(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -112,21 +114,19 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { try { mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.PRIMARY); + Theme.ColorType.PRIMARY); mTextColorType = a.getInt(R.styleable.DynamicTheme_ads_textColorType, - DynamicColorType.TINT_PRIMARY); - mContrastWithColorType = a.getInt( - R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); + Theme.ColorType.TINT_PRIMARY); + mContrastWithColorType = a.getInt(R.styleable.DynamicTheme_ads_contrastWithColorType, + Theme.ColorType.PRIMARY); mColor = a.getColor(R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); mTextColor = a.getColor(R.styleable.DynamicTheme_ads_textColor, WidgetDefaults.ADS_COLOR_UNKNOWN); mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( - R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_NON_BACKGROUND_AWARE); + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger(R.styleable.DynamicTheme_ads_backgroundAware, + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -136,20 +136,20 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mTextColorType != DynamicColorType.NONE - && mTextColorType != DynamicColorType.CUSTOM) { - mTextColor = DynamicTheme.getInstance().getColorFromType(mTextColorType); + if (mTextColorType != Theme.ColorType.NONE + && mTextColorType != Theme.ColorType.CUSTOM) { + mTextColor = DynamicTheme.getInstance().resolveColorType(mTextColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } setColor(); @@ -157,36 +157,36 @@ public void initialize() { } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getTextColorType() { + public @Theme.ColorType int getTextColorType() { return mTextColorType; } @Override - public void setTextColorType(@DynamicColorType int textColorType) { + public void setTextColorType(@Theme.ColorType int textColorType) { this.mTextColorType = textColorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -199,7 +199,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -213,7 +213,7 @@ public void setColor(@ColorInt int color) { @Override public void setTextColor(@ColorInt int textColor) { - this.mTextColorType = DynamicColorType.CUSTOM; + this.mTextColorType = Theme.ColorType.CUSTOM; this.mTextColor = textColor; setColor(); @@ -227,7 +227,7 @@ public void setTextColor(@ColorInt int textColor) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); @@ -235,18 +235,24 @@ public void setContrastWithColor(@ColorInt int contrastWithColor) { } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; - } - - @Override - public void setBackgroundAware(boolean backgroundAware) { + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { this.mBackgroundAware = backgroundAware; setColor(); setTextColor(); } + @Override + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } + + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; + } + @Override public void setEnabled(boolean enabled) { super.setEnabled(enabled); @@ -257,10 +263,6 @@ public void setEnabled(boolean enabled) { @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); - } - setBackgroundColor(mColor); } } @@ -268,14 +270,16 @@ public void setColor() { @Override public void setTextColor() { if (mTextColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mTextColor = DynamicColorUtils.getContrastColor(mTextColor, mContrastWithColor); } @ColorInt int normalColor = DynamicColorUtils.adjustAlpha(mTextColor, WidgetDefaults.ADS_ALPHA_UNCHECKED); - setItemTextColor(DynamicResourceUtils.getColorStateList(normalColor, mTextColor)); - setItemIconTintList(DynamicResourceUtils.getColorStateList(normalColor, mTextColor)); + setItemTextColor(DynamicResourceUtils.getColorStateList( + normalColor, mTextColor, true)); + setItemIconTintList(DynamicResourceUtils.getColorStateList( + normalColor, mTextColor, true)); } } } \ No newline at end of file diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicButton.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicButton.java index 5cd8d5fe1c..87c8b51518 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicButton.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicButton.java @@ -19,38 +19,42 @@ import android.annotation.SuppressLint; import android.content.Context; import android.content.res.TypedArray; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.AppCompatButton; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.google.android.material.button.MaterialButton; import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; import com.pranavpandey.android.dynamic.support.utils.DynamicTintUtils; +import com.pranavpandey.android.dynamic.support.widget.base.DynamicCornerWidget; +import com.pranavpandey.android.dynamic.support.widget.base.DynamicTintWidget; import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; /** - * An AppCompatButton to change its color according to the - * supplied parameters. + * An AppCompatButton to change its color according to the supplied parameters. */ -public class DynamicButton extends AppCompatButton implements DynamicWidget { +public class DynamicButton extends MaterialButton implements + DynamicWidget, DynamicCornerWidget, DynamicTintWidget { /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -58,30 +62,35 @@ public class DynamicButton extends AppCompatButton implements DynamicWidget { private @ColorInt int mColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; /** * {@code true} if style applied to this view is borderless. */ private boolean mStyleBorderless; + /** + * {@code true} to tint background according to the widget color. + */ + private boolean mTintBackground; + public DynamicButton(@NonNull Context context) { this(context, null); } @@ -93,7 +102,7 @@ public DynamicButton(@NonNull Context context, @Nullable AttributeSet attrs) { } public DynamicButton(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -124,20 +133,27 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.NONE); + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, + Theme.ColorType.TINT_BACKGROUND); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); mStyleBorderless = a.getBoolean( - R.styleable.DynamicTheme_ads_styleBorderless, false); + R.styleable.DynamicTheme_ads_styleBorderless, + WidgetDefaults.ADS_STYLE_BORDERLESS); + mTintBackground = a.getBoolean( + R.styleable.DynamicTheme_ads_tintBackground, + WidgetDefaults.ADS_TINT_BACKGROUND); } finally { a.recycle(); } @@ -147,39 +163,40 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } + setCorner(DynamicTheme.getInstance().get().getCornerRadius()); setColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -192,7 +209,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -205,20 +222,38 @@ public void setColor(@ColorInt int color) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); } @Override - public boolean isBackgroundAware() { + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); + } + + @Override + public @Theme.BackgroundAware int getBackgroundAware() { return mBackgroundAware; } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; + } + + @Override + public boolean isTintBackground() { + return mTintBackground; + } + + @Override + public void setTintBackground(boolean tintBackground) { + this.mTintBackground = tintBackground; setColor(); } @@ -230,20 +265,47 @@ public void setEnabled(boolean enabled) { setAlpha(enabled ? WidgetDefaults.ADS_ALPHA_ENABLED : WidgetDefaults.ADS_ALPHA_DISABLED); } + @Override + public void setCorner(Integer cornerRadius) { + setCornerRadius(cornerRadius); + } + + @Override + public Integer getCorner() { + return getCornerRadius(); + } + @SuppressLint("RestrictedApi") @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } + DynamicTintUtils.setViewBackgroundTint(this, mContrastWithColor, + mTintBackground ? mColor : DynamicColorUtils.getTintColor( + mContrastWithColor), mStyleBorderless, false); + if (!mStyleBorderless) { - DynamicTintUtils.setViewBackgroundTint(this, mColor); - setTextColor(DynamicResourceUtils.getColorStateList( - DynamicColorUtils.getTintColor(mColor))); + if (mTintBackground) { + setTextColor(DynamicResourceUtils.getColorStateList( + mContrastWithColor, + DynamicColorUtils.getTintColor(mColor), + DynamicColorUtils.getTintColor(mColor), false)); + } else { + setTextColor(DynamicResourceUtils.getColorStateList( + mContrastWithColor, + DynamicColorUtils.getContrastColor(mColor, + DynamicColorUtils.getTintColor(mContrastWithColor)), + DynamicColorUtils.getContrastColor(mColor, + DynamicColorUtils.getTintColor(mContrastWithColor)), + false)); + } } else { - setTextColor(DynamicResourceUtils.getColorStateList(mColor)); + setTextColor(DynamicResourceUtils.getColorStateList( + DynamicColorUtils.getTintColor(mContrastWithColor), + mColor, mColor, false)); } } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicCardView.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicCardView.java index 943b1f39e3..2f35876046 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicCardView.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicCardView.java @@ -18,36 +18,40 @@ import android.content.Context; import android.content.res.TypedArray; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.CardView; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.google.android.material.card.MaterialCardView; import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; +import com.pranavpandey.android.dynamic.support.theme.Theme; +import com.pranavpandey.android.dynamic.support.widget.base.DynamicCornerWidget; +import com.pranavpandey.android.dynamic.support.widget.base.DynamicTintWidget; import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; /** - * A CardView to change its background color according to the - * supplied parameters. + * A CardView to change its background color according to the supplied parameters. */ -public class DynamicCardView extends CardView implements DynamicWidget { +public class DynamicCardView extends MaterialCardView implements + DynamicWidget, DynamicCornerWidget, DynamicTintWidget { /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -55,24 +59,29 @@ public class DynamicCardView extends CardView implements DynamicWidget { private @ColorInt int mColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; + + /** + * {@code true} to tint background according to the widget color. + */ + private boolean mTintBackground; public DynamicCardView(@NonNull Context context) { this(context, null); @@ -85,7 +94,7 @@ public DynamicCardView(@NonNull Context context, @Nullable AttributeSet attrs) { } public DynamicCardView(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -97,18 +106,24 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.BACKGROUND); + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, + Theme.ColorType.BACKGROUND); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.NONE); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.NONE); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_NON_BACKGROUND_AWARE); + Theme.BackgroundAware.DISABLE); + mTintBackground = a.getBoolean( + R.styleable.DynamicTheme_ads_tintBackground, + WidgetDefaults.ADS_TINT_BACKGROUND); } finally { a.recycle(); } @@ -118,39 +133,40 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } + setCorner((float) DynamicTheme.getInstance().get().getCornerRadius()); setColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -163,7 +179,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -176,32 +192,68 @@ public void setColor(@ColorInt int color) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); } @Override - public boolean isBackgroundAware() { + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); + } + + @Override + public @Theme.BackgroundAware int getBackgroundAware() { return mBackgroundAware; } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; + } + + @Override + public boolean isTintBackground() { + return mTintBackground; + } + + @Override + public void setTintBackground(boolean tintBackground) { + this.mTintBackground = tintBackground; setColor(); } + @Override + public void setBackgroundColor(@ColorInt int color) { + super.setCardBackgroundColor(color); + + setColor(color); + } + + @Override + public void setCorner(Float cornerRadius) { + setRadius(cornerRadius); + } + + @Override + public Float getCorner() { + return getRadius(); + } + @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } - setCardBackgroundColor(DynamicColorUtils.isColorDark(mColor) + setCardBackgroundColor(!mTintBackground ? mColor + : DynamicColorUtils.isColorDark(mColor) ? DynamicColorUtils.getLighterColor(mColor, 0.07f) : DynamicColorUtils.getLighterColor(mColor, 0.2f)); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicCheckBox.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicCheckBox.java index c1f7725d89..f3ea78bc5e 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicCheckBox.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicCheckBox.java @@ -21,39 +21,39 @@ import android.content.Context; import android.content.res.TypedArray; import android.os.Build; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.AppCompatCheckBox; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.google.android.material.checkbox.MaterialCheckBox; import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; +import com.pranavpandey.android.dynamic.support.utils.DynamicTintUtils; import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; -import com.pranavpandey.android.dynamic.utils.DynamicDrawableUtils; -import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils; /** - * A CheckBox to apply color filter according to the supplied - * parameters. + * A CheckBox to apply color filter according to the supplied parameters. */ -public class DynamicCheckBox extends AppCompatCheckBox implements DynamicWidget { +public class DynamicCheckBox extends MaterialCheckBox implements DynamicWidget { /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -61,24 +61,24 @@ public class DynamicCheckBox extends AppCompatCheckBox implements DynamicWidget private @ColorInt int mColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; public DynamicCheckBox(@NonNull Context context) { this(context, null); @@ -91,7 +91,7 @@ public DynamicCheckBox(@NonNull Context context, @Nullable AttributeSet attrs) { } public DynamicCheckBox(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -103,18 +103,21 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.ACCENT); + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, + Theme.ColorType.ACCENT); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -124,39 +127,39 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } setColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -169,7 +172,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -182,22 +185,28 @@ public void setColor(@ColorInt int color) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override @@ -207,22 +216,26 @@ public void setEnabled(boolean enabled) { setAlpha(enabled ? WidgetDefaults.ADS_ALPHA_ENABLED : WidgetDefaults.ADS_ALPHA_DISABLED); } - @SuppressLint("PrivateResource") + @SuppressLint({"RestrictedApi"}) @TargetApi(Build.VERSION_CODES.M) @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); - } + @ColorInt int tintColor = DynamicTheme.getInstance().get().getTintBackgroundColor(); + + if (isBackgroundAware()) { + tintColor = DynamicColorUtils.getContrastColor( + tintColor, DynamicTheme.getInstance().get().getBackgroundColor()); - if (DynamicVersionUtils.isLollipop()) { - setButtonTintList(DynamicResourceUtils.getColorStateList(mColor)); - } else { - setButtonDrawable(DynamicDrawableUtils.colorizeDrawable( - DynamicResourceUtils.getDrawable(getContext(), - R.drawable.abc_btn_check_material), mColor)); + if (mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); + } } + + DynamicTintUtils.setViewBackgroundTint(this, + mContrastWithColor, mColor, true, true); + setSupportButtonTintList(DynamicResourceUtils.getColorStateList( + tintColor, mColor, true)); } } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicCheckedTextView.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicCheckedTextView.java index 6d821e39cd..1510000a4b 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicCheckedTextView.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicCheckedTextView.java @@ -21,39 +21,41 @@ import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.os.Build; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.AppCompatCheckedTextView; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatCheckedTextView; + import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; +import com.pranavpandey.android.dynamic.support.utils.DynamicTintUtils; import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; import com.pranavpandey.android.dynamic.utils.DynamicDrawableUtils; import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils; /** - * A CheckedTextView to change its color according to the - * supplied parameters. + * A CheckedTextView to change its color according to the supplied parameters. */ public class DynamicCheckedTextView extends AppCompatCheckedTextView implements DynamicWidget { /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -61,24 +63,24 @@ public class DynamicCheckedTextView extends AppCompatCheckedTextView implements private @ColorInt int mColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; public DynamicCheckedTextView(@NonNull Context context) { this(context, null); @@ -91,7 +93,7 @@ public DynamicCheckedTextView(@NonNull Context context, @Nullable AttributeSet a } public DynamicCheckedTextView(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -103,18 +105,21 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.ACCENT); + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, + Theme.ColorType.ACCENT); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -124,37 +129,37 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -167,7 +172,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -180,22 +185,28 @@ public void setColor(@ColorInt int color) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override @@ -216,14 +227,25 @@ protected void drawableStateChanged() { @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); + @ColorInt int tintColor = DynamicTheme.getInstance().get().getTintBackgroundColor(); + + if (isBackgroundAware()) { + tintColor = DynamicColorUtils.getContrastColor( + tintColor, DynamicTheme.getInstance().get().getBackgroundColor()); + + if (mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); + } } - final Drawable[] compoundDrawables = getCompoundDrawables(); + DynamicTintUtils.setViewBackgroundTint(this, + mContrastWithColor, mColor, true, true); + if (DynamicVersionUtils.isMarshmallow()) { - setCompoundDrawableTintList(DynamicResourceUtils.getColorStateList(mColor)); + setCompoundDrawableTintList(DynamicResourceUtils.getColorStateList( + tintColor, mColor, true)); } else { + final Drawable[] compoundDrawables = getCompoundDrawables(); for (Drawable compoundDrawable : compoundDrawables) { if (compoundDrawable != null) { DynamicDrawableUtils.colorizeDrawable(compoundDrawable, mColor); diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicDrawerLayout.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicDrawerLayout.java index f167367591..4ea32a82c9 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicDrawerLayout.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicDrawerLayout.java @@ -17,20 +17,21 @@ package com.pranavpandey.android.dynamic.support.widget; import android.content.Context; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.DrawerLayout; import android.util.AttributeSet; import android.view.MotionEvent; +import androidx.annotation.AttrRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.drawerlayout.widget.DrawerLayout; + /** - * A fixed drawer layout when in persistent or locked open state. + * A fixed DrawerLayout when in persistent or locked open state. */ public class DynamicDrawerLayout extends DrawerLayout { /** - * Boolean to disallow the intercept if the drawer is in locked - * state. + * Boolean to disallow the intercept if the drawer is in locked state. */ private boolean mDisallowIntercept; @@ -43,7 +44,7 @@ public DynamicDrawerLayout(@NonNull Context context, @Nullable AttributeSet attr } public DynamicDrawerLayout(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicEditText.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicEditText.java index e37dc1f061..c35ab1259f 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicEditText.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicEditText.java @@ -18,37 +18,38 @@ import android.content.Context; import android.content.res.TypedArray; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.AppCompatEditText; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatEditText; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicInputUtils; import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; /** - * An AppCompatEditText to change its color according to the - * supplied parameters. + * An EditText to change its color according to the supplied parameters. */ public class DynamicEditText extends AppCompatEditText implements DynamicWidget { /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -56,24 +57,24 @@ public class DynamicEditText extends AppCompatEditText implements DynamicWidget private @ColorInt int mColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; public DynamicEditText(@NonNull Context context) { this(context, null); @@ -86,7 +87,7 @@ public DynamicEditText(@NonNull Context context, @Nullable AttributeSet attrs) { } public DynamicEditText(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -98,18 +99,30 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.ACCENT); + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, + Theme.ColorType.ACCENT); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); + + if (mColorType == Theme.ColorType.ACCENT) { + setTextColor(DynamicColorUtils.getContrastColor( + DynamicTheme.getInstance().get().getTextPrimaryColor(), + DynamicTheme.getInstance().get().getBackgroundColor())); + setHintTextColor(DynamicColorUtils.getContrastColor( + DynamicTheme.getInstance().get().getTextSecondaryColor(), + DynamicTheme.getInstance().get().getBackgroundColor())); + } } finally { a.recycle(); } @@ -119,39 +132,39 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } setColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -164,7 +177,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -177,22 +190,28 @@ public void setColor(@ColorInt int color) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override @@ -205,7 +224,7 @@ public void setEnabled(boolean enabled) { @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicFloatingActionButton.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicFloatingActionButton.java index 4b38fb67fd..039e07b333 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicFloatingActionButton.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicFloatingActionButton.java @@ -20,37 +20,38 @@ import android.content.res.TypedArray; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.FloatingActionButton; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicTintUtils; import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; /** - * A FloatingActionButton to change its color according to the - * supplied parameters. + * A FloatingActionButton to change its color according to the supplied parameters. */ public class DynamicFloatingActionButton extends FloatingActionButton implements DynamicWidget { /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -58,24 +59,24 @@ public class DynamicFloatingActionButton extends FloatingActionButton implements private @ColorInt int mColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; public DynamicFloatingActionButton(@NonNull Context context) { this(context, null); @@ -88,7 +89,7 @@ public DynamicFloatingActionButton(@NonNull Context context, @Nullable Attribute } public DynamicFloatingActionButton(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -96,22 +97,24 @@ public DynamicFloatingActionButton(@NonNull Context context, @Override public void loadFromAttributes(@Nullable AttributeSet attrs) { - TypedArray a = getContext().obtainStyledAttributes( - attrs, R.styleable.DynamicTheme); + TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.ACCENT); + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, + Theme.ColorType.ACCENT); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -121,39 +124,39 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } setColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -166,7 +169,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -179,32 +182,28 @@ public void setColor(@ColorInt int color) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; - } - - @Override - public void setBackgroundAware(boolean backgroundAware) { + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { this.mBackgroundAware = backgroundAware; setColor(); } @Override - public void setImageDrawable(@Nullable Drawable drawable) { - super.setImageDrawable(drawable); + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - if (drawable != null && getVisibility() == VISIBLE) { - hide(); - show(); - } + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override @@ -214,14 +213,22 @@ public void setEnabled(boolean enabled) { setAlpha(enabled ? WidgetDefaults.ADS_ALPHA_ENABLED : WidgetDefaults.ADS_ALPHA_DISABLED); } + @Override + public void setImageDrawable(@Nullable Drawable drawable) { + super.setImageDrawable(drawable); + + setColor(); + } + @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } - DynamicTintUtils.setViewBackgroundTint(this, mColor); + DynamicTintUtils.setViewBackgroundTint(this, + mContrastWithColor, mColor, false, false); setColorFilter(DynamicColorUtils.getTintColor(mColor), PorterDuff.Mode.SRC_IN); } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicFrameLayout.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicFrameLayout.java index 5a9b833e0c..42410d3b92 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicFrameLayout.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicFrameLayout.java @@ -19,37 +19,38 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.ColorDrawable; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.AttributeSet; import android.widget.FrameLayout; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; import com.pranavpandey.android.dynamic.utils.DynamicDrawableUtils; /** - * A FrameLayout to apply background color according to the supplied - * parameters. + * A FrameLayout to apply background color according to the supplied parameters. */ public class DynamicFrameLayout extends FrameLayout implements DynamicWidget { /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -57,24 +58,24 @@ public class DynamicFrameLayout extends FrameLayout implements DynamicWidget { private @ColorInt int mColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; public DynamicFrameLayout(@NonNull Context context) { this(context, null); @@ -87,7 +88,7 @@ public DynamicFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs } public DynamicFrameLayout(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -99,18 +100,21 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.NONE); + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, + Theme.ColorType.NONE); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -120,39 +124,39 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } setColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -165,7 +169,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -178,22 +182,28 @@ public void setColor(@ColorInt int color) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override @@ -206,7 +216,7 @@ public void setEnabled(boolean enabled) { @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicGridView.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicGridView.java index da49b6a4fe..affb57fc0b 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicGridView.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicGridView.java @@ -18,37 +18,38 @@ import android.content.Context; import android.content.res.TypedArray; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.AttributeSet; import android.widget.GridView; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicScrollUtils; import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; /** - * A GridView to apply color filter according to the supplied - * parameters. + * A GridView to apply color filter according to the supplied parameters. */ public class DynamicGridView extends GridView implements DynamicWidget { /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -56,24 +57,24 @@ public class DynamicGridView extends GridView implements DynamicWidget { private @ColorInt int mColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; public DynamicGridView(@NonNull Context context) { this(context, null); @@ -86,7 +87,7 @@ public DynamicGridView(@NonNull Context context, @Nullable AttributeSet attrs) { } public DynamicGridView(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -98,18 +99,21 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, WidgetDefaults.ADS_COLOR_EDGE_EFFECT); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -119,39 +123,39 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } setColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -164,7 +168,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -177,28 +181,34 @@ public void setColor(@ColorInt int color) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicHeaderImageView.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicHeaderImageView.java index 0481de73d3..14f96c9e1f 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicHeaderImageView.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicHeaderImageView.java @@ -18,15 +18,14 @@ import android.content.Context; import android.graphics.PorterDuff; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.AttributeSet; -import com.pranavpandey.android.dynamic.support.R; +import androidx.annotation.AttrRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; /** - * A DynamicImageView to apply color filter as - * {@link PorterDuff.Mode#SRC_ATOP}. + * A DynamicImageView to apply color filter as {@link PorterDuff.Mode#SRC_ATOP}. */ public class DynamicHeaderImageView extends DynamicImageView { @@ -39,7 +38,7 @@ public DynamicHeaderImageView(@NonNull Context context, @Nullable AttributeSet a } public DynamicHeaderImageView(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicHueSeekBar.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicHueSeekBar.java index 9c99cebafa..28701858ea 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicHueSeekBar.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicHueSeekBar.java @@ -19,10 +19,12 @@ import android.annotation.TargetApi; import android.content.Context; import android.os.Build; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.utils.DynamicSeekBarUtils; /** @@ -40,7 +42,7 @@ public DynamicHueSeekBar(@NonNull Context context, @Nullable AttributeSet attrs) } public DynamicHueSeekBar(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); } @@ -52,5 +54,7 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { } @Override - public void setProgressBarColor() { } + public void setProgressBarColor() { + // Do nothing as we are using the custom drawable. + } } \ No newline at end of file diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicImageButton.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicImageButton.java index 7625303ab8..3390b1ec46 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicImageButton.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicImageButton.java @@ -20,38 +20,41 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.AppCompatImageButton; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatImageButton; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; +import com.pranavpandey.android.dynamic.support.utils.DynamicTintUtils; +import com.pranavpandey.android.dynamic.support.widget.base.DynamicTintWidget; import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; -import com.pranavpandey.android.dynamic.utils.DynamicDrawableUtils; /** - * An AppCompatButton to change its color according to the - * supplied parameters. + * An AppCompatButton to change its color according to the supplied parameters. */ -public class DynamicImageButton extends AppCompatImageButton implements DynamicWidget { +public class DynamicImageButton extends AppCompatImageButton + implements DynamicWidget, DynamicTintWidget { /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -59,30 +62,35 @@ public class DynamicImageButton extends AppCompatImageButton implements DynamicW private @ColorInt int mColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; /** * {@code true} if style applied to this view is borderless. */ private boolean mStyleBorderless; + /** + * {@code true} to tint background according to the widget color. + */ + private boolean mTintBackground; + public DynamicImageButton(@NonNull Context context) { this(context, null); } @@ -94,7 +102,7 @@ public DynamicImageButton(@NonNull Context context, @Nullable AttributeSet attrs } public DynamicImageButton(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -125,20 +133,27 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.NONE); + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, + Theme.ColorType.ACCENT); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); mStyleBorderless = a.getBoolean( - R.styleable.DynamicTheme_ads_styleBorderless, false); + R.styleable.DynamicTheme_ads_styleBorderless, + WidgetDefaults.ADS_STYLE_BORDERLESS); + mTintBackground = a.getBoolean( + R.styleable.DynamicTheme_ads_tintBackground, + WidgetDefaults.ADS_TINT_BACKGROUND); } finally { a.recycle(); } @@ -148,39 +163,39 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } setColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -193,7 +208,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -206,22 +221,28 @@ public void setColor(@ColorInt int color) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override @@ -238,21 +259,32 @@ public void setEnabled(boolean enabled) { setAlpha(enabled ? WidgetDefaults.ADS_ALPHA_ENABLED : WidgetDefaults.ADS_ALPHA_DISABLED); } + @Override + public boolean isTintBackground() { + return mTintBackground; + } + + @Override + public void setTintBackground(boolean tintBackground) { + this.mTintBackground = tintBackground; + + setColor(); + } + @SuppressLint("RestrictedApi") @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } - if (!mStyleBorderless) { - setSupportBackgroundTintList(DynamicResourceUtils.getColorStateList(mColor)); - DynamicDrawableUtils.colorizeDrawable( - getDrawable(), DynamicColorUtils.getTintColor(mColor)); - } else { - DynamicDrawableUtils.colorizeDrawable(getDrawable(), mColor); - } + DynamicTintUtils.setViewBackgroundTint(this, mContrastWithColor, + mTintBackground ? mColor : DynamicColorUtils.getTintColor( + mContrastWithColor), mStyleBorderless, false); + + setSupportImageTintList(DynamicResourceUtils.getColorStateList( + mColor, mColor, mColor, false)); } } } \ No newline at end of file diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicImageView.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicImageView.java index 28d2c2bda2..6f2c83c263 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicImageView.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicImageView.java @@ -19,36 +19,37 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.PorterDuff; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.AppCompatImageView; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatImageView; + import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; /** - * An ImageView to apply color filter according to the supplied - * parameters. + * An ImageView to apply color filter according to the supplied parameters. */ public class DynamicImageView extends AppCompatImageView implements DynamicWidget { /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -56,24 +57,24 @@ public class DynamicImageView extends AppCompatImageView implements DynamicWidge private @ColorInt int mColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; public DynamicImageView(@NonNull Context context) { this(context, null); @@ -86,7 +87,7 @@ public DynamicImageView(@NonNull Context context, @Nullable AttributeSet attrs) } public DynamicImageView(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -105,18 +106,21 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.NONE); + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, + Theme.ColorType.NONE); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -126,39 +130,39 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } setColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -171,7 +175,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -184,22 +188,28 @@ public void setColor(@ColorInt int color) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override @@ -212,7 +222,7 @@ public void setEnabled(boolean enabled) { @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicLinearLayout.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicLinearLayout.java new file mode 100644 index 0000000000..68d3f2f897 --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicLinearLayout.java @@ -0,0 +1,226 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.ColorDrawable; +import android.util.AttributeSet; +import android.widget.LinearLayout; + +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.pranavpandey.android.dynamic.support.R; +import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; +import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; +import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; +import com.pranavpandey.android.dynamic.utils.DynamicDrawableUtils; + +/** + * A LinearLayout to apply background color according to the supplied parameters. + */ +public class DynamicLinearLayout extends LinearLayout implements DynamicWidget { + + /** + * Color type applied to this view. + * + * @see Theme.ColorType + */ + private @Theme.ColorType int mColorType; + + /** + * Background color type for this view so that it will remain in contrast with this + * color type. + */ + private @Theme.ColorType int mContrastWithColorType; + + /** + * Color applied to this view. + */ + private @ColorInt int mColor; + + /** + * Background color for this view so that it will remain in contrast with this color. + */ + private @ColorInt int mContrastWithColor; + + /** + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. + * + *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. + * + * @see Theme.BackgroundAware + * @see #mContrastWithColor + */ + private @Theme.BackgroundAware int mBackgroundAware; + + public DynamicLinearLayout(@NonNull Context context) { + this(context, null); + } + + public DynamicLinearLayout(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + + loadFromAttributes(attrs); + } + + public DynamicLinearLayout(@NonNull Context context, + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { + super(context, attrs, defStyleAttr); + + loadFromAttributes(attrs); + } + + @Override + public void loadFromAttributes(@Nullable AttributeSet attrs) { + TypedArray a = getContext().obtainStyledAttributes( + attrs, R.styleable.DynamicTheme); + + try { + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, + Theme.ColorType.NONE); + mContrastWithColorType = a.getInt( + R.styleable.DynamicTheme_ads_contrastWithColorType, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, + WidgetDefaults.ADS_COLOR_UNKNOWN); + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( + R.styleable.DynamicTheme_ads_backgroundAware, + WidgetDefaults.getBackgroundAware()); + } finally { + a.recycle(); + } + + initialize(); + } + + @Override + public void initialize() { + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); + } + + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { + mContrastWithColor = DynamicTheme.getInstance() + .resolveColorType(mContrastWithColorType); + } + + setColor(); + } + + @Override + public @Theme.ColorType int getColorType() { + return mColorType; + } + + @Override + public void setColorType(@Theme.ColorType int colorType) { + this.mColorType = colorType; + + initialize(); + } + + @Override + public @Theme.ColorType int getContrastWithColorType() { + return mContrastWithColorType; + } + + @Override + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { + this.mContrastWithColorType = contrastWithColorType; + + initialize(); + } + + @Override + public @ColorInt int getColor() { + return mColor; + } + + @Override + public void setColor(@ColorInt int color) { + this.mColorType = Theme.ColorType.CUSTOM; + this.mColor = color; + + setColor(); + } + + @Override + public @ColorInt int getContrastWithColor() { + return mContrastWithColor; + } + + @Override + public void setContrastWithColor(@ColorInt int contrastWithColor) { + this.mContrastWithColorType = Theme.ColorType.CUSTOM; + this.mContrastWithColor = contrastWithColor; + + setColor(); + } + + @Override + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); + } + + @Override + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } + + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + + setAlpha(enabled ? WidgetDefaults.ADS_ALPHA_ENABLED : WidgetDefaults.ADS_ALPHA_DISABLED); + } + + @Override + public void setColor() { + if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); + } + + DynamicDrawableUtils.setBackground(this, new ColorDrawable(mColor)); + } + } +} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicListView.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicListView.java index b3281ec1e7..5a87e5629a 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicListView.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicListView.java @@ -18,44 +18,38 @@ import android.content.Context; import android.content.res.TypedArray; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.AttributeSet; import android.widget.ListView; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicScrollUtils; import com.pranavpandey.android.dynamic.support.widget.base.DynamicScrollableWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; /** - * A ListView to apply color filter according to the supplied - * parameters}. + * A ListView to apply color filter according to the supplied parameters. */ public class DynamicListView extends ListView implements DynamicScrollableWidget { /** * Color type applied to this view. * - * @see DynamicColorType - */ - private @DynamicColorType int mColorType; - - /** - * Scroll bar color type applied to this view. - * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mScrollBarColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -63,29 +57,36 @@ public class DynamicListView extends ListView implements DynamicScrollableWidget private @ColorInt int mColor; /** - * Scroll bar color applied to this view. - */ - private @ColorInt int mScrollBarColor; - - /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; + + /** + * Scroll bar color type applied to this view. + * + * @see Theme.ColorType + */ + private @Theme.ColorType int mScrollBarColorType; + + /** + * Scroll bar color applied to this view. + */ + private @ColorInt int mScrollBarColor; public DynamicListView(@NonNull Context context) { this(context, null); @@ -98,7 +99,7 @@ public DynamicListView(@NonNull Context context, @Nullable AttributeSet attrs) { } public DynamicListView(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -110,22 +111,27 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, WidgetDefaults.ADS_COLOR_EDGE_EFFECT); - mScrollBarColorType = a.getInt(R.styleable.DynamicTheme_ads_scrollBarColorType, + mScrollBarColorType = a.getInt( + R.styleable.DynamicTheme_ads_scrollBarColorType, WidgetDefaults.ADS_COLOR_SCROLL_BAR); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mScrollBarColor = a.getColor(R.styleable.DynamicTheme_ads_scrollBarColor, + mScrollBarColor = a.getColor( + R.styleable.DynamicTheme_ads_scrollBarColor, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -135,57 +141,57 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mScrollBarColorType != DynamicColorType.NONE - && mScrollBarColorType != DynamicColorType.CUSTOM) { + if (mScrollBarColorType != Theme.ColorType.NONE + && mScrollBarColorType != Theme.ColorType.CUSTOM) { mScrollBarColor = DynamicTheme.getInstance() - .getColorFromType(mScrollBarColorType); + .resolveColorType(mScrollBarColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } setColor(true); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getScrollBarColorType() { + public @Theme.ColorType int getScrollBarColorType() { return mScrollBarColorType; } @Override - public void setScrollBarColorType(@DynamicColorType int scrollBarColorType) { + public void setScrollBarColorType(@Theme.ColorType int scrollBarColorType) { this.mScrollBarColorType = scrollBarColorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -198,7 +204,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(true); @@ -211,7 +217,7 @@ public void setColor(@ColorInt int color) { @Override public void setScrollBarColor(@ColorInt int scrollBarColor) { - this.mScrollBarColorType = DynamicColorType.CUSTOM; + this.mScrollBarColorType = Theme.ColorType.CUSTOM; this.mScrollBarColor = scrollBarColor; setScrollBarColor(); @@ -224,28 +230,34 @@ public void setScrollBarColor(@ColorInt int scrollBarColor) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(true); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(true); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } @@ -256,7 +268,7 @@ public void setColor() { @Override public void setScrollBarColor() { if (mScrollBarColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mScrollBarColor = DynamicColorUtils.getContrastColor( mScrollBarColor, mContrastWithColor); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicNavigationView.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicNavigationView.java index 967e17b0e9..68fc02bd56 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicNavigationView.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicNavigationView.java @@ -18,87 +18,118 @@ import android.content.Context; import android.content.res.TypedArray; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.NavigationView; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.google.android.material.navigation.NavigationView; import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; import com.pranavpandey.android.dynamic.support.utils.DynamicScrollUtils; +import com.pranavpandey.android.dynamic.support.widget.base.DynamicBackgroundWidget; import com.pranavpandey.android.dynamic.support.widget.base.DynamicScrollableWidget; +import com.pranavpandey.android.dynamic.support.widget.base.DynamicStateSelectedWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; +import com.pranavpandey.android.dynamic.utils.DynamicDrawableUtils; +import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils; /** - * A NavigationView to change its selected item and edge effect color - * according to the supplied parameters. + * A NavigationView to change its selected item and edge effect color according to the + * supplied parameters. */ -public class DynamicNavigationView extends NavigationView implements DynamicScrollableWidget { +public class DynamicNavigationView extends NavigationView implements + DynamicBackgroundWidget, DynamicScrollableWidget, DynamicStateSelectedWidget { /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** - * Scroll bar color type applied to this view. + * Background color type for this view so that it will remain in contrast with this + * color type. + */ + private @Theme.ColorType int mContrastWithColorType; + + /** + * Color applied to this view. + */ + private @ColorInt int mColor; + + /** + * Background color for this view so that it will remain in contrast with this color. + */ + private @ColorInt int mContrastWithColor; + + /** + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. + * + *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * - * @see DynamicColorType + * @see Theme.BackgroundAware + * @see #mContrastWithColor */ - private @DynamicColorType int mScrollBarColorType; + private @Theme.BackgroundAware int mBackgroundAware; /** - * Selected item color type applied to this view. + * Color type applied to the background of this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mItemSelectedColorType; + private @Theme.ColorType int mBackgroundColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Scroll bar color type applied to this view. + * + * @see Theme.ColorType */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mScrollBarColorType; /** - * Color applied to this view. + * Normal item color type applied to this view. + * + * @see Theme.ColorType */ - private @ColorInt int mColor; + private @Theme.ColorType int mStateNormalColorType; /** - * Scroll bar color applied to this view. + * Selected item color type applied to this view. + * + * @see Theme.ColorType */ - private @ColorInt int mScrollBarColor; + private @Theme.ColorType int mStateSelectedColorType; /** - * Selected item color applied to this view. + * Background color applied to this view. */ - private @ColorInt int mItemSelectedColor; + private @ColorInt int mBackgroundColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Scroll bar color applied to this view. */ - private @ColorInt int mContrastWithColor; + private @ColorInt int mScrollBarColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. - * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

- * - * @see #mContrastWithColor + * Normal item color applied to this view. */ - private boolean mBackgroundAware; + private @ColorInt int mStateNormalColor; + + /** + * Selected item color applied to this view. + */ + private @ColorInt int mStateSelectedColor; public DynamicNavigationView(@NonNull Context context) { this(context, null); @@ -111,7 +142,7 @@ public DynamicNavigationView(@NonNull Context context, @Nullable AttributeSet at } public DynamicNavigationView(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -123,29 +154,45 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, + mBackgroundColorType = a.getInt( + R.styleable.DynamicTheme_ads_backgroundColorType, + Theme.ColorType.BACKGROUND); + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, WidgetDefaults.ADS_COLOR_EDGE_EFFECT); - mScrollBarColorType = a.getInt(R.styleable.DynamicTheme_ads_scrollBarColorType, + mScrollBarColorType = a.getInt( + R.styleable.DynamicTheme_ads_scrollBarColorType, WidgetDefaults.ADS_COLOR_SCROLL_BAR); - mItemSelectedColorType = a.getInt( - R.styleable.DynamicTheme_ads_itemSelectedColorType, - DynamicColorType.ACCENT); + mStateNormalColorType = a.getInt( + R.styleable.DynamicTheme_ads_stateNormalColorType, + Theme.ColorType.TEXT_PRIMARY); + mStateSelectedColorType = a.getInt( + R.styleable.DynamicTheme_ads_stateSelectedColorType, + Theme.ColorType.ACCENT); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mBackgroundColor = a.getColor( + R.styleable.DynamicTheme_ads_backgroundColor, + WidgetDefaults.ADS_COLOR_UNKNOWN); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, + WidgetDefaults.ADS_COLOR_UNKNOWN); + mScrollBarColor = a.getColor( + R.styleable.DynamicTheme_ads_scrollBarColor, WidgetDefaults.ADS_COLOR_UNKNOWN); - mScrollBarColor = a.getColor(R.styleable.DynamicTheme_ads_scrollBarColor, + mStateNormalColor = a.getColor( + R.styleable.DynamicTheme_ads_stateNormalColor, WidgetDefaults.ADS_COLOR_UNKNOWN); - mItemSelectedColor = a.getColor( - R.styleable.DynamicTheme_ads_itemSelectedColor, + mStateSelectedColor = a.getColor( + R.styleable.DynamicTheme_ads_stateSelectedColor, WidgetDefaults.ADS_COLOR_UNKNOWN); mContrastWithColor = a.getColor( R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -155,87 +202,124 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mBackgroundColorType != Theme.ColorType.NONE + && mBackgroundColorType != Theme.ColorType.CUSTOM) { + mBackgroundColor = DynamicTheme.getInstance() + .resolveColorType(mBackgroundColorType); } - if (mScrollBarColorType != DynamicColorType.NONE - && mScrollBarColorType != DynamicColorType.CUSTOM) { + + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); + } + + if (mScrollBarColorType != Theme.ColorType.NONE + && mScrollBarColorType != Theme.ColorType.CUSTOM) { mScrollBarColor = DynamicTheme.getInstance() - .getColorFromType(mScrollBarColorType); + .resolveColorType(mScrollBarColorType); } - if (mItemSelectedColorType != DynamicColorType.NONE - && mItemSelectedColorType != DynamicColorType.CUSTOM) { - mItemSelectedColor = DynamicTheme.getInstance() - .getColorFromType(mItemSelectedColorType); + if (mStateNormalColorType != Theme.ColorType.NONE + && mStateNormalColorType != Theme.ColorType.CUSTOM) { + mStateNormalColor = DynamicTheme.getInstance() + .resolveColorType(mStateNormalColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mStateSelectedColorType != Theme.ColorType.NONE + && mStateSelectedColorType != Theme.ColorType.CUSTOM) { + mStateSelectedColor = DynamicTheme.getInstance() + .resolveColorType(mStateSelectedColorType); + } + + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } + setBackgroundColor(mBackgroundColor); setColor(true); - setItemSelectedColor(); + setStatesColor(); + } + + @Override + public @Theme.ColorType int getBackgroundColorType() { + return mBackgroundColorType; } @Override - public @DynamicColorType int getColorType() { + public void setBackgroundColorType(@Theme.ColorType int backgroundColorType) { + this.mBackgroundColorType = backgroundColorType; + + initialize(); + } + + @Override + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getScrollBarColorType() { + public @Theme.ColorType int getScrollBarColorType() { return mScrollBarColorType; } @Override - public void setScrollBarColorType(@DynamicColorType int scrollBarColorType) { + public void setScrollBarColorType(@Theme.ColorType int scrollBarColorType) { this.mScrollBarColorType = scrollBarColorType; initialize(); } - /** - * @return The value of {@link #mItemSelectedColorType}. - */ - public @DynamicColorType int getItemSelectedColorType() { - return mItemSelectedColorType; + @Override + public @Theme.ColorType int getStateNormalColorType() { + return mStateNormalColorType; } - /** - * Set the value of {@link #mItemSelectedColorType} and re-initialize this view. - * - * @param itemSelectedColorType for this view. - */ - public void setItemSelectedColorType(int itemSelectedColorType) { - this.mItemSelectedColorType = itemSelectedColorType; + @Override + public void setStateNormalColorType(@Theme.ColorType int stateNormalColorType) { + this.mStateNormalColorType = stateNormalColorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getStateSelectedColorType() { + return mStateSelectedColorType; + } + + @Override + public void setStateSelectedColorType(@Theme.ColorType int stateSelectedColorType) { + this.mStateSelectedColorType = stateSelectedColorType; + + initialize(); + } + + @Override + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); } + @Override + public @ColorInt int getBackgroundColor() { + return mBackgroundColor ; + } + @Override public @ColorInt int getColor() { return mColor; @@ -243,11 +327,10 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(false); - setItemSelectedColor(); } @Override @@ -257,29 +340,36 @@ public void setColor(@ColorInt int color) { @Override public void setScrollBarColor(@ColorInt int scrollBarColor) { - this.mScrollBarColorType = DynamicColorType.CUSTOM; + this.mScrollBarColorType = Theme.ColorType.CUSTOM; this.mScrollBarColor = scrollBarColor; setScrollBarColor(); } - /** - * @return The value of {@link #mItemSelectedColor}. - */ - public @ColorInt int getItemSelectedColor() { - return mItemSelectedColor; + @Override + public @ColorInt int getStateNormalColor() { + return mStateNormalColor; } - /** - * Set the value of {@link #mItemSelectedColor}. - * - * @param itemSelectedColor Text color for this view. - */ - public void setItemSelectedColor(@ColorInt int itemSelectedColor) { - this.mItemSelectedColorType = DynamicColorType.CUSTOM; - this.mItemSelectedColor = itemSelectedColor; + @Override + public void setStateNormalColor(@ColorInt int stateNormalColor) { + this.mStateNormalColorType = Theme.ColorType.CUSTOM; + this.mStateNormalColor = stateNormalColor; + + setStatesColor(); + } - setItemSelectedColor(); + @Override + public @ColorInt int getStateSelectedColor() { + return mStateSelectedColor; + } + + @Override + public void setStateSelectedColor(@ColorInt int stateSelectedColor) { + this.mStateSelectedColorType = Theme.ColorType.CUSTOM; + this.mStateSelectedColor = stateSelectedColor; + + setStatesColor(); } @Override @@ -289,30 +379,45 @@ public void setItemSelectedColor(@ColorInt int itemSelectedColor) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(true); - setItemSelectedColor(); + setStatesColor(); } @Override - public boolean isBackgroundAware() { + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); + } + + @Override + public @Theme.BackgroundAware int getBackgroundAware() { return mBackgroundAware; } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; + } + + @Override + public void setBackgroundColor(@ColorInt int backgroundColor) { + super.setBackgroundColor(backgroundColor); + + this.mBackgroundColorType = Theme.ColorType.CUSTOM; setColor(true); - setItemSelectedColor(); + setStatesColor(); } @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } @@ -323,7 +428,7 @@ public void setColor() { @Override public void setScrollBarColor() { if (mScrollBarColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mScrollBarColor = DynamicColorUtils.getContrastColor( mScrollBarColor, mContrastWithColor); } @@ -345,20 +450,41 @@ public void setColor(boolean setScrollBarColor) { * Set selected item color of this view according to the * supplied values. */ - private void setItemSelectedColor() { - if (mItemSelectedColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - mItemSelectedColor = DynamicColorUtils.getContrastColor( - mItemSelectedColor, mContrastWithColor); + public void setStatesColor() { + if (mStateSelectedColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + mStateNormalColor = DynamicColorUtils.getContrastColor( + mStateNormalColor, mContrastWithColor); + mStateSelectedColor = DynamicColorUtils.getContrastColor( + mStateSelectedColor, mContrastWithColor); + } + + if (DynamicVersionUtils.isLollipop()) { + if (DynamicTheme.getInstance().get().getCornerSizeDp() + >= WidgetDefaults.ADS_CORNER_SELECTOR_ROUND) { + setItemBackgroundResource(R.drawable.ads_list_selector_round); + } else if (DynamicTheme.getInstance().get().getCornerSizeDp() + >= WidgetDefaults.ADS_CORNER_SELECTOR_RECT) { + setItemBackgroundResource(R.drawable.ads_list_selector_rect); + } else { + setItemBackgroundResource(R.drawable.ads_list_selector); + } + + DynamicDrawableUtils.colorizeDrawable(getItemBackground(), + DynamicColorUtils.getLighterColor(DynamicColorUtils.adjustAlpha( + mStateSelectedColor, WidgetDefaults.ADS_ALPHA_SELECTED), + WidgetDefaults.ADS_STATE_LIGHT)); } - setItemIconTintList(DynamicResourceUtils.convertColorStateListWithNormal( - getItemIconTintList(), - DynamicTheme.getInstance().getTintLocalBackgroundColor(), - mItemSelectedColor)); + if (getItemIconTintList() != null) { + setItemIconTintList(DynamicResourceUtils.convertColorStateListWithNormal( + getItemIconTintList(), mStateNormalColor, mStateSelectedColor)); + } - setItemTextColor(DynamicResourceUtils.convertColorStateList( - getItemTextColor(), mItemSelectedColor)); + if (getItemTextColor() != null) { + setItemTextColor(DynamicResourceUtils.convertColorStateListWithNormal( + getItemTextColor(), mStateNormalColor, mStateSelectedColor)); + } } } } \ No newline at end of file diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicNestedGridView.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicNestedGridView.java index c0ecf116da..c6ce5a353a 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicNestedGridView.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicNestedGridView.java @@ -1,18 +1,18 @@ package com.pranavpandey.android.dynamic.support.widget; import android.content.Context; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + /** - * A DynamicGridView which fully expands vertically according - * to its content height which is suitable to show it as a nested - * view. + * A DynamicGridView which fully expands vertically according to its content height which + * is suitable to show it as a nested view. */ public class DynamicNestedGridView extends DynamicGridView { - public DynamicNestedGridView(@NonNull Context context) { super(context); } @@ -22,7 +22,7 @@ public DynamicNestedGridView(@NonNull Context context, @Nullable AttributeSet at } public DynamicNestedGridView(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicNestedListView.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicNestedListView.java index 6bb768a4a1..ef836bdc8f 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicNestedListView.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicNestedListView.java @@ -1,18 +1,18 @@ package com.pranavpandey.android.dynamic.support.widget; import android.content.Context; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + /** - * A DynamicListView which fully expands vertically according - * to its content height which is suitable to show it as a nested - * view. + * A DynamicListView which fully expands vertically according to its content height which + * is suitable to show it as a nested view. */ public class DynamicNestedListView extends DynamicListView { - public DynamicNestedListView(@NonNull Context context) { super(context); } @@ -22,7 +22,7 @@ public DynamicNestedListView(@NonNull Context context, @Nullable AttributeSet at } public DynamicNestedListView(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicNestedScrollView.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicNestedScrollView.java index fc67d09561..adbf72d5a5 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicNestedScrollView.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicNestedScrollView.java @@ -18,45 +18,38 @@ import android.content.Context; import android.content.res.TypedArray; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.NestedScrollView; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.widget.NestedScrollView; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicScrollUtils; import com.pranavpandey.android.dynamic.support.widget.base.DynamicScrollableWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; /** - * A NestedScrollView to apply color filter according to the - * supplied parameters. + * A NestedScrollView to apply color filter according to the supplied parameters. */ -public class DynamicNestedScrollView extends NestedScrollView - implements DynamicScrollableWidget { +public class DynamicNestedScrollView extends NestedScrollView implements DynamicScrollableWidget { /** * Color type applied to this view. * - * @see DynamicColorType - */ - private @DynamicColorType int mColorType; - - /** - * Scroll bar color type applied to this view. - * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mScrollBarColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -64,29 +57,36 @@ public class DynamicNestedScrollView extends NestedScrollView private @ColorInt int mColor; /** - * Scroll bar color applied to this view. - */ - private @ColorInt int mScrollBarColor; - - /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; + + /** + * Scroll bar color type applied to this view. + * + * @see Theme.ColorType + */ + private @Theme.ColorType int mScrollBarColorType; + + /** + * Scroll bar color applied to this view. + */ + private @ColorInt int mScrollBarColor; public DynamicNestedScrollView(@NonNull Context context) { this(context, null); @@ -99,7 +99,7 @@ public DynamicNestedScrollView(@NonNull Context context, @Nullable AttributeSet } public DynamicNestedScrollView(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -111,22 +111,27 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, WidgetDefaults.ADS_COLOR_EDGE_EFFECT); - mScrollBarColorType = a.getInt(R.styleable.DynamicTheme_ads_scrollBarColorType, + mScrollBarColorType = a.getInt( + R.styleable.DynamicTheme_ads_scrollBarColorType, WidgetDefaults.ADS_COLOR_SCROLL_BAR); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mScrollBarColor = a.getColor(R.styleable.DynamicTheme_ads_scrollBarColor, + mScrollBarColor = a.getColor( + R.styleable.DynamicTheme_ads_scrollBarColor, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -136,57 +141,57 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mScrollBarColorType != DynamicColorType.NONE - && mScrollBarColorType != DynamicColorType.CUSTOM) { + if (mScrollBarColorType != Theme.ColorType.NONE + && mScrollBarColorType != Theme.ColorType.CUSTOM) { mScrollBarColor = DynamicTheme.getInstance() - .getColorFromType(mScrollBarColorType); + .resolveColorType(mScrollBarColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } setColor(true); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getScrollBarColorType() { + public @Theme.ColorType int getScrollBarColorType() { return mScrollBarColorType; } @Override - public void setScrollBarColorType(@DynamicColorType int scrollBarColorType) { + public void setScrollBarColorType(@Theme.ColorType int scrollBarColorType) { this.mScrollBarColorType = scrollBarColorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -199,7 +204,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(true); @@ -212,7 +217,7 @@ public void setColor(@ColorInt int color) { @Override public void setScrollBarColor(@ColorInt int scrollBarColor) { - this.mScrollBarColorType = DynamicColorType.CUSTOM; + this.mScrollBarColorType = Theme.ColorType.CUSTOM; this.mScrollBarColor = scrollBarColor; setScrollBarColor(); @@ -225,22 +230,28 @@ public void setScrollBarColor(@ColorInt int scrollBarColor) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(true); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(true); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override @@ -253,7 +264,7 @@ protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolea @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } @@ -265,7 +276,7 @@ public void setColor() { @Override public void setScrollBarColor() { if (mScrollBarColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mScrollBarColor = DynamicColorUtils.getContrastColor( mScrollBarColor, mContrastWithColor); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicPageIndicator.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicPageIndicator.java index 7f6576d61b..6f87824105 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicPageIndicator.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicPageIndicator.java @@ -28,14 +28,15 @@ import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; -import android.support.v4.view.ViewCompat; -import android.support.v4.view.ViewPager; -import android.support.v4.view.animation.FastOutSlowInInterpolator; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.animation.Interpolator; +import androidx.core.view.ViewCompat; +import androidx.interpolator.view.animation.FastOutSlowInInterpolator; +import androidx.viewpager.widget.ViewPager; + import com.pranavpandey.android.dynamic.support.R; import java.util.Arrays; diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicPopupBackground.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicPopupBackground.java new file mode 100644 index 0000000000..9b66c48b23 --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicPopupBackground.java @@ -0,0 +1,51 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.widget; + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.annotation.AttrRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +/** + * A DynamicCardView for the popup background. + */ +public class DynamicPopupBackground extends DynamicCardView { + + public DynamicPopupBackground(@NonNull Context context) { + super(context); + } + + public DynamicPopupBackground(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public DynamicPopupBackground(@NonNull Context context, + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + public void initialize() { + super.initialize(); + + setClipToPadding(false); + setCardElevation(0); + } +} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicProgressBar.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicProgressBar.java index a08e81b763..eece29faa5 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicProgressBar.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicProgressBar.java @@ -20,15 +20,16 @@ import android.content.Context; import android.content.res.TypedArray; import android.os.Build; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.ContentLoadingProgressBar; import android.util.AttributeSet; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.widget.ContentLoadingProgressBar; + import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; @@ -36,23 +37,22 @@ import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils; /** - * A ContentLoadingProgressBar to apply color filter according to the - * supplied parameters. + * A ContentLoadingProgressBar to apply color filter according to the supplied parameters. */ public class DynamicProgressBar extends ContentLoadingProgressBar implements DynamicWidget { /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -60,24 +60,24 @@ public class DynamicProgressBar extends ContentLoadingProgressBar implements Dyn private @ColorInt int mColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; public DynamicProgressBar(@NonNull Context context) { this(context, null); @@ -95,18 +95,21 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.ACCENT); + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, + Theme.ColorType.ACCENT); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -116,39 +119,39 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } setColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -156,7 +159,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public @ColorInt int getColor() { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; return mColor; } @@ -174,22 +177,28 @@ public void setColor(@ColorInt int color) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override @@ -203,7 +212,7 @@ public void setEnabled(boolean enabled) { @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicRadioButton.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicRadioButton.java index b4033c1ce4..96eea774ed 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicRadioButton.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicRadioButton.java @@ -21,39 +21,39 @@ import android.content.Context; import android.content.res.TypedArray; import android.os.Build; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.AppCompatRadioButton; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.google.android.material.radiobutton.MaterialRadioButton; import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; +import com.pranavpandey.android.dynamic.support.utils.DynamicTintUtils; import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; -import com.pranavpandey.android.dynamic.utils.DynamicDrawableUtils; -import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils; /** - * A RadioButton to apply color filter according to the supplied - * parameters. + * A RadioButton to apply color filter according to the supplied parameters. */ -public class DynamicRadioButton extends AppCompatRadioButton implements DynamicWidget { +public class DynamicRadioButton extends MaterialRadioButton implements DynamicWidget { /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -61,24 +61,24 @@ public class DynamicRadioButton extends AppCompatRadioButton implements DynamicW private @ColorInt int mColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; public DynamicRadioButton(@NonNull Context context) { this(context, null); @@ -91,7 +91,7 @@ public DynamicRadioButton(@NonNull Context context, @Nullable AttributeSet attrs } public DynamicRadioButton(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -103,18 +103,21 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.ACCENT); + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, + Theme.ColorType.ACCENT); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -124,39 +127,39 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } setColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -169,7 +172,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -182,22 +185,28 @@ public void setColor(@ColorInt int color) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override @@ -207,22 +216,26 @@ public void setEnabled(boolean enabled) { setAlpha(enabled ? WidgetDefaults.ADS_ALPHA_ENABLED : WidgetDefaults.ADS_ALPHA_DISABLED); } - @SuppressLint("PrivateResource") + @SuppressLint({"RestrictedApi"}) @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); - } + @ColorInt int tintColor = DynamicTheme.getInstance().get().getTintBackgroundColor(); + + if (isBackgroundAware()) { + tintColor = DynamicColorUtils.getContrastColor( + tintColor, DynamicTheme.getInstance().get().getBackgroundColor()); - if (DynamicVersionUtils.isLollipop()) { - setButtonTintList(DynamicResourceUtils.getColorStateList(mColor)); - } else { - setButtonDrawable(DynamicDrawableUtils.colorizeDrawable( - DynamicResourceUtils.getDrawable(getContext(), - R.drawable.abc_btn_radio_material), mColor)); + if (mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); + } } + + DynamicTintUtils.setViewBackgroundTint(this, + mContrastWithColor, mColor, true, true); + setSupportButtonTintList(DynamicResourceUtils.getColorStateList( + tintColor, mColor, true)); } } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicRecyclerView.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicRecyclerView.java index d818b09185..8138197640 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicRecyclerView.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicRecyclerView.java @@ -18,44 +18,38 @@ import android.content.Context; import android.content.res.TypedArray; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.RecyclerView; + import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicScrollUtils; import com.pranavpandey.android.dynamic.support.widget.base.DynamicScrollableWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; /** - * A RecyclerView to apply color filter according to the - * supplied parameters. + * A RecyclerView to apply color filter according to the supplied parameters. */ public class DynamicRecyclerView extends RecyclerView implements DynamicScrollableWidget { /** * Color type applied to this view. * - * @see DynamicColorType - */ - private @DynamicColorType int mColorType; - - /** - * Scroll bar color type applied to this view. - * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mScrollBarColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -63,29 +57,36 @@ public class DynamicRecyclerView extends RecyclerView implements DynamicScrollab private @ColorInt int mColor; /** - * Scroll bar color applied to this view. - */ - private @ColorInt int mScrollBarColor; - - /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; + + /** + * Scroll bar color type applied to this view. + * + * @see Theme.ColorType + */ + private @Theme.ColorType int mScrollBarColorType; + + /** + * Scroll bar color applied to this view. + */ + private @ColorInt int mScrollBarColor; public DynamicRecyclerView(@NonNull Context context) { this(context, null); @@ -98,7 +99,7 @@ public DynamicRecyclerView(@NonNull Context context, @Nullable AttributeSet attr } public DynamicRecyclerView(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -110,22 +111,27 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, WidgetDefaults.ADS_COLOR_EDGE_EFFECT); - mScrollBarColorType = a.getInt(R.styleable.DynamicTheme_ads_scrollBarColorType, + mScrollBarColorType = a.getInt( + R.styleable.DynamicTheme_ads_scrollBarColorType, WidgetDefaults.ADS_COLOR_SCROLL_BAR); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mScrollBarColor = a.getColor(R.styleable.DynamicTheme_ads_scrollBarColor, + mScrollBarColor = a.getColor( + R.styleable.DynamicTheme_ads_scrollBarColor, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -135,57 +141,57 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mScrollBarColorType != DynamicColorType.NONE - && mScrollBarColorType != DynamicColorType.CUSTOM) { + if (mScrollBarColorType != Theme.ColorType.NONE + && mScrollBarColorType != Theme.ColorType.CUSTOM) { mScrollBarColor = DynamicTheme.getInstance() - .getColorFromType(mScrollBarColorType); + .resolveColorType(mScrollBarColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } setColor(true); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getScrollBarColorType() { + public @Theme.ColorType int getScrollBarColorType() { return mScrollBarColorType; } @Override - public void setScrollBarColorType(@DynamicColorType int scrollBarColorType) { + public void setScrollBarColorType(@Theme.ColorType int scrollBarColorType) { this.mScrollBarColorType = scrollBarColorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -198,7 +204,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(false); @@ -211,7 +217,7 @@ public void setColor(@ColorInt int color) { @Override public void setScrollBarColor(@ColorInt int scrollBarColor) { - this.mScrollBarColorType = DynamicColorType.CUSTOM; + this.mScrollBarColorType = Theme.ColorType.CUSTOM; this.mScrollBarColor = scrollBarColor; setScrollBarColor(); @@ -224,22 +230,28 @@ public void setScrollBarColor(@ColorInt int scrollBarColor) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(true); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(true); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override @@ -252,7 +264,7 @@ public void onScrollStateChanged(int state) { @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } @@ -263,7 +275,7 @@ public void setColor() { @Override public void setScrollBarColor() { if (mScrollBarColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mScrollBarColor = DynamicColorUtils.getContrastColor( mScrollBarColor, mContrastWithColor); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicScrollView.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicScrollView.java index cb312633a3..30a88f532a 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicScrollView.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicScrollView.java @@ -18,44 +18,38 @@ import android.content.Context; import android.content.res.TypedArray; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.AttributeSet; import android.widget.ScrollView; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicScrollUtils; import com.pranavpandey.android.dynamic.support.widget.base.DynamicScrollableWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; /** - * A ScrollView to apply color filter according to the supplied - * parameters. + * A ScrollView to apply color filter according to the supplied parameters. */ public class DynamicScrollView extends ScrollView implements DynamicScrollableWidget { /** * Color type applied to this view. * - * @see DynamicColorType - */ - private @DynamicColorType int mColorType; - - /** - * Scroll bar color type applied to this view. - * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mScrollBarColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -63,29 +57,36 @@ public class DynamicScrollView extends ScrollView implements DynamicScrollableWi private @ColorInt int mColor; /** - * Scroll bar color applied to this view. - */ - private @ColorInt int mScrollBarColor; - - /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; + + /** + * Scroll bar color type applied to this view. + * + * @see Theme.ColorType + */ + private @Theme.ColorType int mScrollBarColorType; + + /** + * Scroll bar color applied to this view. + */ + private @ColorInt int mScrollBarColor; public DynamicScrollView(@NonNull Context context) { this(context, null); @@ -98,7 +99,7 @@ public DynamicScrollView(@NonNull Context context, @Nullable AttributeSet attrs) } public DynamicScrollView(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -110,22 +111,27 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, WidgetDefaults.ADS_COLOR_EDGE_EFFECT); - mScrollBarColorType = a.getInt(R.styleable.DynamicTheme_ads_scrollBarColorType, + mScrollBarColorType = a.getInt( + R.styleable.DynamicTheme_ads_scrollBarColorType, WidgetDefaults.ADS_COLOR_SCROLL_BAR); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mScrollBarColor = a.getColor(R.styleable.DynamicTheme_ads_scrollBarColor, + mScrollBarColor = a.getColor( + R.styleable.DynamicTheme_ads_scrollBarColor, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -135,57 +141,57 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mScrollBarColorType != DynamicColorType.NONE - && mScrollBarColorType != DynamicColorType.CUSTOM) { + if (mScrollBarColorType != Theme.ColorType.NONE + && mScrollBarColorType != Theme.ColorType.CUSTOM) { mScrollBarColor = DynamicTheme.getInstance() - .getColorFromType(mScrollBarColorType); + .resolveColorType(mScrollBarColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } setColor(true); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getScrollBarColorType() { + public @Theme.ColorType int getScrollBarColorType() { return mScrollBarColorType; } @Override - public void setScrollBarColorType(@DynamicColorType int scrollBarColorType) { + public void setScrollBarColorType(@Theme.ColorType int scrollBarColorType) { this.mScrollBarColorType = scrollBarColorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -198,7 +204,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(true); @@ -211,7 +217,7 @@ public void setColor(@ColorInt int color) { @Override public void setScrollBarColor(@ColorInt int scrollBarColor) { - this.mScrollBarColorType = DynamicColorType.CUSTOM; + this.mScrollBarColorType = Theme.ColorType.CUSTOM; this.mScrollBarColor = scrollBarColor; setScrollBarColor(); @@ -224,22 +230,28 @@ public void setScrollBarColor(@ColorInt int scrollBarColor) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(true); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(true); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override @@ -252,7 +264,7 @@ protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolea @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } @@ -263,7 +275,7 @@ public void setColor() { @Override public void setScrollBarColor() { if (mScrollBarColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mScrollBarColor = DynamicColorUtils.getContrastColor( mScrollBarColor, mContrastWithColor); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicSeekBar.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicSeekBar.java index 590e3c83b1..5506d665a2 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicSeekBar.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicSeekBar.java @@ -20,15 +20,17 @@ import android.content.Context; import android.content.res.TypedArray; import android.os.Build; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.AppCompatSeekBar; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatSeekBar; + import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; import com.pranavpandey.android.dynamic.support.widget.base.DynamicProgressWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; @@ -36,8 +38,7 @@ import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils; /** - * A SeekBar to change its color according to the supplied - * parameters. + * A SeekBar to change its color according to the supplied parameters. */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) public class DynamicSeekBar extends AppCompatSeekBar implements DynamicProgressWidget { @@ -45,15 +46,15 @@ public class DynamicSeekBar extends AppCompatSeekBar implements DynamicProgressW /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -61,24 +62,24 @@ public class DynamicSeekBar extends AppCompatSeekBar implements DynamicProgressW private @ColorInt int mColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; public DynamicSeekBar(@NonNull Context context) { this(context, null); @@ -91,7 +92,7 @@ public DynamicSeekBar(@NonNull Context context, @Nullable AttributeSet attrs) { } public DynamicSeekBar(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -103,18 +104,21 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.ACCENT); + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, + Theme.ColorType.ACCENT); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -124,39 +128,39 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } setColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -169,7 +173,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -182,22 +186,28 @@ public void setColor(@ColorInt int color) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override @@ -210,7 +220,7 @@ public void setEnabled(boolean enabled) { @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicSpinner.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicSpinner.java index 9fce153c1a..5495a8e0c4 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicSpinner.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicSpinner.java @@ -19,38 +19,39 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.PorterDuff; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.AppCompatSpinner; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatSpinner; + import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; import com.pranavpandey.android.dynamic.utils.DynamicDrawableUtils; import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils; /** - * An AppCompatSpinner to change its color according to the - * supplied parameters. + * A Spinner to change its color according to the supplied parameters. */ public class DynamicSpinner extends AppCompatSpinner implements DynamicWidget { /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -58,24 +59,24 @@ public class DynamicSpinner extends AppCompatSpinner implements DynamicWidget { private @ColorInt int mColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; public DynamicSpinner(@NonNull Context context) { this(context, null); @@ -88,7 +89,7 @@ public DynamicSpinner(@NonNull Context context, @Nullable AttributeSet attrs) { } public DynamicSpinner(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -100,18 +101,21 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.ACCENT); + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, + Theme.ColorType.ACCENT); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -121,39 +125,39 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } setColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -166,7 +170,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -179,22 +183,28 @@ public void setColor(@ColorInt int color) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override @@ -207,18 +217,18 @@ public void setEnabled(boolean enabled) { @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } DynamicDrawableUtils.colorizeDrawable(getBackground(), mColor); - + if (DynamicVersionUtils.isLollipop()) { DynamicDrawableUtils.colorizeDrawable(getPopupBackground(), - DynamicTheme.getInstance().getBackgroundColor()); + DynamicTheme.getInstance().get().getBackgroundColor()); } else { DynamicDrawableUtils.colorizeDrawable(getPopupBackground(), - DynamicTheme.getInstance().getBackgroundColor(), + DynamicTheme.getInstance().get().getBackgroundColor(), PorterDuff.Mode.MULTIPLY); } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicSwipeRefreshLayout.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicSwipeRefreshLayout.java index a770cfde84..eb0120610b 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicSwipeRefreshLayout.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicSwipeRefreshLayout.java @@ -19,36 +19,36 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.Color; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; import android.util.AttributeSet; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; /** - * A SwipeRefreshLayout to apply color filter according to the - * supplied parameters. + * A SwipeRefreshLayout to apply color filter according to the supplied parameters. */ public class DynamicSwipeRefreshLayout extends SwipeRefreshLayout implements DynamicWidget { /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -56,24 +56,24 @@ public class DynamicSwipeRefreshLayout extends SwipeRefreshLayout implements Dyn private @ColorInt int mColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; public DynamicSwipeRefreshLayout(@NonNull Context context) { this(context, null); @@ -91,18 +91,21 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.PRIMARY); + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, + Theme.ColorType.PRIMARY); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -112,39 +115,39 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } setColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -157,7 +160,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -170,29 +173,35 @@ public void setColor(@ColorInt int color) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { @ColorInt int accentColor = DynamicColorUtils.getAccentColor(mColor); - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); accentColor = DynamicColorUtils.getContrastColor(accentColor, mContrastWithColor); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicSwitchCompat.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicSwitchCompat.java index 07f6fe98fa..7812e3cd6a 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicSwitchCompat.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicSwitchCompat.java @@ -18,42 +18,38 @@ import android.content.Context; import android.content.res.TypedArray; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.SwitchCompat; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.google.android.material.switchmaterial.SwitchMaterial; import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; import com.pranavpandey.android.dynamic.support.widget.base.DynamicStateWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; /** - * A SwitchCompat to change its color according to the supplied - * parameters. + * A Switch to change its color according to the supplied parameters. */ -public class DynamicSwitchCompat extends SwitchCompat implements DynamicStateWidget { +public class DynamicSwitchCompat extends SwitchMaterial implements DynamicStateWidget { /** * Color type applied to this view. * - * @see DynamicColorType - */ - private @DynamicColorType int mColorType; - - /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * @see Theme.ColorType */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mColorType; /** - * Normal state color type for this view. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mStateNormalColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -61,29 +57,34 @@ public class DynamicSwitchCompat extends SwitchCompat implements DynamicStateWid private @ColorInt int mColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * Normal state color applied to this view. - */ - private @ColorInt int mStateNormalColor; - - /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; + + /** + * Normal state color type for this view. + */ + private @Theme.ColorType int mStateNormalColorType; + + /** + * Normal state color applied to this view. + */ + private @ColorInt int mStateNormalColor; public DynamicSwitchCompat(@NonNull Context context) { this(context, null); @@ -96,7 +97,7 @@ public DynamicSwitchCompat(@NonNull Context context, @Nullable AttributeSet attr } public DynamicSwitchCompat(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -108,23 +109,27 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.ACCENT); + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, + Theme.ColorType.ACCENT); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); + Theme.ColorType.BACKGROUND); mStateNormalColorType = a.getInt( R.styleable.DynamicTheme_ads_stateNormalColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mStateNormalColor = a.getColor(R.styleable.DynamicTheme_ads_stateNormalColor, + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mStateNormalColor = a.getColor( + R.styleable.DynamicTheme_ads_stateNormalColor, WidgetDefaults.ADS_COLOR_UNKNOWN); - mBackgroundAware = a.getBoolean( + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -134,28 +139,28 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } - if (mStateNormalColorType != DynamicColorType.NONE - && mStateNormalColorType != DynamicColorType.CUSTOM) { + if (mStateNormalColorType != Theme.ColorType.NONE + && mStateNormalColorType != Theme.ColorType.CUSTOM) { mStateNormalColor = DynamicTheme.getInstance() - .getColorFromType(mStateNormalColorType); + .resolveColorType(mStateNormalColorType); } setColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @@ -164,31 +169,31 @@ public void initialize() { * * @param colorType for this view. */ - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); } @Override - public @DynamicColorType int getStateNormalColorType() { + public @Theme.ColorType int getStateNormalColorType() { return mStateNormalColorType; } @Override - public void setStateNormalColorType(@DynamicColorType int stateNormalColorType) { + public void setStateNormalColorType(@Theme.ColorType int stateNormalColorType) { this.mStateNormalColorType = stateNormalColorType; initialize(); @@ -201,7 +206,7 @@ public void setStateNormalColorType(@DynamicColorType int stateNormalColorType) @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -214,7 +219,7 @@ public void setColor(@ColorInt int color) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); @@ -227,22 +232,28 @@ public void setContrastWithColor(@ColorInt int contrastWithColor) { @Override public void setStateNormalColor(@ColorInt int stateNormalColor) { - this.mStateNormalColorType = DynamicColorType.CUSTOM; + this.mStateNormalColorType = Theme.ColorType.CUSTOM; this.mStateNormalColor = stateNormalColor; setColor(); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override @@ -255,25 +266,21 @@ public void setEnabled(boolean enabled) { @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } - @ColorInt int colorOff = DynamicColorUtils.getDarkerColor( - mStateNormalColor, WidgetDefaults.ADS_STATE_DARK); - @ColorInt int colorOffTint = DynamicColorUtils.getDarkerColor( - colorOff, WidgetDefaults.ADS_STATE_DARK); - - if (DynamicColorUtils.isColorDark(mStateNormalColor)) { - colorOff = DynamicColorUtils.getLighterColor( - mStateNormalColor, WidgetDefaults.ADS_STATE_LIGHT); - colorOffTint = DynamicColorUtils.getLighterColor( - colorOff, WidgetDefaults.ADS_STATE_LIGHT); - } + @ColorInt int colorOff = DynamicColorUtils.getStateColor( + mStateNormalColor, WidgetDefaults.ADS_STATE_LIGHT, + WidgetDefaults.ADS_STATE_DARK); + @ColorInt int colorOffTint = DynamicColorUtils.getStateColor( + colorOff, WidgetDefaults.ADS_STATE_LIGHT, + WidgetDefaults.ADS_STATE_DARK); - setThumbTintList(DynamicResourceUtils.getColorStateList(colorOffTint, mColor)); + setThumbTintList(DynamicResourceUtils.getColorStateList( + colorOffTint, mColor, true)); setTrackTintList(DynamicResourceUtils.getColorStateList(colorOff, - DynamicColorUtils.getLighterColor(mColor, 0.3f))); + DynamicColorUtils.getLighterColor(mColor, 0.3f), true)); } } } \ No newline at end of file diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicTabLayout.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicTabLayout.java index 8347b5334b..bec367e282 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicTabLayout.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicTabLayout.java @@ -18,43 +18,41 @@ import android.content.Context; import android.content.res.TypedArray; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.TabLayout; +import android.graphics.Color; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.google.android.material.tabs.TabLayout; import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; +import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; +import com.pranavpandey.android.dynamic.support.widget.base.DynamicBackgroundWidget; import com.pranavpandey.android.dynamic.support.widget.base.DynamicTextWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; /** - * A TabLayout to change its indicator and text color - * according to the supplied parameters. + * A TabLayout to change its indicator and text color according to the supplied parameters. */ -public class DynamicTabLayout extends TabLayout implements DynamicTextWidget { +public class DynamicTabLayout extends TabLayout implements + DynamicBackgroundWidget, DynamicTextWidget { /** * Color type applied to this view. * - * @see DynamicColorType - */ - private @DynamicColorType int mColorType; - - /** - * Text color type applied to this view. - * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mTextColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -62,29 +60,48 @@ public class DynamicTabLayout extends TabLayout implements DynamicTextWidget { private @ColorInt int mColor; /** - * Text color applied to this view. + * Background color for this view so that it will remain in contrast with this color. */ - private @ColorInt int mTextColor; + private @ColorInt int mContrastWithColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. + * + *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. + * + * @see Theme.BackgroundAware + * @see #mContrastWithColor */ - private @ColorInt int mContrastWithColor; + private @Theme.BackgroundAware int mBackgroundAware; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * Color type applied to the background of this view. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ * @see Theme.ColorType + */ + private @Theme.ColorType int mBackgroundColorType; + + /** + * Text color type applied to this view. * - * @see #mContrastWithColor + * @see Theme.ColorType + */ + private @Theme.ColorType int mTextColorType; + + /** + * Background color applied to this view. */ - private boolean mBackgroundAware; + private @ColorInt int mBackgroundColor; + + /** + * Text color applied to this view. + */ + private @ColorInt int mTextColor; public DynamicTabLayout(@NonNull Context context) { this(context, null); @@ -97,7 +114,7 @@ public DynamicTabLayout(@NonNull Context context, @Nullable AttributeSet attrs) } public DynamicTabLayout(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -109,22 +126,33 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.ACCENT); - mTextColorType = a.getInt(R.styleable.DynamicTheme_ads_textColorType, - DynamicColorType.TINT_PRIMARY); + mBackgroundColorType = a.getInt( + R.styleable.DynamicTheme_ads_backgroundColorType, + Theme.ColorType.PRIMARY); + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, + Theme.ColorType.ACCENT); + mTextColorType = a.getInt( + R.styleable.DynamicTheme_ads_textColorType, + Theme.ColorType.TINT_PRIMARY); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.PRIMARY); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.PRIMARY); + mBackgroundColor = a.getColor( + R.styleable.DynamicTheme_ads_backgroundColor, WidgetDefaults.ADS_COLOR_UNKNOWN); - mTextColor = a.getColor(R.styleable.DynamicTheme_ads_textColor, + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, + mTextColor = a.getColor( + R.styleable.DynamicTheme_ads_textColor, WidgetDefaults.ADS_COLOR_UNKNOWN); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.ADS_COLOR_UNKNOWN); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -134,62 +162,86 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mBackgroundColorType != Theme.ColorType.NONE + && mBackgroundColorType != Theme.ColorType.CUSTOM) { + mBackgroundColor = DynamicTheme.getInstance() + .resolveColorType(mBackgroundColorType); } - if (mTextColorType != DynamicColorType.NONE - && mTextColorType != DynamicColorType.CUSTOM) { - mTextColor = DynamicTheme.getInstance().getColorFromType(mTextColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mTextColorType != Theme.ColorType.NONE + && mTextColorType != Theme.ColorType.CUSTOM) { + mTextColor = DynamicTheme.getInstance().resolveColorType(mTextColorType); + } + + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } + setBackgroundColor(mBackgroundColor); setColor(); setTextColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getBackgroundColorType() { + return mBackgroundColorType; + } + + @Override + public void setBackgroundColorType(@Theme.ColorType int backgroundColorType) { + this.mBackgroundColorType = backgroundColorType; + + initialize(); + } + + @Override + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getTextColorType() { + public @Theme.ColorType int getTextColorType() { return mTextColorType; } @Override - public void setTextColorType(@DynamicColorType int textColorType) { + public void setTextColorType(@Theme.ColorType int textColorType) { this.mTextColorType = textColorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); } + @Override + public @ColorInt int getBackgroundColor() { + return mBackgroundColor ; + } + @Override public @ColorInt int getColor() { return mColor; @@ -197,7 +249,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -211,7 +263,7 @@ public void setColor(@ColorInt int color) { @Override public void setTextColor(@ColorInt int textColor) { - this.mTextColorType = DynamicColorType.CUSTOM; + this.mTextColorType = Theme.ColorType.CUSTOM; this.mTextColor = textColor; setColor(); @@ -225,7 +277,7 @@ public void setTextColor(@ColorInt int textColor) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); @@ -233,16 +285,21 @@ public void setContrastWithColor(@ColorInt int contrastWithColor) { } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(); - setTextColor(); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override @@ -252,13 +309,30 @@ public void setEnabled(boolean enabled) { setAlpha(enabled ? WidgetDefaults.ADS_ALPHA_ENABLED : WidgetDefaults.ADS_ALPHA_DISABLED); } + @Override + public void setBackgroundColor(@ColorInt int backgroundColor) { + super.setBackgroundColor(backgroundColor); + + this.mBackgroundColorType = Theme.ColorType.CUSTOM; + + setColor(); + setTextColor(); + } + @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } + if (DynamicTheme.getInstance().get().getCornerSizeDp() + >= WidgetDefaults.ADS_CORNER_MIN_TABS) { + setSelectedTabIndicator(R.drawable.ads_tabs_indicator_corner); + } else { + setSelectedTabIndicator(R.drawable.ads_tabs_indicator); + } + setSelectedTabIndicatorColor(mColor); } } @@ -266,12 +340,15 @@ public void setColor() { @Override public void setTextColor() { if (mTextColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mTextColor = DynamicColorUtils.getContrastColor(mTextColor, mContrastWithColor); } setTabTextColors(DynamicColorUtils.adjustAlpha(mTextColor, WidgetDefaults.ADS_ALPHA_UNCHECKED), mTextColor); + setTabRippleColor(DynamicResourceUtils.getColorStateList( + Color.TRANSPARENT, DynamicColorUtils.adjustAlpha( + mTextColor, WidgetDefaults.ADS_ALPHA_PRESSED), false)); } } } \ No newline at end of file diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicTextInputEditText.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicTextInputEditText.java index 8a4c219dbc..b83cfdfd08 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicTextInputEditText.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicTextInputEditText.java @@ -19,38 +19,39 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.Rect; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.TextInputEditText; -import android.support.v4.view.ViewCompat; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.view.ViewCompat; + +import com.google.android.material.textfield.TextInputEditText; import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicInputUtils; import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; /** - * A TextInputEditText to change its color according to the - * supplied parameters. + * A TextInputEditText to change its color according to the supplied parameters. */ public class DynamicTextInputEditText extends TextInputEditText implements DynamicWidget { /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -58,24 +59,24 @@ public class DynamicTextInputEditText extends TextInputEditText implements Dynam private @ColorInt int mColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; public DynamicTextInputEditText(@NonNull Context context) { this(context, null); @@ -88,7 +89,7 @@ public DynamicTextInputEditText(@NonNull Context context, @Nullable AttributeSet } public DynamicTextInputEditText(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -100,18 +101,30 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.ACCENT); + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, + Theme.ColorType.ACCENT); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); + + if (mColorType == Theme.ColorType.ACCENT) { + setTextColor(DynamicColorUtils.getContrastColor( + DynamicTheme.getInstance().get().getTextPrimaryColor(), + DynamicTheme.getInstance().get().getBackgroundColor())); + setHintTextColor(DynamicColorUtils.getContrastColor( + DynamicTheme.getInstance().get().getTextSecondaryColor(), + DynamicTheme.getInstance().get().getBackgroundColor())); + } } finally { a.recycle(); } @@ -121,39 +134,39 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } setColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -166,7 +179,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -179,22 +192,28 @@ public void setColor(@ColorInt int color) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override @@ -217,7 +236,7 @@ protected void onFocusChanged(boolean gainFocus, @ViewCompat.FocusDirection int @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicTextInputLayout.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicTextInputLayout.java index 721c7ce17b..842f7cfe0c 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicTextInputLayout.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicTextInputLayout.java @@ -18,37 +18,42 @@ import android.content.Context; import android.content.res.TypedArray; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.TextInputLayout; +import android.graphics.Color; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.google.android.material.textfield.TextInputLayout; import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicInputUtils; +import com.pranavpandey.android.dynamic.support.widget.base.DynamicCornerWidget; import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; +import com.pranavpandey.android.dynamic.utils.DynamicUnitUtils; /** - * A TextInputLayout to change its color according to the - * supplied parameters. + * A TextInputLayout to change its color according to the supplied parameters. */ -public class DynamicTextInputLayout extends TextInputLayout implements DynamicWidget { +public class DynamicTextInputLayout extends TextInputLayout implements + DynamicWidget, DynamicCornerWidget { /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -56,24 +61,24 @@ public class DynamicTextInputLayout extends TextInputLayout implements DynamicWi private @ColorInt int mColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; public DynamicTextInputLayout(@NonNull Context context) { this(context, null); @@ -86,7 +91,7 @@ public DynamicTextInputLayout(@NonNull Context context, @Nullable AttributeSet a } public DynamicTextInputLayout(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -98,18 +103,21 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.ACCENT); + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, + Theme.ColorType.ACCENT); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -119,39 +127,40 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } + setCorner((float) DynamicTheme.getInstance().get().getCornerRadius()); setColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -164,7 +173,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -177,22 +186,28 @@ public void setColor(@ColorInt int color) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override @@ -202,13 +217,39 @@ public void setEnabled(boolean enabled) { setAlpha(enabled ? WidgetDefaults.ADS_ALPHA_ENABLED : WidgetDefaults.ADS_ALPHA_DISABLED); } + @Override + public void setCorner(Float cornerRadius) { + cornerRadius = Math.min(cornerRadius, + DynamicUnitUtils.convertDpToPixels(WidgetDefaults.ADS_CORNER_MIN_BOX)); + setBoxCornerRadii(getBoxCornerRadiusTopStart() > 0 ? cornerRadius : 0, + getBoxCornerRadiusTopEnd() > 0 ? cornerRadius : 0, + getBoxCornerRadiusBottomStart() > 0 ? cornerRadius : 0, + getBoxCornerRadiusBottomEnd() > 0 ? cornerRadius : 0); + } + + @Override + public Float getCorner() { + return getBoxCornerRadiusTopStart(); + } + @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } + // Remove alpha as box background color does not supports alpha component. + @ColorInt int boxColor = DynamicColorUtils.removeAlpha( + DynamicColorUtils.getStateColor(mContrastWithColor, + WidgetDefaults.ADS_STATE_BOX_LIGHT, WidgetDefaults.ADS_STATE_BOX_DARK)); + + if (getBoxBackgroundColor() != Color.TRANSPARENT) { + setBoxBackgroundColor(boxColor); + } else { + setBoxStrokeColor(boxColor); + } + DynamicInputUtils.setColor(this, mColor); } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicTextView.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicTextView.java index ab08a7b47a..71f869d242 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicTextView.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicTextView.java @@ -18,36 +18,40 @@ import android.content.Context; import android.content.res.TypedArray; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.AppCompatTextView; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatTextView; + import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; +import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; +import com.pranavpandey.android.dynamic.support.widget.base.DynamicLinkWidget; import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; /** - * A TextView to change its color according to the - * supplied parameters. + * A TextView to change its color according to the supplied parameters. */ -public class DynamicTextView extends AppCompatTextView implements DynamicWidget { +public class DynamicTextView extends AppCompatTextView implements + DynamicWidget, DynamicLinkWidget { /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -55,24 +59,41 @@ public class DynamicTextView extends AppCompatTextView implements DynamicWidget private @ColorInt int mColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; + + /** + * Original text color attribute resource. + */ + private @AttrRes int mColorAttrRes; + + /** + * Link color type applied to this view. + * + * @see Theme.ColorType + */ + private @Theme.ColorType int mLinkColorType; + + /** + * Link color applied to this view. + */ + private @ColorInt int mLinkColor; public DynamicTextView(@NonNull Context context) { this(context, null); @@ -85,7 +106,7 @@ public DynamicTextView(@NonNull Context context, @Nullable AttributeSet attrs) { } public DynamicTextView(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -97,18 +118,32 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.NONE); + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, + Theme.ColorType.NONE); + mLinkColorType = a.getInt( + R.styleable.DynamicTheme_ads_linkColorType, + Theme.ColorType.ACCENT); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mLinkColor = a.getColor( + R.styleable.DynamicTheme_ads_linkColor, + WidgetDefaults.ADS_COLOR_UNKNOWN); + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); + + if (attrs != null) { + mColorAttrRes = DynamicResourceUtils.getResourceIdFromAttributes( + getContext(), attrs, android.R.attr.textColor); + } } finally { a.recycle(); } @@ -118,39 +153,91 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType == Theme.ColorType.NONE) { + if (mColorAttrRes == DynamicResourceUtils.getResourceId( + getContext(), android.R.attr.textColorPrimary)) { + mColorType = Theme.ColorType.TEXT_PRIMARY; + } else if (mColorAttrRes == DynamicResourceUtils.getResourceId( + getContext(), android.R.attr.textColorSecondary)) { + mColorType = Theme.ColorType.TEXT_SECONDARY; + } else if (mColorAttrRes == DynamicResourceUtils.getResourceId( + getContext(), android.R.attr.textColorPrimaryInverse)) { + mColorType = Theme.ColorType.TEXT_PRIMARY_INVERSE; + } else if (mColorAttrRes == DynamicResourceUtils.getResourceId( + getContext(), android.R.attr.textColorSecondaryInverse)) { + mColorType = Theme.ColorType.TEXT_SECONDARY_INVERSE; + } else { + mColorType = Theme.ColorType.TEXT_PRIMARY; + } + } + + if (mLinkColorType == Theme.ColorType.NONE) { + if (mColorAttrRes == DynamicResourceUtils.getResourceId( + getContext(), android.R.attr.textColorPrimary)) { + mLinkColorType = Theme.ColorType.TEXT_PRIMARY; + } else if (mColorAttrRes == DynamicResourceUtils.getResourceId( + getContext(), android.R.attr.textColorSecondary)) { + mLinkColorType = Theme.ColorType.TEXT_SECONDARY; + } else if (mColorAttrRes == DynamicResourceUtils.getResourceId( + getContext(), android.R.attr.textColorPrimaryInverse)) { + mLinkColorType = Theme.ColorType.TEXT_PRIMARY_INVERSE; + } else if (mColorAttrRes == DynamicResourceUtils.getResourceId( + getContext(), android.R.attr.textColorSecondaryInverse)) { + mLinkColorType = Theme.ColorType.TEXT_SECONDARY_INVERSE; + } else { + mLinkColorType = Theme.ColorType.TEXT_PRIMARY; + } } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); + } + + if (mLinkColorType != Theme.ColorType.CUSTOM) { + mLinkColor = DynamicTheme.getInstance().resolveColorType(mLinkColorType); + } + + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } setColor(); + setLinkColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getLinkColorType() { + return mLinkColorType; + } + + @Override + public void setLinkColorType(@Theme.ColorType int linkColorType) { + this.mLinkColorType = linkColorType; + + initialize(); + } + + @Override + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -163,12 +250,25 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); } + @Override + public @ColorInt int getLinkColor() { + return mLinkColor; + } + + @Override + public void setLinkColor(@ColorInt int linkColor) { + this.mLinkColorType = Theme.ColorType.CUSTOM; + this.mLinkColor = linkColor; + + setLinkColor(); + } + @Override public @ColorInt int getContrastWithColor() { return mContrastWithColor; @@ -176,30 +276,39 @@ public void setColor(@ColorInt int color) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); + setLinkColor(); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); + setLinkColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override public void setEnabled(boolean enabled) { super.setEnabled(enabled); - if (mColorType != DynamicColorType.NONE) { - setAlpha(enabled ? WidgetDefaults.ADS_ALPHA_ENABLED : WidgetDefaults.ADS_ALPHA_DISABLED); + if (mColorType != Theme.ColorType.NONE) { + setAlpha(enabled ? WidgetDefaults.ADS_ALPHA_ENABLED + : WidgetDefaults.ADS_ALPHA_DISABLED); } else { setAlpha(WidgetDefaults.ADS_ALPHA_ENABLED); } @@ -208,11 +317,22 @@ public void setEnabled(boolean enabled) { @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } setTextColor(mColor); } } + + @Override + public void setLinkColor() { + if (mLinkColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + mLinkColor = DynamicColorUtils.getContrastColor(mLinkColor, mContrastWithColor); + } + + setLinkTextColor(mLinkColor); + } + } } \ No newline at end of file diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicToolbar.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicToolbar.java index e4c1257321..d97e5dbdda 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicToolbar.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicToolbar.java @@ -18,44 +18,38 @@ import android.content.Context; import android.content.res.TypedArray; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.Toolbar; import android.util.AttributeSet; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.Toolbar; + import com.pranavpandey.android.dynamic.support.R; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicMenuUtils; import com.pranavpandey.android.dynamic.support.widget.base.DynamicTextWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; /** - * A Toolbar to change its background and text color according - * to the supplied parameters. + * A Toolbar to change its background and text color according to the supplied parameters. */ public class DynamicToolbar extends Toolbar implements DynamicTextWidget { /** * Color type applied to this view. * - * @see DynamicColorType - */ - private @DynamicColorType int mColorType; - - /** - * Text color type applied to this view. - * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mTextColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -63,29 +57,36 @@ public class DynamicToolbar extends Toolbar implements DynamicTextWidget { private @ColorInt int mColor; /** - * Text color applied to this view. - */ - private @ColorInt int mTextColor; - - /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; + + /** + * Text color type applied to this view. + * + * @see Theme.ColorType + */ + private @Theme.ColorType int mTextColorType; + + /** + * Text color applied to this view. + */ + private @ColorInt int mTextColor; public DynamicToolbar(@NonNull Context context) { this(context, null); @@ -98,7 +99,7 @@ public DynamicToolbar(@NonNull Context context, @Nullable AttributeSet attrs) { } public DynamicToolbar(@NonNull Context context, - @Nullable AttributeSet attrs, int defStyleAttr) { + @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); loadFromAttributes(attrs); @@ -111,21 +112,19 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { try { mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, - DynamicColorType.PRIMARY); + Theme.ColorType.PRIMARY); mTextColorType = a.getInt(R.styleable.DynamicTheme_ads_textColorType, - DynamicColorType.TINT_PRIMARY); - mContrastWithColorType = a.getInt( - R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.NONE); + Theme.ColorType.TINT_PRIMARY); + mContrastWithColorType = a.getInt(R.styleable.DynamicTheme_ads_contrastWithColorType, + Theme.ColorType.PRIMARY); mColor = a.getColor(R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); mTextColor = a.getColor(R.styleable.DynamicTheme_ads_textColor, WidgetDefaults.ADS_COLOR_UNKNOWN); mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, WidgetDefaults.ADS_COLOR_UNKNOWN); - mBackgroundAware = a.getBoolean( - R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + mBackgroundAware = a.getInteger(R.styleable.DynamicTheme_ads_backgroundAware, + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -135,54 +134,58 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mTextColorType != DynamicColorType.NONE - && mTextColorType != DynamicColorType.CUSTOM) { - mTextColor = DynamicTheme.getInstance().getColorFromType(mTextColorType); + if (mTextColorType != Theme.ColorType.NONE + && mTextColorType != Theme.ColorType.CUSTOM) { + mTextColor = DynamicTheme.getInstance().resolveColorType(mTextColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } + + setColor(); + setTextColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getTextColorType() { + public @Theme.ColorType int getTextColorType() { return mTextColorType; } @Override - public void setTextColorType(@DynamicColorType int textColorType) { + public void setTextColorType(@Theme.ColorType int textColorType) { this.mTextColorType = textColorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType + int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -195,7 +198,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -209,7 +212,7 @@ public void setColor(@ColorInt int color) { @Override public void setTextColor(@ColorInt int textColor) { - this.mTextColorType = DynamicColorType.CUSTOM; + this.mTextColorType = Theme.ColorType.CUSTOM; this.mTextColor = textColor; setColor(); @@ -223,7 +226,7 @@ public void setTextColor(@ColorInt int textColor) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); @@ -231,18 +234,24 @@ public void setContrastWithColor(@ColorInt int contrastWithColor) { } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; - } - - @Override - public void setBackgroundAware(boolean backgroundAware) { + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { this.mBackgroundAware = backgroundAware; setColor(); setTextColor(); } + @Override + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } + + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; + } + @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); @@ -254,10 +263,6 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); - } - setBackgroundColor(mColor); } } @@ -265,8 +270,8 @@ public void setColor() { @Override public void setTextColor() { if (mTextColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mColor!= WidgetDefaults.ADS_COLOR_UNKNOWN) { - mTextColor = DynamicColorUtils.getContrastColor(mTextColor, mColor); + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + mTextColor = DynamicColorUtils.getContrastColor(mTextColor, mContrastWithColor); } setTitleTextColor(mTextColor); diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicViewPager.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicViewPager.java index 227390a99c..d0b81bf41b 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicViewPager.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/DynamicViewPager.java @@ -18,37 +18,37 @@ import android.content.Context; import android.content.res.TypedArray; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.view.ViewPager; import android.util.AttributeSet; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.viewpager.widget.ViewPager; + import com.pranavpandey.android.dynamic.support.R; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicScrollUtils; import com.pranavpandey.android.dynamic.support.widget.base.DynamicWidget; import com.pranavpandey.android.dynamic.utils.DynamicColorUtils; /** - * A ViewPager to apply color filter according to the - * supplied parameters. + * A ViewPager to apply color filter according to the supplied parameters. */ public class DynamicViewPager extends ViewPager implements DynamicWidget { /** * Color type applied to this view. * - * @see DynamicColorType + * @see Theme.ColorType */ - private @DynamicColorType int mColorType; + private @Theme.ColorType int mColorType; /** - * Background color type for this view so that it will remain in - * contrast with this color type. + * Background color type for this view so that it will remain in contrast with this + * color type. */ - private @DynamicColorType int mContrastWithColorType; + private @Theme.ColorType int mContrastWithColorType; /** * Color applied to this view. @@ -56,24 +56,24 @@ public class DynamicViewPager extends ViewPager implements DynamicWidget { private @ColorInt int mColor; /** - * Background color for this view so that it will remain in - * contrast with this color. + * Background color for this view so that it will remain in contrast with this color. */ private @ColorInt int mContrastWithColor; /** - * {@code true} if this view will change its color according - * to the background. It was introduced to provide better legibility for - * colored texts and to avoid dark text on dark background like situations. + * The background aware functionality to change this view color according to the background. + * It was introduced to provide better legibility for colored views and to avoid dark view + * on dark background like situations. * - *

If this boolean is set then, it will check for the contrast color and - * do color calculations according to that color so that this text view will - * always be visible on that background. If no contrast color is found then, - * it will take default background color.

+ *

If this is enabled then, it will check for the contrast color and do color + * calculations according to that color so that this text view will always be visible on + * that background. If no contrast color is found then, it will take the default + * background color. * + * @see Theme.BackgroundAware * @see #mContrastWithColor */ - private boolean mBackgroundAware; + private @Theme.BackgroundAware int mBackgroundAware; public DynamicViewPager(@NonNull Context context) { this(context, null); @@ -91,18 +91,21 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { attrs, R.styleable.DynamicTheme); try { - mColorType = a.getInt(R.styleable.DynamicTheme_ads_colorType, + mColorType = a.getInt( + R.styleable.DynamicTheme_ads_colorType, WidgetDefaults.ADS_COLOR_EDGE_EFFECT); mContrastWithColorType = a.getInt( R.styleable.DynamicTheme_ads_contrastWithColorType, - DynamicColorType.BACKGROUND); - mColor = a.getColor(R.styleable.DynamicTheme_ads_color, + Theme.ColorType.BACKGROUND); + mColor = a.getColor( + R.styleable.DynamicTheme_ads_color, WidgetDefaults.ADS_COLOR_UNKNOWN); - mContrastWithColor = a.getColor(R.styleable.DynamicTheme_ads_contrastWithColor, - WidgetDefaults.getDefaultContrastWithColor(getContext())); - mBackgroundAware = a.getBoolean( + mContrastWithColor = a.getColor( + R.styleable.DynamicTheme_ads_contrastWithColor, + WidgetDefaults.getContrastWithColor(getContext())); + mBackgroundAware = a.getInteger( R.styleable.DynamicTheme_ads_backgroundAware, - WidgetDefaults.ADS_BACKGROUND_AWARE); + WidgetDefaults.getBackgroundAware()); } finally { a.recycle(); } @@ -112,39 +115,39 @@ public void loadFromAttributes(@Nullable AttributeSet attrs) { @Override public void initialize() { - if (mColorType != DynamicColorType.NONE - && mColorType != DynamicColorType.CUSTOM) { - mColor = DynamicTheme.getInstance().getColorFromType(mColorType); + if (mColorType != Theme.ColorType.NONE + && mColorType != Theme.ColorType.CUSTOM) { + mColor = DynamicTheme.getInstance().resolveColorType(mColorType); } - if (mContrastWithColorType != DynamicColorType.NONE - && mContrastWithColorType != DynamicColorType.CUSTOM) { + if (mContrastWithColorType != Theme.ColorType.NONE + && mContrastWithColorType != Theme.ColorType.CUSTOM) { mContrastWithColor = DynamicTheme.getInstance() - .getColorFromType(mContrastWithColorType); + .resolveColorType(mContrastWithColorType); } setColor(); } @Override - public @DynamicColorType int getColorType() { + public @Theme.ColorType int getColorType() { return mColorType; } @Override - public void setColorType(@DynamicColorType int colorType) { + public void setColorType(@Theme.ColorType int colorType) { this.mColorType = colorType; initialize(); } @Override - public @DynamicColorType int getContrastWithColorType() { + public @Theme.ColorType int getContrastWithColorType() { return mContrastWithColorType; } @Override - public void setContrastWithColorType(@DynamicColorType int contrastWithColorType) { + public void setContrastWithColorType(@Theme.ColorType int contrastWithColorType) { this.mContrastWithColorType = contrastWithColorType; initialize(); @@ -157,7 +160,7 @@ public void setContrastWithColorType(@DynamicColorType int contrastWithColorType @Override public void setColor(@ColorInt int color) { - this.mColorType = DynamicColorType.CUSTOM; + this.mColorType = Theme.ColorType.CUSTOM; this.mColor = color; setColor(); @@ -170,28 +173,34 @@ public void setColor(@ColorInt int color) { @Override public void setContrastWithColor(@ColorInt int contrastWithColor) { - this.mContrastWithColorType = DynamicColorType.CUSTOM; + this.mContrastWithColorType = Theme.ColorType.CUSTOM; this.mContrastWithColor = contrastWithColor; setColor(); } @Override - public boolean isBackgroundAware() { - return mBackgroundAware; + public void setBackgroundAware(@Theme.BackgroundAware int backgroundAware) { + this.mBackgroundAware = backgroundAware; + + setColor(); } @Override - public void setBackgroundAware(boolean backgroundAware) { - this.mBackgroundAware = backgroundAware; + public @Theme.BackgroundAware int getBackgroundAware() { + return mBackgroundAware; + } - setColor(); + @Override + public boolean isBackgroundAware() { + return DynamicTheme.getInstance().resolveBackgroundAware( + mBackgroundAware) != Theme.BackgroundAware.DISABLE; } @Override public void setColor() { if (mColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { - if (mBackgroundAware && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { + if (isBackgroundAware() && mContrastWithColor != WidgetDefaults.ADS_COLOR_UNKNOWN) { mColor = DynamicColorUtils.getContrastColor(mColor, mContrastWithColor); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/WidgetDefaults.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/WidgetDefaults.java index 8cc6e8055a..668988a54e 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/WidgetDefaults.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/WidgetDefaults.java @@ -17,11 +17,12 @@ package com.pranavpandey.android.dynamic.support.widget; import android.content.Context; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; + import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils; /** @@ -29,81 +30,157 @@ */ public class WidgetDefaults { + /** + * Minimum corner size in dips to provide the rounded tab indicator. + */ + public static final float ADS_CORNER_MIN_TABS = 6; + + /** + * Minimum corner size in dips for the box background. + */ + public static final float ADS_CORNER_MIN_BOX = 8; + + /** + * Minimum corner size in dips to provide the rounded rectangle list selector. + */ + public static final float ADS_CORNER_SELECTOR_RECT = 4; + + /** + * Minimum corner size in dips to provide the rounded list selector. + */ + public static final float ADS_CORNER_SELECTOR_ROUND = 8; + /** * Default alpha when the widget is enabled. */ public static final float ADS_ALPHA_ENABLED = 1.0f; /** - * Default alpha value for the unselected state to generate - * color state list dynamically. + * Default alpha for the hint. + */ + public static final float ADS_ALPHA_HINT = 0.8f; + + /** + * Default alpha value for the unselected state to generate color state list dynamically. + */ + public static final float ADS_ALPHA_UNCHECKED = 0.7f; + + /** + * Default alpha value for the selected state to generate color state list dynamically. + */ + public static final float ADS_ALPHA_SELECTED = 0.6f; + + /** + * Default alpha when the widget is pressed. + */ + public static final float ADS_ALPHA_PRESSED = 0.2f; + + /** + * Default alpha for the scrim insets. */ - public static final float ADS_ALPHA_UNCHECKED = 0.65f; + public static final float ADS_ALPHA_SCRIM = 0.7f; /** * Default alpha when the widget is disabled. */ - public static final float ADS_ALPHA_DISABLED = 0.4f; + public static final float ADS_ALPHA_DISABLED = 0.5f; /** - * Default state value to lighten the color. + * Default light state value for the box background. + */ + public static final float ADS_STATE_BOX_LIGHT = 0.12f; + + /** + * Default dark state value for the box background. + */ + public static final float ADS_STATE_BOX_DARK = 0.1f; + + /** + * Default value to lighten the color. */ public static final float ADS_STATE_LIGHT = 0.3f; /** - * Default state value to darken the color. + * Default value to darken the color. */ public static final float ADS_STATE_DARK = 0.2f; /** - * Default pressed state value. + * Default value for the pressed state. + */ + public static final float ADS_STATE_PRESSED = 0.3f; + + /** + * Default value to shift a light color. + */ + public static final float ADS_SHIFT_LIGHT = 0.9f; + + /** + * Default value to shift a dark color. */ - public static final float ADS_STATE_PRESSED = 0.15f; + public static final float ADS_SHIFT_DARK = 1.1f; /** * Constant for the unknown color. */ - public static final int ADS_COLOR_UNKNOWN = - DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE ; + public static final int ADS_COLOR_UNKNOWN = DynamicResourceUtils.ADS_DEFAULT_RESOURCE_VALUE; /** * Default edge effect or glow color used by the scrollable widgets. */ - public static final int ADS_COLOR_EDGE_EFFECT = DynamicColorType.PRIMARY; + public static final int ADS_COLOR_EDGE_EFFECT = Theme.ColorType.PRIMARY; /** * Default scroll bar used by the scrollable widgets. */ - public static final int ADS_COLOR_SCROLL_BAR = DynamicColorType.TINT_BACKGROUND; + public static final int ADS_COLOR_SCROLL_BAR = Theme.ColorType.TINT_BACKGROUND; /** - * Default value to make widgets background aware so that they can - * change color according to the theme background to provide best - * visibility. - *

- * {@code true} to make widgets background aware.

+ * Default value to make widgets background aware so that they can change color according + * to the theme background to provide best visibility. + *

{@code true} to make widgets background aware. */ public static final boolean ADS_BACKGROUND_AWARE = true; /** - * Default value to make widgets non background aware so that they - * cannot change color according to the theme background. It will - * be useful for some views like toolbar, card view, - * bottom navigation view, etc. - *

- * {@code false} to make widgets non background aware.

+ * Default borderless value for the widgets. + *

{@code true} if the widget is borderless. */ - public static final boolean ADS_NON_BACKGROUND_AWARE = false; + public static final boolean ADS_STYLE_BORDERLESS = false; + + /** + * Default tint background value for the widgets. + *

{@code true} to enable the background tinting. + */ + public static final boolean ADS_TINT_BACKGROUND = false; /** * Default value to show a divider below the widgets. + *

{@code true} to show the divider. */ public static final boolean ADS_SHOW_DIVIDER = false; /** - * Get default contrast with color from the theme. Generally, it should - * be a background color so that widgets can change their color accordingly - * if they are background aware. + * Default value to fill the empty icon space. + *

{@code true} to fill the space. + */ + public static final boolean ADS_FILL_SPACE = false; + + /** + * Returns the default value for the background functionality used by the various widgets. + * + * @return The default value for the background functionality used by the various widgets. + * + * @see Theme.BackgroundAware + */ + public static @Theme.BackgroundAware int getBackgroundAware() { + return DynamicTheme.getInstance().get().getBackgroundAware(); + } + + /** + * Get default contrast with color from the theme. + *

Generally, it should be a background color so that widgets can change their + * color accordingly if they are background aware. * * @param context The context to retrieve theme and resources. * @@ -111,7 +188,7 @@ public class WidgetDefaults { * * @see com.pranavpandey.android.dynamic.support.R.attr#ads_contrastWithDefault */ - public static @ColorInt int getDefaultContrastWithColor(@NonNull Context context) { + public static @ColorInt int getContrastWithColor(@NonNull Context context) { return DynamicTheme.getInstance().getDefaultContrastWith(); } } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicBackgroundWidget.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicBackgroundWidget.java new file mode 100644 index 0000000000..66f01995f2 --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicBackgroundWidget.java @@ -0,0 +1,61 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.widget.base; + +import androidx.annotation.ColorInt; + +import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; + +/** + * Interface to create dynamic widgets with a background which can be tinted according + * to the {@link DynamicTheme}. + */ +public interface DynamicBackgroundWidget { + + /** + * Returns the background color type applied to this widget. + * + * @return The background color type applied to this widget. + * + * @see Theme.ColorType + */ + @Theme.ColorType int getBackgroundColorType(); + + /** + * Set the background color type to this widget. + * + * @param backgroundColorType Text color type for this widget. + * + * @see Theme.ColorType + */ + void setBackgroundColorType(@Theme.ColorType int backgroundColorType); + + /** + * Returns the value of background color applied to this widget. + * + * @return The value of background color applied to this widget. + */ + @ColorInt int getBackgroundColor(); + + /** + * Set the value of background color for this widget. + * + * @param backgroundColor Background color for this widget. + */ + void setBackgroundColor(@ColorInt int backgroundColor); +} \ No newline at end of file diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicCornerWidget.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicCornerWidget.java new file mode 100644 index 0000000000..5a49fd5090 --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicCornerWidget.java @@ -0,0 +1,40 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.widget.base; + +import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; + +/** + * Interface to create dynamic widgets with corner radius support which can be used to modify + * it at runtime according to the {@link DynamicTheme}. + */ +public interface DynamicCornerWidget { + + /** + * Set the corner radius for this widget. + * + * @param cornerRadius The corner radius to be set. + */ + void setCorner(T cornerRadius); + + /** + * Returns the corner radius used by this widget. + * + * @return The corner radius used by this widget. + */ + T getCorner(); +} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicLinkWidget.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicLinkWidget.java new file mode 100644 index 0000000000..bd7efe7d00 --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicLinkWidget.java @@ -0,0 +1,68 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.widget.base; + +import androidx.annotation.ColorInt; + +import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; + +/** + * Interface to create text widgets and tint their link color according to the + * {@link DynamicTheme}. + */ +public interface DynamicLinkWidget extends DynamicWidget { + + /** + * Returns the link color type applied to this widget. + * + * @return The link color type applied to this widget. + * + * @see Theme.ColorType + */ + @Theme.ColorType int getLinkColorType(); + + /** + * Set the link color type to this widget. + * + * @param linkColorType Link color type for this widget. + * + * @see Theme.ColorType + */ + void setLinkColorType(@Theme.ColorType int linkColorType); + + /** + * Returns the value of link color applied to this widget. + * + * @return The value of link color applied to this widget. + */ + @ColorInt int getLinkColor(); + + /** + * Set the value of link color for this widget. + * + * @param linkColor Link color for this widget. + */ + void setLinkColor(@ColorInt int linkColor); + + /** + * Set link color of this widget according to the supplied values. + *

Generally, it should be a tint color so that link will be visible on this + * widget background. + */ + void setLinkColor(); +} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicProgressWidget.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicProgressWidget.java index 9397b22ff3..b9e01f7801 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicProgressWidget.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicProgressWidget.java @@ -17,14 +17,12 @@ package com.pranavpandey.android.dynamic.support.widget.base; /** - * Interface to create dynamic widgets with a progress bar - * and thumb. + * Interface to create dynamic widgets with a progress bar and thumb. */ public interface DynamicProgressWidget extends DynamicWidget { /** - * Set progress bar color according to the supplied - * values. + * Set progress bar color according to the supplied values. */ void setProgressBarColor(); diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicScrollableWidget.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicScrollableWidget.java index db3ffe2d95..af549bd40c 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicScrollableWidget.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicScrollableWidget.java @@ -16,56 +16,57 @@ package com.pranavpandey.android.dynamic.support.widget.base; -import android.support.annotation.ColorInt; +import androidx.annotation.ColorInt; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; /** - * Interface to create dynamic widgets with a scroll bar - * according to the {@link DynamicTheme}. + * Interface to create dynamic widgets with a scroll bar according to the {@link DynamicTheme}. */ public interface DynamicScrollableWidget extends DynamicWidget { /** - * @return The scroll bar color type applied to this view. + * Returns the scroll bar color type applied to this widget. + * + * @return The scroll bar color type applied to this widget. * - * @see DynamicColorType + * @see Theme.ColorType */ - @DynamicColorType int getScrollBarColorType(); + @Theme.ColorType int getScrollBarColorType(); /** - * Set the scroll bar color type to this view. + * Set the scroll bar color type to this widget. * - * @param scrollBarColorType Scroll bar color type for this view. + * @param scrollBarColorType Scroll bar color type for this widget. * - * @see DynamicColorType + * @see Theme.ColorType */ - void setScrollBarColorType(@DynamicColorType int scrollBarColorType); + void setScrollBarColorType(@Theme.ColorType int scrollBarColorType); /** - * @return The value of scroll bar color applied to this view. + * Returns the value of scroll bar color applied to this widget. + * + * @return The value of scroll bar color applied to this widget. */ @ColorInt int getScrollBarColor(); /** - * Set the value of scroll bar color for this view. + * Set the value of scroll bar color for this widget. * - * @param scrollBarColor Scroll bar color for this view. + * @param scrollBarColor Scroll bar color for this widget. */ void setScrollBarColor(@ColorInt int scrollBarColor); /** - * Set scroll bar color of this view according to the supplied - * values. + * Set scroll bar color of this widget according to the supplied values. */ void setScrollBarColor(); /** - * Set color and scroll bar color of this view at once. + * Set color and scroll bar color of this widget at once. * - * @param setScrollBarColor {@code true} to set the scroll bar color - * also. + * @param setScrollBarColor {@code true} to set the scroll bar color also. */ void setColor(boolean setScrollBarColor); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicStateSelectedWidget.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicStateSelectedWidget.java new file mode 100644 index 0000000000..71ed3e459d --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicStateSelectedWidget.java @@ -0,0 +1,61 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.widget.base; + +import androidx.annotation.ColorInt; + +import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; + +/** + * Interface to create dynamic widgets with a normal and selected state according to the + * {@link DynamicTheme}. + */ +public interface DynamicStateSelectedWidget extends DynamicStateWidget { + + /** + * Returns the selected state color type applied to this widget. + * + * @return The selected state color type applied to this widget. + * + * @see Theme.ColorType + */ + @Theme.ColorType int getStateSelectedColorType(); + + /** + * Set the selected state color type to this widget. + * + * @param stateSelectedColorType Normal state color type for this widget. + * + * @see Theme.ColorType + */ + void setStateSelectedColorType(@Theme.ColorType int stateSelectedColorType); + + /** + * Returns the value of selected state color applied to this widget. + * + * @return The value of selected state color applied to this widget. + */ + @ColorInt int getStateSelectedColor(); + + /** + * Set the value of selected state color for this widget. + * + * @param stateSelectedColorColor Normal state color for this widget. + */ + void setStateSelectedColor(@ColorInt int stateSelectedColorColor); +} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicStateWidget.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicStateWidget.java index 19561dd3b5..e47d35f256 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicStateWidget.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicStateWidget.java @@ -16,42 +16,45 @@ package com.pranavpandey.android.dynamic.support.widget.base; -import android.support.annotation.ColorInt; +import androidx.annotation.ColorInt; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; /** - * Interface to create dynamic widgets with a normal and checked - * state according to the {@link DynamicTheme}. + * Interface to create dynamic widgets with a normal state according to the {@link DynamicTheme}. */ public interface DynamicStateWidget extends DynamicWidget { /** - * @return The normal state color type applied to this view. + * Returns the normal state color type applied to this widget. + * + * @return The normal state color type applied to this widget. * - * @see DynamicColorType + * @see Theme.ColorType */ - @DynamicColorType int getStateNormalColorType(); + @Theme.ColorType int getStateNormalColorType(); /** - * Set the normal state color type to this view. + * Set the normal state color type to this widget. * - * @param stateNormalColorType Normal state color type for this view. + * @param stateNormalColorType Normal state color type for this widget. * - * @see DynamicColorType + * @see Theme.ColorType */ - void setStateNormalColorType(@DynamicColorType int stateNormalColorType); + void setStateNormalColorType(@Theme.ColorType int stateNormalColorType); /** - * @return The value of normal state color applied to this view. + * Returns the value of normal state color applied to this widget. + * + * @return The value of normal state color applied to this widget. */ @ColorInt int getStateNormalColor(); /** - * Set the value of normal state color for this view. + * Set the value of normal state color for this widget. * - * @param stateNormalColorColor Normal state color for this view. + * @param stateNormalColorColor Normal state color for this widget. */ void setStateNormalColor(@ColorInt int stateNormalColorColor); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicTextWidget.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicTextWidget.java index ccba9ccee5..d5c5e6049e 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicTextWidget.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicTextWidget.java @@ -16,49 +16,53 @@ package com.pranavpandey.android.dynamic.support.widget.base; -import android.support.annotation.ColorInt; +import androidx.annotation.ColorInt; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; /** - * Interface to create dynamic widgets with a text view which - * can be tinted according to the {@link DynamicTheme}. + * Interface to create dynamic widgets with a text view which can be tinted according to the + * {@link DynamicTheme}. */ public interface DynamicTextWidget extends DynamicWidget { /** - * @return The text color type applied to this view. + * Returns the text color type applied to this widget. + * + * @return The text color type applied to this widget. * - * @see DynamicColorType + * @see Theme.ColorType */ - @DynamicColorType int getTextColorType(); + @Theme.ColorType int getTextColorType(); /** - * Set the text color type to this view. + * Set the text color type to this widget. * - * @param textColorType Text color type for this view. + * @param textColorType Text color type for this widget. * - * @see DynamicColorType + * @see Theme.ColorType */ - void setTextColorType(@DynamicColorType int textColorType); + void setTextColorType(@Theme.ColorType int textColorType); /** - * @return The value of text color applied to this view. + * Returns the value of text color applied to this widget. + * + * @return The value of text color applied to this widget. */ @ColorInt int getTextColor(); /** - * Set the value of text color for this view. + * Set the value of text color for this widget. * - * @param textColor Text color for this view. + * @param textColor Text color for this widget. */ void setTextColor(@ColorInt int textColor); /** - * Set text color of this view according to the supplied values. - * Generally, it should be a tint color so that text will be visible on - * this view background. + * Set text color of this widget according to the supplied values. + *

Generally, it should be a tint color so that text will be visible on this + * widget background. */ void setTextColor(); } diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicTintWidget.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicTintWidget.java new file mode 100644 index 0000000000..f5d2e5b5dd --- /dev/null +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicTintWidget.java @@ -0,0 +1,40 @@ +/* + * Copyright 2018 Pranav Pandey + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.pranavpandey.android.dynamic.support.widget.base; + +import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; + +/** + * Interface to create dynamic widgets with some tint options which can be used to tint their + * background, etc. according to the {@link DynamicTheme}. + */ +public interface DynamicTintWidget { + + /** + * Returns whether to tint the background. + * + * @return {@code true} to tint background according to the widget color. + */ + boolean isTintBackground(); + + /** + * Set the background tinting option for this widget. + * + * @param tintBackground {@code true} to tint background according to the widget color. + */ + void setTintBackground(boolean tintBackground); +} diff --git a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicWidget.java b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicWidget.java index 05017a642e..f2022f2fad 100644 --- a/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicWidget.java +++ b/dynamic-support/src/main/java/com/pranavpandey/android/dynamic/support/widget/base/DynamicWidget.java @@ -16,16 +16,16 @@ package com.pranavpandey.android.dynamic.support.widget.base; -import android.support.annotation.ColorInt; -import android.support.annotation.Nullable; import android.util.AttributeSet; -import com.pranavpandey.android.dynamic.support.theme.DynamicColorType; +import androidx.annotation.ColorInt; +import androidx.annotation.Nullable; + import com.pranavpandey.android.dynamic.support.theme.DynamicTheme; +import com.pranavpandey.android.dynamic.support.theme.Theme; /** - * Interface to create dynamic widgets which can be tinted - * according to the {@link DynamicTheme}. + * Interface to create dynamic widgets which can be tinted according to the {@link DynamicTheme}. */ public interface DynamicWidget { @@ -37,97 +37,108 @@ public interface DynamicWidget { void loadFromAttributes(@Nullable AttributeSet attrs); /** - * Initialize this view by setting color type. If it is background - * aware then, background color will also taken into account while - * setting the color filter. + * Initialize this widget by setting color type. If it is background aware then, background + * color will also taken into account while setting the color filter. * - * @see DynamicColorType + * @see Theme.ColorType */ void initialize(); /** - * @return The color type applied to this view. + * Returns the color type applied to this widget. + * + * @return The color type applied to this widget. * - * @see DynamicColorType + * @see Theme.ColorType */ - @DynamicColorType int getColorType(); + @Theme.ColorType int getColorType(); /** - * Set the color type to this view. + * Set the color type to this widget. * - * @param colorType Color type for this view. + * @param colorType The color type for this widget. * - * @see DynamicColorType + * @see Theme.ColorType */ - void setColorType(@DynamicColorType int colorType); + void setColorType(@Theme.ColorType int colorType); /** - * @return The contrast with color type applied to this view. + * Returns the contrast with color type applied to this widget. + * + * @return The contrast with color type applied to this widget. * - * @see DynamicColorType + * @see Theme.ColorType */ - @DynamicColorType int getContrastWithColorType(); + @Theme.ColorType int getContrastWithColorType(); /** - * Set the contrast with color type to this view. + * Set the contrast with color type to this widget. * - * @param contrastWithColorType Contrast with Color type for - * this view. + * @param contrastWithColorType The contrast with color type for this widget. * - * @see DynamicColorType + * @see Theme.ColorType */ - void setContrastWithColorType(@DynamicColorType int contrastWithColorType); + void setContrastWithColorType(@Theme.ColorType int contrastWithColorType); /** - * @return The value of color applied to this view. + * Returns the value of color applied to this widget. + * + * @return The value of color applied to this widget. */ @ColorInt int getColor(); /** - * Set the value of color for this view. + * Set the value of color for this widget. * - * @param color Color for this view. + * @param color Color for this widget. */ void setColor(@ColorInt int color); /** - * @return The value of contrast with color applied to this view. + * Returns the value of contrast with color applied to this widget. + * + * @return The value of contrast with color applied to this widget. */ @ColorInt int getContrastWithColor(); /** - * Set the value of contrast with color for this view. + * Set the value of contrast with color for this widget. * - * @param contrastWithColor Contrast with color for this view. + * @param contrastWithColor Contrast with color for this widget. */ void setContrastWithColor(@ColorInt int contrastWithColor); /** - * @return {@code true} if this view changes color according - * to the background. + * Returns the background aware functionality used by this widget. + * + * @return The background aware functionality used by this widget. */ - boolean isBackgroundAware(); + @Theme.BackgroundAware int getBackgroundAware(); /** - * Set the value to make this view background aware or not. + * Set the value to make this widget background aware or not. * - * @param backgroundAware {@code true} to make this view - * background aware. + * @param backgroundAware The background aware functionality to be set. + */ + void setBackgroundAware(@Theme.BackgroundAware int backgroundAware); + + /** + * Checks whether the background aware functionality is enabled. + * + * @return {@code true} if this widget changes color according to the background. */ - void setBackgroundAware(boolean backgroundAware); + boolean isBackgroundAware(); /** - * Override this method to handle state changes for this view. - * For example, change alpha according to the enabled or disabled - * state of this view. + * Override this method to handle state changes for this widget. + *

For example, change alpha according to the enabled or disabled state of this widget. * - * @param enabled {@code true} if this widget is enabled and can - * receive click events. + * @param enabled {@code true} if this widget is enabled and can receive click events. */ void setEnabled(boolean enabled); /** - * Set color of this view according to the supplied values. + * Set color of this widget according to the supplied values. */ void setColor(); } diff --git a/dynamic-support/src/main/res/color-v23/ads_selectable_item_background.xml b/dynamic-support/src/main/res/color-v23/ads_selectable_item_background.xml new file mode 100644 index 0000000000..922243bd4e --- /dev/null +++ b/dynamic-support/src/main/res/color-v23/ads_selectable_item_background.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/dynamic-support/src/main/res/color/ads_selectable_item_background.xml b/dynamic-support/src/main/res/color/ads_selectable_item_background.xml new file mode 100644 index 0000000000..79d5a18020 --- /dev/null +++ b/dynamic-support/src/main/res/color/ads_selectable_item_background.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/dynamic-support/src/main/res/drawable-hdpi/adt_ic_error.png b/dynamic-support/src/main/res/drawable-hdpi/adt_ic_error.png new file mode 100644 index 0000000000..fb200ac27e Binary files /dev/null and b/dynamic-support/src/main/res/drawable-hdpi/adt_ic_error.png differ diff --git a/dynamic-support/src/main/res/drawable-hdpi/adt_ic_success.png b/dynamic-support/src/main/res/drawable-hdpi/adt_ic_success.png new file mode 100644 index 0000000000..7f6cfeb837 Binary files /dev/null and b/dynamic-support/src/main/res/drawable-hdpi/adt_ic_success.png differ diff --git a/dynamic-support/src/main/res/drawable-hdpi/adt_ic_warning.png b/dynamic-support/src/main/res/drawable-hdpi/adt_ic_warning.png new file mode 100644 index 0000000000..908c5e907a Binary files /dev/null and b/dynamic-support/src/main/res/drawable-hdpi/adt_ic_warning.png differ diff --git a/dynamic-support/src/main/res/drawable-mdpi/adt_ic_error.png b/dynamic-support/src/main/res/drawable-mdpi/adt_ic_error.png new file mode 100644 index 0000000000..d028527bab Binary files /dev/null and b/dynamic-support/src/main/res/drawable-mdpi/adt_ic_error.png differ diff --git a/dynamic-support/src/main/res/drawable-mdpi/adt_ic_success.png b/dynamic-support/src/main/res/drawable-mdpi/adt_ic_success.png new file mode 100644 index 0000000000..3bdb1c147d Binary files /dev/null and b/dynamic-support/src/main/res/drawable-mdpi/adt_ic_success.png differ diff --git a/dynamic-support/src/main/res/drawable-mdpi/adt_ic_warning.png b/dynamic-support/src/main/res/drawable-mdpi/adt_ic_warning.png new file mode 100644 index 0000000000..09582e9625 Binary files /dev/null and b/dynamic-support/src/main/res/drawable-mdpi/adt_ic_warning.png differ diff --git a/dynamic-support/src/main/res/drawable-v21/ads_list_selector.xml b/dynamic-support/src/main/res/drawable-v21/ads_list_selector.xml new file mode 100644 index 0000000000..3fef89c41d --- /dev/null +++ b/dynamic-support/src/main/res/drawable-v21/ads_list_selector.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable-v21/ads_list_selector_rect.xml b/dynamic-support/src/main/res/drawable-v21/ads_list_selector_rect.xml new file mode 100644 index 0000000000..306dec6dcf --- /dev/null +++ b/dynamic-support/src/main/res/drawable-v21/ads_list_selector_rect.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable-v21/ads_list_selector_round.xml b/dynamic-support/src/main/res/drawable-v21/ads_list_selector_round.xml new file mode 100644 index 0000000000..b744e2135f --- /dev/null +++ b/dynamic-support/src/main/res/drawable-v21/ads_list_selector_round.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable-xhdpi/adt_ic_error.png b/dynamic-support/src/main/res/drawable-xhdpi/adt_ic_error.png new file mode 100644 index 0000000000..ae6ecc567a Binary files /dev/null and b/dynamic-support/src/main/res/drawable-xhdpi/adt_ic_error.png differ diff --git a/dynamic-support/src/main/res/drawable-xhdpi/adt_ic_success.png b/dynamic-support/src/main/res/drawable-xhdpi/adt_ic_success.png new file mode 100644 index 0000000000..1950291845 Binary files /dev/null and b/dynamic-support/src/main/res/drawable-xhdpi/adt_ic_success.png differ diff --git a/dynamic-support/src/main/res/drawable-xhdpi/adt_ic_warning.png b/dynamic-support/src/main/res/drawable-xhdpi/adt_ic_warning.png new file mode 100644 index 0000000000..78b2d8854a Binary files /dev/null and b/dynamic-support/src/main/res/drawable-xhdpi/adt_ic_warning.png differ diff --git a/dynamic-support/src/main/res/drawable-xxhdpi/adt_ic_error.png b/dynamic-support/src/main/res/drawable-xxhdpi/adt_ic_error.png new file mode 100644 index 0000000000..bd143abc8c Binary files /dev/null and b/dynamic-support/src/main/res/drawable-xxhdpi/adt_ic_error.png differ diff --git a/dynamic-support/src/main/res/drawable-xxhdpi/adt_ic_success.png b/dynamic-support/src/main/res/drawable-xxhdpi/adt_ic_success.png new file mode 100644 index 0000000000..4e6b6ff5c6 Binary files /dev/null and b/dynamic-support/src/main/res/drawable-xxhdpi/adt_ic_success.png differ diff --git a/dynamic-support/src/main/res/drawable-xxhdpi/adt_ic_warning.png b/dynamic-support/src/main/res/drawable-xxhdpi/adt_ic_warning.png new file mode 100644 index 0000000000..eb16431f0d Binary files /dev/null and b/dynamic-support/src/main/res/drawable-xxhdpi/adt_ic_warning.png differ diff --git a/dynamic-support/src/main/res/drawable/ads_background.xml b/dynamic-support/src/main/res/drawable/ads_background.xml index 42d22864e1..865f5396d4 100644 --- a/dynamic-support/src/main/res/drawable/ads_background.xml +++ b/dynamic-support/src/main/res/drawable/ads_background.xml @@ -27,7 +27,7 @@ android:color="#FFFFFF" /> + android:radius="@dimen/ads_corner_radius" /> diff --git a/dynamic-support/src/main/res/drawable/ads_hint_background.xml b/dynamic-support/src/main/res/drawable/ads_hint_background.xml new file mode 100644 index 0000000000..282a936706 --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_hint_background.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dynamic-support/src/main/res/drawable/ads_ic_background_aware.xml b/dynamic-support/src/main/res/drawable/ads_ic_background_aware.xml new file mode 100644 index 0000000000..7de7b88e45 --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_background_aware.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_copy.xml b/dynamic-support/src/main/res/drawable/ads_ic_copy.xml new file mode 100644 index 0000000000..43cc34f080 --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_copy.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_corner.xml b/dynamic-support/src/main/res/drawable/ads_ic_corner.xml new file mode 100644 index 0000000000..18d58ba45b --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_corner.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_donate.xml b/dynamic-support/src/main/res/drawable/ads_ic_donate.xml index 57b2ab9370..84154f0daa 100644 --- a/dynamic-support/src/main/res/drawable/ads_ic_donate.xml +++ b/dynamic-support/src/main/res/drawable/ads_ic_donate.xml @@ -25,6 +25,6 @@ + android:pathData="M21.41,11.58l-9,-9C12.05,2.22 11.55,2 11,2L4,2c-1.1,0 -2,0.9 -2,2v7c0,0.55 0.22,1.05 0.59,1.42l9,9c0.36,0.36 0.86,0.58 1.41,0.58 0.55,0 1.05,-0.22 1.41,-0.59l7,-7c0.37,-0.36 0.59,-0.86 0.59,-1.41 0,-0.55 -0.23,-1.06 -0.59,-1.42zM5.5,7C4.67,7 4,6.33 4,5.5S4.67,4 5.5,4 7,4.67 7,5.5 6.33,7 5.5,7zM17.27,15.27L13,19.54l-4.27,-4.27C8.28,14.81 8,14.19 8,13.5c0,-1.38 1.12,-2.5 2.5,-2.5 0.69,0 1.32,0.28 1.77,0.74l0.73,0.72 0.73,-0.73c0.45,-0.45 1.08,-0.73 1.77,-0.73 1.38,0 2.5,1.12 2.5,2.5 0,0.69 -0.28,1.32 -0.73,1.77z" /> diff --git a/dynamic-support/src/main/res/drawable/ads_ic_feedback.xml b/dynamic-support/src/main/res/drawable/ads_ic_feedback.xml new file mode 100644 index 0000000000..5bfd5c1fe3 --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_feedback.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_flag_cn.xml b/dynamic-support/src/main/res/drawable/ads_ic_flag_cn.xml index 9626d88012..5460b34252 100644 --- a/dynamic-support/src/main/res/drawable/ads_ic_flag_cn.xml +++ b/dynamic-support/src/main/res/drawable/ads_ic_flag_cn.xml @@ -25,27 +25,27 @@ android:autoMirrored="true"> diff --git a/dynamic-support/src/main/res/drawable/ads_ic_flag_de.xml b/dynamic-support/src/main/res/drawable/ads_ic_flag_de.xml index 97a13f2a0e..6dcb37334d 100644 --- a/dynamic-support/src/main/res/drawable/ads_ic_flag_de.xml +++ b/dynamic-support/src/main/res/drawable/ads_ic_flag_de.xml @@ -25,7 +25,7 @@ android:autoMirrored="true"> diff --git a/dynamic-support/src/main/res/drawable/ads_ic_flag_es.xml b/dynamic-support/src/main/res/drawable/ads_ic_flag_es.xml index 2af406e7a5..0101ee3f25 100644 --- a/dynamic-support/src/main/res/drawable/ads_ic_flag_es.xml +++ b/dynamic-support/src/main/res/drawable/ads_ic_flag_es.xml @@ -25,15 +25,15 @@ android:autoMirrored="true"> - + - @@ -1383,47 +1383,47 @@ android:strokeWidth=".4" /> - @@ -1435,7 +1435,7 @@ android:strokeWidth=".4" /> @@ -1687,7 +1687,7 @@ android:strokeWidth=".5" /> @@ -2039,7 +2039,7 @@ android:strokeWidth=".4" /> @@ -2412,7 +2412,7 @@ android:pathData="M185.3,262.6v-4c0,-0.7 -0.5,-2.7 -3.1,-2.7 -2.4,0 -2.9,2 -2.9,2.7v4h6zM178.4,249.9v-4.2c0,-1 -0.6,-2.2 -2,-2.2s-2,1.1 -2,2.2v4.3h4zM186.2,249.9v-4.2c0,-1 0.7,-2.2 2,-2.2s2,1.1 2,2.2v4.3h-4z" /> + + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_flag_it.xml b/dynamic-support/src/main/res/drawable/ads_ic_flag_it.xml new file mode 100644 index 0000000000..f7dbe29689 --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_flag_it.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_flag_tr.xml b/dynamic-support/src/main/res/drawable/ads_ic_flag_tr.xml index b24312bb18..59edf0519c 100644 --- a/dynamic-support/src/main/res/drawable/ads_ic_flag_tr.xml +++ b/dynamic-support/src/main/res/drawable/ads_ic_flag_tr.xml @@ -25,21 +25,21 @@ android:autoMirrored="true"> diff --git a/dynamic-support/src/main/res/drawable/ads_ic_help.xml b/dynamic-support/src/main/res/drawable/ads_ic_help.xml new file mode 100644 index 0000000000..5232a6b6dd --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_help.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_help_outline.xml b/dynamic-support/src/main/res/drawable/ads_ic_help_outline.xml new file mode 100644 index 0000000000..354c7b2753 --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_help_outline.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_license.xml b/dynamic-support/src/main/res/drawable/ads_ic_license.xml index 119963dd8a..120b35558f 100644 --- a/dynamic-support/src/main/res/drawable/ads_ic_license.xml +++ b/dynamic-support/src/main/res/drawable/ads_ic_license.xml @@ -1,5 +1,6 @@ + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_more.xml b/dynamic-support/src/main/res/drawable/ads_ic_more.xml new file mode 100644 index 0000000000..f00f67e01a --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_more.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_more_horizontal.xml b/dynamic-support/src/main/res/drawable/ads_ic_more_horizontal.xml new file mode 100644 index 0000000000..5faa5291cc --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_more_horizontal.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_paint.xml b/dynamic-support/src/main/res/drawable/ads_ic_paint.xml new file mode 100644 index 0000000000..f812ed4b61 --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_paint.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_paint_bucket.xml b/dynamic-support/src/main/res/drawable/ads_ic_paint_bucket.xml new file mode 100644 index 0000000000..29dd0976f6 --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_paint_bucket.xml @@ -0,0 +1,35 @@ + + + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_play.xml b/dynamic-support/src/main/res/drawable/ads_ic_play.xml new file mode 100644 index 0000000000..6503a74144 --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_play.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_preview.xml b/dynamic-support/src/main/res/drawable/ads_ic_preview.xml new file mode 100644 index 0000000000..f64f56ffdf --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_preview.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_public.xml b/dynamic-support/src/main/res/drawable/ads_ic_public.xml index 76c805ccaa..beae33ccbe 100644 --- a/dynamic-support/src/main/res/drawable/ads_ic_public.xml +++ b/dynamic-support/src/main/res/drawable/ads_ic_public.xml @@ -1,5 +1,6 @@ + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_refresh.xml b/dynamic-support/src/main/res/drawable/ads_ic_refresh.xml new file mode 100644 index 0000000000..004c6df533 --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_refresh.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_reset.xml b/dynamic-support/src/main/res/drawable/ads_ic_reset.xml new file mode 100644 index 0000000000..e623ab459c --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_reset.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_save.xml b/dynamic-support/src/main/res/drawable/ads_ic_save.xml new file mode 100644 index 0000000000..7853744002 --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_save.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_search.xml b/dynamic-support/src/main/res/drawable/ads_ic_search.xml index a793a74325..8497ebd8f4 100644 --- a/dynamic-support/src/main/res/drawable/ads_ic_search.xml +++ b/dynamic-support/src/main/res/drawable/ads_ic_search.xml @@ -23,6 +23,8 @@ android:viewportWidth="24" android:autoMirrored="true"> - + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_security.xml b/dynamic-support/src/main/res/drawable/ads_ic_security.xml index ba0b013e8c..bc5ee2d1dd 100644 --- a/dynamic-support/src/main/res/drawable/ads_ic_security.xml +++ b/dynamic-support/src/main/res/drawable/ads_ic_security.xml @@ -1,5 +1,6 @@ - + - + - \ No newline at end of file + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_setup_small.xml b/dynamic-support/src/main/res/drawable/ads_ic_setup_small.xml index d03d211b11..36fb259714 100644 --- a/dynamic-support/src/main/res/drawable/ads_ic_setup_small.xml +++ b/dynamic-support/src/main/res/drawable/ads_ic_setup_small.xml @@ -24,10 +24,10 @@ android:autoMirrored="true"> + android:pivotY="12" + android:scaleX="0.8" + android:scaleY="0.8"> + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_shop_outline.xml b/dynamic-support/src/main/res/drawable/ads_ic_shop_outline.xml new file mode 100644 index 0000000000..a000bcd4a7 --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_shop_outline.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_social_community.xml b/dynamic-support/src/main/res/drawable/ads_ic_social_community.xml new file mode 100644 index 0000000000..29c92faad4 --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_social_community.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_social_community_small.xml b/dynamic-support/src/main/res/drawable/ads_ic_social_community_small.xml new file mode 100644 index 0000000000..c480c38432 --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_social_community_small.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_style.xml b/dynamic-support/src/main/res/drawable/ads_ic_style.xml new file mode 100644 index 0000000000..97a45cea88 --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_style.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_support.xml b/dynamic-support/src/main/res/drawable/ads_ic_support.xml new file mode 100644 index 0000000000..4c08623b2b --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_support.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_text_color.xml b/dynamic-support/src/main/res/drawable/ads_ic_text_color.xml new file mode 100644 index 0000000000..000af72901 --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_text_color.xml @@ -0,0 +1,35 @@ + + + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_theme_day.xml b/dynamic-support/src/main/res/drawable/ads_ic_theme_day.xml new file mode 100644 index 0000000000..e3f3c8d891 --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_theme_day.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_theme_night.xml b/dynamic-support/src/main/res/drawable/ads_ic_theme_night.xml new file mode 100644 index 0000000000..dbcaa16f23 --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_ic_theme_night.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_license_small.xml b/dynamic-support/src/main/res/drawable/ads_list_selector.xml similarity index 67% rename from dynamic-support/src/main/res/drawable/ads_ic_license_small.xml rename to dynamic-support/src/main/res/drawable/ads_list_selector.xml index b7eaaa88b3..0757b77517 100644 --- a/dynamic-support/src/main/res/drawable/ads_ic_license_small.xml +++ b/dynamic-support/src/main/res/drawable/ads_list_selector.xml @@ -1,6 +1,6 @@ + + + + + + + + + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_list_selector_round.xml b/dynamic-support/src/main/res/drawable/ads_list_selector_round.xml new file mode 100644 index 0000000000..220d851168 --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_list_selector_round.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + diff --git a/dynamic-support/src/main/res/drawable/ads_ic_public_small.xml b/dynamic-support/src/main/res/drawable/ads_tabs_indicator.xml similarity index 72% rename from dynamic-support/src/main/res/drawable/ads_ic_public_small.xml rename to dynamic-support/src/main/res/drawable/ads_tabs_indicator.xml index d65f1ed7a0..c51f44d612 100644 --- a/dynamic-support/src/main/res/drawable/ads_ic_public_small.xml +++ b/dynamic-support/src/main/res/drawable/ads_tabs_indicator.xml @@ -18,10 +18,16 @@ - + + + + + + + + + \ No newline at end of file diff --git a/dynamic-support/src/main/res/drawable/ads_tabs_indicator_corner.xml b/dynamic-support/src/main/res/drawable/ads_tabs_indicator_corner.xml new file mode 100644 index 0000000000..f9e90893ae --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_tabs_indicator_corner.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dynamic-support/src/main/res/drawable/ads_toast_background.xml b/dynamic-support/src/main/res/drawable/ads_toast_background.xml new file mode 100644 index 0000000000..aa244a95fc --- /dev/null +++ b/dynamic-support/src/main/res/drawable/ads_toast_background.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dynamic-support/src/main/res/drawable/ads_widget_frame.xml b/dynamic-support/src/main/res/drawable/ads_widget_frame.xml index 6d06cc151a..d10f1d1a59 100644 --- a/dynamic-support/src/main/res/drawable/ads_widget_frame.xml +++ b/dynamic-support/src/main/res/drawable/ads_widget_frame.xml @@ -18,31 +18,13 @@ - - - - - - - - - - - - + android:color="@color/ads_color_control_remote" /> diff --git a/dynamic-support/src/main/res/layout-land/ads_fragment_tutorial_simple.xml b/dynamic-support/src/main/res/layout-land/ads_fragment_tutorial_simple.xml index 69f9ddc868..d65f4deb7c 100644 --- a/dynamic-support/src/main/res/layout-land/ads_fragment_tutorial_simple.xml +++ b/dynamic-support/src/main/res/layout-land/ads_fragment_tutorial_simple.xml @@ -30,7 +30,7 @@ android:layout_weight="@integer/ads_weight_tutorial_image" android:padding="@dimen/ads_margin_medium" android:layout_gravity="center_vertical" - app:ads_backgroundAware="false" /> + app:ads_backgroundAware="disable" /> + style="@style/TextAppearance.DynamicApp.Headline5.Tutorial" + app:ads_backgroundAware="disable" /> + style="@style/TextAppearance.DynamicApp.Subtitle1.Tutorial" + app:ads_backgroundAware="disable" /> + style="@style/TextAppearance.DynamicApp.Body1.Tutorial" + app:ads_backgroundAware="disable" /> diff --git a/dynamic-support/src/main/res/layout/ads_activity.xml b/dynamic-support/src/main/res/layout/ads_activity.xml index d4e2ade77c..683b3999ea 100644 --- a/dynamic-support/src/main/res/layout/ads_activity.xml +++ b/dynamic-support/src/main/res/layout/ads_activity.xml @@ -21,7 +21,7 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - + app:ads_backgroundAware="disable"> - + - + app:ads_backgroundAware="disable"> - - + - + - + app:headerLayout="@layout/ads_header_drawer" + android:theme="@style/Widget.DynamicApp.NavigationView.ThemeOverlay" + style="@style/Widget.DynamicApp.NavigationView" /> diff --git a/dynamic-support/src/main/res/layout/ads_activity_drawer_collapsing.xml b/dynamic-support/src/main/res/layout/ads_activity_drawer_collapsing.xml index 5171a66bac..0f97c891cc 100644 --- a/dynamic-support/src/main/res/layout/ads_activity_drawer_collapsing.xml +++ b/dynamic-support/src/main/res/layout/ads_activity_drawer_collapsing.xml @@ -35,7 +35,7 @@ - - + app:ads_backgroundAware="disable" /> + app:ads_backgroundAware="disable" + app:ads_tintBackground="true" /> @@ -89,13 +88,13 @@ android:layout_marginLeft="@dimen/ads_icon_small" android:layout_marginStart="@dimen/ads_icon_small" android:layout_gravity="start|center_vertical" - android:background="?attr/selectableItemBackgroundBorderless" + style="@style/Widget.DynamicApp.Button.ImageButton" app:srcCompat="@drawable/ads_ic_chevron_right" - app:ads_backgroundAware="false" - style="@style/Widget.DynamicApp.Button.Borderless" /> + app:ads_backgroundAware="disable" + app:ads_tintBackground="true" /> - \ No newline at end of file + \ No newline at end of file diff --git a/dynamic-support/src/main/res/layout/ads_alert_dialog.xml b/dynamic-support/src/main/res/layout/ads_alert_dialog.xml index c97930dccf..2fbebc4780 100644 --- a/dynamic-support/src/main/res/layout/ads_alert_dialog.xml +++ b/dynamic-support/src/main/res/layout/ads_alert_dialog.xml @@ -16,94 +16,99 @@ limitations under the License. --> - + style="@style/Widget.DynamicApp.Card.Floating.Dialog"> - - - + android:gravity="start|top" + android:orientation="vertical"> + + - + android:minHeight="48dp"> - + android:layout_height="wrap_content" + android:orientation="vertical"> - + - + - + android:clipToPadding="false"> - + - + + android:layout_height="wrap_content" + android:minHeight="48dp"> + + + + - + + + - - + - - - + android:layout_height="wrap_content" /> - + - \ No newline at end of file + \ No newline at end of file diff --git a/dynamic-support/src/main/res/layout/ads_alert_dialog_button_bar.xml b/dynamic-support/src/main/res/layout/ads_alert_dialog_button_bar.xml index 74ae6796e4..306c04b138 100644 --- a/dynamic-support/src/main/res/layout/ads_alert_dialog_button_bar.xml +++ b/dynamic-support/src/main/res/layout/ads_alert_dialog_button_bar.xml @@ -16,7 +16,7 @@ limitations under the License. --> - - - - + - \ No newline at end of file + \ No newline at end of file diff --git a/dynamic-support/src/main/res/layout/ads_alert_dialog_title.xml b/dynamic-support/src/main/res/layout/ads_alert_dialog_title.xml index 32bcf15e44..5f30ab544a 100644 --- a/dynamic-support/src/main/res/layout/ads_alert_dialog_title.xml +++ b/dynamic-support/src/main/res/layout/ads_alert_dialog_title.xml @@ -33,7 +33,7 @@ android:orientation="horizontal" android:paddingLeft="?attr/dialogPreferredPadding" android:paddingRight="?attr/dialogPreferredPadding" - android:paddingTop="@dimen/add_dialog_margin_title_top"> + android:paddingTop="@dimen/ads_dialog_margin_title_top"> - - diff --git a/dynamic-support/src/main/res/layout/ads_color_picker.xml b/dynamic-support/src/main/res/layout/ads_color_picker.xml index 800f999ec1..587eddcdf4 100644 --- a/dynamic-support/src/main/res/layout/ads_color_picker.xml +++ b/dynamic-support/src/main/res/layout/ads_color_picker.xml @@ -22,11 +22,13 @@ android:id="@+id/ads_color_picker" style="@style/Widget.DynamicApp.Scroller.Vertical"> - + android:paddingRight="@dimen/ads_dialog_margin_start_end_small" + android:orientation="vertical" + android:focusableInTouchMode="true"> + android:verticalSpacing="@dimen/ads_margin_small" + style="@style/Widget.DynamicApp.Scroller.Nested.GridView" /> + android:verticalSpacing="@dimen/ads_margin_small" + style="@style/Widget.DynamicApp.Scroller.Nested.GridView" /> @@ -101,13 +97,10 @@ android:id="@+id/ads_color_picker_recents" android:layout_width="match_parent" android:layout_height="wrap_content" - android:cacheColorHint="@null" android:columnWidth="@dimen/ads_picker_recents_size" android:horizontalSpacing="@dimen/ads_margin_tiny" - android:listSelector="@null" - android:numColumns="auto_fit" - android:stretchMode="columnWidth" - android:verticalSpacing="@dimen/ads_margin_small" /> + android:verticalSpacing="@dimen/ads_margin_small" + style="@style/Widget.DynamicApp.Scroller.Nested.GridView" /> @@ -138,23 +131,23 @@ android:layout_weight="0.3" android:layout_marginRight="@dimen/ads_margin_small" android:layout_marginEnd="@dimen/ads_margin_small" - app:ads_dynamicColorView_shape="rectangle" - app:ads_dynamicColorView_color= "#123456" /> + app:ads_shape="rectangle" + app:ads_color= "#123456" /> + app:ads_shape="rectangle" + app:ads_color= "#123456" /> - @@ -192,7 +184,8 @@ android:layout_height="wrap_content" android:layout_weight="1.0" android:text="@string/ads_picker_all" - style="@style/Widget.DynamicApp.Button.Borderless.Primary" /> + style="@style/Widget.DynamicApp.Button.TextButton" + app:ads_colorType="primary" /> + style="@style/Widget.DynamicApp.Button.TextButton" + app:ads_colorType="primary" /> + style="@style/Widget.DynamicApp.Button.TextButton" + app:ads_colorType="primary" /> @@ -222,31 +217,31 @@ android:id="@+id/ads_color_picker_seek_hue" android:layout_width="match_parent" android:layout_height="wrap_content" - app:ads_dynamicPreference_title="H" - app:ads_dynamicPreference_min="0" - app:ads_dynamicPreference_max="360" - app:ads_dynamicPreference_interval="1" - app:ads_dynamicPreference_controls="true" /> + app:ads_title="H" + app:ads_min="0" + app:ads_max="360" + app:ads_interval="1" + app:ads_controls="true" /> + app:ads_title="S" + app:ads_min="0" + app:ads_max="100" + app:ads_interval="1" + app:ads_controls="true" /> + app:ads_title="V" + app:ads_min="0" + app:ads_max="100" + app:ads_interval="1" + app:ads_controls="true" /> @@ -254,11 +249,11 @@ android:id="@+id/ads_color_picker_seek_alpha" android:layout_width="match_parent" android:layout_height="wrap_content" - app:ads_dynamicPreference_title="A" - app:ads_dynamicPreference_min="0" - app:ads_dynamicPreference_max="255" - app:ads_dynamicPreference_interval="1" - app:ads_dynamicPreference_controls="true" /> + app:ads_title="A" + app:ads_min="0" + app:ads_max="255" + app:ads_interval="1" + app:ads_controls="true" /> + app:ads_title="R" + app:ads_min="0" + app:ads_max="255" + app:ads_interval="1" + app:ads_controls="true" /> + app:ads_title="G" + app:ads_min="0" + app:ads_max="255" + app:ads_interval="1" + app:ads_controls="true" /> + app:ads_title="B" + app:ads_min="0" + app:ads_max="255" + app:ads_interval="1" + app:ads_controls="true" /> - + \ No newline at end of file diff --git a/dynamic-support/src/main/res/layout/ads_color_picker_popup.xml b/dynamic-support/src/main/res/layout/ads_color_picker_popup.xml index 30dcaa3816..280fefadc8 100644 --- a/dynamic-support/src/main/res/layout/ads_color_picker_popup.xml +++ b/dynamic-support/src/main/res/layout/ads_color_picker_popup.xml @@ -34,11 +34,7 @@ android:columnWidth="@dimen/ads_icon_medium" android:horizontalSpacing="@dimen/ads_margin_tiny" android:verticalSpacing="@dimen/ads_margin_small" - android:numColumns="auto_fit" - android:stretchMode="columnWidth" - android:listSelector="@null" - android:cacheColorHint="@null" - style="@style/Widget.DynamicApp.Scroller.Nested" /> + style="@style/Widget.DynamicApp.Scroller.Nested.GridView" /> diff --git a/dynamic-support/src/main/res/layout/ads_color_picker_popup_footer.xml b/dynamic-support/src/main/res/layout/ads_color_picker_popup_footer.xml index 0cf98ce0e7..28cee98b73 100644 --- a/dynamic-support/src/main/res/layout/ads_color_picker_popup_footer.xml +++ b/dynamic-support/src/main/res/layout/ads_color_picker_popup_footer.xml @@ -39,18 +39,18 @@ android:orientation="vertical" android:layout_gravity="center_vertical"> - + style="@style/TextAppearance.DynamicApp.Subtitle1.Caps" /> - diff --git a/dynamic-support/src/main/res/layout/ads_dialog_general.xml b/dynamic-support/src/main/res/layout/ads_dialog_general.xml new file mode 100644 index 0000000000..fc4724dcab --- /dev/null +++ b/dynamic-support/src/main/res/layout/ads_dialog_general.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dynamic-support/src/main/res/layout/ads_dialog_select_item.xml b/dynamic-support/src/main/res/layout/ads_dialog_select_item.xml index a62cba783f..e370de2ced 100644 --- a/dynamic-support/src/main/res/layout/ads_dialog_select_item.xml +++ b/dynamic-support/src/main/res/layout/ads_dialog_select_item.xml @@ -22,7 +22,8 @@ This layout file is inflated and used as the TextView to display individual items. --> - + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dynamic-support/src/main/res/layout/ads_fragment_permissions.xml b/dynamic-support/src/main/res/layout/ads_fragment_permissions.xml index a72407dadc..49cc39826a 100644 --- a/dynamic-support/src/main/res/layout/ads_fragment_permissions.xml +++ b/dynamic-support/src/main/res/layout/ads_fragment_permissions.xml @@ -15,7 +15,7 @@ limitations under the License. --> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dynamic-support/src/main/res/layout/ads_fragment_tutorial_simple.xml b/dynamic-support/src/main/res/layout/ads_fragment_tutorial_simple.xml index 77d025102c..d870b2eead 100644 --- a/dynamic-support/src/main/res/layout/ads_fragment_tutorial_simple.xml +++ b/dynamic-support/src/main/res/layout/ads_fragment_tutorial_simple.xml @@ -30,14 +30,14 @@ android:layout_weight="1.0" android:padding="@dimen/ads_margin_medium" android:layout_gravity="center_vertical" - app:ads_backgroundAware="false" /> + app:ads_backgroundAware="disable" /> + style="@style/TextAppearance.DynamicApp.Headline5.Tutorial" + app:ads_backgroundAware="disable" /> + style="@style/TextAppearance.DynamicApp.Subtitle1.Tutorial" + app:ads_backgroundAware="disable" /> + style="@style/TextAppearance.DynamicApp.Body1.Tutorial" + app:ads_backgroundAware="disable" /> diff --git a/dynamic-support/src/main/res/layout/ads_fragment_view_pager.xml b/dynamic-support/src/main/res/layout/ads_fragment_view_pager.xml index ffbb675165..2b303316fb 100644 --- a/dynamic-support/src/main/res/layout/ads_fragment_view_pager.xml +++ b/dynamic-support/src/main/res/layout/ads_fragment_view_pager.xml @@ -15,9 +15,7 @@ limitations under the License. --> - diff --git a/dynamic-support/src/main/res/layout/ads_header.xml b/dynamic-support/src/main/res/layout/ads_header.xml index cc2273545b..6e3022e1d9 100644 --- a/dynamic-support/src/main/res/layout/ads_header.xml +++ b/dynamic-support/src/main/res/layout/ads_header.xml @@ -18,14 +18,14 @@ + style="@style/TextAppearance.DynamicApp.Subtitle2" /> - + style="@style/TextAppearance.DynamicApp.Body1" /> diff --git a/dynamic-support/src/main/res/layout/ads_header_drawer.xml b/dynamic-support/src/main/res/layout/ads_header_drawer.xml index 19a281ace6..81e2feb214 100644 --- a/dynamic-support/src/main/res/layout/ads_header_drawer.xml +++ b/dynamic-support/src/main/res/layout/ads_header_drawer.xml @@ -23,7 +23,7 @@ android:layout_height="wrap_content" android:fitsSystemWindows="true" app:ads_colorType="primary" - app:ads_backgroundAware="false"> + app:ads_backgroundAware="disable"> + app:ads_contrastWithColorType="primary" /> + app:ads_contrastWithColorType="primary" /> + app:ads_contrastWithColorType="primary" + style="@style/TextAppearance.DynamicApp.Subtitle1" /> diff --git a/dynamic-support/src/main/res/layout/ads_info_view.xml b/dynamic-support/src/main/res/layout/ads_info_view.xml index 872827e621..824fa4ae14 100644 --- a/dynamic-support/src/main/res/layout/ads_info_view.xml +++ b/dynamic-support/src/main/res/layout/ads_info_view.xml @@ -50,20 +50,20 @@ android:id="@+id/ads_info_view_title" android:layout_width="match_parent" android:layout_height="wrap_content" - style="@style/TextAppearance.DynamicApp.Title.Card.Info" /> + style="@style/TextAppearance.DynamicApp.Headline5.Card.Info" /> + style="@style/TextAppearance.DynamicApp.Subtitle1" /> - + style="@style/TextAppearance.DynamicApp.Body1" /> diff --git a/dynamic-support/src/main/res/layout/ads_info_view_big.xml b/dynamic-support/src/main/res/layout/ads_info_view_big.xml index b364b4aa5f..f8650a07e5 100644 --- a/dynamic-support/src/main/res/layout/ads_info_view_big.xml +++ b/dynamic-support/src/main/res/layout/ads_info_view_big.xml @@ -50,20 +50,20 @@ android:id="@+id/ads_info_view_title" android:layout_width="match_parent" android:layout_height="wrap_content" - style="@style/TextAppearance.DynamicApp.Title.Card.Info" /> + style="@style/TextAppearance.DynamicApp.Headline5.Card.Info" /> + style="@style/TextAppearance.DynamicApp.Subtitle1" /> - + style="@style/TextAppearance.DynamicApp.Body1" /> diff --git a/dynamic-support/src/main/res/layout/ads_item_view.xml b/dynamic-support/src/main/res/layout/ads_item_view.xml index 437f7cd530..5842878d9f 100644 --- a/dynamic-support/src/main/res/layout/ads_item_view.xml +++ b/dynamic-support/src/main/res/layout/ads_item_view.xml @@ -51,13 +51,13 @@ android:id="@+id/ads_item_view_title" android:layout_width="match_parent" android:layout_height="wrap_content" - android:textAppearance="@style/TextAppearance.DynamicApp.Subtitle.Caps" /> + android:textAppearance="@style/TextAppearance.DynamicApp.Subtitle1.Caps" /> - + style="@style/TextAppearance.DynamicApp.Body1" /> diff --git a/dynamic-support/src/main/res/layout/ads_layout_array_item_popup.xml b/dynamic-support/src/main/res/layout/ads_layout_array_item_popup.xml index 8dbf677187..9392257706 100644 --- a/dynamic-support/src/main/res/layout/ads_layout_array_item_popup.xml +++ b/dynamic-support/src/main/res/layout/ads_layout_array_item_popup.xml @@ -25,12 +25,12 @@ android:background="?selectableItemBackground" android:orientation="horizontal"> - + style="@style/TextAppearance.DynamicApp.Headline5.Card" /> + style="@style/TextAppearance.DynamicApp.Subtitle1" /> - + style="@style/TextAppearance.DynamicApp.Body1" /> diff --git a/dynamic-support/src/main/res/layout/ads_layout_color_item.xml b/dynamic-support/src/main/res/layout/ads_layout_color_item.xml index ea229366e4..9220049c66 100644 --- a/dynamic-support/src/main/res/layout/ads_layout_color_item.xml +++ b/dynamic-support/src/main/res/layout/ads_layout_color_item.xml @@ -25,9 +25,6 @@ android:id="@+id/ads_color_item_view" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_margin="@dimen/ads_margin_extra_tiny" - android:clickable="true" - android:focusable="true" - android:background="@null" /> + android:layout_margin="@dimen/ads_margin_extra_tiny" /> \ No newline at end of file diff --git a/dynamic-support/src/main/res/layout/ads_layout_container.xml b/dynamic-support/src/main/res/layout/ads_layout_container.xml index e2dbb39a65..b936760259 100644 --- a/dynamic-support/src/main/res/layout/ads_layout_container.xml +++ b/dynamic-support/src/main/res/layout/ads_layout_container.xml @@ -15,7 +15,7 @@ limitations under the License. --> - - \ No newline at end of file + \ No newline at end of file diff --git a/dynamic-support/src/main/res/layout/ads_layout_header_appbar.xml b/dynamic-support/src/main/res/layout/ads_layout_header_appbar.xml index ee043474b1..a78bbd38e4 100644 --- a/dynamic-support/src/main/res/layout/ads_layout_header_appbar.xml +++ b/dynamic-support/src/main/res/layout/ads_layout_header_appbar.xml @@ -44,17 +44,17 @@ android:id="@+id/ads_header_toolbar_title" android:layout_width="match_parent" android:layout_height="wrap_content" - android:textAppearance="@style/TextAppearance.DynamicApp.Title.Bold" + android:textAppearance="@style/TextAppearance.DynamicApp.Headline6" app:ads_colorType="tint_primary" - app:ads_backgroundAware="false" /> + app:ads_contrastWithColorType="primary" /> + app:ads_contrastWithColorType="primary" /> diff --git a/dynamic-support/src/main/res/layout/ads_layout_info.xml b/dynamic-support/src/main/res/layout/ads_layout_info.xml index c99b94f322..9898f87420 100644 --- a/dynamic-support/src/main/res/layout/ads_layout_info.xml +++ b/dynamic-support/src/main/res/layout/ads_layout_info.xml @@ -46,36 +46,35 @@ android:id="@+id/ads_info_title" android:layout_width="match_parent" android:layout_height="wrap_content" - style="@style/TextAppearance.DynamicApp.Title.Card" /> + style="@style/TextAppearance.DynamicApp.Headline5.Card" /> + style="@style/TextAppearance.DynamicApp.Subtitle1.Caps" /> - + style="@style/TextAppearance.DynamicApp.Subtitle1.Secondary" /> - + style="@style/TextAppearance.DynamicApp.Body1" /> + style="@style/TextAppearance.DynamicApp.Subtitle1.Caps" /> diff --git a/dynamic-support/src/main/res/layout/ads_layout_spinner_item.xml b/dynamic-support/src/main/res/layout/ads_layout_spinner_item.xml index fdbf914e6b..a5e0d5ac47 100644 --- a/dynamic-support/src/main/res/layout/ads_layout_spinner_item.xml +++ b/dynamic-support/src/main/res/layout/ads_layout_spinner_item.xml @@ -29,12 +29,12 @@ android:layout_height="@dimen/ads_popup_selector_icon_size" style="@style/Widget.DynamicApp.Image.Preference" /> - \ No newline at end of file diff --git a/dynamic-support/src/main/res/layout/ads_layout_theme_preview.xml b/dynamic-support/src/main/res/layout/ads_layout_theme_preview.xml new file mode 100644 index 0000000000..d702adb862 --- /dev/null +++ b/dynamic-support/src/main/res/layout/ads_layout_theme_preview.xml @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dynamic-support/src/main/res/layout/ads_popup.xml b/dynamic-support/src/main/res/layout/ads_popup.xml index 9962044e74..f70ddfcbf2 100644 --- a/dynamic-support/src/main/res/layout/ads_popup.xml +++ b/dynamic-support/src/main/res/layout/ads_popup.xml @@ -16,8 +16,8 @@ --> diff --git a/dynamic-support/src/main/res/layout/ads_preference_check.xml b/dynamic-support/src/main/res/layout/ads_preference_check.xml index 4e40beace0..c9bb67c51b 100644 --- a/dynamic-support/src/main/res/layout/ads_preference_check.xml +++ b/dynamic-support/src/main/res/layout/ads_preference_check.xml @@ -15,71 +15,13 @@ limitations under the License. --> - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + android:layout_marginLeft="@dimen/ads_page_horizontal_margin" + android:layout_marginStart="@dimen/ads_page_horizontal_margin" + android:layout_gravity="center_vertical" + android:background="@android:color/transparent" + android:clickable="false" /> \ No newline at end of file diff --git a/dynamic-support/src/main/res/layout/ads_preference_seek_bar.xml b/dynamic-support/src/main/res/layout/ads_preference_seek_bar.xml index 31000c3163..cc68cf6b4a 100644 --- a/dynamic-support/src/main/res/layout/ads_preference_seek_bar.xml +++ b/dynamic-support/src/main/res/layout/ads_preference_seek_bar.xml @@ -18,10 +18,10 @@ + style="@style/Widget.DynamicApp.Content.Card.Clickable"> - + style="@style/TextAppearance.DynamicApp.Headline5.Card" /> - + style="@style/TextAppearance.DynamicApp.Subtitle1" /> - + + + style="@style/TextAppearance.DynamicApp.Body1" /> @@ -84,13 +91,14 @@ android:gravity="center_vertical" android:orientation="horizontal"> - @@ -101,13 +109,13 @@ android:layout_gravity="center_vertical" android:layout_weight="1.0" /> - diff --git a/dynamic-support/src/main/res/layout/ads_preference_simple.xml b/dynamic-support/src/main/res/layout/ads_preference_simple.xml index 73dc70c574..16357f9b33 100644 --- a/dynamic-support/src/main/res/layout/ads_preference_simple.xml +++ b/dynamic-support/src/main/res/layout/ads_preference_simple.xml @@ -18,7 +18,7 @@ @@ -34,7 +34,7 @@ android:orientation="horizontal"> - + style="@style/TextAppearance.DynamicApp.Headline5.Card" /> - + style="@style/TextAppearance.DynamicApp.Subtitle1" /> + app:ads_colorType="accent" + style="@style/TextAppearance.DynamicApp.Subtitle1.Secondary" /> - + style="@style/TextAppearance.DynamicApp.Body1" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dynamic-support/src/main/res/layout/ads_recycler_view.xml b/dynamic-support/src/main/res/layout/ads_recycler_view.xml index f2f6b4eb6a..7ec916372b 100644 --- a/dynamic-support/src/main/res/layout/ads_recycler_view.xml +++ b/dynamic-support/src/main/res/layout/ads_recycler_view.xml @@ -28,7 +28,6 @@ diff --git a/dynamic-support/src/main/res/layout/ads_recycler_view_dialog.xml b/dynamic-support/src/main/res/layout/ads_recycler_view_dialog.xml index 732f0c3c3a..f7d3828c94 100644 --- a/dynamic-support/src/main/res/layout/ads_recycler_view_dialog.xml +++ b/dynamic-support/src/main/res/layout/ads_recycler_view_dialog.xml @@ -23,7 +23,6 @@ \ No newline at end of file diff --git a/dynamic-support/src/main/res/layout/ads_seek_bar_compact.xml b/dynamic-support/src/main/res/layout/ads_seek_bar_compact.xml index 5be0a513c8..87f1fb8709 100644 --- a/dynamic-support/src/main/res/layout/ads_seek_bar_compact.xml +++ b/dynamic-support/src/main/res/layout/ads_seek_bar_compact.xml @@ -18,7 +18,7 @@ @@ -47,18 +47,18 @@ android:layout_gravity="center_vertical" android:visibility="gone"> - + style="@style/TextAppearance.DynamicApp.Subtitle1" /> - + style="@style/TextAppearance.DynamicApp.Body1" /> @@ -71,8 +71,8 @@ android:gravity="center_vertical" android:orientation="horizontal"> - - @@ -94,11 +94,11 @@ android:layout_height="wrap_content" android:layout_weight="1.0" /> - diff --git a/dynamic-support/src/main/res/layout/ads_seek_bar_hue.xml b/dynamic-support/src/main/res/layout/ads_seek_bar_hue.xml index 175ded955a..55fdc16372 100644 --- a/dynamic-support/src/main/res/layout/ads_seek_bar_hue.xml +++ b/dynamic-support/src/main/res/layout/ads_seek_bar_hue.xml @@ -18,7 +18,7 @@ @@ -47,18 +47,18 @@ android:layout_gravity="center_vertical" android:visibility="gone"> - + style="@style/TextAppearance.DynamicApp.Subtitle1" /> - + style="@style/TextAppearance.DynamicApp.Body1" /> @@ -71,8 +71,8 @@ android:gravity="center_vertical" android:orientation="horizontal"> - - @@ -94,11 +94,11 @@ android:layout_height="wrap_content" android:layout_weight="1.0" /> - diff --git a/dynamic-support/src/main/res/layout/ads_tabs.xml b/dynamic-support/src/main/res/layout/ads_tabs.xml index b3f5afebbd..aa362bff3a 100644 --- a/dynamic-support/src/main/res/layout/ads_tabs.xml +++ b/dynamic-support/src/main/res/layout/ads_tabs.xml @@ -24,4 +24,4 @@ app:tabMinWidth="@dimen/ads_tab_min_width" app:tabMode="scrollable" app:tabContentStart="@dimen/ads_tab_inset_start" - app:ads_contrastWithColorType="primary" /> \ No newline at end of file + app:tabIndicatorHeight="@dimen/ads_tab_indicator_height" /> \ No newline at end of file diff --git a/dynamic-support/src/main/res/layout/ads_theme_preview.xml b/dynamic-support/src/main/res/layout/ads_theme_preview.xml new file mode 100644 index 0000000000..c2d5dc8522 --- /dev/null +++ b/dynamic-support/src/main/res/layout/ads_theme_preview.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dynamic-support/src/main/res/layout/ads_toolbar_collapsing.xml b/dynamic-support/src/main/res/layout/ads_toolbar_collapsing.xml index a69647fb6a..3847a4a2ef 100644 --- a/dynamic-support/src/main/res/layout/ads_toolbar_collapsing.xml +++ b/dynamic-support/src/main/res/layout/ads_toolbar_collapsing.xml @@ -27,18 +27,10 @@ android:layout_height="?attr/actionBarSize" app:layout_collapseMode="pin" app:contentInsetStartWithNavigation="@dimen/ads_toolbar_inset_start_collapsing" - app:ads_colorType="none" - app:ads_backgroundAware="false"> + app:ads_colorType="none"> - - \ No newline at end of file diff --git a/dynamic-support/src/main/res/layout/ads_toolbar_pin.xml b/dynamic-support/src/main/res/layout/ads_toolbar_pin.xml index 15169aafd4..2d6f069917 100644 --- a/dynamic-support/src/main/res/layout/ads_toolbar_pin.xml +++ b/dynamic-support/src/main/res/layout/ads_toolbar_pin.xml @@ -24,21 +24,14 @@ + app:ads_colorType="none"> - - \ No newline at end of file diff --git a/dynamic-support/src/main/res/layout/ads_toolbar_scroll.xml b/dynamic-support/src/main/res/layout/ads_toolbar_scroll.xml index c02c21f2e7..69fde37e67 100644 --- a/dynamic-support/src/main/res/layout/ads_toolbar_scroll.xml +++ b/dynamic-support/src/main/res/layout/ads_toolbar_scroll.xml @@ -24,21 +24,14 @@ + app:ads_colorType="none"> - - \ No newline at end of file diff --git a/dynamic-support/src/main/res/layout/ads_toolbar_search_view.xml b/dynamic-support/src/main/res/layout/ads_toolbar_search_view.xml index c51176ad6d..6366376e39 100644 --- a/dynamic-support/src/main/res/layout/ads_toolbar_search_view.xml +++ b/dynamic-support/src/main/res/layout/ads_toolbar_search_view.xml @@ -39,7 +39,7 @@ android:imeOptions="actionSearch|flagNoExtractUi" app:ads_colorType="tint_primary" app:ads_textColorType="tint_primary" - app:ads_backgroundAware="false" /> + app:ads_contrastWithColorType="primary" /> + app:ads_contrastWithColorType="primary" /> \ No newline at end of file diff --git a/dynamic-support/src/main/res/menu/ads_menu_about.xml b/dynamic-support/src/main/res/menu/ads_menu_about.xml index 2767799b98..3ef370d952 100644 --- a/dynamic-support/src/main/res/menu/ads_menu_about.xml +++ b/dynamic-support/src/main/res/menu/ads_menu_about.xml @@ -22,7 +22,7 @@ diff --git a/dynamic-support/src/main/res/menu/ads_menu_permissions.xml b/dynamic-support/src/main/res/menu/ads_menu_permissions.xml index 7864eb0a02..583e4c7408 100644 --- a/dynamic-support/src/main/res/menu/ads_menu_permissions.xml +++ b/dynamic-support/src/main/res/menu/ads_menu_permissions.xml @@ -22,7 +22,7 @@ diff --git a/dynamic-support/src/main/res/menu/ads_menu_theme.xml b/dynamic-support/src/main/res/menu/ads_menu_theme.xml new file mode 100644 index 0000000000..f791936b50 --- /dev/null +++ b/dynamic-support/src/main/res/menu/ads_menu_theme.xml @@ -0,0 +1,66 @@ + + + +

+ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dynamic-support/src/main/res/values-de/strings.xml b/dynamic-support/src/main/res/values-de/strings.xml index 93931c2cf6..c54888c522 100644 --- a/dynamic-support/src/main/res/values-de/strings.xml +++ b/dynamic-support/src/main/res/values-de/strings.xml @@ -23,9 +23,11 @@ Version %1$s + Keine Ergebnisse für \"%1$s\" gefunden. App + Text Symbol Größe Wert @@ -46,6 +48,7 @@ Ja, bin dabei Mehr Info Auswählen + Kopieren Speichern Laden Erstellen @@ -56,6 +59,7 @@ Fertig Letzte Eigene + Aktualisieren Bearbeiten Zurücksetzen Standard @@ -73,7 +77,7 @@ Verknüpfung erstellt Wähle eine Verknüpfung, um sie auf deine Startseite hinzuzufügen. - + Menü Unterstütze die Entwicklung Beitragen @@ -126,6 +130,7 @@ Sicherung umbenennen Sicherung wurde erfolgreich erstellt Sicherung kann nicht erstellt werden + Ungültige Sicherung Wiederherstellen Sicherung wiederherstellen Sicherung kann nicht gespeichert werden @@ -166,26 +171,36 @@ Löschen Sicherung senden - + Thema + Konfiguriere das Thema unten. Thema wird automatisch entsprechend der aktuellen Android-Version angepasst. + Ungültiges Thema + Dieses Thema konnte nicht verifiziert werden. Bitte versuchen Sie es erneut mit den entsprechenden Daten. Farbpalette Primäre und Akzent Farb-Voreinstellungen. Hintergrundfarbe Hintergrundfarbe des Themas. Primärfarbe In primären Elementen genutzte Farbe. + Systemfarbe + In systemelementen Elementen genutzte Farbe. Akzentfarbe + Sekundärefarbe In sekundären Elementen genutzte Farbe - Hintergrundberechnung - Manche Farben werden automatisch entsprechend der Hintergrundfarbe angepasst, um gute Sichtbarkeit zu garantieren. + Tönungsfarbe + Inversfarbe + Eckgröße + Eckenradius des App. + Hintergrundberechnung + Passen Sie die Farben entsprechend dem Hintergrund an, um gute Sichtbarkeit zu garantieren. App-Thema - Grundstil der App. + Stil der App. Wähle auto, um das Tages- und das Nachtthema zu benutzen. Tagesthema - Grundstil der App am Tag. + Stil der App am Tag. Nachtthema - Grundstil der App zur Nacht. + Stil der App zur Nacht. Dies wird nur funktionieren, wenn das automatische Thema ausgewählt ist. Toast-Nachricht Thema Zeige Toast-Nachrichten entsprechend der Primärfarbe. @@ -205,12 +220,19 @@ Zeige App-Verknüpfungen entsprechend der Primärfarbe. Zeige standard App-Verknüpfungen entsprechend dem Thema der App und der Symbolfarbe. Halte das Symbol im Launcher gedrückt, um App-Verknüpfungen zu zeigen. Deine Startseite muss dies unterstützen. + Thema wurde zum Standard zurückgesetzt. + Thema wurde erfolgreich importiert. + Das Thema wurde erfolgreich kopiert. - + Standard Toast-Nachricht Toast-Nachrichten mit Thema Auto - Wähle auto, um die Farbpalette der App zu benutzen. + Wählen auto, um die App-Einstellungen zu verwenden. + Wählen auto, um die Standard-Einstellungen zu verwenden. + Wähle auto, um die Farbpalette der App zu benutzen. + Wähle auto, um die Farbpalette der Standard zu benutzen. + Wähle auto, um die Farbpalette der App zu benutzen. Passen Sie die Farben entsprechend dem Hintergrund an, um gute Sichtbarkeit zu garantieren. Hell Dunkel Eigene @@ -235,6 +257,10 @@ Dunkelbraun Dunkelgrau + + Zeigen + Löschen + Alle Auswählen @@ -246,7 +272,7 @@ In dieser App genutzte Sprache. System - + Priorität der Benachrichtigung Bestimme, mit welcher Priorität die Benachrichtigung oben erscheinen soll. Wähle niedrige Priorität, um die Benachrichtigung aus der Statusleiste und vom Sperrbildschirm zu entfernen. @@ -262,6 +288,11 @@ Konfiguriere das Widget unten. Vorschau Layout des Widget kann automatisch entsprechend der Größe variieren, um gute Handhabung zu garantieren. + Kopfzeile + Sichtbarkeit des Widget-Kopfzeiles. + Wähle auto, um die Kopfzeile anzuzeigen, wenn genügend Speicherplatz verfügbar ist. + Eckenradius des Widget-Hingergrunds. + Wähle auto, um die Eckgröße der App zu benutzen. Deckkraft des Hintergrunds Deckkraft des Widget-Hingergrunds. Widget wurde zum Standard zurückgesetzt. @@ -270,6 +301,7 @@ Bewerten Kontakt + Feedback Melden Fehlerbericht senden Kontaktiere den Entwickler per Email. @@ -312,6 +344,8 @@ Übersetzungen Übersetzer Übersetzen + Werde ein Übersetzer. + Tragen Sie dazu bei, diese App in mehreren Sprachen verfügbar zu machen. Kontaktiere mich per Email, wenn du übersetzen möchtest. @@ -321,4 +355,4 @@ Quellcode Quellcode auf GitHub ansehen. - + \ No newline at end of file diff --git a/dynamic-support/src/main/res/values-es/strings.xml b/dynamic-support/src/main/res/values-es/strings.xml index e0e497793b..813010ca7b 100644 --- a/dynamic-support/src/main/res/values-es/strings.xml +++ b/dynamic-support/src/main/res/values-es/strings.xml @@ -23,9 +23,11 @@ Versión %1$s + No se encontraron resultados para \"%1$s\". Aplicación + Texto Ícono Tamaño Valor @@ -46,6 +48,7 @@ Sí, acepto Más información Seleccionar + Dupdo Guardar Cargar Crear @@ -57,6 +60,7 @@ Recientes Personalizados Editar + Actualizar Reiniciar Por defecto Organizar @@ -73,7 +77,7 @@ Atajo creado Escoge un atajo para añadirlo a la pantalla de inicio. - + Menú Inicio Configuración @@ -126,6 +130,7 @@ Renombrar respaldo El respaldo se creó exitosamente No se pudo crear el respaldo + Copia de respaldo inválida Restaurar Restaurar respaldo No se pudo guardar el respaldo @@ -166,26 +171,36 @@ Eliminar Enviar respaldo - + Tema + Configurar el tema abajo. El tema se ajustará automáticamente según la versión actual de Android. + Tema inválido + Este tema no pudo ser verificado. Por favor, intente de nuevo con los datos apropiados. Paleta de colores Color primario y de acento. Color de fondo Color de fondo del tema. Color principal Color utilizado por los elementos principales. + Color del sistema + Color utilizado por los elementos del sistema. Color de énfasis + Color secundario Color usado por los elementos secundarios. - Color automático - Algunos colores cambiarán automáticamente dependiendo del fondo para mejorar la visibilidad. + Tinte de color + Inverso de color + Tamaño de la esquina + Radio de la esquina del aplicación. + Color automático + Ajuste los colores dependiendo del fondo para mejorar la visibilidad. Tema de la aplicación - Tema base de la aplicación. + Estilo de la aplicación. Selecciona auto para usar los temas diurno y nocturno. Tema diurno - Tema base de la aplicación durante el día. + Estilo de la aplicación durante el día. Tema nocturno - Tema base de la aplicación durante la noche. + Estilo de la aplicación durante la noche. Esto funcionará únicamente cuando se aplique el tema auto. Tema de los mensajes toast Mostrar los mensajes toast coloreados según el color primario de la aplicación. @@ -198,19 +213,26 @@ Paleta de colores para la notificación. Estilo de la notificación Estilo del diseño de la notificación - Elige el estilo clásico para usar la paleta de colores como fondo + Elige clásico para usar la paleta de colores como fondo Tema del widget Paleta de colores para el widget Tema de los atajos del launcher Mostrar los atajos del launcher coloreados según el color primario de la aplicación. Mostrar los atajos de la aplicación por defecto según el tema de la aplicación y el color del ícono de Rotation. Mantén presionado el ícono del launcher para mostrar los atajos de la aplicación. Se requiere un launcher con soporte para atajos. + El tema se ha restablecido a su configuración por defecto. + El tema ha sido importado con éxito. + El tema ha sido copiado con éxito. - - Mensaje toast coloreado + Mensaje toast por defecto + Mensaje toast coloreado Auto - Elige el estilo auto para usar la paleta de colores de la aplicación. + Elige auto para usar la configuración de la aplicación. + Elige auto para usar la configuración de la defecto. + Elige auto para usar la paleta de colores de la aplicación. + Elige auto para usar la paleta de colores de la defecto. + Elige auto para usar la paleta de colores de la aplicación. Ajuste los colores dependiendo del fondo para mejorar la visibilidad. Claro Oscuro Personalizado @@ -235,6 +257,10 @@ Café oscuro Gris oscuro + + Mostrar + Esconder + Todo Escoger @@ -246,7 +272,7 @@ Idioma utilizado por la aplicación. Sistema - + Prioridad de la notificación Escoge una prioridad para determinar el orden de la notificación en el cajón de notificaciones. Escoge la prioridad baja para esconder la notificación en la barra de estado y la pantalla de bloqueo. @@ -259,9 +285,14 @@ Personalizar + Configurar el widget abajo. Previsualización El diseño del widget puede cambiar automáticamente según su tamaño real para una mejor experiencia. - Configurar el widget abajo. + Encabezamiento + Visibilidad del encabezado del widget. + Selecciona auto para mostrar el encabezado si hay suficiente espacio disponible. + Radio de la esquina del fondo del widget. + Elige auto para usar la tamaño de la esquina de la aplicación. Opacidad del fondo Opacidad del fondo del widget. El widget se ha restablecido a su configuración por defecto. @@ -270,6 +301,7 @@ Calificar Contacto + Realimentación Reportar Enviar reporte de error Contactar al desarrollador por correo @@ -312,6 +344,8 @@ Traducciones Traductores Traducir + Conviértete en un traductor. + Contribuye para que esta aplicación esté disponible en más idiomas. Contácteme por correo si desea traducir. @@ -321,4 +355,4 @@ Fuentes Ver las fuentes en GitHub. - + \ No newline at end of file diff --git a/dynamic-support/src/main/res/values-land/dimens.xml b/dynamic-support/src/main/res/values-land/dimens.xml index 9baa282dfa..35813a5708 100644 --- a/dynamic-support/src/main/res/values-land/dimens.xml +++ b/dynamic-support/src/main/res/values-land/dimens.xml @@ -18,7 +18,7 @@ - 300dp + 320dp 160dp diff --git a/dynamic-support/src/main/res/values-night/colors.xml b/dynamic-support/src/main/res/values-night/colors.xml index 6d735bc8a0..94f2b8200e 100644 --- a/dynamic-support/src/main/res/values-night/colors.xml +++ b/dynamic-support/src/main/res/values-night/colors.xml @@ -24,6 +24,7 @@ @color/ads_card_background + @color/ads_color_control @color/ads_window_background \ No newline at end of file diff --git a/dynamic-support/src/main/res/values-sw400dp/dimens.xml b/dynamic-support/src/main/res/values-sw400dp/dimens.xml new file mode 100644 index 0000000000..bc1c3d9468 --- /dev/null +++ b/dynamic-support/src/main/res/values-sw400dp/dimens.xml @@ -0,0 +1,24 @@ + + + + + + + 320dp + 360dp + + \ No newline at end of file diff --git a/dynamic-support/src/main/res/values-sw600dp/dimens.xml b/dynamic-support/src/main/res/values-sw600dp/dimens.xml index f2711ae3af..cd6e0022b6 100644 --- a/dynamic-support/src/main/res/values-sw600dp/dimens.xml +++ b/dynamic-support/src/main/res/values-sw600dp/dimens.xml @@ -18,7 +18,7 @@ - 280dp + 300dp @dimen/ads_drawer_size 240dp @@ -26,6 +26,7 @@ 240dp - 400dp + 380dp + 400dp \ No newline at end of file diff --git a/dynamic-support/src/main/res/values-sw720dp/dimens.xml b/dynamic-support/src/main/res/values-sw720dp/dimens.xml index 9341346ceb..593f5c6166 100644 --- a/dynamic-support/src/main/res/values-sw720dp/dimens.xml +++ b/dynamic-support/src/main/res/values-sw720dp/dimens.xml @@ -18,6 +18,6 @@ - 300dp + 320dp \ No newline at end of file diff --git a/dynamic-support/src/main/res/values-tr/strings.xml b/dynamic-support/src/main/res/values-tr/strings.xml index 30d72d91b5..81b7f814b8 100644 --- a/dynamic-support/src/main/res/values-tr/strings.xml +++ b/dynamic-support/src/main/res/values-tr/strings.xml @@ -22,9 +22,11 @@ Sürüm %1$s + \"%1$s\" için eşleşme bulunamadı. Uygulama + Metin Simge Boyut Değer @@ -45,6 +47,7 @@ Evet, İlgiliyim Daha fazla bilgi Seç + Kopya Kaydet Yükle Oluştur @@ -56,6 +59,7 @@ Son Özel Düzenle + Yenile Sıfırla Varsayılan Sırala @@ -72,7 +76,7 @@ Kısayol oluşturuldu Ana ekrana eklemek için bir kısayol seçin. - + Menü Ana sayfa Ayarlar @@ -125,6 +129,7 @@ Yedeği yeniden adlandır Yedek başarıyla oluşturuldu Yedek oluşturulamadı + Geçersiz yedek Geri yükle Yedeği geri yükle Yedek kaydedilemiyor @@ -165,26 +170,36 @@ Sil Yedeği gönder - + Tema + Tema\'ı aşağıdan yapılandırın. Tema mevcut Android sürümüne göre otomatik olarak ayarlanacaktır. + Geçersiz tema + Bu tema doğrulanamadı. Lütfen uygun verilerle tekrar deneyin. Renk paleti Birincil ve vurgu rengi hazır ayarları. Arka plan rengi Temanın arka plan rengi. Ana renk Ana öğeler tarafından kullanılan renk. + Sistem renk + Sistem öğeler tarafından kullanılan renk. Vurgu rengi + Ara renk İkincil öğeler tarafından kullanılan renk. - Arka plan farkında - Bazı renkler en iyi görünürlüğü sağlamak için arka plana göre otomatik olarak değişecektir. + Ton renk + Ters renk + Köşe ölçüsü + Uygulamanın köşe yarıçapı. + Arka plan farkında + En iyi görmeyi sağlamak için renkleri arka plana göre ayarlayın. Uygulama teması - Uygulamanın temel stili. + Uygulamanın stili. Gündüz ve gece temalarını kullanmak için otomatiği seçin. Gündüz teması - Gün boyunca uygulamanın temel stili. + Gün boyunca uygulamanın stili. Gece teması - Geceleri uygulamanın temel stili. + Geceleri uygulamanın stili. Bu sadece otomatik tema uygulandığında çalışır. Bildirim mesajları teması Uygulama ana rengine göre temalı bildirim mesajlarını göster. @@ -204,12 +219,19 @@ Uygulama ana rengine göre temalı uygulama kısayollarını göster. Uygulama temasına ve marka rengine göre varsayılan uygulama kısayollarını göster. Uygulama kısayollarını göstermek için başlatıcı simgesine uzun basın, başlatıcı desteği gerekir. + Tema varsayılana sıfırlandı. + Tema başarıyla içe aktarıldı. + Tema başarıyla kopyalandı. - - Temalı bildirim mesajı + Varsayılan bildirim mesajı + Temalı bildirim mesajı Otomatik - Uygulama renk paletini kullanmak için otomatiği seçin. + Uygulama ayarlarını kullanmak için otomatik seçin. + Varsayılan ayarlarını kullanmak için otomatik seçin. + Uygulama renk paletini kullanmak için otomatiği seçin. + Varsayılan renk paletini kullanmak için otomatiği seçin. + Uygulama renk paletini kullanmak için otomatiği seçin. En iyi görmeyi sağlamak için renkleri arka plana göre ayarlayın. Açık Koyu Özel @@ -234,6 +256,10 @@ Koyu kahverengi Koyu gri + + Göstermek + Gizlemek + Tümü Seç @@ -245,7 +271,7 @@ Uygulama tarafından kullanılan dil. Sistem - + Bildirim önceliği Bildirim çekmecesindeki sırasını belirlemek için öncelik seçin. Bildirimi durum çubuğundan ve kilit ekranından gizlemek için düşük önceliği seçin. @@ -258,9 +284,14 @@ Özelleştir + Widget\'ı aşağıdan yapılandırın. Önizleme Widget düzeni, en iyi deneyimi sağlamak için kullanılan gerçek boyuta göre otomatik olarak değişebilir. - Widget\'ı aşağıdan yapılandırın. + Başlık + Widget başlığının görünürlüğü. + Yeterli alan varsa başlığı göstermek için otomatik seçeneğini seçin. + Widget arka planının köşe yarıçapı. + Uygulama köşe ölçüsü kullanmak için otomatiği seçin. Arka plan opaklığı Widget arka planının opaklığı. Widget varsayılana sıfırlandı. @@ -269,6 +300,7 @@ Oyla İletişim + Geri bildirim Bildir Hata raporu gönder E-posta ile geliştiriciyle iletişime geç. @@ -311,6 +343,8 @@ Çeviriler Çevirenler Çevir + Çevirmen ol. + Bu uygulamayı daha fazla dilde kullanıma sunmak için katkıda bulunun. Çevirmek isterseniz e-posta ile ulaşın. @@ -320,4 +354,4 @@ Kaynaklar GitHub\'daki kaynakları görüntüleyin. - + \ No newline at end of file diff --git a/dynamic-support/src/main/res/values-v21/dimens.xml b/dynamic-support/src/main/res/values-v21/dimens.xml index a9faa22905..8cc981b11d 100644 --- a/dynamic-support/src/main/res/values-v21/dimens.xml +++ b/dynamic-support/src/main/res/values-v21/dimens.xml @@ -17,7 +17,22 @@ + + @dimen/ads_margin_regular + @dimen/ads_margin_regular + @dimen/ads_margin_tiny + + @dimen/ads_margin_small + @dimen/ads_margin_small + @dimen/ads_margin_normal + @dimen/ads_dialog_margin_small + + + @dimen/ads_margin_small + 0dp + 0dp + \ No newline at end of file diff --git a/dynamic-support/src/main/res/values-v21/themes.xml b/dynamic-support/src/main/res/values-v21/themes.xml index e0b4641c5d..588a5274ef 100644 --- a/dynamic-support/src/main/res/values-v21/themes.xml +++ b/dynamic-support/src/main/res/values-v21/themes.xml @@ -71,9 +71,11 @@ - @@ -47,39 +66,77 @@ @color/ads_card_background_dark - - @@ -125,6 +182,7 @@ @layout/ads_dialog_select_item @layout/ads_dialog_multi_choice @layout/ads_dialog_single_choice + @dimen/ads_dialog_button_icon_size - - - - + + - + + + + + + + + - - - - + + - - - - - - + + + + + + + + + + - - + + + + - - + + + + + + + + + + + + + + + + + + - + + - + + + + + + - - - - - - - - - - - - diff --git a/gradle.properties b/gradle.properties index e617e5f2fc..f6853fb4f5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,14 +1,19 @@ # Project-wide Gradle settings. - # IDE (e.g. Android Studio) users: # Gradle settings configured through the IDE *will override* # any settings specified in this file. - # For more details on how to configure your build environment visit # http://www.gradle.org/docs/current/userguide/build_environment.html - -# Daemon heap size 1.5GB. -org.gradle.jvmargs=-Xmx1536M - -# Enable the build cache. -org.gradle.caching=true \ No newline at end of file +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true \ No newline at end of file diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index c74a894d51..2b92df0006 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -15,7 +15,8 @@ limitations under the License. --> - + android:allowBackup="false"> diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/SampleApplication.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/SampleApplication.kt index 509f7bdf31..7e638590e0 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/SampleApplication.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/SampleApplication.kt @@ -26,10 +26,10 @@ import android.graphics.drawable.Icon import android.graphics.drawable.LayerDrawable import android.os.Build import android.os.Handler -import android.support.annotation.ColorInt -import android.support.annotation.DrawableRes -import android.support.annotation.StyleRes -import android.support.v4.graphics.drawable.IconCompat +import androidx.annotation.ColorInt +import androidx.annotation.DrawableRes +import androidx.annotation.StyleRes +import androidx.core.graphics.drawable.IconCompat import com.pranavpandey.android.dynamic.support.DynamicApplication import com.pranavpandey.android.dynamic.support.sample.activity.ActionActivity import com.pranavpandey.android.dynamic.support.sample.controller.Constants @@ -42,27 +42,23 @@ import com.pranavpandey.android.dynamic.utils.DynamicVersionUtils import java.util.* /** - * Sample application extending the [DynamicApplication], - * it must be done to initialize the base components of dynamic - * support library. + * Sample application extending the [DynamicApplication], it must be done to initialize the + * base components of dynamic support library. * - * This must be registered in the manifest using `name` - * attribute of the `application` tag. + * This must be registered in the manifest using `name` attribute of the `application` tag. */ class SampleApplication : DynamicApplication() { companion object { /** - * Theme change delay to apply correct app shortcuts - * theme. + * Theme change delay to apply correct app shortcuts theme. */ const val THEME_CHANGE_DELAY = 150 } override fun onInitialize() { - // Do any startup work here like initializing the other - // libraries, analytics, etc. + // Do any startup work here like initializing the other libraries, analytics, etc. SampleController.initializeInstance(this) } @@ -150,9 +146,8 @@ class SampleApplication : DynamicApplication() { } /** - * Generate a dynamic app shortcut icon from the supplied - * drawable resource and theme it according the app colors. - * It must contain a background and foreground layers with + * Generate a dynamic app shortcut icon from the supplied drawable resource and theme + * it according the app colors. It must contain a background and foreground layers with * the appropriate ids. * * @param context The context to retrieve the resources. @@ -160,13 +155,13 @@ class SampleApplication : DynamicApplication() { */ @TargetApi(Build.VERSION_CODES.M) private fun getShortcutIcon(context: Context, @DrawableRes drawableRes: Int): Icon? { - @ColorInt var primaryColor = DynamicTheme.getInstance().primaryColor - @ColorInt var tintPrimaryColor = DynamicTheme.getInstance().tintPrimaryColor + @ColorInt var primaryColor = DynamicTheme.getInstance().get().primaryColor + @ColorInt var tintPrimaryColor = DynamicTheme.getInstance().get().tintPrimaryColor val drawable = DynamicResourceUtils.getDrawable(context, drawableRes) if (!SampleController.instance.isThemeAppShortcuts) { - primaryColor = DynamicTheme.getInstance().backgroundColor - tintPrimaryColor = DynamicTheme.getInstance().tintBackgroundColor + primaryColor = DynamicTheme.getInstance().get().backgroundColor + tintPrimaryColor = DynamicTheme.getInstance().get().tintBackgroundColor } if (drawable != null) { @@ -175,8 +170,7 @@ class SampleApplication : DynamicApplication() { DynamicDrawableUtils.colorizeDrawable(drawable .findDrawableByLayerId(R.id.foreground), tintPrimaryColor) - // Use IconCompat to support adaptive icons on Android O - // or above devices. + // Use IconCompat to support adaptive icons on Android O or above devices. return IconCompat.createWithAdaptiveBitmap(DynamicResourceUtils .getBitmapFromVectorDrawable(drawable)!!).toIcon() } diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/ActionActivity.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/ActionActivity.kt index 2be5221e14..b05f743248 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/ActionActivity.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/ActionActivity.kt @@ -23,8 +23,9 @@ import com.pranavpandey.android.dynamic.support.sample.controller.Constants import com.pranavpandey.android.dynamic.utils.DynamicLinkUtils /** - * Activity to handle app shortcuts intent. For now, just - * opening the GitHub page. + * Activity to handle app shortcuts intent. + * + * For now, just opening the GitHub page. */ class ActionActivity : Activity() { diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/BottomNavigationActivity.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/BottomNavigationActivity.kt index 84937a4332..af5030b890 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/BottomNavigationActivity.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/BottomNavigationActivity.kt @@ -17,7 +17,7 @@ package com.pranavpandey.android.dynamic.support.sample.activity import android.os.Bundle -import android.support.annotation.StyleRes +import androidx.annotation.StyleRes import com.pranavpandey.android.dynamic.support.activity.DynamicActivity import com.pranavpandey.android.dynamic.support.activity.DynamicDrawerActivity import com.pranavpandey.android.dynamic.support.sample.R @@ -34,8 +34,7 @@ import com.pranavpandey.android.dynamic.utils.DynamicLinkUtils import java.util.* /** - * Implementing a bottom navigation view by using - * [DynamicDrawerActivity]. + * Implementing a bottom navigation view by using [DynamicDrawerActivity]. */ class BottomNavigationActivity : DynamicActivity() { @@ -130,9 +129,9 @@ class BottomNavigationActivity : DynamicActivity() { */ private fun themeBottomNavigationView() { if (mBottomNavigationView != null) { - mBottomNavigationView!!.color = DynamicTheme.getInstance().primaryColor + mBottomNavigationView!!.color = DynamicTheme.getInstance().get().primaryColor mBottomNavigationView!!.textColor = DynamicColorUtils.getTintColor( - DynamicTheme.getInstance().primaryColor) + DynamicTheme.getInstance().get().primaryColor) } } diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/CollapsingAppBarActivity.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/CollapsingAppBarActivity.kt index 4919025337..bb7092cc99 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/CollapsingAppBarActivity.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/CollapsingAppBarActivity.kt @@ -17,10 +17,10 @@ package com.pranavpandey.android.dynamic.support.sample.activity import android.os.Bundle -import android.support.annotation.StyleRes import android.view.View import android.widget.ImageView import android.widget.TextView +import androidx.annotation.StyleRes import com.pranavpandey.android.dynamic.support.activity.DynamicActivity import com.pranavpandey.android.dynamic.support.sample.R import com.pranavpandey.android.dynamic.support.sample.controller.SampleController @@ -29,8 +29,7 @@ import com.pranavpandey.android.dynamic.support.sample.fragment.AppSettingsFragm import java.util.* /** - * Implementing a collapsing app bar layout by using - * [DynamicActivity]. + * Implementing a collapsing app bar layout by using [DynamicActivity]. */ class CollapsingAppBarActivity : DynamicActivity() { diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/DrawerActivity.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/DrawerActivity.kt index 9ea6d06942..3331b823a0 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/DrawerActivity.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/DrawerActivity.kt @@ -19,10 +19,10 @@ package com.pranavpandey.android.dynamic.support.sample.activity import android.content.Intent import android.os.Bundle import android.os.Handler -import android.support.annotation.IdRes -import android.support.annotation.StyleRes -import android.support.v4.view.GravityCompat import android.view.MenuItem +import androidx.annotation.IdRes +import androidx.annotation.StyleRes +import androidx.core.view.GravityCompat import com.pranavpandey.android.dynamic.support.activity.DynamicDrawerActivity import com.pranavpandey.android.dynamic.support.sample.R import com.pranavpandey.android.dynamic.support.sample.controller.Constants @@ -125,7 +125,7 @@ class DrawerActivity : DynamicDrawerActivity() { switchFragment(AboutFragment.newInstance(0), false) } R.id.nav_donate -> DynamicLinkUtils.viewUrl(this, Constants.URL_DONATE) - R.id.nav_share -> DynamicLinkUtils.shareApp(this, null, + R.id.nav_share -> DynamicLinkUtils.share(this, null, String.format(getString(R.string.ads_format_next_line), getString(R.string.app_share), Constants.URL_GITHUB)) } diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/SplashActivity.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/SplashActivity.kt index 73828087ed..44f1c0d30f 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/SplashActivity.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/SplashActivity.kt @@ -18,9 +18,9 @@ package com.pranavpandey.android.dynamic.support.sample.activity import android.content.Intent import android.graphics.drawable.Animatable -import android.support.annotation.StyleRes -import android.support.v7.widget.AppCompatImageView import android.view.View +import androidx.annotation.StyleRes +import androidx.appcompat.widget.AppCompatImageView import com.pranavpandey.android.dynamic.support.sample.R import com.pranavpandey.android.dynamic.support.sample.controller.SampleController import com.pranavpandey.android.dynamic.support.sample.controller.SampleTheme @@ -52,8 +52,8 @@ class SplashActivity : DynamicSplashActivity() { override fun onCustomiseTheme() { // Customise activity theme after applying the base style. SampleTheme.setLocalTheme(this) - DynamicTheme.getInstance().setLocalPrimaryColorDark( - DynamicTheme.getInstance().localPrimaryColor, true) + DynamicTheme.getInstance().get().setPrimaryColorDark( + DynamicTheme.getInstance().get().primaryColor, true) } override fun setNavigationBarTheme(): Boolean { diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/TutorialActivity.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/TutorialActivity.kt index 3a6177569d..34f88af246 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/TutorialActivity.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/activity/TutorialActivity.kt @@ -17,8 +17,8 @@ package com.pranavpandey.android.dynamic.support.sample.activity import android.os.Bundle -import android.support.annotation.StyleRes -import android.support.v4.view.ViewPager +import androidx.annotation.StyleRes +import androidx.viewpager.widget.ViewPager import com.pranavpandey.android.dynamic.support.sample.R import com.pranavpandey.android.dynamic.support.sample.controller.Constants import com.pranavpandey.android.dynamic.support.sample.controller.SampleController @@ -72,8 +72,7 @@ class TutorialActivity : DynamicTutorialActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - // Add a view pager listener to perform actions according to the - // tutorial screen. + // Add a view pager listener to perform actions according to the tutorial screen. viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { @@ -95,8 +94,7 @@ class TutorialActivity : DynamicTutorialActivity() { override fun onResume() { super.onResume() - // Update action button after performing some action like - // granting a permission. + // Update action button after performing some action like granting a permission. if (viewPagerAdapter != null) { setTutorialAction(viewPager.currentItem) } @@ -134,7 +132,7 @@ class TutorialActivity : DynamicTutorialActivity() { // TODO: Add a simple dynamic tutorial. tutorials.add(DynamicSimpleTutorial(TUTORIAL_WELCOME, - DynamicTheme.getInstance().primaryColor, + DynamicTheme.getInstance().get().primaryColor, getString(R.string.tutorial_welcome), getString(R.string.tutorial_welcome_subtitle), getString(R.string.tutorial_welcome_desc), @@ -142,7 +140,7 @@ class TutorialActivity : DynamicTutorialActivity() { // TODO: Add another simple dynamic tutorial. tutorials.add(DynamicSimpleTutorial(TUTORIAL_FINISH, - DynamicTheme.getInstance().accentColor, + DynamicTheme.getInstance().get().accentColor, getString(R.string.tutorial_finish), getString(R.string.tutorial_finish_subtitle), getString(R.string.tutorial_finish_desc), diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/adapter/AppInfoAdapter.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/adapter/AppInfoAdapter.kt index eb5040dc2b..6f9e8ec594 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/adapter/AppInfoAdapter.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/adapter/AppInfoAdapter.kt @@ -23,8 +23,7 @@ import com.pranavpandey.android.dynamic.support.sample.binder.AuthorInfoBinder import com.pranavpandey.android.dynamic.support.sample.binder.TranslatorsBinder /** - * A binder adapter to display a list of [DynamicInfo] by - * using [DynamicSimpleBinderAdapter]. + * A binder adapter to display a list of [DynamicInfo] by using [DynamicSimpleBinderAdapter]. */ class AppInfoAdapter : DynamicSimpleBinderAdapter() { diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/adapter/LicensesAdapter.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/adapter/LicensesAdapter.kt index dd31040521..ca5d7a818b 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/adapter/LicensesAdapter.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/adapter/LicensesAdapter.kt @@ -16,7 +16,6 @@ package com.pranavpandey.android.dynamic.support.sample.adapter -import android.support.v7.widget.RecyclerView import com.pranavpandey.android.dynamic.support.model.DynamicInfo import com.pranavpandey.android.dynamic.support.recyclerview.adapter.DynamicSimpleBinderAdapter import com.pranavpandey.android.dynamic.support.recyclerview.binder.DynamicInfoBigBinder @@ -24,14 +23,12 @@ import com.pranavpandey.android.dynamic.support.sample.binder.LicenseBinder import java.util.* /** - * A binder adapter to display a list of [DynamicInfo] by - * using [DynamicSimpleBinderAdapter]. + * A binder adapter to display a list of [DynamicInfo] by using [DynamicSimpleBinderAdapter]. */ class LicensesAdapter( /** * Data set used by this adapter. - * Getter for [.mDataSet]. */ private val dataSet: ArrayList?) : DynamicSimpleBinderAdapter() { @@ -45,7 +42,7 @@ class LicensesAdapter( return 0 } - override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) { + override fun onBindViewHolder(viewHolder: androidx.recyclerview.widget.RecyclerView.ViewHolder, position: Int) { (getDataBinder(getItemViewType(position)) as DynamicInfoBigBinder).data = getItem(position) @@ -57,9 +54,11 @@ class LicensesAdapter( } /** - * @return The item according the position. + * Returns the item according the position. * * @param position The position to retrieve the item. + * + * @return The item according the position. */ private fun getItem(position: Int): DynamicInfo { return dataSet!![position] diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/binder/AppInfoBinder.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/binder/AppInfoBinder.kt index 3c58e6868b..2f8c56a08f 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/binder/AppInfoBinder.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/binder/AppInfoBinder.kt @@ -16,11 +16,10 @@ package com.pranavpandey.android.dynamic.support.sample.binder -import android.support.v7.widget.RecyclerView import android.view.LayoutInflater import android.view.View import android.view.ViewGroup - +import androidx.recyclerview.widget.RecyclerView import com.pranavpandey.android.dynamic.support.recyclerview.adapter.DynamicBinderAdapter import com.pranavpandey.android.dynamic.support.recyclerview.binder.DynamicRecyclerViewBinder import com.pranavpandey.android.dynamic.support.sample.R @@ -28,8 +27,7 @@ import com.pranavpandey.android.dynamic.support.utils.DynamicLayoutUtils import com.pranavpandey.android.dynamic.support.view.DynamicInfoView /** - * A recycler view binder to display app info by using - * [DynamicRecyclerViewBinder]. + * A recycler view binder to display app info by using [DynamicRecyclerViewBinder]. */ class AppInfoBinder(dynamicBinderAdapter: DynamicBinderAdapter) : DynamicRecyclerViewBinder(dynamicBinderAdapter) { diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/binder/AuthorInfoBinder.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/binder/AuthorInfoBinder.kt index 896ec42271..a970f750ac 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/binder/AuthorInfoBinder.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/binder/AuthorInfoBinder.kt @@ -16,11 +16,10 @@ package com.pranavpandey.android.dynamic.support.sample.binder -import android.support.v7.widget.RecyclerView import android.view.LayoutInflater import android.view.View import android.view.ViewGroup - +import androidx.recyclerview.widget.RecyclerView import com.pranavpandey.android.dynamic.support.recyclerview.adapter.DynamicBinderAdapter import com.pranavpandey.android.dynamic.support.recyclerview.binder.DynamicRecyclerViewBinder import com.pranavpandey.android.dynamic.support.sample.R @@ -28,8 +27,7 @@ import com.pranavpandey.android.dynamic.support.utils.DynamicLayoutUtils import com.pranavpandey.android.dynamic.support.view.DynamicInfoView /** - * A recycler view binder to display author info by using - * [DynamicRecyclerViewBinder]. + * A recycler view binder to display author info by using [DynamicRecyclerViewBinder]. */ class AuthorInfoBinder(dynamicBinderAdapter: DynamicBinderAdapter) : DynamicRecyclerViewBinder(dynamicBinderAdapter) { diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/binder/LicenseBinder.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/binder/LicenseBinder.kt index 128b62b3c2..e3710cc9d3 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/binder/LicenseBinder.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/binder/LicenseBinder.kt @@ -16,18 +16,16 @@ package com.pranavpandey.android.dynamic.support.sample.binder -import android.support.v7.widget.RecyclerView import android.view.LayoutInflater import android.view.ViewGroup - +import androidx.recyclerview.widget.RecyclerView import com.pranavpandey.android.dynamic.support.recyclerview.adapter.DynamicBinderAdapter import com.pranavpandey.android.dynamic.support.recyclerview.binder.DynamicInfoBigBinder import com.pranavpandey.android.dynamic.support.recyclerview.binder.DynamicRecyclerViewBinder import com.pranavpandey.android.dynamic.support.sample.R /** - * A recycler view binder to display licenses by using - * [DynamicRecyclerViewBinder]. + * A recycler view binder to display licenses by using [DynamicRecyclerViewBinder]. */ class LicenseBinder(dynamicBinderAdapter: DynamicBinderAdapter) : DynamicInfoBigBinder(dynamicBinderAdapter) { diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/binder/TranslatorsBinder.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/binder/TranslatorsBinder.kt index 0f2e29297c..81e1c47c8c 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/binder/TranslatorsBinder.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/binder/TranslatorsBinder.kt @@ -16,12 +16,11 @@ package com.pranavpandey.android.dynamic.support.sample.binder -import android.support.annotation.ColorInt -import android.support.v7.widget.RecyclerView import android.view.LayoutInflater import android.view.View import android.view.ViewGroup - +import androidx.annotation.ColorInt +import androidx.recyclerview.widget.RecyclerView import com.pranavpandey.android.dynamic.support.recyclerview.adapter.DynamicBinderAdapter import com.pranavpandey.android.dynamic.support.recyclerview.binder.DynamicRecyclerViewBinder import com.pranavpandey.android.dynamic.support.sample.R @@ -31,8 +30,7 @@ import com.pranavpandey.android.dynamic.support.view.DynamicInfoView import com.pranavpandey.android.dynamic.support.widget.DynamicImageView /** - * A recycler view binder to display translators info by using - * [DynamicRecyclerViewBinder]. + * A recycler view binder to display translators info by using [DynamicRecyclerViewBinder]. */ class TranslatorsBinder(dynamicBinderAdapter: DynamicBinderAdapter) : DynamicRecyclerViewBinder(dynamicBinderAdapter) { @@ -60,15 +58,15 @@ class TranslatorsBinder(dynamicBinderAdapter: DynamicBinderAdapter) init { dynamicInfoView.linksView.recyclerViewLayoutManager = DynamicLayoutUtils.getGridLayoutManager(dynamicInfoView.context, - DynamicLayoutUtils.getGridCount(dynamicInfoView.context)) + DynamicLayoutUtils.getGridCountCompact(dynamicInfoView.context)) (dynamicInfoView.iconView as DynamicImageView).color = - DynamicTheme.getInstance().primaryColor + DynamicTheme.getInstance().get().primaryColor if (dynamicInfoView.linksColors != null) { @ColorInt val colors = dynamicInfoView.linksColors - colors?.set(colors.size - 1, DynamicTheme.getInstance().accentColor) + colors?.set(colors.size - 1, DynamicTheme.getInstance().get().accentColor) dynamicInfoView.linksColors = colors - dynamicInfoView.update() + dynamicInfoView.onUpdate() } } } diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/controller/Constants.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/controller/Constants.kt index 200ed0f558..c69c3469ea 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/controller/Constants.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/controller/Constants.kt @@ -17,9 +17,8 @@ package com.pranavpandey.android.dynamic.support.sample.controller import android.graphics.Color -import android.support.annotation.ColorInt - -import com.pranavpandey.android.dynamic.support.theme.DynamicTheme +import androidx.annotation.ColorInt +import com.pranavpandey.android.dynamic.support.theme.Theme /** * Helper class to hold constants and shared preferences. @@ -62,7 +61,7 @@ object Constants { * * `Auto` to use day and night themes. */ - @ColorInt const val APP_THEME_COLOR = DynamicTheme.ADS_THEME_AUTO + @ColorInt const val APP_THEME_COLOR = Theme.AUTO /** * TODO: Default value for app theme day color. diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/controller/SampleController.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/controller/SampleController.kt index 222df34317..2674b924e9 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/controller/SampleController.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/controller/SampleController.kt @@ -17,12 +17,11 @@ package com.pranavpandey.android.dynamic.support.sample.controller import android.app.Application -import android.support.annotation.ColorInt +import androidx.annotation.ColorInt import com.pranavpandey.android.dynamic.support.preference.DynamicPreferences /** - * Singleton class to perform common operations throughout - * the app. + * Singleton class to perform common operations throughout the app. */ class SampleController { @@ -32,8 +31,7 @@ class SampleController { var context: Application? = null /** - * Getter and Setter for the [Constants.PREF_FIRST_LAUNCH] - * shared preference. + * Getter and Setter for the [Constants.PREF_FIRST_LAUNCH] shared preference. */ var isFirstLaunch: Boolean get() = DynamicPreferences.getInstance().loadPrefs( @@ -43,7 +41,7 @@ class SampleController { Constants.PREF_FIRST_LAUNCH, firstLaunch) /** - * @return The app theme primary color. + * The app theme primary color. */ val colorPrimaryApp: Int @ColorInt get() = DynamicPreferences.getInstance().loadPrefs( @@ -51,7 +49,7 @@ class SampleController { Constants.PREF_SETTINGS_APP_THEME_COLOR_PRIMARY_DEFAULT) /** - * @return The app theme accent color. + * The app theme accent color. */ val colorAccentApp: Int @ColorInt get() = DynamicPreferences.getInstance().loadPrefs( @@ -59,7 +57,7 @@ class SampleController { Constants.PREF_SETTINGS_APP_THEME_COLOR_ACCENT_DEFAULT) /** - * @return `true` to apply the navigation bar theme. + * true` to apply the navigation bar theme. */ val isThemeNavigationBar: Boolean get() = DynamicPreferences.getInstance().loadPrefs( @@ -67,7 +65,7 @@ class SampleController { Constants.PREF_SETTINGS_NAVIGATION_BAR_THEME_DEFAULT) /** - * @return `true` to apply the app shortcuts theme. + * true` to apply the app shortcuts theme. */ val isThemeAppShortcuts: Boolean get() = DynamicPreferences.getInstance().loadPrefs( @@ -75,8 +73,8 @@ class SampleController { Constants.PREF_SETTINGS_APP_SHORTCUTS_THEME_DEFAULT) /** - * Making default constructor private so that it cannot be initialized - * without a context. Use [.initializeInstance] instead. + * Making default constructor private so that it cannot be initialized without a context. + * Use [.initializeInstance] instead. */ private constructor() {} @@ -95,8 +93,8 @@ class SampleController { private var sInstance: SampleController? = null /** - * Initialize this controller when application starts. Must be - * initialize once. + * Initialize this controller when application starts. + * Must be initialize once. * * @param context The context to retrieve resources. */ @@ -112,8 +110,8 @@ class SampleController { } /** - * Get instance to access public methods. Must be called before accessing - * methods. + * Get instance to access public methods. + * Must be called before accessing methods. * * @return [.sInstance] Singleton [SampleController] instance. */ diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/controller/SampleTheme.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/controller/SampleTheme.kt index 3fbadfb9e6..e645134463 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/controller/SampleTheme.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/controller/SampleTheme.kt @@ -17,12 +17,13 @@ package com.pranavpandey.android.dynamic.support.sample.controller import android.content.Context -import android.support.annotation.ColorInt -import android.support.annotation.StyleRes +import androidx.annotation.ColorInt +import androidx.annotation.StyleRes import com.pranavpandey.android.dynamic.support.preference.DynamicPreferences import com.pranavpandey.android.dynamic.support.sample.R import com.pranavpandey.android.dynamic.support.theme.DynamicTheme +import com.pranavpandey.android.dynamic.support.theme.Theme import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils import com.pranavpandey.android.dynamic.utils.DynamicColorUtils @@ -32,9 +33,9 @@ import com.pranavpandey.android.dynamic.utils.DynamicColorUtils object SampleTheme { /** - * @return `true` if `auto` theme is selected. + * `true` if `auto` theme is selected. */ - val isAutoTheme: Boolean get() = appThemeColor == DynamicTheme.ADS_THEME_AUTO + val isAutoTheme: Boolean get() = appThemeColor == Theme.AUTO /** @@ -68,11 +69,10 @@ object SampleTheme { Constants.PREF_SETTINGS_APP_THEME_NIGHT_COLOR, color) /** - * @return The app theme style according to the current - * settings. + * The app theme style according to the current settings. */ val splashStyle: Int - @StyleRes get() = if (appThemeColor == DynamicTheme.ADS_THEME_AUTO) { + @StyleRes get() = if (appThemeColor == Theme.AUTO) { getSplashStyle(if (DynamicResourceUtils.isNight()) appThemeNightColor else @@ -82,11 +82,10 @@ object SampleTheme { } /** - * @return The app theme splash style according to the current - * settings. + * The app theme splash style according to the current settings. */ val appStyle: Int - @StyleRes get() = if (appThemeColor == DynamicTheme.ADS_THEME_AUTO) { + @StyleRes get() = if (appThemeColor == Theme.AUTO) { getAppStyle(if (DynamicResourceUtils.isNight()) appThemeNightColor else @@ -96,11 +95,10 @@ object SampleTheme { } /** - * @return The background color according to the current - * settings. + * The background color according to the current settings. */ private val backgroundColor: Int - @ColorInt get() = if (appThemeColor == DynamicTheme.ADS_THEME_AUTO) { + @ColorInt get() = if (appThemeColor == Theme.AUTO) { if (DynamicResourceUtils.isNight()) appThemeNightColor else @@ -110,9 +108,11 @@ object SampleTheme { } /** - * @return The app theme style according to the supplied color. + * Returns the app theme style according to the supplied color. * * @param color The color used for the background. + * + * @return The app theme style according to the supplied color. */ @StyleRes private fun getAppStyle(@ColorInt color: Int): Int { return if (DynamicColorUtils.isColorDark(color)) @@ -122,10 +122,12 @@ object SampleTheme { } /** - * @return The app theme splash style according to the supplied - * color. + * + * Returns the app theme splash style according to the supplied color. * * @param color The color used for the background. + * + * @return The app theme splash style according to the supplied color. */ @StyleRes private fun getSplashStyle(@ColorInt color: Int): Int { return if (DynamicColorUtils.isColorDark(color)) @@ -141,12 +143,11 @@ object SampleTheme { */ fun setApplicationTheme(applicationContext: Context) { @ColorInt val colorPrimary = SampleController.instance.colorPrimaryApp - DynamicTheme.getInstance().setPrimaryColor(colorPrimary) + DynamicTheme.getInstance().application.setPrimaryColor(colorPrimary) .setPrimaryColorDark(DynamicColorUtils.shiftColor( colorPrimary, DynamicTheme.ADS_COLOR_SHIFT_DARK_DEFAULT)) .setAccentColor(SampleController.instance.colorAccentApp) - .setBackgroundColor(backgroundColor) - .initializeColors().initializeRemoteColors(true) + .setBackgroundColor(backgroundColor).autoGenerateColors(); } /** @@ -156,11 +157,10 @@ object SampleTheme { */ fun setLocalTheme(context: Context) { @ColorInt val colorPrimary = SampleController.instance.colorPrimaryApp - DynamicTheme.getInstance().setLocalPrimaryColor(colorPrimary) - .setLocalPrimaryColorDark(DynamicColorUtils.shiftColor( + DynamicTheme.getInstance().get().setPrimaryColor(colorPrimary) + .setPrimaryColorDark(DynamicColorUtils.shiftColor( colorPrimary, DynamicTheme.ADS_COLOR_SHIFT_DARK_DEFAULT)) - .setLocalAccentColor(SampleController.instance.colorAccentApp) - .setLocalBackgroundColor(backgroundColor) - .initializeLocalColors() + .setAccentColor(SampleController.instance.colorAccentApp) + .setBackgroundColor(backgroundColor).autoGenerateColors() } } diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/AboutFragment.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/AboutFragment.kt index abc418c3ba..31e2e975d7 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/AboutFragment.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/AboutFragment.kt @@ -17,11 +17,10 @@ package com.pranavpandey.android.dynamic.support.sample.fragment import android.os.Bundle -import android.support.design.widget.AppBarLayout -import android.support.v4.app.Fragment import android.view.Menu import android.view.MenuInflater import android.view.MenuItem +import com.google.android.material.appbar.AppBarLayout import com.pranavpandey.android.dynamic.support.fragment.DynamicViewPagerFragment import com.pranavpandey.android.dynamic.support.sample.R import com.pranavpandey.android.dynamic.support.sample.controller.Constants @@ -30,19 +29,20 @@ import com.pranavpandey.android.dynamic.utils.DynamicPackageUtils import java.util.* /** - * About fragment to show app info and licences by using - * [DynamicViewPagerFragment]. + * About fragment to show app info and licences by using [DynamicViewPagerFragment]. */ class AboutFragment : DynamicViewPagerFragment() { companion object { /** - * @return The new instance of [AboutFragment]. + * Returns the new instance of this fragment. * * @param page The default selected page. + * + * @return The new instance of [AboutFragment]. */ - fun newInstance(page: Int): Fragment { + fun newInstance(page: Int): androidx.fragment.app.Fragment { val fragment = AboutFragment() val args = Bundle() args.putInt(DynamicViewPagerFragment.ADS_ARGS_VIEW_PAGER_PAGE, page) @@ -54,8 +54,7 @@ class AboutFragment : DynamicViewPagerFragment() { override fun getSubtitle(): CharSequence? { // Set subtitle for the app compat activity. - return String.format(getString(R.string.ads_format_version), - DynamicPackageUtils.getAppVersion(context!!)) + return DynamicPackageUtils.getAppVersion(context!!) } override fun setNavigationViewCheckedItem(): Int { @@ -75,9 +74,9 @@ class AboutFragment : DynamicViewPagerFragment() { return titles } - override fun getPages(): List { + override fun getPages(): List { // Initialize an empty fragment array for view pages pages. - val pages = ArrayList() + val pages = ArrayList() // TODO: Add view pager fragments. pages.add(AppInfoFragment.newInstance()) diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/AppInfoFragment.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/AppInfoFragment.kt index ece4773b76..000e38f5ef 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/AppInfoFragment.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/AppInfoFragment.kt @@ -25,8 +25,7 @@ import com.pranavpandey.android.dynamic.support.fragment.DynamicFragment import com.pranavpandey.android.dynamic.support.sample.R /** - * App info fragment to show app links and developer info by - * using [DynamicFragment]. + * App info fragment to show app links and developer info by using [DynamicFragment]. */ class AppInfoFragment : DynamicFragment() { @@ -38,6 +37,8 @@ class AppInfoFragment : DynamicFragment() { companion object { /** + * Returns the new instance of this fragment. + * * @return The new instance of [AppInfoFragment]. */ fun newInstance(): AppInfoFragment { diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/AppSettingsFragment.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/AppSettingsFragment.kt index 3fb1569ff1..f5ec1b12ee 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/AppSettingsFragment.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/AppSettingsFragment.kt @@ -28,8 +28,7 @@ import com.pranavpandey.android.dynamic.support.setting.DynamicColorPreference import com.pranavpandey.android.dynamic.utils.DynamicWindowUtils /** - * App Settings fragment to control theme settings by using - * [DynamicFragment]. + * App Settings fragment to control theme settings by using [DynamicFragment]. */ class AppSettingsFragment : DynamicFragment() { @@ -46,6 +45,8 @@ class AppSettingsFragment : DynamicFragment() { companion object { /** + * Returns the new instance of this fragment. + * * @return The new instance of [AppSettingsFragment]. */ fun newInstance(): AppSettingsFragment { @@ -78,8 +79,7 @@ class AppSettingsFragment : DynamicFragment() { } /** - * Enable or disable day and night theme according to - * the app theme. + * Enable or disable day and night theme according to the app theme. */ private fun updatePreferences() { if (SampleTheme.isAutoTheme) { diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/HomeFragment.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/HomeFragment.kt index d62b61a62d..09550ee117 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/HomeFragment.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/HomeFragment.kt @@ -18,11 +18,10 @@ package com.pranavpandey.android.dynamic.support.sample.fragment import android.content.Intent import android.os.Bundle -import android.support.design.widget.AppBarLayout import android.view.LayoutInflater import android.view.View import android.view.ViewGroup - +import com.google.android.material.appbar.AppBarLayout import com.pranavpandey.android.dynamic.support.fragment.DynamicFragment import com.pranavpandey.android.dynamic.support.sample.R import com.pranavpandey.android.dynamic.support.sample.activity.BottomNavigationActivity @@ -35,14 +34,16 @@ import com.pranavpandey.android.dynamic.utils.DynamicLinkUtils import com.pranavpandey.android.dynamic.utils.DynamicPackageUtils /** - * Home fragment to show some of the features of dynamic-support - * library by using [DynamicFragment]. + * Home fragment to show some of the features of dynamic-support library by + * using [DynamicFragment]. */ class HomeFragment : DynamicFragment() { companion object { /** + * Returns the new instance of this fragment. + * * @return The new instance of [HomeFragment]. */ fun newInstance(): HomeFragment { diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/LicensesFragment.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/LicensesFragment.kt index 819314c526..a1c0e5a2dd 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/LicensesFragment.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/LicensesFragment.kt @@ -25,8 +25,7 @@ import com.pranavpandey.android.dynamic.support.fragment.DynamicFragment import com.pranavpandey.android.dynamic.support.sample.R /** - * Licenses fragment to show license and by using - * [DynamicFragment]. + * Licenses fragment to show license and by using [DynamicFragment]. */ class LicensesFragment : DynamicFragment() { @@ -38,6 +37,8 @@ class LicensesFragment : DynamicFragment() { companion object { /** + * Returns the new instance of this fragment. + * * @return The new instance of [LicensesFragment]. */ fun newInstance(): LicensesFragment { diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/SettingsFragment.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/SettingsFragment.kt index fae1ee684c..34d510720e 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/SettingsFragment.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/SettingsFragment.kt @@ -17,26 +17,26 @@ package com.pranavpandey.android.dynamic.support.sample.fragment import android.os.Bundle -import android.support.design.widget.AppBarLayout -import android.support.v4.app.Fragment +import com.google.android.material.appbar.AppBarLayout import com.pranavpandey.android.dynamic.support.fragment.DynamicViewPagerFragment import com.pranavpandey.android.dynamic.support.sample.R import java.util.* /** - * Settings fragment to show app settings and widgets by using - * [DynamicViewPagerFragment]. + * Settings fragment to show app settings and widgets by using [DynamicViewPagerFragment]. */ class SettingsFragment : DynamicViewPagerFragment() { companion object { /** - * @return The new instance of [SettingsFragment]. + * Returns the new instance of this fragment. * * @param page The default selected page. + * + * @return The new instance of [SettingsFragment]. */ - fun newInstance(page: Int): Fragment { + fun newInstance(page: Int): androidx.fragment.app.Fragment { val fragment = SettingsFragment() val args = Bundle() args.putInt(DynamicViewPagerFragment.ADS_ARGS_VIEW_PAGER_PAGE, page) @@ -68,9 +68,9 @@ class SettingsFragment : DynamicViewPagerFragment() { return titles } - override fun getPages(): List { + override fun getPages(): List { // Initialize an empty fragment array for view pages pages. - val pages = ArrayList() + val pages = ArrayList() // TODO: Add view pager fragments. pages.add(AppSettingsFragment.newInstance()) diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/WidgetsFragment.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/WidgetsFragment.kt index 62da9bb732..5da4509fd6 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/WidgetsFragment.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/fragment/WidgetsFragment.kt @@ -32,8 +32,7 @@ import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils import java.util.* /** - * Widgets fragment to show various widgets and their states - * by using [DynamicFragment]. + * Widgets fragment to show various widgets and their states by using [DynamicFragment]. */ class WidgetsFragment : DynamicFragment(), DynamicSearchListener, TextWatcher { @@ -55,6 +54,8 @@ class WidgetsFragment : DynamicFragment(), DynamicSearchListener, TextWatcher { companion object { /** + * Returns the new instance of this fragment. + * * @return The new instance of [WidgetsFragment]. */ fun newInstance(): WidgetsFragment { diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/view/AppInfoView.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/view/AppInfoView.kt index 68334e4ad3..a9a67e3a28 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/view/AppInfoView.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/view/AppInfoView.kt @@ -17,16 +17,16 @@ package com.pranavpandey.android.dynamic.support.sample.view import android.content.Context -import android.support.v7.widget.LinearLayoutManager -import android.support.v7.widget.RecyclerView import android.util.AttributeSet +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView import com.pranavpandey.android.dynamic.support.recyclerview.DynamicRecyclerViewFrame import com.pranavpandey.android.dynamic.support.sample.adapter.AppInfoAdapter import com.pranavpandey.android.dynamic.support.utils.DynamicLayoutUtils /** - * App info view to display app and developer info by using - * [AppInfoAdapter] and [DynamicRecyclerViewFrame]. + * App info view to display app and developer info by using [AppInfoAdapter] + * and [DynamicRecyclerViewFrame]. */ class AppInfoView : DynamicRecyclerViewFrame { @@ -42,7 +42,7 @@ class AppInfoView : DynamicRecyclerViewFrame { override fun getRecyclerViewLayoutManager(): RecyclerView.LayoutManager? { return DynamicLayoutUtils.getLinearLayoutManager( - context, LinearLayoutManager.VERTICAL) + context, androidx.recyclerview.widget.LinearLayoutManager.VERTICAL) } private fun setAdapter(): AppInfoView { diff --git a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/view/LicenseView.kt b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/view/LicenseView.kt index 44a3baffc3..2e4370d3c4 100644 --- a/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/view/LicenseView.kt +++ b/sample/src/main/java/com/pranavpandey/android/dynamic/support/sample/view/LicenseView.kt @@ -17,9 +17,9 @@ package com.pranavpandey.android.dynamic.support.sample.view import android.content.Context -import android.support.v7.widget.RecyclerView -import android.support.v7.widget.StaggeredGridLayoutManager import android.util.AttributeSet +import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.StaggeredGridLayoutManager import com.pranavpandey.android.dynamic.support.model.DynamicInfo import com.pranavpandey.android.dynamic.support.recyclerview.DynamicRecyclerViewFrame import com.pranavpandey.android.dynamic.support.sample.R @@ -29,8 +29,8 @@ import com.pranavpandey.android.dynamic.support.utils.DynamicResourceUtils import java.util.* /** - * License view to display a list of licences by using - * [LicensesAdapter] and [DynamicRecyclerViewFrame]. + * License view to display a list of licences by using [LicensesAdapter] + * and [DynamicRecyclerViewFrame]. */ class LicenseView : DynamicRecyclerViewFrame { @@ -47,7 +47,7 @@ class LicenseView : DynamicRecyclerViewFrame { override fun getRecyclerViewLayoutManager(): RecyclerView.LayoutManager? { return DynamicLayoutUtils.getStaggeredGridLayoutManager( DynamicLayoutUtils.getGridCount(context), - StaggeredGridLayoutManager.VERTICAL) + androidx.recyclerview.widget.StaggeredGridLayoutManager.VERTICAL) } private fun setAdapter(): LicenseView { @@ -67,14 +67,14 @@ class LicenseView : DynamicRecyclerViewFrame { context, R.drawable.ads_ic_android))) licenses.add(DynamicInfo() .setTitle(context - .getString(R.string.ads_license_plaid)) + .getString(R.string.ads_license_gson_plaid)) .setDescription(context.getString(R.string.ads_license_copy_google_15)) .setLinks(resources.getStringArray( R.array.ads_license_links_apache)) .setLinksSubtitles(resources.getStringArray( R.array.ads_license_links_subtitles)) .setLinksUrls(resources.getStringArray( - R.array.ads_license_links_urls_plaid)) + R.array.ads_license_links_urls_gson_plaid)) .setLinksIconsResId(R.array.ads_license_links_icons) .setLinksColorsResId(R.array.ads_license_links_colors) .setIconBig(DynamicResourceUtils.getDrawable( diff --git a/sample/src/main/res/drawable/ic_launcher_foreground.xml b/sample/src/main/res/drawable/ic_launcher_foreground.xml index 4e717e64e7..7f92330828 100644 --- a/sample/src/main/res/drawable/ic_launcher_foreground.xml +++ b/sample/src/main/res/drawable/ic_launcher_foreground.xml @@ -1,6 +1,6 @@ - \ No newline at end of file + android:layout_height="match_parent" + android:focusableInTouchMode="true"> + + + + \ No newline at end of file diff --git a/sample/src/main/res/layout/fragment_app_settings.xml b/sample/src/main/res/layout/fragment_app_settings.xml index 56180132b5..3beabedcfb 100644 --- a/sample/src/main/res/layout/fragment_app_settings.xml +++ b/sample/src/main/res/layout/fragment_app_settings.xml @@ -37,94 +37,94 @@ + app:ads_title="@string/ads_theme" /> + app:ads_key="pref_settings_app_theme_color" + app:ads_icon="@drawable/ic_style" + app:ads_title="@string/ads_theme_app" + app:ads_summary="@string/ads_theme_app_summary" + app:ads_description="@string/ads_theme_app_desc" + app:ads_shape="square" + app:ads_popup="true" + app:ads_popupColors="@array/pref_app_theme_colors" /> + app:ads_key="pref_settings_app_theme_day_color" + app:ads_icon="@drawable/ic_paint_bucket" + app:ads_title="@string/ads_theme_app_day" + app:ads_summary="@string/ads_theme_app_day_summary" + app:ads_description="@string/ads_theme_app_day_night_desc" + app:ads_color="@color/ads_window_background_light" + app:ads_shape="square" + app:ads_popup="true" + app:ads_popupColors="@array/pref_app_theme_day_colors" /> + app:ads_key="pref_settings_app_theme_night_color" + app:ads_icon="@drawable/ic_paint_bucket" + app:ads_title="@string/ads_theme_app_night" + app:ads_summary="@string/ads_theme_app_night_summary" + app:ads_description="@string/ads_theme_app_day_night_desc" + app:ads_color="@color/ads_window_background" + app:ads_shape="square" + app:ads_popup="true" + app:ads_popupColors="@array/pref_app_theme_night_colors" /> + app:ads_key="pref_settings_app_theme_color_primary" + app:ads_icon="@drawable/ads_ic_palette" + app:ads_title="@string/ads_theme_color_primary" + app:ads_summary="@string/ads_theme_color_primary_summary" + app:ads_description="@string/ads_theme_background_aware_desc" + app:ads_color="@color/color_primary" + app:ads_popup="true" + app:ads_alphaEnabled="true" /> + app:ads_key="pref_settings_app_theme_color_accent" + app:ads_icon="@drawable/ads_ic_palette" + app:ads_title="@string/ads_theme_color_accent" + app:ads_summary="@string/ads_theme_color_accent_summary" + app:ads_description="@string/ads_theme_background_aware_desc" + app:ads_color="@color/color_accent" + app:ads_popup="true" + app:ads_alphaEnabled="true" /> + app:ads_key="pref_settings_navigation_bar_theme" + app:ads_icon="@drawable/ic_paint_brush" + app:ads_title="@string/ads_theme_navigation_bar" + app:ads_summary="@string/ads_theme_navigation_bar_summary" + app:ads_unchecked="@string/ads_theme_navigation_bar_summary_unchecked" + app:ads_description="@string/ads_theme_navigation_bar_desc" /> + app:ads_key="pref_settings_app_shortcuts_theme" + app:ads_icon="@drawable/ic_shortcut" + app:ads_title="@string/ads_theme_app_shortcuts" + app:ads_summary="@string/ads_theme_app_shortcuts_summary" + app:ads_unchecked="@string/ads_theme_app_shortcuts_summary_unchecked" + app:ads_description="@string/ads_theme_app_shortcuts_desc" + app:ads_checked="true" /> diff --git a/sample/src/main/res/layout/fragment_home.xml b/sample/src/main/res/layout/fragment_home.xml index dfed496b51..710a5e1515 100644 --- a/sample/src/main/res/layout/fragment_home.xml +++ b/sample/src/main/res/layout/fragment_home.xml @@ -33,10 +33,10 @@ android:id="@+id/item_gradle" android:layout_width="match_parent" android:layout_height="wrap_content" - app:ads_dynamicInfo_icon="@drawable/ads_ic_extension" - app:ads_dynamicInfo_title="@string/gradle" - app:ads_dynamicInfo_subtitle="@string/format_version" - app:ads_dynamicInfo_colorType="primary" /> + app:ads_icon="@drawable/ads_ic_extension" + app:ads_title="@string/gradle" + app:ads_subtitle="@string/format_version" + app:ads_colorType="primary" /> @@ -51,31 +51,31 @@ + app:ads_title="@string/ads_general" /> + app:ads_icon="@drawable/ads_ic_tutorial" + app:ads_title="@string/tutorial" + app:ads_summary="@string/tutorial_activity_subtitle" /> + app:ads_icon="@drawable/ic_collapsing_app_bar" + app:ads_title="@string/collapsing_app_bar" + app:ads_summary="@string/collapsing_app_bar_subtitle" /> + app:ads_icon="@drawable/ic_bottom_navigation" + app:ads_title="@string/bottom_navigation" + app:ads_summary="@string/bottom_navigation_subtitle" /> @@ -88,10 +88,10 @@ android:id="@+id/item_rotation" android:layout_width="match_parent" android:layout_height="wrap_content" - app:ads_dynamicInfo_icon="@drawable/ic_rotation" - app:ads_dynamicInfo_title="@string/rotation" - app:ads_dynamicInfo_subtitle="@string/rotation_subtitle" - app:ads_dynamicInfo_colorType="primary" /> + app:ads_icon="@drawable/ic_rotation" + app:ads_title="@string/rotation" + app:ads_subtitle="@string/rotation_subtitle" + app:ads_colorType="primary" /> diff --git a/sample/src/main/res/layout/fragment_licenses.xml b/sample/src/main/res/layout/fragment_licenses.xml index 675c96d019..ae74965b5d 100644 --- a/sample/src/main/res/layout/fragment_licenses.xml +++ b/sample/src/main/res/layout/fragment_licenses.xml @@ -15,8 +15,15 @@ limitations under the License. --> - \ No newline at end of file + android:layout_height="match_parent" + android:focusableInTouchMode="true"> + + + + \ No newline at end of file diff --git a/sample/src/main/res/layout/fragment_widgets.xml b/sample/src/main/res/layout/fragment_widgets.xml index c3f1deb87d..081c417b6b 100644 --- a/sample/src/main/res/layout/fragment_widgets.xml +++ b/sample/src/main/res/layout/fragment_widgets.xml @@ -39,7 +39,7 @@ + app:ads_title="@string/widget_buttons" /> + style="@style/Widget.DynamicApp.Button" /> + style="@style/Widget.DynamicApp.Button" /> + app:ads_colorType="primary" + style="@style/Widget.DynamicApp.Button" /> @@ -82,7 +83,7 @@ android:layout_height="wrap_content" android:layout_weight="1.0" android:text="@string/widget_button_flat" - style="@style/Widget.DynamicApp.Button.Borderless" /> + style="@style/Widget.DynamicApp.Button.TextButton" /> + style="@style/Widget.DynamicApp.Button.TextButton" /> + app:ads_colorType="primary" + style="@style/Widget.DynamicApp.Button.TextButton" /> @@ -116,7 +118,7 @@ + app:ads_title="@string/widget_checked" /> + app:ads_title="@string/widget_input" /> + app:ads_title="@string/widget_progress" /> + app:ads_title="@string/widget_spinner" /> + app:ads_icon="@drawable/ic_sample" + app:ads_iconBig="@drawable/ic_sample_splash" + app:ads_title="@string/app_name" + app:ads_subtitle="@string/app_subtitle" + app:ads_description="@string/ads_info_made_in" + app:ads_links="@array/info_app_links" + app:ads_subtitles="@array/info_app_subtitles" + app:ads_urls="@array/info_app_urls" + app:ads_icons="@array/info_app_icons" + app:ads_colors="@array/info_app_colors" /> \ No newline at end of file diff --git a/sample/src/main/res/layout/layout_info_author.xml b/sample/src/main/res/layout/layout_info_author.xml index ce62c79a28..d42689659a 100644 --- a/sample/src/main/res/layout/layout_info_author.xml +++ b/sample/src/main/res/layout/layout_info_author.xml @@ -24,15 +24,15 @@ android:id="@+id/info_author" android:layout_width="match_parent" android:layout_height="wrap_content" - app:ads_dynamicInfo_icon="@drawable/ic_author_logo" - app:ads_dynamicInfo_iconBig="@drawable/ads_ic_person" - app:ads_dynamicInfo_title="@string/ads_info_made_by" - app:ads_dynamicInfo_subtitle="@string/ads_info_me" - app:ads_dynamicInfo_description="@string/ads_info_quote" - app:ads_dynamicInfo_links="@array/ads_about_author_links" - app:ads_dynamicInfo_linksSubtitles="@array/ads_about_author_links_subtitles" - app:ads_dynamicInfo_linksUrls="@array/ads_about_author_links_urls" - app:ads_dynamicInfo_linksIcons="@array/ads_about_author_links_icons" - app:ads_dynamicInfo_linksColors="@array/ads_about_author_links_colors" /> + app:ads_icon="@drawable/ic_author_logo" + app:ads_iconBig="@drawable/ads_ic_person" + app:ads_title="@string/ads_info_made_by" + app:ads_subtitle="@string/ads_info_me" + app:ads_description="@string/ads_info_quote" + app:ads_links="@array/ads_about_author_links" + app:ads_subtitles="@array/ads_about_author_links_subtitles" + app:ads_urls="@array/ads_about_author_links_urls" + app:ads_icons="@array/ads_about_author_links_icons" + app:ads_colors="@array/ads_about_author_links_colors" /> \ No newline at end of file diff --git a/sample/src/main/res/layout/layout_info_translators.xml b/sample/src/main/res/layout/layout_info_translators.xml index ea770cb7d6..cfcdf377ed 100644 --- a/sample/src/main/res/layout/layout_info_translators.xml +++ b/sample/src/main/res/layout/layout_info_translators.xml @@ -24,14 +24,14 @@ android:id="@+id/info_translators" android:layout_width="match_parent" android:layout_height="wrap_content" - app:ads_dynamicInfo_icon="@drawable/ads_ic_language" - app:ads_dynamicInfo_iconBig="@drawable/ads_ic_translate" - app:ads_dynamicInfo_title="@string/ads_translators" - app:ads_dynamicInfo_description="@string/ads_contributors_desc" - app:ads_dynamicInfo_links="@array/info_translators_languages" - app:ads_dynamicInfo_linksSubtitles="@array/info_translators_authors" - app:ads_dynamicInfo_linksUrls="@array/info_translators_urls" - app:ads_dynamicInfo_linksIcons="@array/info_translators_flags" - app:ads_dynamicInfo_linksColors="@array/info_translators_colors" /> + app:ads_icon="@drawable/ads_ic_language" + app:ads_iconBig="@drawable/ads_ic_translate" + app:ads_title="@string/ads_translators" + app:ads_description="@string/ads_contributors_desc" + app:ads_links="@array/info_translators_languages" + app:ads_subtitles="@array/info_translators_authors" + app:ads_urls="@array/info_translators_urls" + app:ads_icons="@array/info_translators_flags" + app:ads_colors="@array/info_translators_colors" /> \ No newline at end of file diff --git a/sample/src/main/res/values/arrays.xml b/sample/src/main/res/values/arrays.xml index 781a73bd3c..5bd00044db 100644 --- a/sample/src/main/res/values/arrays.xml +++ b/sample/src/main/res/values/arrays.xml @@ -19,7 +19,7 @@ - 0 + -3 @color/ads_window_background_light @color/ads_window_background @color/window_background_yellow @@ -80,22 +80,22 @@ - + @string/ads_license_sources_desc - + https://github.com/pranavpandey/dynamic-support - + @drawable/ads_ic_social_github - + @color/ads_social_github @@ -114,7 +114,7 @@ Dave Fatih Fırıncı 残念 - @string/ads_translators_contact + @string/ads_translators_translate_summary diff --git a/sample/src/main/res/values/strings.xml b/sample/src/main/res/values/strings.xml index fa61a7eb19..8de672d858 100644 --- a/sample/src/main/res/values/strings.xml +++ b/sample/src/main/res/values/strings.xml @@ -15,7 +15,9 @@ limitations under the License. --> - + Dynamic Support