├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── magicasakura ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── bilibili │ │ └── magicasakura │ │ ├── drawables │ │ └── FilterableStateListDrawable.java │ │ ├── utils │ │ ├── ColorStateListUtils.java │ │ ├── DrawableInflateDelegate.java │ │ ├── DrawableUtils.java │ │ ├── GradientDrawableInflateImpl.java │ │ ├── InputConnectionImpl.java │ │ ├── LayerDrawableInflateImpl.java │ │ ├── RippleDrawableInflateImpl.java │ │ ├── StateListDrawableInflateImpl.java │ │ ├── ThemeUtils.java │ │ ├── TintInfo.java │ │ ├── TintManager.java │ │ └── VectorDrawableInflateImpl.java │ │ └── widgets │ │ ├── AppCompatBackgroundHelper.java │ │ ├── AppCompatBaseHelper.java │ │ ├── AppCompatCompoundButtonHelper.java │ │ ├── AppCompatCompoundDrawableHelper.java │ │ ├── AppCompatForegroundHelper.java │ │ ├── AppCompatImageHelper.java │ │ ├── AppCompatProgressBarHelper.java │ │ ├── AppCompatSwitchHelper.java │ │ ├── AppCompatTextHelper.java │ │ ├── TintAppAlertDialogDividingView.java │ │ ├── TintAppBarLayout.java │ │ ├── TintAutoCompleteTextView.java │ │ ├── TintButton.java │ │ ├── TintCheckBox.java │ │ ├── TintCheckedTextView.java │ │ ├── TintConstraintLayout.java │ │ ├── TintEditText.java │ │ ├── TintFrameLayout.java │ │ ├── TintGridLayout.java │ │ ├── TintImageView.java │ │ ├── TintLinearLayout.java │ │ ├── TintProgressBar.java │ │ ├── TintProgressDialog.java │ │ ├── TintRadioButton.java │ │ ├── TintRelativeLayout.java │ │ ├── TintSwitchCompat.java │ │ ├── TintTextView.java │ │ ├── TintToolbar.java │ │ ├── TintView.java │ │ └── Tintable.java │ ├── res-public │ └── values │ │ └── public.xml │ └── res │ ├── layout │ ├── dialog_alert_progress.xml │ └── dialog_progress.xml │ └── values │ └── attrs.xml ├── sample ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── bilibili │ │ └── magicasakurademo │ │ ├── MainActivity.java │ │ ├── MyApplication.java │ │ ├── dialog │ │ ├── CardPickerDialog.java │ │ ├── ProgressCheckDialog.java │ │ └── ProgressStyleDialog.java │ │ ├── utils │ │ ├── SnackAnimationUtil.java │ │ └── ThemeHelper.java │ │ └── widgets │ │ └── KeyEditText.java │ └── res │ ├── anim │ ├── snack_in.xml │ └── snack_out.xml │ ├── color │ ├── selector_compound.xml │ ├── selector_focus.xml │ ├── selector_primary_click.xml │ ├── selector_switch_thumb.xml │ ├── selector_switch_track.xml │ └── selector_text.xml │ ├── drawable-v21 │ └── selector_login.xml │ ├── drawable-xhdpi │ ├── ic_adb_white_24dp.png │ ├── ic_card_24dp.png │ ├── ic_card_48dp.png │ ├── ic_card_background.9.png │ ├── ic_check_white_12dp.png │ ├── ic_check_white_18dp.png │ ├── ic_check_white_24dp.png │ ├── ic_edit_text_default.9.png │ ├── ic_lock_open_white_24dp.png │ ├── ic_lock_outline_white_24dp.png │ ├── ic_lock_white_24dp.png │ ├── ic_looks_1.png │ ├── ic_looks_2.png │ ├── ic_looks_3.png │ ├── ic_magicasakura.png │ ├── ic_person_outline_white_24dp.png │ └── ic_tag_white_24dp.png │ ├── drawable │ ├── edittext_cursor.xml │ ├── selector_lock.xml │ ├── selector_login.xml │ ├── selector_pick_item.xml │ ├── selector_unlock.xml │ └── shape_rectangle_nocorner.xml │ ├── layout │ ├── activity_main.xml │ ├── dialog_check_layout.xml │ ├── dialog_progress_layout.xml │ ├── dialog_theme_picker.xml │ ├── fragment_layout_snack.xml │ ├── fragment_layout_theme_picker.xml │ ├── layout_list_item_choice.xml │ ├── layout_list_item_header.xml │ ├── layout_list_item_label.xml │ └── layout_list_item_login.xml │ ├── menu │ └── main_menu.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-v21 │ └── themes.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── selector.xml │ ├── strings.xml │ ├── styles.xml │ └── themes.xml ├── screenshot ├── magicasakura.gif └── magicasakura_cover.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | 15 | # Gradle files 16 | .gradle/ 17 | build/ 18 | 19 | # Local configuration file (sdk path, etc) 20 | local_true.properties 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | *.DS_Store 30 | .idea/ 31 | 32 | *.iml 33 | *.pyc 34 | 35 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | google() 7 | } 8 | dependencies { 9 | classpath "com.android.tools.build:gradle:4.2.1" 10 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' 11 | classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:1.0" 12 | // NOTE: Do not place your application dependencies here; they belong 13 | // in the individual module build.gradle files 14 | } 15 | } 16 | 17 | allprojects { 18 | repositories { 19 | jcenter() 20 | google() 21 | } 22 | } 23 | 24 | task clean(type: Delete) { 25 | delete rootProject.buildDir 26 | } 27 | 28 | ext { 29 | buildToolsVersion = '30.0.2' 30 | targetSdkVersion = 30 31 | compileSdkVersion = 30 32 | minSdkVersion = 15 33 | supportVersion = '27.1.1' 34 | constraintVersion = '1.0.2' 35 | } 36 | 37 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Nov 06 23:10:43 CST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /magicasakura/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /magicasakura/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'com.github.dcendents.android-maven' 3 | apply plugin: 'com.jfrog.bintray' 4 | 5 | version = "0.1.9-beta3" 6 | 7 | android { 8 | compileSdkVersion rootProject.ext.compileSdkVersion 9 | buildToolsVersion rootProject.ext.buildToolsVersion 10 | 11 | defaultConfig { 12 | minSdkVersion rootProject.ext.minSdkVersion 13 | targetSdkVersion rootProject.ext.targetSdkVersion 14 | versionCode 1 15 | versionName version 16 | } 17 | sourceSets{ 18 | main.res.srcDirs 'res', 'res-public' 19 | } 20 | buildTypes { 21 | release { 22 | minifyEnabled false 23 | consumerProguardFiles 'proguard-rules.pro' 24 | } 25 | } 26 | } 27 | 28 | def siteUrl = "https://github.com/Bilibili/MagicaSakura" 29 | def gitUrl = "https://github.com/Bilibili/MagicaSakura.git" 30 | 31 | group = "com.bilibili" 32 | 33 | install { 34 | repositories.mavenInstaller { 35 | // This generates POM.xml with proper paramters 36 | pom.project { 37 | packaging 'aar' 38 | 39 | // Add your description here 40 | name 'MagicaSakura' 41 | url siteUrl 42 | 43 | // Set your license 44 | licenses { 45 | license { 46 | name 'The Apache Software License, Version 2.0' 47 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt' 48 | } 49 | } 50 | 51 | developers { 52 | developer { 53 | id 'xyczero' 54 | name 'xiayuncheng' 55 | email 'xyczero617@gmail.com' 56 | } 57 | } 58 | 59 | scm { 60 | connection gitUrl 61 | developerConnection gitUrl 62 | url siteUrl 63 | } 64 | } 65 | } 66 | } 67 | 68 | task sourcesJar(type: Jar) { 69 | from android.sourceSets.main.java.sourceFiles 70 | classifier = 'sources' 71 | } 72 | 73 | artifacts { 74 | archives sourcesJar 75 | } 76 | 77 | Properties properties = new Properties() 78 | properties.load(project.rootProject.file('local.properties').newDataInputStream()) 79 | 80 | bintray { 81 | user = properties.getProperty("bintray.user") 82 | key = properties.getProperty("bintray.apikey") 83 | 84 | configurations = ['archives'] 85 | 86 | pkg { 87 | repo = "maven" 88 | name = "MagicaSakura" 89 | websiteUrl = siteUrl 90 | vcsUrl = gitUrl 91 | licenses = ["Apache-2.0"] 92 | publish = true 93 | } 94 | } 95 | 96 | 97 | dependencies { 98 | implementation fileTree(dir: 'libs', include: ['*.jar']) 99 | 100 | implementation "com.android.support:design:${rootProject.ext.supportVersion}" 101 | implementation "com.android.support.constraint:constraint-layout:${rootProject.ext.constraintVersion}" 102 | 103 | } 104 | -------------------------------------------------------------------------------- /magicasakura/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/xyczero/xyczero/android-sdk-macosx/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | -keepnames class android.widget.AbsListView{ 20 | android.widget.AbsListView$RecycleBin mRecycler; 21 | } 22 | 23 | -keepnames class android.widget.AbsListView$RecycleBin{ 24 | void clear(); 25 | } 26 | 27 | -keepnames class android.support.v7.widget.RecyclerView{ 28 | android.support.v7.widget.RecyclerView$Recycler mRecycler; 29 | } 30 | 31 | -keepnames class android.support.v7.widget.RecyclerView$Recycler{ 32 | public void clear(); 33 | } -------------------------------------------------------------------------------- /magicasakura/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/drawables/FilterableStateListDrawable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.drawables; 18 | 19 | import android.graphics.ColorFilter; 20 | import android.graphics.drawable.Drawable; 21 | import android.graphics.drawable.StateListDrawable; 22 | import android.support.annotation.RestrictTo; 23 | import android.util.SparseArray; 24 | 25 | import static android.support.annotation.RestrictTo.Scope.LIBRARY; 26 | 27 | /** 28 | * This is an extension to {@link android.graphics.drawable.StateListDrawable} that workaround a bug not allowing 29 | * to set a {@link android.graphics.ColorFilter} to the drawable in one of the states., it add a method 30 | * {@link #addState(int[], android.graphics.drawable.Drawable, android.graphics.ColorFilter)} for that purpose. 31 | */ 32 | @RestrictTo(LIBRARY) 33 | public final class FilterableStateListDrawable extends StateListDrawable { 34 | 35 | private int currIdx = -1; 36 | private int childrenCount = 0; 37 | private SparseArray filterMap; 38 | 39 | public FilterableStateListDrawable() { 40 | super(); 41 | filterMap = new SparseArray<>(); 42 | } 43 | 44 | @Override 45 | public void addState(int[] stateSet, Drawable drawable) { 46 | super.addState(stateSet, drawable); 47 | childrenCount++; 48 | } 49 | 50 | /** 51 | * Same as {@link #addState(int[], Drawable)}, but allow to set a colorFilter associated to this Drawable. 52 | * 53 | * @param stateSet - An array of resource Ids to associate with the image. 54 | * Switch to this image by calling setState(). 55 | * @param drawable -The image to show. 56 | * @param colorFilter - The {@link ColorFilter} to apply to this state 57 | */ 58 | public void addState(int[] stateSet, Drawable drawable, ColorFilter colorFilter) { 59 | if (colorFilter == null) { 60 | addState(stateSet, drawable); 61 | return; 62 | } 63 | // this is a new custom method, does not exist in parent class 64 | int currChild = childrenCount; 65 | addState(stateSet, drawable); 66 | filterMap.put(currChild, colorFilter); 67 | } 68 | 69 | @Override 70 | public boolean selectDrawable(int idx) { 71 | 72 | boolean result = super.selectDrawable(idx); 73 | // check if the drawable has been actually changed to the one I expect 74 | if (getCurrent() != null) { 75 | currIdx = result ? idx : currIdx; 76 | setColorFilter(getColorFilterForIdx(currIdx)); 77 | } else { 78 | currIdx = -1; 79 | setColorFilter(null); 80 | } 81 | return result; 82 | } 83 | 84 | private ColorFilter getColorFilterForIdx(int idx) { 85 | return filterMap != null ? filterMap.get(idx) : null; 86 | } 87 | 88 | @Override 89 | public ConstantState getConstantState() { 90 | return super.getConstantState(); 91 | } 92 | 93 | } -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/utils/ColorStateListUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.utils; 18 | 19 | import android.content.Context; 20 | import android.content.res.ColorStateList; 21 | import android.content.res.TypedArray; 22 | import android.content.res.XmlResourceParser; 23 | import android.graphics.Color; 24 | import android.support.annotation.RestrictTo; 25 | import android.support.v4.graphics.ColorUtils; 26 | import android.util.AttributeSet; 27 | import android.util.StateSet; 28 | import android.util.TypedValue; 29 | import android.util.Xml; 30 | 31 | import org.xmlpull.v1.XmlPullParser; 32 | import org.xmlpull.v1.XmlPullParserException; 33 | 34 | import java.io.IOException; 35 | import java.util.LinkedList; 36 | 37 | import static android.support.annotation.RestrictTo.Scope.LIBRARY; 38 | 39 | /** 40 | * @author xyczero617@gmail.com 41 | * @time 16/2/22 42 | */ 43 | @RestrictTo(LIBRARY) 44 | final class ColorStateListUtils { 45 | 46 | static ColorStateList createColorStateList(Context context, int resId) { 47 | if (resId <= 0) return null; 48 | 49 | TypedValue value = new TypedValue(); 50 | context.getResources().getValue(resId, value, true); 51 | ColorStateList cl = null; 52 | if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT 53 | && value.type <= TypedValue.TYPE_LAST_COLOR_INT) { 54 | //Assume that "color/theme_color_primary" and "color/theme_color_profile" have the same color value; 55 | //However, "color/theme_color_primary" need to replace by themeId, "color/theme_color_profile" not. 56 | //If use value.data may cause "color/theme_color_profile" still been replaced by themeId 57 | cl = ColorStateList.valueOf(ThemeUtils.replaceColorById(context, value.resourceId)); 58 | } else { 59 | final String file = value.string.toString(); 60 | try { 61 | if (file.endsWith("xml")) { 62 | final XmlResourceParser rp = context.getResources().getAssets().openXmlResourceParser( 63 | value.assetCookie, file); 64 | final AttributeSet attrs = Xml.asAttributeSet(rp); 65 | int type; 66 | 67 | while ((type = rp.next()) != XmlPullParser.START_TAG 68 | && type != XmlPullParser.END_DOCUMENT) { 69 | // Seek parser to start tag. 70 | } 71 | 72 | if (type != XmlPullParser.START_TAG) { 73 | throw new XmlPullParserException("No start tag found"); 74 | } 75 | 76 | cl = createFromXmlInner(context, rp, attrs); 77 | rp.close(); 78 | } 79 | } catch (IOException e) { 80 | e.printStackTrace(); 81 | } catch (XmlPullParserException e) { 82 | e.printStackTrace(); 83 | } 84 | } 85 | return cl; 86 | } 87 | 88 | static ColorStateList createFromXmlInner(Context context, XmlPullParser parser, AttributeSet attrs) throws IOException, XmlPullParserException { 89 | 90 | final String name = parser.getName(); 91 | if (!name.equals("selector")) { 92 | throw new XmlPullParserException( 93 | parser.getPositionDescription() + ": invalid color state list tag " + name); 94 | } 95 | 96 | return inflateColorStateList(context, parser, attrs); 97 | } 98 | 99 | static ColorStateList inflateColorStateList(Context context, XmlPullParser parser, AttributeSet attrs) throws IOException, XmlPullParserException { 100 | final int innerDepth = parser.getDepth() + 1; 101 | int depth; 102 | int type; 103 | 104 | LinkedList stateList = new LinkedList<>(); 105 | LinkedList colorList = new LinkedList<>(); 106 | 107 | while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 108 | && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) { 109 | if (type != XmlPullParser.START_TAG || depth > innerDepth 110 | || !parser.getName().equals("item")) { 111 | continue; 112 | } 113 | 114 | TypedArray a1 = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.color}); 115 | final int value = a1.getResourceId(0, Color.MAGENTA); 116 | final int baseColor = value == Color.MAGENTA ? Color.MAGENTA : ThemeUtils.replaceColorById(context, value); 117 | a1.recycle(); 118 | TypedArray a2 = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.alpha}); 119 | final float alphaMod = a2.getFloat(0, 1.0f); 120 | a2.recycle(); 121 | colorList.add(alphaMod != 1.0f 122 | ? ColorUtils.setAlphaComponent(baseColor, Math.round(Color.alpha(baseColor) * alphaMod)) 123 | : baseColor); 124 | 125 | stateList.add(extractStateSet(attrs)); 126 | } 127 | 128 | if (stateList.size() > 0 && stateList.size() == colorList.size()) { 129 | int[] colors = new int[colorList.size()]; 130 | for (int i = 0; i < colorList.size(); i++) { 131 | colors[i] = colorList.get(i); 132 | } 133 | return new ColorStateList(stateList.toArray(new int[stateList.size()][]), colors); 134 | } 135 | return null; 136 | } 137 | 138 | protected static int[] extractStateSet(AttributeSet attrs) { 139 | int j = 0; 140 | final int numAttrs = attrs.getAttributeCount(); 141 | int[] states = new int[numAttrs]; 142 | for (int i = 0; i < numAttrs; i++) { 143 | final int stateResId = attrs.getAttributeNameResource(i); 144 | switch (stateResId) { 145 | case 0: 146 | break; 147 | case android.R.attr.color: 148 | case android.R.attr.alpha: 149 | // Ignore attributes from StateListDrawableItem and 150 | // AnimatedStateListDrawableItem. 151 | continue; 152 | default: 153 | states[j++] = attrs.getAttributeBooleanValue(i, false) 154 | ? stateResId : -stateResId; 155 | } 156 | } 157 | states = StateSet.trimStateSet(states, j); 158 | return states; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/utils/DrawableInflateDelegate.java: -------------------------------------------------------------------------------- 1 | package com.bilibili.magicasakura.utils; 2 | 3 | import android.content.Context; 4 | import android.graphics.drawable.Drawable; 5 | import android.util.AttributeSet; 6 | 7 | import org.xmlpull.v1.XmlPullParser; 8 | import org.xmlpull.v1.XmlPullParserException; 9 | 10 | import java.io.IOException; 11 | 12 | /** 13 | * @author xyczero617@gmail.com 14 | * @time 16/11/6 15 | */ 16 | 17 | interface DrawableInflateDelegate { 18 | Drawable inflateDrawable(Context context, XmlPullParser parser, AttributeSet attrs) throws IOException, XmlPullParserException; 19 | } 20 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/utils/InputConnectionImpl.java: -------------------------------------------------------------------------------- 1 | package com.bilibili.magicasakura.utils; 2 | 3 | import android.support.annotation.RestrictTo; 4 | import android.view.inputmethod.InputConnection; 5 | import android.view.inputmethod.InputConnectionWrapper; 6 | 7 | import static android.support.annotation.RestrictTo.Scope.LIBRARY; 8 | 9 | /** 10 | * just used for fix
java.lang.IndexOutOfBoundsException
while 11 | * invoke {@link InputConnection#setSelection(int, int)} 12 | * @author Yann Chou 13 | * @email zhouyanbin1029@gmail.com 14 | * @create 2016-08-29 11:37 15 | */ 16 | 17 | @RestrictTo(LIBRARY) 18 | public final class InputConnectionImpl extends InputConnectionWrapper { 19 | 20 | public InputConnectionImpl(InputConnection target, boolean mutable) { 21 | super(target, mutable); 22 | } 23 | @Override 24 | public boolean setSelection(int start, int end) { 25 | if (start < 0 || end < 0) { 26 | // If the given selection is out of bounds, just ignore it. 27 | // Most likely the text was changed out from under the IME, 28 | // and the IME is going to have to update all of its state 29 | // anyway. 30 | return true; 31 | } 32 | return super.setSelection(start, end); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/utils/LayerDrawableInflateImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.utils; 18 | 19 | import android.content.Context; 20 | import android.content.res.ColorStateList; 21 | import android.graphics.drawable.Drawable; 22 | import android.graphics.drawable.LayerDrawable; 23 | import android.os.Build; 24 | import android.util.AttributeSet; 25 | 26 | import com.bilibili.magicasakura.R; 27 | 28 | import org.xmlpull.v1.XmlPullParser; 29 | import org.xmlpull.v1.XmlPullParserException; 30 | 31 | import java.io.IOException; 32 | 33 | /** 34 | * @author xyczero617@gmail.com 35 | * @time 16/3/17 36 | */ 37 | class LayerDrawableInflateImpl implements DrawableInflateDelegate { 38 | static final int STEP = 1; 39 | 40 | static final int[] ATTRS = new int[]{ 41 | android.R.attr.left, android.R.attr.top, android.R.attr.right, 42 | android.R.attr.bottom, android.R.attr.id}; 43 | 44 | @Override 45 | public Drawable inflateDrawable(Context context, XmlPullParser parser, AttributeSet attrs) throws IOException, XmlPullParserException { 46 | final int innerDepth = parser.getDepth() + 1; 47 | int type; 48 | int depth; 49 | int layerAttrUseCount = 0; 50 | int drawableUseCount = 0; 51 | int space = STEP << 1; 52 | //L,T,R,B,S,E,id 53 | int[][] childLayersAttrs = new int[space][ATTRS.length]; 54 | Drawable[] drawables = new Drawable[space]; 55 | 56 | while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 57 | && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) { 58 | if (type != XmlPullParser.START_TAG) { 59 | continue; 60 | } 61 | 62 | if (depth > innerDepth || !parser.getName().equals("item")) { 63 | continue; 64 | } 65 | 66 | if (layerAttrUseCount >= childLayersAttrs.length) { 67 | int[][] dstInt = new int[drawables.length + STEP][ATTRS.length]; 68 | System.arraycopy(childLayersAttrs, 0, dstInt, 0, childLayersAttrs.length); 69 | childLayersAttrs = dstInt; 70 | } 71 | updateLayerAttrs(context, attrs, childLayersAttrs[layerAttrUseCount]); 72 | layerAttrUseCount++; 73 | 74 | Drawable drawable = DrawableUtils.getAttrDrawable(context, attrs, android.R.attr.drawable); 75 | 76 | // If the layer doesn't have a drawable or unresolved theme 77 | // attribute for a drawable, attempt to parse one from the child 78 | // element. 79 | if (drawable == null) { 80 | while ((type = parser.next()) == XmlPullParser.TEXT) { 81 | } 82 | if (type != XmlPullParser.START_TAG) { 83 | throw new XmlPullParserException(parser.getPositionDescription() 84 | + ": tag requires a 'drawable' attribute or " 85 | + "child tag defining a drawable"); 86 | } 87 | drawable = DrawableUtils.createFromXmlInner(context, parser, attrs); 88 | } else { 89 | final ColorStateList cls = DrawableUtils.getTintColorList(context, attrs, R.attr.drawableTint); 90 | if (cls != null) { 91 | drawable = ThemeUtils.tintDrawable(drawable, cls, DrawableUtils.getTintMode(context, attrs, R.attr.drawableTintMode)); 92 | } 93 | } 94 | 95 | if (drawable != null) { 96 | if (drawableUseCount >= drawables.length) { 97 | Drawable[] dst = new Drawable[drawables.length + STEP]; 98 | System.arraycopy(drawables, 0, dst, 0, drawables.length); 99 | drawables = dst; 100 | } 101 | drawables[drawableUseCount] = drawable; 102 | drawableUseCount++; 103 | } 104 | } 105 | 106 | if (!isDrawableValidCompat(drawables) || drawableUseCount != layerAttrUseCount) { 107 | return null; 108 | } else { 109 | LayerDrawable layerDrawable = new LayerDrawable(drawables); 110 | for (int i = 0; i < drawables.length; i++) { 111 | int[] childLayersAttr = childLayersAttrs[i]; 112 | if (childLayersAttr[0] != 0 || childLayersAttr[1] != 0 || childLayersAttr[2] != 0 || childLayersAttr[3] != 0) { 113 | layerDrawable.setLayerInset(i, childLayersAttr[0], childLayersAttr[1], childLayersAttr[2], childLayersAttr[3]); 114 | } 115 | if (childLayersAttr[4] != 0) { 116 | layerDrawable.setId(i, childLayersAttr[4]); 117 | } 118 | } 119 | return layerDrawable; 120 | } 121 | } 122 | 123 | void updateLayerAttrs(Context context, AttributeSet attrs, int[] childLayersAttrs) { 124 | childLayersAttrs[0] = DrawableUtils.getAttrDimensionPixelOffset(context, attrs, ATTRS[0]); 125 | childLayersAttrs[1] = DrawableUtils.getAttrDimensionPixelOffset(context, attrs, ATTRS[1]); 126 | childLayersAttrs[2] = DrawableUtils.getAttrDimensionPixelOffset(context, attrs, ATTRS[2]); 127 | childLayersAttrs[3] = DrawableUtils.getAttrDimensionPixelOffset(context, attrs, ATTRS[3]); 128 | childLayersAttrs[4] = DrawableUtils.getAttrResourceId(context, attrs, ATTRS[4], 0); 129 | } 130 | 131 | 132 | private boolean isDrawableValidCompat(Drawable[] drawables) { 133 | if (drawables == null) { 134 | return false; 135 | } 136 | boolean aboveP = Build.VERSION.SDK_INT > Build.VERSION_CODES.P; 137 | for (Drawable drawable : drawables) { 138 | if (drawable == null && !aboveP) { 139 | return false; 140 | } 141 | } 142 | return true; 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/utils/StateListDrawableInflateImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.utils; 18 | 19 | import android.content.Context; 20 | import android.graphics.ColorFilter; 21 | import android.graphics.drawable.Drawable; 22 | import android.graphics.drawable.StateListDrawable; 23 | import android.util.AttributeSet; 24 | import android.util.SparseArray; 25 | 26 | import com.bilibili.magicasakura.R; 27 | import com.bilibili.magicasakura.drawables.FilterableStateListDrawable; 28 | 29 | import org.xmlpull.v1.XmlPullParser; 30 | import org.xmlpull.v1.XmlPullParserException; 31 | 32 | import java.io.IOException; 33 | import java.util.ArrayList; 34 | 35 | /** 36 | * @author xyczero617@gmail.com 37 | * @time 16/2/22 38 | */ 39 | class StateListDrawableInflateImpl implements DrawableInflateDelegate { 40 | 41 | @Override 42 | public Drawable inflateDrawable(Context context, XmlPullParser parser, AttributeSet attrs) throws IOException, XmlPullParserException { 43 | StateListDrawable sd = null; 44 | ArrayList states = new ArrayList<>(); 45 | ArrayList drawables = new ArrayList<>(); 46 | SparseArray mColorFilterMap = null; 47 | final int innerDepth = parser.getDepth() + 1; 48 | int type; 49 | int depth; 50 | 51 | while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 52 | && ((depth = parser.getDepth()) >= innerDepth 53 | || type != XmlPullParser.END_TAG)) { 54 | if (type != XmlPullParser.START_TAG) { 55 | continue; 56 | } 57 | 58 | if (depth > innerDepth || !parser.getName().equals("item")) { 59 | continue; 60 | } 61 | 62 | Drawable dr = DrawableUtils.getAttrDrawable(context, attrs, android.R.attr.drawable); 63 | 64 | states.add(DrawableUtils.extractStateSet(attrs)); 65 | 66 | // Loading child elements modifies the state of the AttributeSet's 67 | // underlying parser, so it needs to happen after obtaining 68 | // attributes and extracting states. 69 | if (dr == null) { 70 | while ((type = parser.next()) == XmlPullParser.TEXT) { 71 | } 72 | if (type != XmlPullParser.START_TAG) { 73 | throw new XmlPullParserException( 74 | parser.getPositionDescription() 75 | + ": tag requires a 'drawable' attribute or " 76 | + "child tag defining a drawable"); 77 | } 78 | dr = DrawableUtils.createFromXmlInner(context, parser, attrs); 79 | } else { 80 | ColorFilter colorFilter = DrawableUtils.getAttrColorFilter(context, attrs, R.attr.drawableTint, R.attr.drawableTintMode); 81 | if (colorFilter != null) { 82 | if (mColorFilterMap == null) { 83 | mColorFilterMap = new SparseArray<>(); 84 | } 85 | mColorFilterMap.put(drawables.size(), colorFilter); 86 | } 87 | } 88 | drawables.add(dr); 89 | } 90 | if (states.size() >= 1) { 91 | if (mColorFilterMap != null) { 92 | sd = new FilterableStateListDrawable(); 93 | for (int i = 0; i < states.size(); i++) { 94 | ((FilterableStateListDrawable) sd).addState(states.get(i), drawables.get(i), mColorFilterMap.get(i)); 95 | } 96 | } else { 97 | sd = new StateListDrawable(); 98 | for (int i = 0; i < states.size(); i++) { 99 | sd.addState(states.get(i), drawables.get(i)); 100 | } 101 | } 102 | } 103 | return sd; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/utils/TintInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.utils; 18 | 19 | import android.content.res.ColorStateList; 20 | import android.graphics.PorterDuff; 21 | import android.support.annotation.RestrictTo; 22 | 23 | import java.util.LinkedList; 24 | 25 | import static android.support.annotation.RestrictTo.Scope.LIBRARY; 26 | 27 | /** 28 | * @author xyczero617@gmail.com 29 | * @time 15/11/21 30 | */ 31 | 32 | @RestrictTo(LIBRARY) 33 | public class TintInfo { 34 | public ColorStateList mTintList; 35 | public PorterDuff.Mode mTintMode; 36 | public boolean mHasTintMode; 37 | public boolean mHasTintList; 38 | 39 | int[] mTintColors; 40 | int[][] mTintStates; 41 | 42 | public TintInfo() { 43 | 44 | } 45 | 46 | public TintInfo(LinkedList stateList, LinkedList colorList) { 47 | if (colorList == null || stateList == null) return; 48 | 49 | mTintColors = new int[colorList.size()]; 50 | for (int i = 0; i < colorList.size(); i++) 51 | mTintColors[i] = colorList.get(i); 52 | mTintStates = stateList.toArray(new int[stateList.size()][]); 53 | } 54 | 55 | public boolean isInvalid() { 56 | return mTintColors == null || mTintStates == null || mTintColors.length != mTintStates.length; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/utils/VectorDrawableInflateImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2017 BiliBili Inc. 3 | */ 4 | 5 | package com.bilibili.magicasakura.utils; 6 | 7 | import android.content.Context; 8 | import android.content.res.ColorStateList; 9 | import android.content.res.TypedArray; 10 | import android.graphics.drawable.Drawable; 11 | import android.support.graphics.drawable.VectorDrawableCompat; 12 | import android.support.v4.graphics.drawable.DrawableCompat; 13 | import android.util.AttributeSet; 14 | import android.util.Log; 15 | 16 | import org.xmlpull.v1.XmlPullParser; 17 | import org.xmlpull.v1.XmlPullParserException; 18 | 19 | import java.io.IOException; 20 | 21 | import static com.bilibili.magicasakura.utils.DrawableUtils.obtainAttributes; 22 | 23 | /** 24 | * @author Jungly 25 | * @email jungly.ik@gmail.com 26 | * @since 2017/05/26 27 | */ 28 | class VectorDrawableInflateImpl implements DrawableInflateDelegate { 29 | 30 | private int resId; 31 | 32 | public VectorDrawableInflateImpl(int resId) { 33 | this.resId = resId; 34 | } 35 | 36 | @Override 37 | public Drawable inflateDrawable(Context context, XmlPullParser parser, AttributeSet attrs) throws IOException, XmlPullParserException { 38 | ColorStateList colorFilter = getTintColorList(context, attrs, android.R.attr.tint); 39 | Drawable d; 40 | if (resId == 0) { 41 | d = VectorDrawableCompat.createFromXmlInner(context.getResources(), parser, attrs); 42 | } else { 43 | d = VectorDrawableCompat.create(context.getResources(), resId, context.getTheme()); 44 | } 45 | if (d != null && colorFilter != null) { 46 | DrawableCompat.setTintList(d, colorFilter); 47 | } 48 | return d; 49 | } 50 | 51 | private ColorStateList getTintColorList(Context context, AttributeSet attrs, int tintAttr) { 52 | TypedArray a = obtainAttributes(context.getResources(), context.getTheme(), attrs, new int[]{tintAttr}); 53 | if (!a.hasValue(0)) { 54 | a.recycle(); 55 | return null; 56 | } 57 | ColorStateList cls = null; 58 | int colorRes = a.getResourceId(0, 0); 59 | if (colorRes != 0) { 60 | cls = TintManager.get(context).getColorStateList(colorRes); 61 | } else { 62 | int color = ThemeUtils.replaceColor(context, a.getColor(0, 0)); 63 | if (color != 0) { 64 | int[][] states = new int[1][]; 65 | states[0] = new int[]{}; 66 | cls = new ColorStateList(states, new int[]{color}); 67 | } 68 | } 69 | a.recycle(); 70 | return cls; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/widgets/AppCompatBaseHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.widgets; 18 | 19 | import android.util.AttributeSet; 20 | import android.view.View; 21 | 22 | import com.bilibili.magicasakura.utils.TintManager; 23 | 24 | /** 25 | * @author xyczero617@gmail.com 26 | * @time 15/10/1 27 | */ 28 | abstract class AppCompatBaseHelper { 29 | protected T mView; 30 | protected TintManager mTintManager; 31 | 32 | private boolean mSkipNextApply; 33 | 34 | AppCompatBaseHelper(T view, TintManager tintManager) { 35 | mView = view; 36 | mTintManager = tintManager; 37 | } 38 | 39 | protected boolean skipNextApply() { 40 | if (mSkipNextApply) { 41 | mSkipNextApply = false; 42 | return true; 43 | } 44 | mSkipNextApply = true; 45 | return false; 46 | } 47 | 48 | protected void setSkipNextApply(boolean flag) { 49 | mSkipNextApply = flag; 50 | } 51 | 52 | abstract void loadFromAttribute(AttributeSet attrs, int defStyleAttr); 53 | 54 | public abstract void tint(); 55 | } 56 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/widgets/AppCompatImageHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.widgets; 18 | 19 | import android.content.res.TypedArray; 20 | import android.graphics.PorterDuff; 21 | import android.graphics.drawable.Drawable; 22 | import android.support.v4.content.ContextCompat; 23 | import android.support.v4.graphics.drawable.DrawableCompat; 24 | import android.util.AttributeSet; 25 | import android.widget.ImageView; 26 | 27 | import com.bilibili.magicasakura.R; 28 | import com.bilibili.magicasakura.utils.DrawableUtils; 29 | import com.bilibili.magicasakura.utils.TintInfo; 30 | import com.bilibili.magicasakura.utils.TintManager; 31 | 32 | /** 33 | * @author xyczero617@gmail.com 34 | * @time 15/11/15 35 | */ 36 | class AppCompatImageHelper extends AppCompatBaseHelper { 37 | 38 | private TintInfo mImageTintInfo; 39 | private int mImageResId; 40 | private int mImageTintResId; 41 | 42 | AppCompatImageHelper(ImageView view, TintManager tintManager) { 43 | super(view, tintManager); 44 | } 45 | 46 | @SuppressWarnings("ResourceType") 47 | @Override 48 | void loadFromAttribute(AttributeSet attrs, int defStyleAttr) { 49 | TypedArray array = mView.getContext().obtainStyledAttributes(attrs, R.styleable.TintImageHelper, defStyleAttr, 0); 50 | // first resolve srcCompat due to not extending by AppCompatImageView 51 | if (mView.getDrawable() == null) { 52 | Drawable image = mTintManager.getDrawable(mImageResId = array.getResourceId(R.styleable.TintImageHelper_srcCompat, 0)); 53 | if (image != null) { 54 | setImageDrawable(image); 55 | } 56 | } 57 | if (array.hasValue(R.styleable.TintImageHelper_imageTint)) { 58 | mImageTintResId = array.getResourceId(R.styleable.TintImageHelper_imageTint, 0); 59 | if (array.hasValue(R.styleable.TintImageHelper_imageTintMode)) { 60 | setSupportImageTintMode(DrawableUtils.parseTintMode(array.getInt(R.styleable.TintImageHelper_imageTintMode, 0), null)); 61 | } 62 | setSupportImageTint(mImageTintResId); 63 | } else if (mImageResId == 0) { 64 | Drawable image = mTintManager.getDrawable(mImageResId = array.getResourceId(R.styleable.TintImageHelper_android_src, 0)); 65 | if (image != null) { 66 | setImageDrawable(image); 67 | } 68 | } 69 | array.recycle(); 70 | } 71 | 72 | /** 73 | * External use 74 | */ 75 | public void setImageDrawable() { 76 | if (skipNextApply()) return; 77 | 78 | resetTintResource(0); 79 | setSkipNextApply(false); 80 | } 81 | 82 | public void setImageResId(int resId) { 83 | if (mImageResId != resId) { 84 | resetTintResource(resId); 85 | 86 | if (resId != 0) { 87 | Drawable image = mTintManager.getDrawable(resId); 88 | setImageDrawable(image != null ? image : ContextCompat.getDrawable(mView.getContext(), resId)); 89 | } 90 | } 91 | } 92 | 93 | public void setImageTintList(int resId, PorterDuff.Mode mode) { 94 | if (mImageTintResId != resId) { 95 | mImageTintResId = resId; 96 | if (mImageTintInfo != null) { 97 | mImageTintInfo.mHasTintList = false; 98 | mImageTintInfo.mTintList = null; 99 | } 100 | setSupportImageTintMode(mode); 101 | setSupportImageTint(resId); 102 | } 103 | } 104 | 105 | /** 106 | * Internal use 107 | */ 108 | private void setImageDrawable(Drawable drawable) { 109 | if (skipNextApply()) return; 110 | 111 | mView.setImageDrawable(drawable); 112 | } 113 | 114 | private boolean setSupportImageTint(int resId) { 115 | if (resId != 0) { 116 | if (mImageTintInfo == null) { 117 | mImageTintInfo = new TintInfo(); 118 | } 119 | mImageTintInfo.mHasTintList = true; 120 | mImageTintInfo.mTintList = mTintManager.getColorStateList(resId); 121 | } 122 | return applySupportImageTint(); 123 | } 124 | 125 | private void setSupportImageTintMode(PorterDuff.Mode mode) { 126 | if (mImageTintResId != 0 && mode != null) { 127 | if (mImageTintInfo == null) { 128 | mImageTintInfo = new TintInfo(); 129 | } 130 | mImageTintInfo.mHasTintMode = true; 131 | mImageTintInfo.mTintMode = mode; 132 | } 133 | } 134 | 135 | private boolean applySupportImageTint() { 136 | Drawable image = mView.getDrawable(); 137 | if (image != null && mImageTintInfo != null && mImageTintInfo.mHasTintList) { 138 | Drawable tintDrawable = image.mutate(); 139 | tintDrawable = DrawableCompat.wrap(tintDrawable); 140 | if (mImageTintInfo.mHasTintList) { 141 | DrawableCompat.setTintList(tintDrawable, mImageTintInfo.mTintList); 142 | } 143 | if (mImageTintInfo.mHasTintMode) { 144 | DrawableCompat.setTintMode(tintDrawable, mImageTintInfo.mTintMode); 145 | } 146 | if (tintDrawable.isStateful()) { 147 | tintDrawable.setState(mView.getDrawableState()); 148 | } 149 | setImageDrawable(tintDrawable); 150 | if (image == tintDrawable) { 151 | tintDrawable.invalidateSelf(); 152 | } 153 | return true; 154 | } 155 | return false; 156 | } 157 | 158 | private void resetTintResource(int resId/*background resource id*/) { 159 | mImageResId = resId; 160 | mImageTintResId = 0; 161 | if (mImageTintInfo != null) { 162 | mImageTintInfo.mHasTintList = false; 163 | mImageTintInfo.mTintList = null; 164 | mImageTintInfo.mHasTintMode = false; 165 | mImageTintInfo.mTintMode = null; 166 | } 167 | } 168 | 169 | @Override 170 | public void tint() { 171 | if (mImageTintResId == 0 || !setSupportImageTint(mImageTintResId)) { 172 | Drawable drawable = mTintManager.getDrawable(mImageResId); 173 | if (drawable == null) { 174 | drawable = mImageResId == 0 ? null : ContextCompat.getDrawable(mView.getContext(), mImageResId); 175 | } 176 | setImageDrawable(drawable); 177 | } 178 | } 179 | 180 | public interface ImageExtensible { 181 | void setImageTintList(int resId); 182 | 183 | void setImageTintList(int resId, PorterDuff.Mode mode); 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/widgets/AppCompatProgressBarHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.widgets; 18 | 19 | import android.content.res.TypedArray; 20 | import android.graphics.drawable.Drawable; 21 | import android.graphics.drawable.LayerDrawable; 22 | import android.support.annotation.Nullable; 23 | import android.util.AttributeSet; 24 | 25 | import com.bilibili.magicasakura.R; 26 | import com.bilibili.magicasakura.utils.TintInfo; 27 | import com.bilibili.magicasakura.utils.TintManager; 28 | 29 | /** 30 | * @author xyczero617@gmail.com 31 | * @time 16/2/4 32 | */ 33 | class AppCompatProgressBarHelper extends AppCompatBaseHelper { 34 | 35 | private int mProgressTintResId; 36 | private int mIndeterminateTintResId; 37 | 38 | private TintInfo mProgressTintInfo; 39 | private TintInfo mIndeterminateTintInfo; 40 | 41 | AppCompatProgressBarHelper(TintProgressBar view, TintManager tintManager) { 42 | super(view, tintManager); 43 | } 44 | 45 | @SuppressWarnings("ResourceType") 46 | @Override 47 | void loadFromAttribute(AttributeSet attrs, int defStyleAttr) { 48 | TypedArray array = mView.getContext().obtainStyledAttributes(attrs, R.styleable.TintProgressBarHelper, defStyleAttr, 0); 49 | if (array.hasValue(R.styleable.TintProgressBarHelper_progressTint)) { 50 | setSupportProgressTint(mProgressTintResId = array.getResourceId(R.styleable.TintProgressBarHelper_progressTint, 0)); 51 | } 52 | if (array.hasValue(R.styleable.TintProgressBarHelper_progressIndeterminateTint)) { 53 | setSupportIndeterminateTint(mIndeterminateTintResId = array.getResourceId(R.styleable.TintProgressBarHelper_progressIndeterminateTint, 0)); 54 | } 55 | array.recycle(); 56 | } 57 | 58 | private void setSupportProgressTint(int resId) { 59 | if (resId != 0) { 60 | if (mProgressTintInfo == null) { 61 | mProgressTintInfo = new TintInfo(); 62 | } 63 | mProgressTintInfo.mHasTintList = true; 64 | mProgressTintInfo.mTintList = mTintManager.getColorStateList(resId); 65 | } 66 | applySupportProgressTint(); 67 | } 68 | 69 | private void setSupportIndeterminateTint(int resId) { 70 | if (resId != 0) { 71 | if (mIndeterminateTintInfo == null) { 72 | mIndeterminateTintInfo = new TintInfo(); 73 | } 74 | mIndeterminateTintInfo.mHasTintList = true; 75 | mIndeterminateTintInfo.mTintList = mTintManager.getColorStateList(resId); 76 | } 77 | applySupportIndeterminateTint(); 78 | } 79 | 80 | private void applySupportProgressTint() { 81 | if (mProgressTintInfo != null 82 | && (mProgressTintInfo.mHasTintList || mProgressTintInfo.mHasTintMode)) { 83 | final Drawable target = getTintTarget(android.R.id.progress, true); 84 | if (target != null) { 85 | TintManager.tintViewDrawable(mView, target, mProgressTintInfo); 86 | // The drawable (or one of its children) may not have been 87 | // stateful before applying the tint, so let's try again. 88 | if (target.isStateful()) { 89 | target.setState(mView.getDrawableState()); 90 | } 91 | } 92 | } 93 | } 94 | 95 | private void applySupportIndeterminateTint() { 96 | Drawable mIndeterminateDrawable = mView.getIndeterminateDrawable(); 97 | if (mIndeterminateDrawable != null && mIndeterminateTintInfo != null) { 98 | final TintInfo tintInfo = mIndeterminateTintInfo; 99 | if (tintInfo.mHasTintList || tintInfo.mHasTintMode) { 100 | mView.setIndeterminateDrawable(mIndeterminateDrawable = mIndeterminateDrawable.mutate()); 101 | TintManager.tintViewDrawable(mView, mIndeterminateDrawable, mIndeterminateTintInfo); 102 | // The drawable (or one of its children) may not have been 103 | // stateful before applying the tint, so let's try again. 104 | if (mIndeterminateDrawable.isStateful()) { 105 | mIndeterminateDrawable.setState(mView.getDrawableState()); 106 | } 107 | } 108 | } 109 | } 110 | 111 | @Nullable 112 | private Drawable getTintTarget(int layerId, boolean shouldFallback) { 113 | Drawable layer = null; 114 | 115 | final Drawable d = mView.getProgressDrawable(); 116 | if (d != null) { 117 | mView.setProgressDrawable(d.mutate()); 118 | 119 | if (d instanceof LayerDrawable) { 120 | layer = ((LayerDrawable) d).findDrawableByLayerId(layerId); 121 | } 122 | 123 | if (shouldFallback && layer == null) { 124 | layer = d; 125 | } 126 | } 127 | 128 | return layer; 129 | } 130 | 131 | @Override 132 | public void tint() { 133 | if (mProgressTintResId != 0) { 134 | setSupportProgressTint(mProgressTintResId); 135 | } 136 | if (mIndeterminateTintResId != 0) { 137 | setSupportIndeterminateTint(mIndeterminateTintResId); 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/widgets/AppCompatTextHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.widgets; 18 | 19 | import android.content.res.ColorStateList; 20 | import android.content.res.TypedArray; 21 | import android.support.annotation.ColorRes; 22 | import android.util.AttributeSet; 23 | import android.widget.TextView; 24 | 25 | import com.bilibili.magicasakura.R; 26 | import com.bilibili.magicasakura.utils.TintInfo; 27 | import com.bilibili.magicasakura.utils.TintManager; 28 | 29 | /** 30 | * @author xyczero617@gmail.com 31 | * @time 15/9/26 32 | */ 33 | class AppCompatTextHelper extends AppCompatBaseHelper { 34 | 35 | //If writing like this: 36 | //int[] ATTRS = { R.attr.tintText, android.R.attr.textColor, android.R.attr.textColorLink, ...}; 37 | //we can't get textColor value when api is below 20; 38 | 39 | private int mTextColorId; 40 | private int mTextLinkColorId; 41 | 42 | private TintInfo mTextColorTintInfo; 43 | private TintInfo mTextLinkColorTintInfo; 44 | 45 | AppCompatTextHelper(TextView view, TintManager tintManager) { 46 | super(view, tintManager); 47 | } 48 | 49 | @SuppressWarnings("ResourceType") 50 | @Override 51 | void loadFromAttribute(AttributeSet attrs, int defStyleAttr) { 52 | TypedArray array = mView.getContext().obtainStyledAttributes(attrs, R.styleable.TintTextHelper , defStyleAttr, 0); 53 | 54 | int textColorId = array.getResourceId(R.styleable.TintTextHelper_android_textColor, 0); 55 | if (textColorId == 0) { 56 | setTextAppearanceForTextColor(array.getResourceId(R.styleable.TintTextHelper_android_textAppearance, 0), false); 57 | } else { 58 | setTextColor(textColorId); 59 | } 60 | 61 | if (array.hasValue(R.styleable.TintTextHelper_android_textColorLink)) { 62 | setLinkTextColor(array.getResourceId(R.styleable.TintTextHelper_android_textColorLink, 0)); 63 | } 64 | array.recycle(); 65 | } 66 | 67 | 68 | /** 69 | * External use 70 | */ 71 | public void setTextColor() { 72 | if (skipNextApply()) return; 73 | 74 | resetTextColorTintResource(0); 75 | setSkipNextApply(false); 76 | } 77 | 78 | /** 79 | * useless for setLinkTextColor is final 80 | */ 81 | @Deprecated 82 | public void setTextLinkColor() { 83 | if (skipNextApply()) return; 84 | 85 | resetTextLinkColorTintResource(0); 86 | setSkipNextApply(false); 87 | } 88 | 89 | public void setTextAppearanceForTextColor(int resId) { 90 | resetTextColorTintResource(0); 91 | setTextAppearanceForTextColor(resId, true); 92 | } 93 | 94 | public void setTextAppearanceForTextColor(int resId, boolean isForced) { 95 | boolean isTextColorForced = isForced || mTextColorId == 0; 96 | TypedArray appearance = mView.getContext().obtainStyledAttributes(resId, R.styleable.TextAppearance); 97 | if (appearance.hasValue(R.styleable.TextAppearance_android_textColor) && isTextColorForced) { 98 | setTextColor(appearance.getResourceId(R.styleable.TextAppearance_android_textColor, 0)); 99 | } 100 | appearance.recycle(); 101 | } 102 | 103 | public void setTextColorById(@ColorRes int colorId) { 104 | setTextColor(colorId); 105 | } 106 | 107 | /** 108 | * Internal use 109 | */ 110 | private void setTextColor(ColorStateList tint) { 111 | if (skipNextApply()) return; 112 | 113 | mView.setTextColor(tint); 114 | } 115 | 116 | private void setTextColor(@ColorRes int resId) { 117 | if (mTextColorId != resId) { 118 | resetTextColorTintResource(resId); 119 | 120 | if (resId != 0) { 121 | setSupportTextColorTint(resId); 122 | } 123 | } 124 | } 125 | 126 | private void setLinkTextColor(@ColorRes int resId) { 127 | if (mTextLinkColorId != resId) { 128 | resetTextLinkColorTintResource(resId); 129 | 130 | if (resId != 0) { 131 | setSupportTextLinkColorTint(resId); 132 | } 133 | } 134 | } 135 | 136 | private void setSupportTextColorTint(int resId) { 137 | if (resId != 0) { 138 | if (mTextColorTintInfo == null) { 139 | mTextColorTintInfo = new TintInfo(); 140 | } 141 | mTextColorTintInfo.mHasTintList = true; 142 | mTextColorTintInfo.mTintList = mTintManager.getColorStateList(resId); 143 | } 144 | applySupportTextColorTint(); 145 | } 146 | 147 | private void setSupportTextLinkColorTint(int resId) { 148 | if (resId != 0) { 149 | if (mTextLinkColorTintInfo == null) { 150 | mTextLinkColorTintInfo = new TintInfo(); 151 | } 152 | mTextLinkColorTintInfo.mHasTintList = true; 153 | mTextLinkColorTintInfo.mTintList = mTintManager.getColorStateList(resId); 154 | } 155 | applySupportTextLinkColorTint(); 156 | } 157 | 158 | private void applySupportTextColorTint() { 159 | if (mTextColorTintInfo != null && mTextColorTintInfo.mHasTintList) { 160 | setTextColor(mTextColorTintInfo.mTintList); 161 | } 162 | } 163 | 164 | private void applySupportTextLinkColorTint() { 165 | if (mTextLinkColorTintInfo != null && mTextLinkColorTintInfo.mHasTintList) { 166 | mView.setLinkTextColor(mTextLinkColorTintInfo.mTintList); 167 | } 168 | } 169 | 170 | private void resetTextColorTintResource(@ColorRes int resId/*text resource id*/) { 171 | mTextColorId = resId; 172 | if (mTextColorTintInfo != null) { 173 | mTextColorTintInfo.mHasTintList = false; 174 | mTextColorTintInfo.mTintList = null; 175 | } 176 | } 177 | 178 | private void resetTextLinkColorTintResource(@ColorRes int resId/*text resource id*/) { 179 | mTextLinkColorId = resId; 180 | if (mTextLinkColorTintInfo != null) { 181 | mTextLinkColorTintInfo.mHasTintList = false; 182 | mTextLinkColorTintInfo.mTintList = null; 183 | } 184 | } 185 | 186 | @Override 187 | public void tint() { 188 | if (mTextColorId != 0) { 189 | setSupportTextColorTint(mTextColorId); 190 | } 191 | if (mTextLinkColorId != 0) { 192 | setSupportTextLinkColorTint(mTextLinkColorId); 193 | } 194 | } 195 | 196 | public interface TextExtensible { 197 | void setTextColorById(@ColorRes int colorId); 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/widgets/TintAppAlertDialogDividingView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.widgets; 18 | 19 | import android.content.Context; 20 | import android.content.res.TypedArray; 21 | import android.util.AttributeSet; 22 | import android.view.View; 23 | 24 | import com.bilibili.magicasakura.R; 25 | import com.bilibili.magicasakura.utils.ThemeUtils; 26 | 27 | /** 28 | * @author xyczero617@gmail.com 29 | * @time 2015/9/1 30 | */ 31 | public class TintAppAlertDialogDividingView extends View { 32 | public static final int[] TINT_ATTRS = { 33 | android.R.attr.background 34 | }; 35 | 36 | public TintAppAlertDialogDividingView(Context context) { 37 | this(context, null); 38 | } 39 | 40 | public TintAppAlertDialogDividingView(Context context, AttributeSet attrs) { 41 | this(context, attrs, 0); 42 | } 43 | 44 | public TintAppAlertDialogDividingView(Context context, AttributeSet attrs, int defStyleAttr) { 45 | super(context, attrs, defStyleAttr); 46 | TypedArray a = context.obtainStyledAttributes(attrs, TINT_ATTRS); 47 | if (a.hasValue(0)) { 48 | if (a.getResourceId(0, 0) == android.R.color.holo_blue_light) { 49 | setBackgroundColor(ThemeUtils.getThemeAttrColor(context, R.attr.themeColorSecondary)); 50 | } 51 | } 52 | a.recycle(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/widgets/TintAppBarLayout.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.widgets; 18 | 19 | import android.content.Context; 20 | import android.graphics.PorterDuff; 21 | import android.graphics.drawable.Drawable; 22 | import android.support.design.widget.AppBarLayout; 23 | import android.util.AttributeSet; 24 | 25 | import com.bilibili.magicasakura.utils.TintManager; 26 | 27 | /** 28 | * @author xyczero617@gmail.com 29 | * @time 16/2/14 30 | */ 31 | public class TintAppBarLayout extends AppBarLayout implements Tintable, AppCompatBackgroundHelper.BackgroundExtensible { 32 | private AppCompatBackgroundHelper mBackgroundHelper; 33 | 34 | public TintAppBarLayout(Context context) { 35 | this(context, null); 36 | } 37 | 38 | public TintAppBarLayout(Context context, AttributeSet attrs) { 39 | super(context, attrs); 40 | if (isInEditMode()) { 41 | return; 42 | } 43 | TintManager tintManager = TintManager.get(context); 44 | 45 | mBackgroundHelper = new AppCompatBackgroundHelper(this, tintManager); 46 | mBackgroundHelper.loadFromAttribute(attrs, 0); 47 | } 48 | 49 | @Override 50 | public void setBackgroundDrawable(Drawable background) { 51 | super.setBackgroundDrawable(background); 52 | if (mBackgroundHelper != null) { 53 | mBackgroundHelper.setBackgroundDrawableExternal(background); 54 | } 55 | } 56 | 57 | @Override 58 | public void setBackgroundResource(int resId) { 59 | if (mBackgroundHelper != null) { 60 | mBackgroundHelper.setBackgroundResId(resId); 61 | } else { 62 | super.setBackgroundResource(resId); 63 | } 64 | } 65 | 66 | @Override 67 | public void setBackgroundColor(int color) { 68 | super.setBackgroundColor(color); 69 | if (mBackgroundHelper != null) { 70 | mBackgroundHelper.setBackgroundColor(color); 71 | } 72 | } 73 | 74 | @Override 75 | public void setBackgroundTintList(int resId) { 76 | if (mBackgroundHelper != null) { 77 | mBackgroundHelper.setBackgroundTintList(resId, null); 78 | } 79 | } 80 | 81 | @Override 82 | public void setBackgroundTintList(int resId, PorterDuff.Mode mode) { 83 | if (mBackgroundHelper != null) { 84 | mBackgroundHelper.setBackgroundTintList(resId, mode); 85 | } 86 | } 87 | 88 | @Override 89 | public void tint() { 90 | if (mBackgroundHelper != null) { 91 | mBackgroundHelper.tint(); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/widgets/TintAutoCompleteTextView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.widgets; 18 | 19 | import android.annotation.SuppressLint; 20 | import android.content.Context; 21 | import android.graphics.PorterDuff; 22 | import android.graphics.drawable.Drawable; 23 | import android.util.AttributeSet; 24 | import android.widget.AutoCompleteTextView; 25 | 26 | import com.bilibili.magicasakura.utils.TintManager; 27 | 28 | /** 29 | * @author xyczero617@gmail.com 30 | * @time 16/2/14 31 | */ 32 | @SuppressLint("AppCompatCustomView") 33 | public class TintAutoCompleteTextView extends AutoCompleteTextView implements Tintable, AppCompatBackgroundHelper.BackgroundExtensible, 34 | AppCompatCompoundDrawableHelper.CompoundDrawableExtensible { 35 | private AppCompatBackgroundHelper mBackgroundHelper; 36 | private AppCompatCompoundDrawableHelper mCompoundDrawableHelper; 37 | 38 | public TintAutoCompleteTextView(Context context) { 39 | this(context, null); 40 | } 41 | 42 | public TintAutoCompleteTextView(Context context, AttributeSet attrs) { 43 | this(context, attrs, android.R.attr.autoCompleteTextViewStyle); 44 | } 45 | 46 | public TintAutoCompleteTextView(Context context, AttributeSet attrs, int defStyleAttr) { 47 | super(context, attrs, defStyleAttr); 48 | if (isInEditMode()) { 49 | return; 50 | } 51 | TintManager tintManager = TintManager.get(getContext()); 52 | 53 | mBackgroundHelper = new AppCompatBackgroundHelper(this, tintManager); 54 | mBackgroundHelper.loadFromAttribute(attrs, defStyleAttr); 55 | 56 | mCompoundDrawableHelper = new AppCompatCompoundDrawableHelper(this, tintManager); 57 | mCompoundDrawableHelper.loadFromAttribute(attrs, defStyleAttr); 58 | } 59 | 60 | @Override 61 | public void setBackground(Drawable background) { 62 | super.setBackground(background); 63 | if (mBackgroundHelper != null) { 64 | mBackgroundHelper.setBackgroundDrawableExternal(background); 65 | } 66 | } 67 | 68 | @Override 69 | public void setBackgroundResource(int resId) { 70 | if (mBackgroundHelper != null) { 71 | mBackgroundHelper.setBackgroundResId(resId); 72 | } else { 73 | super.setBackgroundResource(resId); 74 | } 75 | } 76 | 77 | @Override 78 | public void setBackgroundColor(int color) { 79 | if (mBackgroundHelper != null) { 80 | mBackgroundHelper.setBackgroundColor(color); 81 | } else { 82 | super.setBackgroundColor(color); 83 | } 84 | } 85 | 86 | @Override 87 | public void setCompoundDrawablesWithIntrinsicBounds(int left, int top, int right, int bottom) { 88 | if (mCompoundDrawableHelper != null) { 89 | mCompoundDrawableHelper.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom); 90 | } else { 91 | super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom); 92 | } 93 | } 94 | 95 | @Override 96 | public void setCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top, Drawable right, Drawable bottom) { 97 | super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom); 98 | if (mCompoundDrawableHelper != null) { 99 | mCompoundDrawableHelper.setCompoundDrawablesWithIntrinsicBounds(); 100 | } 101 | } 102 | 103 | @Override 104 | public void setBackgroundTintList(int resId) { 105 | if (mBackgroundHelper != null) { 106 | mBackgroundHelper.setBackgroundTintList(resId, null); 107 | } 108 | } 109 | 110 | @Override 111 | public void setBackgroundTintList(int resId, PorterDuff.Mode mode) { 112 | if (mBackgroundHelper != null) { 113 | mBackgroundHelper.setBackgroundTintList(resId, mode); 114 | } 115 | } 116 | 117 | @Override 118 | public void setCompoundDrawableTintList(int leftResId, int topResId, int rightResId, int bottomResId) { 119 | if (mCompoundDrawableHelper != null) { 120 | mCompoundDrawableHelper.setCompoundDrawablesTintList(leftResId, topResId, rightResId, bottomResId); 121 | } 122 | } 123 | 124 | @Override 125 | public void tint() { 126 | if (mBackgroundHelper != null) { 127 | mBackgroundHelper.tint(); 128 | } 129 | if (mCompoundDrawableHelper != null) { 130 | mCompoundDrawableHelper.tint(); 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/widgets/TintButton.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.widgets; 18 | 19 | import android.annotation.SuppressLint; 20 | import android.annotation.TargetApi; 21 | import android.content.Context; 22 | import android.content.res.ColorStateList; 23 | import android.graphics.PorterDuff; 24 | import android.graphics.drawable.Drawable; 25 | import android.os.Build; 26 | import android.support.annotation.ColorRes; 27 | import android.util.AttributeSet; 28 | import android.widget.Button; 29 | 30 | import com.bilibili.magicasakura.utils.TintManager; 31 | 32 | /** 33 | * @author xyczero617@gmail.com 34 | * @time 15/10/25 35 | */ 36 | 37 | @SuppressLint("AppCompatCustomView") 38 | public class TintButton extends Button implements Tintable, AppCompatBackgroundHelper.BackgroundExtensible, 39 | AppCompatTextHelper.TextExtensible { 40 | private AppCompatTextHelper mTextHelper; 41 | private AppCompatBackgroundHelper mBackgroundHelper; 42 | 43 | public TintButton(Context context) { 44 | this(context, null); 45 | } 46 | 47 | public TintButton(Context context, AttributeSet attrs) { 48 | this(context, attrs, android.R.attr.buttonStyle); 49 | } 50 | 51 | public TintButton(Context context, AttributeSet attrs, int defStyleAttr) { 52 | super(context, attrs, defStyleAttr); 53 | if (isInEditMode()) { 54 | return; 55 | } 56 | TintManager tintManager = TintManager.get(context); 57 | 58 | mBackgroundHelper = new AppCompatBackgroundHelper(this, tintManager); 59 | mBackgroundHelper.loadFromAttribute(attrs, defStyleAttr); 60 | 61 | mTextHelper = new AppCompatTextHelper(this, tintManager); 62 | mTextHelper.loadFromAttribute(attrs, defStyleAttr); 63 | } 64 | 65 | @Override 66 | protected void drawableStateChanged() { 67 | super.drawableStateChanged(); 68 | if (getBackground() != null) { 69 | invalidateDrawable(getBackground()); 70 | } 71 | } 72 | 73 | @Override 74 | public void setTextColor(int color) { 75 | super.setTextColor(color); 76 | if (mTextHelper != null) { 77 | mTextHelper.setTextColor(); 78 | } 79 | } 80 | 81 | @Override 82 | public void setTextColor(ColorStateList colors) { 83 | super.setTextColor(colors); 84 | if (mTextHelper != null) { 85 | mTextHelper.setTextColor(); 86 | } 87 | } 88 | 89 | @TargetApi(Build.VERSION_CODES.M) 90 | @Override 91 | public void setTextAppearance(int resId) { 92 | super.setTextAppearance(resId); 93 | if (mTextHelper != null) { 94 | mTextHelper.setTextAppearanceForTextColor(resId); 95 | } 96 | } 97 | 98 | @Override 99 | public void setTextAppearance(Context context, int resId) { 100 | super.setTextAppearance(context, resId); 101 | if (mTextHelper != null) { 102 | mTextHelper.setTextAppearanceForTextColor(resId); 103 | } 104 | } 105 | 106 | @Override 107 | public void setBackgroundDrawable(Drawable background) { 108 | super.setBackgroundDrawable(background); 109 | if (mBackgroundHelper != null) { 110 | mBackgroundHelper.setBackgroundDrawableExternal(background); 111 | } 112 | } 113 | 114 | @Override 115 | public void setBackgroundResource(int resId) { 116 | if (mBackgroundHelper != null) { 117 | mBackgroundHelper.setBackgroundResId(resId); 118 | } else { 119 | super.setBackgroundResource(resId); 120 | } 121 | } 122 | 123 | @Override 124 | public void setBackgroundColor(int color) { 125 | super.setBackgroundColor(color); 126 | if (mBackgroundHelper != null) { 127 | mBackgroundHelper.setBackgroundColor(color); 128 | } 129 | } 130 | 131 | @Override 132 | public void setBackgroundTintList(int resId) { 133 | if (mBackgroundHelper != null) { 134 | mBackgroundHelper.setBackgroundTintList(resId, null); 135 | } 136 | } 137 | 138 | @Override 139 | public void setBackgroundTintList(int resId, PorterDuff.Mode mode) { 140 | if (mBackgroundHelper != null) { 141 | mBackgroundHelper.setBackgroundTintList(resId, mode); 142 | } 143 | } 144 | 145 | @Override 146 | public void setTextColorById(@ColorRes int colorId) { 147 | if (mTextHelper != null) { 148 | mTextHelper.setTextColorById(colorId); 149 | } 150 | } 151 | 152 | @Override 153 | public void tint() { 154 | if (mTextHelper != null) { 155 | mTextHelper.tint(); 156 | } 157 | if (mBackgroundHelper != null) { 158 | mBackgroundHelper.tint(); 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/widgets/TintCheckedTextView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.widgets; 18 | 19 | import android.annotation.SuppressLint; 20 | import android.content.Context; 21 | import android.content.res.TypedArray; 22 | import android.graphics.PorterDuff; 23 | import android.graphics.drawable.Drawable; 24 | import android.os.Build; 25 | import android.support.annotation.DrawableRes; 26 | import android.support.v4.graphics.drawable.DrawableCompat; 27 | import android.util.AttributeSet; 28 | import android.widget.CheckedTextView; 29 | 30 | import com.bilibili.magicasakura.R; 31 | import com.bilibili.magicasakura.utils.TintManager; 32 | 33 | /** 34 | * @author xyczero617@gmail.com 35 | * @time 16/2/1 36 | *

37 | * special view for replacing view in preference , not recommend to use it in common 38 | * layout: select_dialog_singlechoice_xxx 39 | */ 40 | @SuppressLint("AppCompatCustomView") 41 | public class TintCheckedTextView extends CheckedTextView implements Tintable { 42 | private static final int[] ATTRS = { 43 | android.R.attr.drawableLeft, 44 | R.attr.drawableLeftTint 45 | }; 46 | 47 | public TintCheckedTextView(Context context) { 48 | this(context, null); 49 | } 50 | 51 | public TintCheckedTextView(Context context, AttributeSet attrs) { 52 | this(context, attrs, R.attr.checkedTextViewStyle); 53 | } 54 | 55 | public TintCheckedTextView(Context context, AttributeSet attrs, int defStyleAttr) { 56 | super(context, attrs, defStyleAttr); 57 | TypedArray array = context.obtainStyledAttributes(attrs, ATTRS); 58 | final int drawLeftId = array.getResourceId(0, 0); 59 | final int drawLeftTintId = array.getResourceId(1, 0); 60 | array.recycle(); 61 | if (drawLeftId != 0 && drawLeftTintId != 0) { 62 | tintCheckTextView(drawLeftId, drawLeftTintId); 63 | } 64 | } 65 | 66 | public void tintCheckTextView(@DrawableRes int resId, int tintId) { 67 | Drawable drawable = DrawableCompat.wrap(getResources().getDrawable(resId)); 68 | DrawableCompat.setTintList(drawable, TintManager.get(getContext()).getColorStateList(tintId)); 69 | DrawableCompat.setTintMode(drawable, PorterDuff.Mode.SRC_IN); 70 | //android-sdk-23 material layout is deprecate android.R.styleable#CheckedTextView_checkMark 71 | //follow android native style, check position is left when version is above 5.0 72 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 73 | setCompoundDrawablesRelativeWithIntrinsicBounds(drawable, null, null, null); 74 | setCheckMarkDrawable(null); 75 | } else { 76 | setCheckMarkDrawable(drawable); 77 | setCompoundDrawablesWithIntrinsicBounds(null, null, null, null); 78 | } 79 | } 80 | 81 | @Override 82 | public void setCheckMarkDrawable(Drawable d) { 83 | super.setCheckMarkDrawable(d); 84 | //FIXME:recommend not to use it 85 | } 86 | 87 | @Override 88 | public void setCheckMarkDrawable(int resId) { 89 | super.setCheckMarkDrawable(resId); 90 | //FIXME:recommend not to use it 91 | } 92 | 93 | @Override 94 | public void tint() { 95 | 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/widgets/TintConstraintLayout.java: -------------------------------------------------------------------------------- 1 | package com.bilibili.magicasakura.widgets; 2 | 3 | import android.content.Context; 4 | import android.graphics.PorterDuff; 5 | import android.graphics.drawable.Drawable; 6 | import android.support.constraint.ConstraintLayout; 7 | import android.util.AttributeSet; 8 | 9 | import com.bilibili.magicasakura.utils.TintManager; 10 | 11 | /** 12 | * Created by feifan on 2017/4/11. 13 | * Contacts me:404619986@qq.com 14 | */ 15 | public class TintConstraintLayout extends ConstraintLayout implements Tintable, AppCompatBackgroundHelper.BackgroundExtensible, 16 | AppCompatForegroundHelper.ForegroundExtensible { 17 | 18 | private AppCompatBackgroundHelper mBackgroundHelper; 19 | private AppCompatForegroundHelper mForegroundHelper; 20 | 21 | public TintConstraintLayout(Context context) { 22 | this(context, null); 23 | } 24 | 25 | public TintConstraintLayout(Context context, AttributeSet attrs) { 26 | this(context, attrs, 0); 27 | } 28 | 29 | public TintConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) { 30 | super(context, attrs, defStyleAttr); 31 | if (isInEditMode()) { 32 | return; 33 | } 34 | TintManager tintManager = TintManager.get(context); 35 | 36 | mBackgroundHelper = new AppCompatBackgroundHelper(this, tintManager); 37 | mBackgroundHelper.loadFromAttribute(attrs, defStyleAttr); 38 | 39 | mForegroundHelper = new AppCompatForegroundHelper(this, tintManager); 40 | mForegroundHelper.loadFromAttribute(attrs, defStyleAttr); 41 | } 42 | 43 | @Override 44 | protected void drawableStateChanged() { 45 | super.drawableStateChanged(); 46 | if (getBackground() != null) { 47 | invalidateDrawable(getBackground()); 48 | } 49 | } 50 | 51 | @Override 52 | public void setForeground(Drawable foreground) { 53 | super.setForeground(foreground); 54 | if (mForegroundHelper != null) { 55 | mForegroundHelper.setForegroundDrawableExternal(foreground); 56 | } 57 | } 58 | 59 | public void setForegroundResource(int resId) { 60 | if (mForegroundHelper != null) { 61 | mForegroundHelper.setForegroundResId(resId); 62 | } 63 | } 64 | 65 | @Override 66 | public void setForegroundTintList(int resId) { 67 | if (mForegroundHelper != null) { 68 | mForegroundHelper.setForegroundTintList(resId, null); 69 | } 70 | } 71 | 72 | @Override 73 | public void setForegroundTintList(int resId, PorterDuff.Mode mode) { 74 | if (mForegroundHelper != null) { 75 | mForegroundHelper.setForegroundTintList(resId, mode); 76 | } 77 | } 78 | 79 | @Override 80 | public void setBackgroundDrawable(Drawable background) { 81 | super.setBackgroundDrawable(background); 82 | if (mBackgroundHelper != null) { 83 | mBackgroundHelper.setBackgroundDrawableExternal(background); 84 | } 85 | } 86 | 87 | @Override 88 | public void setBackgroundResource(int resId) { 89 | if (mBackgroundHelper != null) { 90 | mBackgroundHelper.setBackgroundResId(resId); 91 | } else { 92 | super.setBackgroundResource(resId); 93 | } 94 | } 95 | 96 | @Override 97 | public void setBackgroundColor(int color) { 98 | super.setBackgroundColor(color); 99 | if (mBackgroundHelper != null) { 100 | mBackgroundHelper.setBackgroundColor(color); 101 | } 102 | } 103 | 104 | @Override 105 | public void setBackgroundTintList(int resId) { 106 | if (mBackgroundHelper != null) { 107 | mBackgroundHelper.setBackgroundTintList(resId, null); 108 | } 109 | } 110 | 111 | @Override 112 | public void setBackgroundTintList(int resId, PorterDuff.Mode mode) { 113 | if (mBackgroundHelper != null) { 114 | mBackgroundHelper.setBackgroundTintList(resId, mode); 115 | } 116 | } 117 | 118 | @Override 119 | public void tint() { 120 | if (mBackgroundHelper != null) { 121 | mBackgroundHelper.tint(); 122 | } 123 | if (mForegroundHelper != null) { 124 | mForegroundHelper.tint(); 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/widgets/TintEditText.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.widgets; 18 | 19 | import android.annotation.TargetApi; 20 | import android.annotation.SuppressLint; 21 | import android.content.Context; 22 | import android.content.res.ColorStateList; 23 | import android.graphics.PorterDuff; 24 | import android.graphics.drawable.Drawable; 25 | import android.os.Build; 26 | import android.support.annotation.ColorRes; 27 | import android.util.AttributeSet; 28 | import android.view.inputmethod.EditorInfo; 29 | import android.view.inputmethod.InputConnection; 30 | import android.widget.EditText; 31 | 32 | import com.bilibili.magicasakura.utils.InputConnectionImpl; 33 | import com.bilibili.magicasakura.utils.TintManager; 34 | 35 | /** 36 | * @author xyczero617@gmail.com 37 | * @time 16/2/1 38 | */ 39 | @SuppressLint("AppCompatCustomView") 40 | public class TintEditText extends EditText implements Tintable, AppCompatBackgroundHelper.BackgroundExtensible, 41 | AppCompatCompoundDrawableHelper.CompoundDrawableExtensible, AppCompatTextHelper.TextExtensible { 42 | private AppCompatBackgroundHelper mBackgroundHelper; 43 | private AppCompatCompoundDrawableHelper mCompoundDrawableHelper; 44 | private AppCompatTextHelper mTextHelper; 45 | 46 | public TintEditText(Context context) { 47 | this(context, null); 48 | } 49 | 50 | public TintEditText(Context context, AttributeSet attrs) { 51 | this(context, attrs, android.R.attr.editTextStyle); 52 | } 53 | 54 | public TintEditText(Context context, AttributeSet attrs, int defStyleAttr) { 55 | super(context, attrs, defStyleAttr); 56 | if (isInEditMode()) { 57 | return; 58 | } 59 | TintManager tintManager = TintManager.get(getContext()); 60 | 61 | mTextHelper = new AppCompatTextHelper(this, tintManager); 62 | mTextHelper.loadFromAttribute(attrs, defStyleAttr); 63 | 64 | mBackgroundHelper = new AppCompatBackgroundHelper(this, tintManager); 65 | mBackgroundHelper.loadFromAttribute(attrs, defStyleAttr); 66 | 67 | mCompoundDrawableHelper = new AppCompatCompoundDrawableHelper(this, tintManager); 68 | mCompoundDrawableHelper.loadFromAttribute(attrs, defStyleAttr); 69 | } 70 | 71 | @Override 72 | public void setTextColor(int color) { 73 | super.setTextColor(color); 74 | if (mTextHelper != null) { 75 | mTextHelper.setTextColor(); 76 | } 77 | } 78 | 79 | @Override 80 | public void setTextColor(ColorStateList colors) { 81 | super.setTextColor(colors); 82 | if (mTextHelper != null) { 83 | mTextHelper.setTextColor(); 84 | } 85 | } 86 | 87 | @TargetApi(Build.VERSION_CODES.M) 88 | @Override 89 | public void setTextAppearance(int resId) { 90 | super.setTextAppearance(resId); 91 | if (mTextHelper != null) { 92 | mTextHelper.setTextAppearanceForTextColor(resId); 93 | } 94 | } 95 | 96 | @Override 97 | public void setTextAppearance(Context context, int resId) { 98 | super.setTextAppearance(context, resId); 99 | if (mTextHelper != null) { 100 | mTextHelper.setTextAppearanceForTextColor(resId); 101 | } 102 | } 103 | 104 | @Override 105 | public void setBackground(Drawable background) { 106 | super.setBackground(background); 107 | if (mBackgroundHelper != null) { 108 | mBackgroundHelper.setBackgroundDrawableExternal(background); 109 | } 110 | } 111 | 112 | @Override 113 | public void setBackgroundResource(int resId) { 114 | if (mBackgroundHelper != null) { 115 | mBackgroundHelper.setBackgroundResId(resId); 116 | } else { 117 | super.setBackgroundResource(resId); 118 | } 119 | } 120 | 121 | @Override 122 | public void setBackgroundColor(int color) { 123 | if (mBackgroundHelper != null) { 124 | mBackgroundHelper.setBackgroundColor(color); 125 | } else { 126 | super.setBackgroundColor(color); 127 | } 128 | } 129 | 130 | @Override 131 | public void setCompoundDrawablesWithIntrinsicBounds(int left, int top, int right, int bottom) { 132 | if (mCompoundDrawableHelper != null) { 133 | mCompoundDrawableHelper.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom); 134 | } else { 135 | super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom); 136 | } 137 | } 138 | 139 | @Override 140 | public void setCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top, Drawable right, Drawable bottom) { 141 | super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom); 142 | if (mCompoundDrawableHelper != null) { 143 | mCompoundDrawableHelper.setCompoundDrawablesWithIntrinsicBounds(); 144 | } 145 | } 146 | 147 | @Override 148 | public void setBackgroundTintList(int resId) { 149 | if (mBackgroundHelper != null) { 150 | mBackgroundHelper.setBackgroundTintList(resId, null); 151 | } 152 | } 153 | 154 | @Override 155 | public void setBackgroundTintList(int resId, PorterDuff.Mode mode) { 156 | if (mBackgroundHelper != null) { 157 | mBackgroundHelper.setBackgroundTintList(resId, mode); 158 | } 159 | } 160 | 161 | @Override 162 | public void setCompoundDrawableTintList(int leftResId, int topResId, int rightResId, int bottomResId) { 163 | if (mCompoundDrawableHelper != null) { 164 | mCompoundDrawableHelper.setCompoundDrawablesTintList(leftResId, topResId, rightResId, bottomResId); 165 | } 166 | } 167 | 168 | @Override 169 | public void setTextColorById(@ColorRes int colorId) { 170 | if (mTextHelper != null) { 171 | mTextHelper.setTextColorById(colorId); 172 | } 173 | } 174 | 175 | @Override 176 | public void tint() { 177 | if (mTextHelper != null) { 178 | mTextHelper.tint(); 179 | } 180 | if (mBackgroundHelper != null) { 181 | mBackgroundHelper.tint(); 182 | } 183 | if (mCompoundDrawableHelper != null) { 184 | mCompoundDrawableHelper.tint(); 185 | } 186 | } 187 | 188 | @Override 189 | public InputConnection onCreateInputConnection(EditorInfo outAttrs) { 190 | InputConnection conn = super.onCreateInputConnection(outAttrs); 191 | if (conn != null) { 192 | return new InputConnectionImpl(conn, false); 193 | } 194 | return null; 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/widgets/TintFrameLayout.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.widgets; 18 | 19 | import android.content.Context; 20 | import android.graphics.PorterDuff; 21 | import android.graphics.drawable.Drawable; 22 | import android.util.AttributeSet; 23 | import android.widget.FrameLayout; 24 | 25 | import com.bilibili.magicasakura.utils.TintManager; 26 | 27 | /** 28 | * @author xyczero617@gmail.com 29 | * @time 16/2/14 30 | */ 31 | public class TintFrameLayout extends FrameLayout implements Tintable, AppCompatBackgroundHelper.BackgroundExtensible, 32 | AppCompatForegroundHelper.ForegroundExtensible { 33 | 34 | private AppCompatBackgroundHelper mBackgroundHelper; 35 | private AppCompatForegroundHelper mForegroundHelper; 36 | 37 | public TintFrameLayout(Context context) { 38 | this(context, null); 39 | } 40 | 41 | public TintFrameLayout(Context context, AttributeSet attrs) { 42 | this(context, attrs, 0); 43 | } 44 | 45 | public TintFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) { 46 | super(context, attrs, defStyleAttr); 47 | if (isInEditMode()) { 48 | return; 49 | } 50 | TintManager tintManager = TintManager.get(context); 51 | 52 | mBackgroundHelper = new AppCompatBackgroundHelper(this, tintManager); 53 | mBackgroundHelper.loadFromAttribute(attrs, defStyleAttr); 54 | 55 | mForegroundHelper = new AppCompatForegroundHelper(this, tintManager); 56 | mForegroundHelper.loadFromAttribute(attrs, defStyleAttr); 57 | } 58 | 59 | @Override 60 | protected void drawableStateChanged() { 61 | super.drawableStateChanged(); 62 | if (getBackground() != null) { 63 | invalidateDrawable(getBackground()); 64 | } 65 | } 66 | 67 | @Override 68 | public void setForeground(Drawable foreground) { 69 | super.setForeground(foreground); 70 | if (mForegroundHelper != null) { 71 | mForegroundHelper.setForegroundDrawableExternal(foreground); 72 | } 73 | } 74 | 75 | public void setForegroundResource(int resId) { 76 | if (mForegroundHelper != null) { 77 | mForegroundHelper.setForegroundResId(resId); 78 | } 79 | } 80 | 81 | @Override 82 | public void setForegroundTintList(int resId) { 83 | if (mForegroundHelper != null) { 84 | mForegroundHelper.setForegroundTintList(resId, null); 85 | } 86 | } 87 | 88 | @Override 89 | public void setForegroundTintList(int resId, PorterDuff.Mode mode) { 90 | if (mForegroundHelper != null) { 91 | mForegroundHelper.setForegroundTintList(resId, mode); 92 | } 93 | } 94 | 95 | @Override 96 | public void setBackgroundDrawable(Drawable background) { 97 | super.setBackgroundDrawable(background); 98 | if (mBackgroundHelper != null) { 99 | mBackgroundHelper.setBackgroundDrawableExternal(background); 100 | } 101 | } 102 | 103 | @Override 104 | public void setBackgroundResource(int resId) { 105 | if (mBackgroundHelper != null) { 106 | mBackgroundHelper.setBackgroundResId(resId); 107 | } else { 108 | super.setBackgroundResource(resId); 109 | } 110 | } 111 | 112 | @Override 113 | public void setBackgroundColor(int color) { 114 | super.setBackgroundColor(color); 115 | if (mBackgroundHelper != null) { 116 | mBackgroundHelper.setBackgroundColor(color); 117 | } 118 | } 119 | 120 | @Override 121 | public void setBackgroundTintList(int resId) { 122 | if (mBackgroundHelper != null) { 123 | mBackgroundHelper.setBackgroundTintList(resId, null); 124 | } 125 | } 126 | 127 | @Override 128 | public void setBackgroundTintList(int resId, PorterDuff.Mode mode) { 129 | if (mBackgroundHelper != null) { 130 | mBackgroundHelper.setBackgroundTintList(resId, mode); 131 | } 132 | } 133 | 134 | @Override 135 | public void tint() { 136 | if (mBackgroundHelper != null) { 137 | mBackgroundHelper.tint(); 138 | } 139 | if (mForegroundHelper != null) { 140 | mForegroundHelper.tint(); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/widgets/TintGridLayout.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.widgets; 18 | 19 | import android.content.Context; 20 | import android.graphics.PorterDuff; 21 | import android.graphics.drawable.Drawable; 22 | import android.util.AttributeSet; 23 | import android.widget.GridLayout; 24 | 25 | import com.bilibili.magicasakura.utils.TintManager; 26 | 27 | /** 28 | * @author xyczero617@gmail.com 29 | * @time 16/2/23 30 | */ 31 | public class TintGridLayout extends GridLayout implements Tintable, AppCompatBackgroundHelper.BackgroundExtensible { 32 | private AppCompatBackgroundHelper mBackgroundHelper; 33 | 34 | public TintGridLayout(Context context) { 35 | this(context, null); 36 | } 37 | 38 | public TintGridLayout(Context context, AttributeSet attrs) { 39 | this(context, attrs, 0); 40 | } 41 | 42 | public TintGridLayout(Context context, AttributeSet attrs, int defStyleAttr) { 43 | super(context, attrs, defStyleAttr); 44 | if (isInEditMode()) { 45 | return; 46 | } 47 | TintManager tintManager = TintManager.get(context); 48 | 49 | mBackgroundHelper = new AppCompatBackgroundHelper(this, tintManager); 50 | mBackgroundHelper.loadFromAttribute(attrs, defStyleAttr); 51 | } 52 | 53 | @Override 54 | public void setBackgroundDrawable(Drawable background) { 55 | super.setBackgroundDrawable(background); 56 | if (mBackgroundHelper != null) { 57 | mBackgroundHelper.setBackgroundDrawableExternal(background); 58 | } 59 | } 60 | 61 | @Override 62 | public void setBackgroundResource(int resId) { 63 | if (mBackgroundHelper != null) { 64 | mBackgroundHelper.setBackgroundResId(resId); 65 | } else { 66 | super.setBackgroundResource(resId); 67 | } 68 | } 69 | 70 | @Override 71 | public void setBackgroundColor(int color) { 72 | super.setBackgroundColor(color); 73 | if (mBackgroundHelper != null) { 74 | mBackgroundHelper.setBackgroundColor(color); 75 | } 76 | } 77 | 78 | @Override 79 | public void setBackgroundTintList(int resId) { 80 | if (mBackgroundHelper != null) { 81 | mBackgroundHelper.setBackgroundTintList(resId, null); 82 | } 83 | } 84 | 85 | @Override 86 | public void setBackgroundTintList(int resId, PorterDuff.Mode mode) { 87 | if (mBackgroundHelper != null) { 88 | mBackgroundHelper.setBackgroundTintList(resId, mode); 89 | } 90 | } 91 | 92 | @Override 93 | public void tint() { 94 | if (mBackgroundHelper != null) { 95 | mBackgroundHelper.tint(); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/widgets/TintImageView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.widgets; 18 | 19 | import android.annotation.SuppressLint; 20 | import android.content.Context; 21 | import android.graphics.PorterDuff; 22 | import android.graphics.drawable.Drawable; 23 | import android.util.AttributeSet; 24 | import android.widget.ImageView; 25 | 26 | import com.bilibili.magicasakura.utils.TintManager; 27 | 28 | /** 29 | * @author xyczero617@gmail.com 30 | * @time 15/11/8 31 | */ 32 | @SuppressLint("AppCompatCustomView") 33 | public class TintImageView extends ImageView implements Tintable, AppCompatBackgroundHelper.BackgroundExtensible, 34 | AppCompatImageHelper.ImageExtensible { 35 | private AppCompatBackgroundHelper mBackgroundHelper; 36 | private AppCompatImageHelper mImageHelper; 37 | 38 | public TintImageView(Context context) { 39 | this(context, null); 40 | } 41 | 42 | public TintImageView(Context context, AttributeSet attrs) { 43 | this(context, attrs, 0); 44 | } 45 | 46 | public TintImageView(Context context, AttributeSet attrs, int defStyleAttr) { 47 | super(context, attrs, defStyleAttr); 48 | if (isInEditMode()) { 49 | return; 50 | } 51 | TintManager tintManager = TintManager.get(context); 52 | 53 | mBackgroundHelper = new AppCompatBackgroundHelper(this, tintManager); 54 | mBackgroundHelper.loadFromAttribute(attrs, defStyleAttr); 55 | 56 | mImageHelper = new AppCompatImageHelper(this, tintManager); 57 | mImageHelper.loadFromAttribute(attrs, defStyleAttr); 58 | } 59 | 60 | @Override 61 | protected void drawableStateChanged() { 62 | super.drawableStateChanged(); 63 | if (getBackground() != null) { 64 | invalidateDrawable(getBackground()); 65 | } 66 | } 67 | 68 | @Override 69 | public void setBackgroundDrawable(Drawable background) { 70 | super.setBackgroundDrawable(background); 71 | if (mBackgroundHelper != null) { 72 | mBackgroundHelper.setBackgroundDrawableExternal(background); 73 | } 74 | } 75 | 76 | @Override 77 | public void setBackgroundResource(int resId) { 78 | if (mBackgroundHelper != null) { 79 | mBackgroundHelper.setBackgroundResId(resId); 80 | } else { 81 | super.setBackgroundResource(resId); 82 | } 83 | } 84 | 85 | @Override 86 | public void setBackgroundColor(int color) { 87 | super.setBackgroundColor(color); 88 | if (mBackgroundHelper != null) { 89 | mBackgroundHelper.setBackgroundColor(color); 90 | } 91 | } 92 | 93 | @Override 94 | public void setImageDrawable(Drawable drawable) { 95 | super.setImageDrawable(drawable); 96 | if (mImageHelper != null) { 97 | mImageHelper.setImageDrawable(); 98 | } 99 | } 100 | 101 | @Override 102 | public void setImageResource(int resId) { 103 | if (mImageHelper != null) { 104 | mImageHelper.setImageResId(resId); 105 | } else { 106 | super.setImageResource(resId); 107 | } 108 | } 109 | 110 | @Override 111 | public void setBackgroundTintList(int resId) { 112 | if (mBackgroundHelper != null) { 113 | mBackgroundHelper.setBackgroundTintList(resId, null); 114 | } 115 | } 116 | 117 | @Override 118 | public void setBackgroundTintList(int resId, PorterDuff.Mode mode) { 119 | if (mBackgroundHelper != null) { 120 | mBackgroundHelper.setBackgroundTintList(resId, mode); 121 | } 122 | } 123 | 124 | @Override 125 | public void setImageTintList(int resId) { 126 | if (mImageHelper != null) { 127 | mImageHelper.setImageTintList(resId, null); 128 | } 129 | } 130 | 131 | @Override 132 | public void setImageTintList(int resId, PorterDuff.Mode mode) { 133 | if (mImageHelper != null) { 134 | mImageHelper.setImageTintList(resId, mode); 135 | } 136 | } 137 | 138 | @Override 139 | public void tint() { 140 | if (mBackgroundHelper != null) { 141 | mBackgroundHelper.tint(); 142 | } 143 | if (mImageHelper != null) { 144 | mImageHelper.tint(); 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/widgets/TintLinearLayout.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.widgets; 18 | 19 | import android.content.Context; 20 | import android.graphics.PorterDuff; 21 | import android.graphics.drawable.Drawable; 22 | import android.util.AttributeSet; 23 | import android.widget.LinearLayout; 24 | 25 | import com.bilibili.magicasakura.utils.TintManager; 26 | 27 | /** 28 | * @author xyczero617@gmail.com 29 | * @time 16/2/14 30 | */ 31 | public class TintLinearLayout extends LinearLayout implements Tintable, AppCompatBackgroundHelper.BackgroundExtensible { 32 | private AppCompatBackgroundHelper mBackgroundHelper; 33 | 34 | public TintLinearLayout(Context context) { 35 | this(context, null); 36 | } 37 | 38 | public TintLinearLayout(Context context, AttributeSet attrs) { 39 | this(context, attrs, 0); 40 | } 41 | 42 | public TintLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) { 43 | super(context, attrs, defStyleAttr); 44 | if (isInEditMode()) { 45 | return; 46 | } 47 | TintManager tintManager = TintManager.get(context); 48 | 49 | mBackgroundHelper = new AppCompatBackgroundHelper(this, tintManager); 50 | mBackgroundHelper.loadFromAttribute(attrs, defStyleAttr); 51 | } 52 | 53 | @Override 54 | protected void drawableStateChanged() { 55 | super.drawableStateChanged(); 56 | if (getBackground() != null) { 57 | invalidateDrawable(getBackground()); 58 | } 59 | } 60 | 61 | @Override 62 | public void setBackgroundDrawable(Drawable background) { 63 | super.setBackgroundDrawable(background); 64 | if (mBackgroundHelper != null) { 65 | mBackgroundHelper.setBackgroundDrawableExternal(background); 66 | } 67 | } 68 | 69 | @Override 70 | public void setBackgroundResource(int resId) { 71 | if (mBackgroundHelper != null) { 72 | mBackgroundHelper.setBackgroundResId(resId); 73 | } else { 74 | super.setBackgroundResource(resId); 75 | } 76 | } 77 | 78 | @Override 79 | public void setBackgroundColor(int color) { 80 | super.setBackgroundColor(color); 81 | if (mBackgroundHelper != null) { 82 | mBackgroundHelper.setBackgroundColor(color); 83 | } 84 | } 85 | 86 | @Override 87 | public void setBackgroundTintList(int resId) { 88 | if (mBackgroundHelper != null) { 89 | mBackgroundHelper.setBackgroundTintList(resId, null); 90 | } 91 | } 92 | 93 | @Override 94 | public void setBackgroundTintList(int resId, PorterDuff.Mode mode) { 95 | if (mBackgroundHelper != null) { 96 | mBackgroundHelper.setBackgroundTintList(resId, mode); 97 | } 98 | } 99 | 100 | @Override 101 | public void tint() { 102 | if (mBackgroundHelper != null) { 103 | mBackgroundHelper.tint(); 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/widgets/TintProgressBar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.widgets; 18 | 19 | import android.content.Context; 20 | import android.util.AttributeSet; 21 | import android.widget.ProgressBar; 22 | 23 | import com.bilibili.magicasakura.utils.TintManager; 24 | 25 | /** 26 | * @author xyczero617@gmail.com 27 | * @time 16/2/4 28 | */ 29 | public class TintProgressBar extends ProgressBar implements Tintable { 30 | private AppCompatProgressBarHelper mProgressBarHelper; 31 | 32 | public TintProgressBar(Context context) { 33 | this(context, null); 34 | } 35 | 36 | public TintProgressBar(Context context, AttributeSet attrs) { 37 | this(context, attrs, android.R.attr.progressBarStyle); 38 | } 39 | 40 | public TintProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { 41 | super(context, attrs, defStyleAttr); 42 | if (isInEditMode()) { 43 | return; 44 | } 45 | TintManager tintManage = TintManager.get(context); 46 | 47 | mProgressBarHelper = new AppCompatProgressBarHelper(this, tintManage); 48 | mProgressBarHelper.loadFromAttribute(attrs, defStyleAttr); 49 | } 50 | 51 | @Override 52 | public void tint() { 53 | if (mProgressBarHelper != null) { 54 | mProgressBarHelper.tint(); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/widgets/TintRelativeLayout.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.widgets; 18 | 19 | import android.content.Context; 20 | import android.graphics.PorterDuff; 21 | import android.graphics.drawable.Drawable; 22 | import android.util.AttributeSet; 23 | import android.widget.RelativeLayout; 24 | 25 | import com.bilibili.magicasakura.utils.TintManager; 26 | 27 | /** 28 | * @author xyczero617@gmail.com 29 | * @time 16/2/14 30 | */ 31 | public class TintRelativeLayout extends RelativeLayout implements Tintable, AppCompatBackgroundHelper.BackgroundExtensible { 32 | private AppCompatBackgroundHelper mBackgroundHelper; 33 | 34 | public TintRelativeLayout(Context context) { 35 | this(context, null); 36 | } 37 | 38 | public TintRelativeLayout(Context context, AttributeSet attrs) { 39 | this(context, attrs, 0); 40 | } 41 | 42 | public TintRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) { 43 | super(context, attrs, defStyleAttr); 44 | if (isInEditMode()) { 45 | return; 46 | } 47 | TintManager tintManager = TintManager.get(context); 48 | 49 | mBackgroundHelper = new AppCompatBackgroundHelper(this, tintManager); 50 | mBackgroundHelper.loadFromAttribute(attrs, defStyleAttr); 51 | } 52 | 53 | @Override 54 | protected void drawableStateChanged() { 55 | super.drawableStateChanged(); 56 | if (getBackground() != null) { 57 | invalidateDrawable(getBackground()); 58 | } 59 | } 60 | 61 | @Override 62 | public void setBackgroundDrawable(Drawable background) { 63 | super.setBackgroundDrawable(background); 64 | if (mBackgroundHelper != null) { 65 | mBackgroundHelper.setBackgroundDrawableExternal(background); 66 | } 67 | } 68 | 69 | @Override 70 | public void setBackgroundResource(int resId) { 71 | if (mBackgroundHelper != null) { 72 | mBackgroundHelper.setBackgroundResId(resId); 73 | } else { 74 | super.setBackgroundResource(resId); 75 | } 76 | } 77 | 78 | @Override 79 | public void setBackgroundColor(int color) { 80 | super.setBackgroundColor(color); 81 | if (mBackgroundHelper != null) { 82 | mBackgroundHelper.setBackgroundColor(color); 83 | } 84 | } 85 | 86 | @Override 87 | public void setBackgroundTintList(int resId) { 88 | if (mBackgroundHelper != null) { 89 | mBackgroundHelper.setBackgroundTintList(resId, null); 90 | } 91 | } 92 | 93 | @Override 94 | public void setBackgroundTintList(int resId, PorterDuff.Mode mode) { 95 | if (mBackgroundHelper != null) { 96 | mBackgroundHelper.setBackgroundTintList(resId, mode); 97 | } 98 | } 99 | 100 | @Override 101 | public void tint() { 102 | if (mBackgroundHelper != null) { 103 | mBackgroundHelper.tint(); 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/widgets/TintToolbar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.widgets; 18 | 19 | import android.content.Context; 20 | import android.graphics.PorterDuff; 21 | import android.graphics.drawable.Drawable; 22 | import android.support.v7.widget.Toolbar; 23 | import android.util.AttributeSet; 24 | 25 | import com.bilibili.magicasakura.R; 26 | import com.bilibili.magicasakura.utils.TintManager; 27 | 28 | /** 29 | * @author xyczero617@gmail.com 30 | * @time 15/10/19 31 | */ 32 | public class TintToolbar extends Toolbar implements Tintable, AppCompatBackgroundHelper.BackgroundExtensible { 33 | private AppCompatBackgroundHelper mBackgroundHelper; 34 | 35 | public TintToolbar(Context context) { 36 | this(context, null); 37 | } 38 | 39 | public TintToolbar(Context context, AttributeSet attrs) { 40 | this(context, attrs, R.attr.toolbarStyle); 41 | } 42 | 43 | public TintToolbar(Context context, AttributeSet attrs, int defStyleAttr) { 44 | super(context, attrs, defStyleAttr); 45 | if (isInEditMode()) { 46 | return; 47 | } 48 | TintManager mTintManager = TintManager.get(getContext()); 49 | 50 | mBackgroundHelper = new AppCompatBackgroundHelper(this, mTintManager); 51 | mBackgroundHelper.loadFromAttribute(attrs, defStyleAttr); 52 | } 53 | 54 | @Override 55 | public void setBackgroundDrawable(Drawable background) { 56 | super.setBackgroundDrawable(background); 57 | if (mBackgroundHelper != null) { 58 | mBackgroundHelper.setBackgroundDrawableExternal(background); 59 | } 60 | } 61 | 62 | @Override 63 | public void setBackgroundResource(int resId) { 64 | if (mBackgroundHelper != null) { 65 | mBackgroundHelper.setBackgroundResId(resId); 66 | } else { 67 | super.setBackgroundResource(resId); 68 | } 69 | } 70 | 71 | @Override 72 | public void setBackgroundColor(int color) { 73 | super.setBackgroundColor(color); 74 | if (mBackgroundHelper != null) { 75 | mBackgroundHelper.setBackgroundColor(color); 76 | } 77 | } 78 | 79 | @Override 80 | public void setBackgroundTintList(int resId) { 81 | if (mBackgroundHelper != null) { 82 | mBackgroundHelper.setBackgroundTintList(resId, null); 83 | } 84 | } 85 | 86 | @Override 87 | public void setBackgroundTintList(int resId, PorterDuff.Mode mode) { 88 | if (mBackgroundHelper != null) { 89 | mBackgroundHelper.setBackgroundTintList(resId, mode); 90 | } 91 | } 92 | 93 | @Override 94 | public void tint() { 95 | if (mBackgroundHelper != null) { 96 | mBackgroundHelper.tint(); 97 | } 98 | } 99 | } -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/widgets/TintView.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.widgets; 18 | 19 | import android.content.Context; 20 | import android.graphics.PorterDuff; 21 | import android.graphics.drawable.Drawable; 22 | import android.util.AttributeSet; 23 | import android.view.View; 24 | 25 | import com.bilibili.magicasakura.utils.TintManager; 26 | 27 | /** 28 | * @author xyczero617@gmail.com 29 | * @time 16/2/18 30 | */ 31 | public class TintView extends View implements Tintable, AppCompatBackgroundHelper.BackgroundExtensible { 32 | private AppCompatBackgroundHelper mBackgroundHelper; 33 | 34 | public TintView(Context context) { 35 | this(context, null); 36 | } 37 | 38 | public TintView(Context context, AttributeSet attrs) { 39 | this(context, attrs, 0); 40 | } 41 | 42 | public TintView(Context context, AttributeSet attrs, int defStyleAttr) { 43 | super(context, attrs, defStyleAttr); 44 | if (isInEditMode()) { 45 | return; 46 | } 47 | TintManager tintManager = TintManager.get(context); 48 | 49 | mBackgroundHelper = new AppCompatBackgroundHelper(this, tintManager); 50 | mBackgroundHelper.loadFromAttribute(attrs, defStyleAttr); 51 | } 52 | 53 | @Override 54 | public void setBackgroundDrawable(Drawable background) { 55 | super.setBackgroundDrawable(background); 56 | if (mBackgroundHelper != null) { 57 | mBackgroundHelper.setBackgroundDrawableExternal(background); 58 | } 59 | } 60 | 61 | @Override 62 | public void setBackgroundResource(int resId) { 63 | if (mBackgroundHelper != null) { 64 | mBackgroundHelper.setBackgroundResId(resId); 65 | } else { 66 | super.setBackgroundResource(resId); 67 | } 68 | } 69 | 70 | @Override 71 | public void setBackgroundColor(int color) { 72 | super.setBackgroundColor(color); 73 | if (mBackgroundHelper != null) { 74 | mBackgroundHelper.setBackgroundColor(color); 75 | } 76 | } 77 | 78 | @Override 79 | public void setBackgroundTintList(int resId) { 80 | if (mBackgroundHelper != null) { 81 | mBackgroundHelper.setBackgroundTintList(resId, null); 82 | } 83 | } 84 | 85 | @Override 86 | public void setBackgroundTintList(int resId, PorterDuff.Mode mode) { 87 | if (mBackgroundHelper != null) { 88 | mBackgroundHelper.setBackgroundTintList(resId, mode); 89 | } 90 | } 91 | 92 | @Override 93 | public void tint() { 94 | if (mBackgroundHelper != null) { 95 | mBackgroundHelper.tint(); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /magicasakura/src/main/java/com/bilibili/magicasakura/widgets/Tintable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakura.widgets; 18 | 19 | import android.content.Context; 20 | 21 | /** 22 | * Created by xyczero on 15/9/6. 23 | * Email : xyczero@sina.com 24 | * 25 | * Developers can implement this interface, the view that implement it will be refreshed when calling 26 | * {@link com.bilibili.magicasakura.utils.ThemeUtils#refreshUI(Context)} 27 | */ 28 | public interface Tintable { 29 | void tint(); 30 | } 31 | -------------------------------------------------------------------------------- /magicasakura/src/main/res-public/values/public.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /magicasakura/src/main/res/layout/dialog_alert_progress.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 25 | 26 | 35 | 36 | 43 | 44 | 51 | 52 | -------------------------------------------------------------------------------- /magicasakura/src/main/res/layout/dialog_progress.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 22 | 23 | 33 | 34 | 41 | 42 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /sample/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /sample/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | 5 | compileSdkVersion rootProject.ext.compileSdkVersion 6 | buildToolsVersion rootProject.ext.buildToolsVersion 7 | 8 | defaultConfig { 9 | applicationId "com.bilibili.magicasakurademo" 10 | minSdkVersion rootProject.ext.minSdkVersion 11 | targetSdkVersion rootProject.ext.targetSdkVersion 12 | versionCode 1 13 | versionName '1.0' 14 | } 15 | 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | } 23 | 24 | dependencies { 25 | implementation fileTree(dir: 'libs', include: ['*.jar']) 26 | implementation project(':magicasakura') 27 | 28 | implementation "com.android.support:design:${rootProject.ext.supportVersion}" 29 | implementation "com.android.support:preference-v7:${rootProject.ext.supportVersion}" 30 | } 31 | -------------------------------------------------------------------------------- /sample/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/xyczero/xyczero/android-sdk-macosx/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /sample/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /sample/src/main/java/com/bilibili/magicasakurademo/MyApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakurademo; 18 | 19 | import android.app.Application; 20 | import android.content.Context; 21 | import android.support.annotation.ColorInt; 22 | import android.support.annotation.ColorRes; 23 | 24 | import com.bilibili.magicasakurademo.utils.ThemeHelper; 25 | import com.bilibili.magicasakura.utils.ThemeUtils; 26 | 27 | /** 28 | * @author xyczero 29 | * @time 16/5/2 30 | */ 31 | public class MyApplication extends Application implements ThemeUtils.switchColor { 32 | 33 | @Override 34 | public void onCreate() { 35 | super.onCreate(); 36 | ThemeUtils.setSwitchColor(this); 37 | } 38 | 39 | @Override 40 | public int replaceColorById(Context context, @ColorRes int colorId) { 41 | if (ThemeHelper.isDefaultTheme(context)) { 42 | return context.getResources().getColor(colorId); 43 | } 44 | String theme = getTheme(context); 45 | if (theme != null) { 46 | colorId = getThemeColorId(context, colorId, theme); 47 | } 48 | return context.getResources().getColor(colorId); 49 | } 50 | 51 | @Override 52 | public int replaceColor(Context context, @ColorInt int originColor) { 53 | if (ThemeHelper.isDefaultTheme(context)) { 54 | return originColor; 55 | } 56 | String theme = getTheme(context); 57 | int colorId = -1; 58 | 59 | if (theme != null) { 60 | colorId = getThemeColor(context, originColor, theme); 61 | } 62 | return colorId != -1 ? getResources().getColor(colorId) : originColor; 63 | } 64 | 65 | private String getTheme(Context context) { 66 | if (ThemeHelper.getTheme(context) == ThemeHelper.CARD_STORM) { 67 | return "blue"; 68 | } else if (ThemeHelper.getTheme(context) == ThemeHelper.CARD_HOPE) { 69 | return "purple"; 70 | } else if (ThemeHelper.getTheme(context) == ThemeHelper.CARD_WOOD) { 71 | return "green"; 72 | } else if (ThemeHelper.getTheme(context) == ThemeHelper.CARD_LIGHT) { 73 | return "green_light"; 74 | } else if (ThemeHelper.getTheme(context) == ThemeHelper.CARD_THUNDER) { 75 | return "yellow"; 76 | } else if (ThemeHelper.getTheme(context) == ThemeHelper.CARD_SAND) { 77 | return "orange"; 78 | } else if (ThemeHelper.getTheme(context) == ThemeHelper.CARD_FIREY) { 79 | return "red"; 80 | } 81 | return null; 82 | } 83 | 84 | private 85 | @ColorRes 86 | int getThemeColorId(Context context, int colorId, String theme) { 87 | switch (colorId) { 88 | case R.color.theme_color_primary: 89 | return context.getResources().getIdentifier(theme, "color", getPackageName()); 90 | case R.color.theme_color_primary_dark: 91 | return context.getResources().getIdentifier(theme + "_dark", "color", getPackageName()); 92 | case R.color.theme_color_primary_trans: 93 | return context.getResources().getIdentifier(theme + "_trans", "color", getPackageName()); 94 | } 95 | return colorId; 96 | } 97 | 98 | private 99 | @ColorRes 100 | int getThemeColor(Context context, int color, String theme) { 101 | switch (color) { 102 | case 0xfffb7299: 103 | return context.getResources().getIdentifier(theme, "color", getPackageName()); 104 | case 0xffb85671: 105 | return context.getResources().getIdentifier(theme + "_dark", "color", getPackageName()); 106 | case 0x99f0486c: 107 | return context.getResources().getIdentifier(theme + "_trans", "color", getPackageName()); 108 | } 109 | return -1; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /sample/src/main/java/com/bilibili/magicasakurademo/dialog/CardPickerDialog.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakurademo.dialog; 18 | 19 | import android.os.Bundle; 20 | import android.support.annotation.Nullable; 21 | import android.support.v4.app.DialogFragment; 22 | import android.view.LayoutInflater; 23 | import android.view.View; 24 | import android.view.ViewGroup; 25 | import android.widget.Button; 26 | import android.widget.ImageView; 27 | 28 | import com.bilibili.magicasakurademo.R; 29 | import com.bilibili.magicasakurademo.utils.ThemeHelper; 30 | 31 | /** 32 | * @author xyczero 33 | * @time 16/5/29 34 | */ 35 | public class CardPickerDialog extends DialogFragment implements View.OnClickListener { 36 | public static final String TAG = "CardPickerDialog"; 37 | ImageView[] mCards = new ImageView[8]; 38 | Button mConfirm; 39 | Button mCancel; 40 | 41 | private int mCurrentTheme; 42 | private ClickListener mClickListener; 43 | 44 | @Override 45 | public void onCreate(@Nullable Bundle savedInstanceState) { 46 | super.onCreate(savedInstanceState); 47 | setStyle(DialogFragment.STYLE_NO_TITLE, R.style.AppTheme_AppCompat_Dialog_Alert); 48 | mCurrentTheme = ThemeHelper.getTheme(getActivity()); 49 | } 50 | 51 | @Nullable 52 | @Override 53 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 54 | return inflater.inflate(R.layout.dialog_theme_picker, container, false); 55 | } 56 | 57 | @Override 58 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 59 | super.onViewCreated(view, savedInstanceState); 60 | mCancel = (Button) view.findViewById(android.R.id.button2); 61 | mConfirm = (Button) view.findViewById(android.R.id.button1); 62 | mCards[0] = (ImageView) view.findViewById(R.id.theme_pink); 63 | mCards[1] = (ImageView) view.findViewById(R.id.theme_purple); 64 | mCards[2] = (ImageView) view.findViewById(R.id.theme_blue); 65 | mCards[3] = (ImageView) view.findViewById(R.id.theme_green); 66 | mCards[4] = (ImageView) view.findViewById(R.id.theme_green_light); 67 | mCards[5] = (ImageView) view.findViewById(R.id.theme_yellow); 68 | mCards[6] = (ImageView) view.findViewById(R.id.theme_orange); 69 | mCards[7] = (ImageView) view.findViewById(R.id.theme_red); 70 | setImageButtons(mCurrentTheme); 71 | for (ImageView card : mCards) { 72 | card.setOnClickListener(this); 73 | } 74 | mCancel.setOnClickListener(this); 75 | mConfirm.setOnClickListener(this); 76 | } 77 | 78 | @Override 79 | public void onClick(View v) { 80 | switch (v.getId()) { 81 | case android.R.id.button1: 82 | if (mClickListener != null) { 83 | mClickListener.onConfirm(mCurrentTheme); 84 | } 85 | case android.R.id.button2: 86 | dismiss(); 87 | break; 88 | case R.id.theme_pink: 89 | mCurrentTheme = ThemeHelper.CARD_SAKURA; 90 | setImageButtons(mCurrentTheme); 91 | break; 92 | case R.id.theme_purple: 93 | mCurrentTheme = ThemeHelper.CARD_HOPE; 94 | setImageButtons(mCurrentTheme); 95 | break; 96 | case R.id.theme_blue: 97 | mCurrentTheme = ThemeHelper.CARD_STORM; 98 | setImageButtons(mCurrentTheme); 99 | break; 100 | case R.id.theme_green: 101 | mCurrentTheme = ThemeHelper.CARD_WOOD; 102 | setImageButtons(mCurrentTheme); 103 | break; 104 | case R.id.theme_green_light: 105 | mCurrentTheme = ThemeHelper.CARD_LIGHT; 106 | setImageButtons(mCurrentTheme); 107 | break; 108 | case R.id.theme_yellow: 109 | mCurrentTheme = ThemeHelper.CARD_THUNDER; 110 | setImageButtons(mCurrentTheme); 111 | break; 112 | case R.id.theme_orange: 113 | mCurrentTheme = ThemeHelper.CARD_SAND; 114 | setImageButtons(mCurrentTheme); 115 | break; 116 | case R.id.theme_red: 117 | mCurrentTheme = ThemeHelper.CARD_FIREY; 118 | setImageButtons(mCurrentTheme); 119 | break; 120 | default: 121 | break; 122 | } 123 | } 124 | 125 | private void setImageButtons(int currentTheme) { 126 | mCards[0].setSelected(currentTheme == ThemeHelper.CARD_SAKURA); 127 | mCards[1].setSelected(currentTheme == ThemeHelper.CARD_HOPE); 128 | mCards[2].setSelected(currentTheme == ThemeHelper.CARD_STORM); 129 | mCards[3].setSelected(currentTheme == ThemeHelper.CARD_WOOD); 130 | mCards[4].setSelected(currentTheme == ThemeHelper.CARD_LIGHT); 131 | mCards[5].setSelected(currentTheme == ThemeHelper.CARD_THUNDER); 132 | mCards[6].setSelected(currentTheme == ThemeHelper.CARD_SAND); 133 | mCards[7].setSelected(currentTheme == ThemeHelper.CARD_FIREY); 134 | } 135 | 136 | public void setClickListener(ClickListener clickListener) { 137 | mClickListener = clickListener; 138 | } 139 | 140 | public interface ClickListener { 141 | void onConfirm(int currentTheme); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /sample/src/main/java/com/bilibili/magicasakurademo/dialog/ProgressCheckDialog.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakurademo.dialog; 18 | 19 | import android.os.Bundle; 20 | import android.support.annotation.Nullable; 21 | import android.support.v4.app.DialogFragment; 22 | import android.view.LayoutInflater; 23 | import android.view.View; 24 | import android.view.ViewGroup; 25 | 26 | import com.bilibili.magicasakurademo.R; 27 | 28 | /** 29 | * @author xyczero 30 | * @time 16/5/23 31 | */ 32 | public class ProgressCheckDialog extends DialogFragment{ 33 | public static final String TAG = ProgressCheckDialog.class.getSimpleName(); 34 | 35 | @Override 36 | public void onCreate(@Nullable Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | setStyle(DialogFragment.STYLE_NO_TITLE, R.style.AppTheme_AppCompat_Dialog_Alert); 39 | } 40 | 41 | @Nullable 42 | @Override 43 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 44 | return inflater.inflate(R.layout.dialog_check_layout, container, false); 45 | } 46 | 47 | @Override 48 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 49 | super.onViewCreated(view, savedInstanceState); 50 | View cancelButton = view.findViewById(android.R.id.button2); 51 | cancelButton.setOnClickListener(new View.OnClickListener() { 52 | @Override 53 | public void onClick(View v) { 54 | dismiss(); 55 | } 56 | }); 57 | View confirmButton = view.findViewById(android.R.id.button1); 58 | confirmButton.setOnClickListener(new View.OnClickListener() { 59 | @Override 60 | public void onClick(View v) { 61 | dismiss(); 62 | } 63 | }); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /sample/src/main/java/com/bilibili/magicasakurademo/dialog/ProgressStyleDialog.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakurademo.dialog; 18 | 19 | import android.os.Bundle; 20 | import android.support.annotation.Nullable; 21 | import android.support.v4.app.DialogFragment; 22 | import android.view.LayoutInflater; 23 | import android.view.View; 24 | import android.view.ViewGroup; 25 | import android.widget.RadioButton; 26 | 27 | import com.bilibili.magicasakurademo.R; 28 | 29 | 30 | /** 31 | * @author xyczero 32 | * @time 16/5/23 33 | */ 34 | public class ProgressStyleDialog extends DialogFragment implements View.OnClickListener { 35 | public static final String TAG = ProgressStyleDialog.class.getSimpleName(); 36 | 37 | private RadioButton mRadioButton1; 38 | private RadioButton mRadioButton2; 39 | 40 | @Override 41 | public void onCreate(@Nullable Bundle savedInstanceState) { 42 | super.onCreate(savedInstanceState); 43 | setStyle(DialogFragment.STYLE_NO_TITLE, R.style.AppTheme_AppCompat_Dialog_Alert); 44 | } 45 | 46 | @Nullable 47 | @Override 48 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 49 | return inflater.inflate(R.layout.dialog_progress_layout, container, false); 50 | } 51 | 52 | @Override 53 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 54 | super.onViewCreated(view, savedInstanceState); 55 | mRadioButton1 = (RadioButton) view.findViewById(R.id.progress_style_1); 56 | mRadioButton2 = (RadioButton) view.findViewById(R.id.progress_style_2); 57 | mRadioButton1.setOnClickListener(this); 58 | mRadioButton2.setOnClickListener(this); 59 | } 60 | 61 | @Override 62 | public void onClick(View v) { 63 | mRadioButton1.setChecked(v.getId() == R.id.progress_style_1); 64 | mRadioButton2.setChecked(v.getId() == R.id.progress_style_2); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /sample/src/main/java/com/bilibili/magicasakurademo/utils/SnackAnimationUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakurademo.utils; 18 | 19 | import android.content.Context; 20 | import android.support.annotation.AnimRes; 21 | import android.view.View; 22 | import android.view.animation.Animation; 23 | import android.view.animation.AnimationUtils; 24 | 25 | /** 26 | * @author xyczero617@gmail.com 27 | * @time 16/6/24 28 | */ 29 | 30 | public class SnackAnimationUtil { 31 | private View mTargetView; 32 | private long mAutoDismissTime; 33 | private Animation mSnackInAnim; 34 | private Animation mSnackOutAnim; 35 | private SnackAnimationCallback mSnackAnimationCallback; 36 | 37 | public static SnackAnimationUtil with(Context context, @AnimRes int snackInRes, @AnimRes int snackOutRes) { 38 | return new SnackAnimationUtil(context, snackInRes, snackOutRes); 39 | } 40 | 41 | private SnackAnimationUtil(Context context, @AnimRes int snackInRes, @AnimRes int snackOutRes) { 42 | mSnackInAnim = AnimationUtils.loadAnimation(context, snackInRes); 43 | mSnackOutAnim = AnimationUtils.loadAnimation(context, snackOutRes); 44 | } 45 | 46 | public SnackAnimationUtil setDismissDelayTime(long autoDismissTime) { 47 | mAutoDismissTime = autoDismissTime; 48 | return this; 49 | } 50 | 51 | public SnackAnimationUtil setTarget(View playView) { 52 | mTargetView = playView; 53 | return this; 54 | } 55 | 56 | public SnackAnimationUtil setDismissDelayCallback(SnackAnimationCallback snackAnimationCallback){ 57 | mSnackAnimationCallback = snackAnimationCallback; 58 | return this; 59 | } 60 | 61 | public void play() { 62 | if (mTargetView == null || mSnackInAnim == null || mSnackOutAnim == null) { 63 | return; 64 | } 65 | mTargetView.setVisibility(View.VISIBLE); 66 | mSnackInAnim.setAnimationListener(new Animation.AnimationListener() { 67 | @Override 68 | public void onAnimationStart(Animation animation) { 69 | } 70 | 71 | @Override 72 | public void onAnimationEnd(Animation animation) { 73 | playSnackOutAnimation(); 74 | } 75 | 76 | @Override 77 | public void onAnimationRepeat(Animation animation) { 78 | 79 | } 80 | }); 81 | mTargetView.startAnimation(mSnackInAnim); 82 | } 83 | 84 | private void playSnackOutAnimation() { 85 | mSnackOutAnim.setAnimationListener(new Animation.AnimationListener() { 86 | @Override 87 | public void onAnimationStart(Animation animation) { 88 | 89 | } 90 | 91 | @Override 92 | public void onAnimationEnd(Animation animation) { 93 | mTargetView.setVisibility(View.GONE); 94 | if (mSnackAnimationCallback != null) { 95 | mSnackAnimationCallback.dismissCallback(); 96 | } 97 | } 98 | 99 | @Override 100 | public void onAnimationRepeat(Animation animation) { 101 | 102 | } 103 | }); 104 | mTargetView.postDelayed(new Runnable() { 105 | @Override 106 | public void run() { 107 | mTargetView.startAnimation(mSnackOutAnim); 108 | } 109 | }, mAutoDismissTime); 110 | } 111 | 112 | public interface SnackAnimationCallback { 113 | void dismissCallback(); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /sample/src/main/java/com/bilibili/magicasakurademo/utils/ThemeHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakurademo.utils; 18 | 19 | import android.content.Context; 20 | import android.content.SharedPreferences; 21 | 22 | 23 | /** 24 | * @author xyczero 25 | * @time 16/5/2 26 | */ 27 | public class ThemeHelper { 28 | private static final String CURRENT_THEME = "theme_current"; 29 | 30 | public static final int CARD_SAKURA = 0x1; 31 | public static final int CARD_HOPE = 0x2; 32 | public static final int CARD_STORM = 0x3; 33 | public static final int CARD_WOOD = 0x4; 34 | public static final int CARD_LIGHT = 0x5; 35 | public static final int CARD_THUNDER = 0x6; 36 | public static final int CARD_SAND = 0x7; 37 | public static final int CARD_FIREY = 0x8; 38 | 39 | public static SharedPreferences getSharePreference(Context context) { 40 | return context.getSharedPreferences("multiple_theme", Context.MODE_PRIVATE); 41 | } 42 | 43 | public static void setTheme(Context context, int themeId) { 44 | getSharePreference(context).edit() 45 | .putInt(CURRENT_THEME, themeId) 46 | .commit(); 47 | } 48 | 49 | public static int getTheme(Context context) { 50 | return getSharePreference(context).getInt(CURRENT_THEME, CARD_SAKURA); 51 | } 52 | 53 | public static boolean isDefaultTheme(Context context) { 54 | return getTheme(context) == CARD_SAKURA; 55 | } 56 | 57 | public static String getName(int currentTheme) { 58 | switch (currentTheme) { 59 | case CARD_SAKURA: 60 | return "THE SAKURA"; 61 | case CARD_STORM: 62 | return "THE STORM"; 63 | case CARD_WOOD: 64 | return "THE WOOD"; 65 | case CARD_LIGHT: 66 | return "THE LIGHT"; 67 | case CARD_HOPE: 68 | return "THE HOPE"; 69 | case CARD_THUNDER: 70 | return "THE THUNDER"; 71 | case CARD_SAND: 72 | return "THE SAND"; 73 | case CARD_FIREY: 74 | return "THE FIREY"; 75 | } 76 | return "THE RETURN"; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /sample/src/main/java/com/bilibili/magicasakurademo/widgets/KeyEditText.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bilibili 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.bilibili.magicasakurademo.widgets; 18 | 19 | import android.content.Context; 20 | import android.util.AttributeSet; 21 | import android.view.KeyEvent; 22 | 23 | import com.bilibili.magicasakura.widgets.TintEditText; 24 | 25 | /** 26 | * @author xyczero 27 | * @time 16/5/23 28 | */ 29 | public class KeyEditText extends TintEditText { 30 | private KeyPreImeListener mKeyPreImeListener; 31 | 32 | public KeyEditText(Context context) { 33 | super(context); 34 | } 35 | 36 | public KeyEditText(Context context, AttributeSet attrs) { 37 | super(context, attrs); 38 | } 39 | 40 | public KeyEditText(Context context, AttributeSet attrs, int defStyleAttr) { 41 | super(context, attrs, defStyleAttr); 42 | } 43 | 44 | @Override 45 | public boolean onKeyPreIme(int keyCode, KeyEvent event) { 46 | if (keyCode == KeyEvent.KEYCODE_BACK) { 47 | if (event.getAction() == KeyEvent.ACTION_UP) { 48 | if (mKeyPreImeListener != null) { 49 | mKeyPreImeListener.onKeyPreImeUp(keyCode, event); 50 | } 51 | } 52 | } 53 | return super.onKeyPreIme(keyCode, event); 54 | } 55 | 56 | public void setKeyPreImeListener(KeyPreImeListener listener) { 57 | mKeyPreImeListener = listener; 58 | } 59 | 60 | public interface KeyPreImeListener { 61 | void onKeyPreImeUp(int keyCode, KeyEvent event); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /sample/src/main/res/anim/snack_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 22 | 25 | -------------------------------------------------------------------------------- /sample/src/main/res/anim/snack_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 22 | 25 | -------------------------------------------------------------------------------- /sample/src/main/res/color/selector_compound.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /sample/src/main/res/color/selector_focus.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /sample/src/main/res/color/selector_primary_click.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /sample/src/main/res/color/selector_switch_thumb.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /sample/src/main/res/color/selector_switch_track.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /sample/src/main/res/color/selector_text.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable-v21/selector_login.xml: -------------------------------------------------------------------------------- 1 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 32 | 35 | 36 | 37 | 38 | 39 | 40 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_adb_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/drawable-xhdpi/ic_adb_white_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_card_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/drawable-xhdpi/ic_card_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_card_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/drawable-xhdpi/ic_card_48dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_card_background.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/drawable-xhdpi/ic_card_background.9.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_check_white_12dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/drawable-xhdpi/ic_check_white_12dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_check_white_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/drawable-xhdpi/ic_check_white_18dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_check_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/drawable-xhdpi/ic_check_white_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_edit_text_default.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/drawable-xhdpi/ic_edit_text_default.9.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_lock_open_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/drawable-xhdpi/ic_lock_open_white_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_lock_outline_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/drawable-xhdpi/ic_lock_outline_white_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_lock_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/drawable-xhdpi/ic_lock_white_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_looks_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/drawable-xhdpi/ic_looks_1.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_looks_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/drawable-xhdpi/ic_looks_2.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_looks_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/drawable-xhdpi/ic_looks_3.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_magicasakura.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/drawable-xhdpi/ic_magicasakura.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_person_outline_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/drawable-xhdpi/ic_person_outline_white_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_tag_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/drawable-xhdpi/ic_tag_white_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable/edittext_cursor.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable/selector_lock.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable/selector_login.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable/selector_pick_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable/selector_unlock.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable/shape_rectangle_nocorner.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 22 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 23 | 24 | 31 | 32 | 40 | 41 | 42 | 43 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/dialog_check_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 24 | 25 | 39 | 40 | 50 | 51 | 55 | 56 | 65 | 66 | 75 | 76 | 85 | 86 | 87 | 90 | 91 | 100 | 101 | 110 | 111 | 120 | 121 | 122 | 123 | 124 | 135 | 136 | 141 | 142 | 151 | 152 | 160 | 161 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/dialog_progress_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 24 | 25 | 39 | 40 | 50 | 51 | 55 | 56 | 64 | 65 | 73 | 74 | 75 | 78 | 79 | 87 | 88 | 92 | 93 | 99 | 100 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/fragment_layout_snack.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 27 | 28 | 36 | 37 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/fragment_layout_theme_picker.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 25 | 26 | 32 | 33 | 39 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/layout_list_item_choice.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 25 | 26 | 33 | 34 | 39 | 40 | 47 | 48 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/layout_list_item_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 24 | 25 | 32 | 33 | 43 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/layout_list_item_label.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 25 | 26 | 38 | 39 | 52 | 53 | 63 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/layout_list_item_login.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 28 | 29 | 43 | 44 | 60 | 61 | 72 | -------------------------------------------------------------------------------- /sample/src/main/res/menu/main_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 |

21 | 26 | -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/values-v21/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 22 | 23 | -------------------------------------------------------------------------------- /sample/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /sample/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #fb7299 4 | #b85671 5 | #99f0486c 6 | #fb7299 7 | 8 | #2d2d2d 9 | #eaeaea 10 | 11 | #333333 12 | 13 | #ffffff 14 | #99ffffff 15 | 16 | #bbbbbb 17 | #999999 18 | #44999999 19 | #dcdcdc 20 | 21 | 22 | #fb7299 23 | #b85671 24 | #99f0486c 25 | 26 | #2196F3 27 | #1565C0 28 | #B41A78C3 29 | 30 | #673AB7 31 | #311B92 32 | #99673AB7 33 | 34 | #4CAF50 35 | #2E7D32 36 | #994CAF50 37 | 38 | #8BC34A 39 | #558B2F 40 | #998BC34A 41 | 42 | #FDD835 43 | #FBC02D 44 | #99FDD835 45 | 46 | #FF9800 47 | #EF6C00 48 | #99FF9800 49 | 50 | #F44336 51 | #C62828 52 | #99F44336 53 | 54 | 55 | -------------------------------------------------------------------------------- /sample/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 16dp 6 | 8dp 7 | 8 | 18sp 9 | 16sp 10 | 14sp 11 | 12 | -------------------------------------------------------------------------------- /sample/src/main/res/values/selector.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /sample/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | MagicaSakura 3 | 4 | cancel 5 | ok 6 | Lock Setting 7 | You can unlock it to open the new world ! 8 | Go to : https://github.com/Bilibili/MagicaSakura 9 | 10 | 隐藏着黑暗力量的钥匙啊,在我面前显示你真正的力量,小樱命令你,封印解除! 11 | 隐藏着星星力量的钥匙啊,在我面前显示你真正的力量,小樱命令你,封印解除! 12 | 库洛里多创造的库洛牌啊,请你舍弃旧形象,以小樱之名命令你,封印解除! 13 | 14 | -------------------------------------------------------------------------------- /sample/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /sample/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 13 | 14 | 19 | 20 | 25 | 26 | -------------------------------------------------------------------------------- /screenshot/magicasakura.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/screenshot/magicasakura.gif -------------------------------------------------------------------------------- /screenshot/magicasakura_cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bilibili/MagicaSakura/9a2e2061e32a67946d91c4ce44c050c72007494a/screenshot/magicasakura_cover.png -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':magicasakura', ':sample' 2 | --------------------------------------------------------------------------------