Use Vector
This commit is contained in:
1 parent
e3134bbea1
commit
aeb49f4bb6
38 files changed
+876
-2291
No files matched your search
Generated
+22
-23
@@ -1,23 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<option name="DEFAULT_COMPILER" value="Javac" />
|
||||
<resourceExtensions />
|
||||
<wildcardResourcePatterns>
|
||||
<entry name="!?*.java" />
|
||||
<entry name="!?*.form" />
|
||||
<entry name="!?*.class" />
|
||||
<entry name="!?*.groovy" />
|
||||
<entry name="!?*.scala" />
|
||||
<entry name="!?*.flex" />
|
||||
<entry name="!?*.kt" />
|
||||
<entry name="!?*.clj" />
|
||||
</wildcardResourcePatterns>
|
||||
<annotationProcessing>
|
||||
<profile default="true" name="Default" enabled="false">
|
||||
<processorPath useClasspath="true" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
</project>
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<resourceExtensions />
|
||||
<wildcardResourcePatterns>
|
||||
<entry name="!?*.java" />
|
||||
<entry name="!?*.form" />
|
||||
<entry name="!?*.class" />
|
||||
<entry name="!?*.groovy" />
|
||||
<entry name="!?*.scala" />
|
||||
<entry name="!?*.flex" />
|
||||
<entry name="!?*.kt" />
|
||||
<entry name="!?*.clj" />
|
||||
<entry name="!?*.aj" />
|
||||
</wildcardResourcePatterns>
|
||||
<annotationProcessing>
|
||||
<profile default="true" name="Default" enabled="false">
|
||||
<processorPath useClasspath="true" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+5
-5
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" defaultCharsetForPropertiesFiles="UTF-8">
|
||||
<file url="PROJECT" charset="UTF-8" />
|
||||
</component>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="PROJECT" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+18
-17
@@ -1,18 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="1.7" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
</set>
|
||||
</option>
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="1.7" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
<option value="$PROJECT_DIR$/vector" />
|
||||
</set>
|
||||
</option>
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0" is_locked="false">
|
||||
<option name="myName" value="Project Default" />
|
||||
<option name="myLocal" value="false" />
|
||||
<inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false">
|
||||
<option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" />
|
||||
<option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||
<option name="processCode" value="true" />
|
||||
<option name="processLiterals" value="true" />
|
||||
<option name="processComments" value="true" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="PROJECT_PROFILE" value="Project Default" />
|
||||
<option name="USE_PROJECT_PROFILE" value="true" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
Generated
+45
-32
@@ -1,33 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EntryPointsManager">
|
||||
<entry_points version="2.0" />
|
||||
</component>
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="org.jetbrains.annotations.Nullable" />
|
||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EntryPointsManager">
|
||||
<entry_points version="2.0" />
|
||||
</component>
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
|
||||
<OptionsSetting value="true" id="Add" />
|
||||
<OptionsSetting value="true" id="Remove" />
|
||||
<OptionsSetting value="true" id="Checkout" />
|
||||
<OptionsSetting value="true" id="Update" />
|
||||
<OptionsSetting value="true" id="Status" />
|
||||
<OptionsSetting value="true" id="Edit" />
|
||||
<ConfirmationsSetting value="0" id="Add" />
|
||||
<ConfirmationsSetting value="0" id="Remove" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+10
-10
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/EhViewer.iml" filepath="$PROJECT_DIR$/EhViewer.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/EhViewer.iml" filepath="$PROJECT_DIR$/EhViewer.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/vector/vector.iml" filepath="$PROJECT_DIR$/vector/vector.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+12
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
Generated
-5
@@ -1,5 +0,0 @@
|
||||
<component name="DependencyValidationManager">
|
||||
<state>
|
||||
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
|
||||
</state>
|
||||
</component>
|
||||
Generated
+6
-7
@@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
+97
-96
@@ -1,97 +1,98 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="EhViewer" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="android-gradle" name="Android-Gradle">
|
||||
<configuration>
|
||||
<option name="GRADLE_PROJECT_PATH" value=":app" />
|
||||
</configuration>
|
||||
</facet>
|
||||
<facet type="android" name="Android">
|
||||
<configuration>
|
||||
<option name="SELECTED_BUILD_VARIANT" value="debug" />
|
||||
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
|
||||
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
|
||||
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
|
||||
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
|
||||
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
|
||||
<afterSyncTasks>
|
||||
<task>generateDebugAndroidTestSources</task>
|
||||
<task>generateDebugSources</task>
|
||||
</afterSyncTasks>
|
||||
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
||||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
|
||||
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
|
||||
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
|
||||
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
|
||||
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
|
||||
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/22.2.0/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/22.2.0/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Android API 22 Platform" jdkType="Android SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" exported="" name="support-v4-22.2.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="support-annotations-22.2.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="recyclerview-v7-22.2.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="libGoogleAnalyticsServices" level="project" />
|
||||
</component>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="EhViewer" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="android-gradle" name="Android-Gradle">
|
||||
<configuration>
|
||||
<option name="GRADLE_PROJECT_PATH" value=":app" />
|
||||
</configuration>
|
||||
</facet>
|
||||
<facet type="android" name="Android">
|
||||
<configuration>
|
||||
<option name="SELECTED_BUILD_VARIANT" value="debug" />
|
||||
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
|
||||
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
|
||||
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
|
||||
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
|
||||
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
|
||||
<afterSyncTasks>
|
||||
<task>generateDebugAndroidTestSources</task>
|
||||
<task>generateDebugSources</task>
|
||||
</afterSyncTasks>
|
||||
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
||||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
|
||||
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
|
||||
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
|
||||
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
|
||||
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
|
||||
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/22.2.1/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/22.2.1/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Android API 22 Platform" jdkType="Android SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" exported="" name="support-v4-22.2.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="recyclerview-v7-22.2.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="libGoogleAnalyticsServices" level="project" />
|
||||
<orderEntry type="library" exported="" name="support-annotations-22.2.1" level="project" />
|
||||
<orderEntry type="module" module-name="vector" exported="" />
|
||||
</component>
|
||||
</module>
|
||||
+13
-5
@@ -4,14 +4,14 @@ apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 22
|
||||
buildToolsVersion '23.0.0 rc2'
|
||||
buildToolsVersion '22.0.1'
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.hippo.ehviewer"
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 22
|
||||
versionCode 46
|
||||
versionName "0.6.16.2"
|
||||
versionCode 47
|
||||
versionName "0.6.16.3"
|
||||
}
|
||||
buildTypes {
|
||||
debug {
|
||||
@@ -24,6 +24,13 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
checkReleaseBuilds false
|
||||
// Or, if you prefer, you can continue to check for errors in release builds,
|
||||
// but continue the build even when errors are found:
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
// Disable default NdkCompile task
|
||||
// Set new jni lib dir
|
||||
sourceSets.main {
|
||||
@@ -59,6 +66,7 @@ clean {
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile 'com.android.support:support-v4:22.2.0'
|
||||
compile 'com.android.support:recyclerview-v7:22.2.0'
|
||||
compile project(':vector')
|
||||
compile 'com.android.support:support-v4:22.2.1'
|
||||
compile 'com.android.support:recyclerview-v7:22.2.1'
|
||||
}
|
||||
@@ -1,220 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.content.res;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.v4.util.LongSparseArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
import android.util.Xml;
|
||||
|
||||
import com.hippo.vectorold.drawable.AnimatedVectorDrawable;
|
||||
import com.hippo.vectorold.drawable.VectorDrawable;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
// TODO Only load register drawable from itself
|
||||
/**
|
||||
* It is a wrap
|
||||
*/
|
||||
public class VectorResources extends Resources {
|
||||
|
||||
private static final String TAG = VectorResources.class.getSimpleName();
|
||||
|
||||
private Context mContext;
|
||||
private Resources mBase;
|
||||
|
||||
// These are protected by mAccessLock.
|
||||
|
||||
/*package*/ final Object mAccessLock = new Object();
|
||||
/*package*/ final LongSparseArray<WeakReference<Drawable.ConstantState> > mDrawableCache
|
||||
= new LongSparseArray<WeakReference<Drawable.ConstantState> >(0);
|
||||
/*package*/ final LongSparseArray<WeakReference<Drawable.ConstantState> > mColorDrawableCache
|
||||
= new LongSparseArray<WeakReference<Drawable.ConstantState> >(0);
|
||||
|
||||
public VectorResources(Context context, Resources res) {
|
||||
super(res.getAssets(), res.getDisplayMetrics(), res.getConfiguration());
|
||||
mContext = context;
|
||||
mBase = res;
|
||||
}
|
||||
|
||||
public boolean isBase(Resources res) {
|
||||
return mBase == res;
|
||||
}
|
||||
|
||||
@Override
|
||||
Drawable loadDrawable(TypedValue value, int id)
|
||||
throws NotFoundException {
|
||||
boolean isColorDrawable = false;
|
||||
if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT &&
|
||||
value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
|
||||
isColorDrawable = true;
|
||||
}
|
||||
final long key = isColorDrawable ? value.data :
|
||||
(((long) value.assetCookie) << 32) | value.data;
|
||||
|
||||
Drawable dr = getCachedDrawable(isColorDrawable ? mColorDrawableCache : mDrawableCache, key);
|
||||
|
||||
if (dr != null) {
|
||||
return dr;
|
||||
}
|
||||
|
||||
if (isColorDrawable) {
|
||||
dr = new ColorDrawable(value.data);
|
||||
}
|
||||
|
||||
if (dr == null) {
|
||||
if (value.string == null) {
|
||||
throw new NotFoundException(
|
||||
"Resource is not a Drawable (color or path): " + value);
|
||||
}
|
||||
|
||||
String file = value.string.toString();
|
||||
|
||||
if (file.endsWith(".xml")) {
|
||||
// Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
|
||||
try {
|
||||
XmlResourceParser rp = getXml(id);
|
||||
// XmlResourceParser rp = loadXmlResourceParser(
|
||||
// file, id, value.assetCookie, "drawable");
|
||||
dr = createDrawableFromXml(rp);
|
||||
rp.close();
|
||||
} catch (Exception e) {
|
||||
// Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
|
||||
NotFoundException rnf = new NotFoundException(
|
||||
"File " + file + " from drawable resource ID #0x"
|
||||
+ Integer.toHexString(id));
|
||||
rnf.initCause(e);
|
||||
throw rnf;
|
||||
}
|
||||
// Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
|
||||
|
||||
} else {
|
||||
// Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
|
||||
try {
|
||||
InputStream is = openRawResource(id, value);
|
||||
//InputStream is = mAssets.openNonAsset(
|
||||
// value.assetCookie, file, AssetManager.ACCESS_STREAMING);
|
||||
// System.out.println("Opened file " + file + ": " + is);
|
||||
dr = Drawable.createFromResourceStream(this, value, is,
|
||||
file, null);
|
||||
is.close();
|
||||
// System.out.println("Created stream: " + dr);
|
||||
} catch (Exception e) {
|
||||
// Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
|
||||
NotFoundException rnf = new NotFoundException(
|
||||
"File " + file + " from drawable resource ID #0x"
|
||||
+ Integer.toHexString(id));
|
||||
rnf.initCause(e);
|
||||
throw rnf;
|
||||
}
|
||||
// Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
|
||||
}
|
||||
}
|
||||
Drawable.ConstantState cs;
|
||||
if (dr != null) {
|
||||
dr.setChangingConfigurations(value.changingConfigurations);
|
||||
cs = dr.getConstantState();
|
||||
if (cs != null) {
|
||||
synchronized (mAccessLock) {
|
||||
//Log.i(TAG, "Saving cached drawable @ #" +
|
||||
// Integer.toHexString(key.intValue())
|
||||
// + " in " + this + ": " + cs);
|
||||
if (isColorDrawable) {
|
||||
mColorDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));
|
||||
} else {
|
||||
mDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dr;
|
||||
}
|
||||
|
||||
private Drawable getCachedDrawable(
|
||||
LongSparseArray<WeakReference<Drawable.ConstantState>> drawableCache,
|
||||
long key) {
|
||||
synchronized (mAccessLock) {
|
||||
WeakReference<Drawable.ConstantState> wr = drawableCache.get(key);
|
||||
if (wr != null) { // we have the key
|
||||
Drawable.ConstantState entry = wr.get();
|
||||
if (entry != null) {
|
||||
//Log.i(TAG, "Returning cached drawable @ #" +
|
||||
// Integer.toHexString(((Integer)key).intValue())
|
||||
// + " in " + this + ": " + entry);
|
||||
return entry.newDrawable(this);
|
||||
}
|
||||
else { // our entry has been purged
|
||||
drawableCache.delete(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Drawable createDrawableFromXml(XmlResourceParser parser)
|
||||
throws XmlPullParserException, IOException {
|
||||
AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||
|
||||
int type;
|
||||
while ((type=parser.next()) != XmlPullParser.START_TAG &&
|
||||
type != XmlPullParser.END_DOCUMENT) {
|
||||
// Empty loop
|
||||
}
|
||||
|
||||
if (type != XmlPullParser.START_TAG) {
|
||||
throw new XmlPullParserException("No start tag found");
|
||||
}
|
||||
|
||||
Drawable drawable = createDrawableFromXmlInner(parser, attrs);
|
||||
|
||||
if (drawable == null) {
|
||||
throw new RuntimeException("Unknown initial tag: " + parser.getName());
|
||||
}
|
||||
|
||||
return drawable;
|
||||
}
|
||||
|
||||
private Drawable createDrawableFromXmlInner(XmlPullParser parser, AttributeSet attrs)
|
||||
throws XmlPullParserException, IOException {
|
||||
final Drawable drawable;
|
||||
final String name = parser.getName();
|
||||
switch (name) {
|
||||
case "vector":
|
||||
VectorDrawable vectorDrawable = new VectorDrawable();
|
||||
vectorDrawable.inflate(this, parser, attrs);
|
||||
drawable = vectorDrawable;
|
||||
break;
|
||||
case "animated-vector":
|
||||
AnimatedVectorDrawable animatedVectorDrawable = new AnimatedVectorDrawable();
|
||||
animatedVectorDrawable.inflate(mContext, parser, attrs);
|
||||
drawable = animatedVectorDrawable;
|
||||
break;
|
||||
default:
|
||||
drawable = Drawable.createFromXmlInner(this, parser, attrs);
|
||||
}
|
||||
return drawable;
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,6 @@ import com.hippo.ehviewer.util.Utils;
|
||||
import com.hippo.ehviewer.util.ViewUtils;
|
||||
import com.hippo.ehviewer.widget.MaterialToast;
|
||||
import com.hippo.ehviewer.widget.SlidingDrawerLayout;
|
||||
import com.hippo.vectorold.content.VectorContext;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@@ -177,9 +176,4 @@ public class AppContext extends Application implements UncaughtExceptionHandler
|
||||
public Typeface getFaceTypeface() {
|
||||
return mFaceTypeface;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(Context newBase) {
|
||||
super.attachBaseContext(VectorContext.wrapContext(newBase));
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import com.hippo.ehviewer.util.Secret;
|
||||
import com.hippo.ehviewer.util.ViewUtils;
|
||||
import com.hippo.ehviewer.widget.LockPatternUtils;
|
||||
import com.hippo.ehviewer.widget.SimpleImageView;
|
||||
import com.hippo.vector.VectorDrawable;
|
||||
|
||||
public class StartActivity extends AbsActivity {
|
||||
|
||||
@@ -188,7 +189,7 @@ public class StartActivity extends AbsActivity {
|
||||
TextView text = (TextView) findViewById(R.id.text);
|
||||
text.setTypeface(Typeface.createFromAsset(getAssets(),"fonts/GloriaHallelujah.ttf"));
|
||||
SimpleImageView image = (SimpleImageView) findViewById(R.id.image);
|
||||
image.setDrawable(R.drawable.sad_pandroid);
|
||||
image.setDrawable(VectorDrawable.create(this, R.drawable.sad_pandroid));
|
||||
|
||||
// Update secret image here
|
||||
int state = Network.getNetworkState(this);
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.util.Config;
|
||||
import com.hippo.ehviewer.util.MathUtils;
|
||||
import com.hippo.ehviewer.util.Utils;
|
||||
import com.hippo.vector.VectorDrawable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@@ -107,7 +108,7 @@ public class EhInfo {
|
||||
mContext = context;
|
||||
mInfoPref = mContext.getSharedPreferences(PREF_NAME, 0);
|
||||
if (DEFAULT_AVATAR == null)
|
||||
DEFAULT_AVATAR = context.getResources().getDrawable(R.drawable.default_avatar);
|
||||
DEFAULT_AVATAR = VectorDrawable.create(context, R.drawable.default_avatar);
|
||||
|
||||
mIsLogin = mInfoPref.getBoolean(KEY_LOGIN, DEFAULT_LOGIN);
|
||||
mUsername = mInfoPref.getString(KEY_USERNAME, DEFAULT_NAME);
|
||||
|
||||
@@ -34,7 +34,6 @@ import com.hippo.ehviewer.ehclient.ExDownloaderManager;
|
||||
import com.hippo.ehviewer.ui.DownloadActivity;
|
||||
import com.hippo.ehviewer.util.Config;
|
||||
import com.hippo.ehviewer.util.Utils;
|
||||
import com.hippo.vectorold.content.VectorContext;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -487,9 +486,4 @@ public class DownloadService extends Service
|
||||
tryToStartDownload();
|
||||
notifyUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(Context newBase) {
|
||||
super.attachBaseContext(VectorContext.wrapContext(newBase));
|
||||
}
|
||||
}
|
||||
@@ -17,13 +17,11 @@
|
||||
package com.hippo.ehviewer.ui;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
||||
import com.google.analytics.tracking.android.EasyTracker;
|
||||
import com.hippo.ehviewer.cache.ImageCache;
|
||||
import com.hippo.ehviewer.util.Config;
|
||||
import com.hippo.ehviewer.util.Ui;
|
||||
import com.hippo.vectorold.content.VectorContext;
|
||||
|
||||
public abstract class AbsActivity extends Activity {
|
||||
|
||||
@@ -56,9 +54,4 @@ public abstract class AbsActivity extends Activity {
|
||||
if (Config.getAllowAnalyics())
|
||||
EasyTracker.getInstance(this).activityStop(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(Context newBase) {
|
||||
super.attachBaseContext(VectorContext.wrapContext(newBase));
|
||||
}
|
||||
}
|
||||
@@ -16,13 +16,11 @@
|
||||
|
||||
package com.hippo.ehviewer.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.preference.PreferenceActivity;
|
||||
|
||||
import com.google.analytics.tracking.android.EasyTracker;
|
||||
import com.hippo.ehviewer.util.Config;
|
||||
import com.hippo.ehviewer.util.Ui;
|
||||
import com.hippo.vectorold.content.VectorContext;
|
||||
|
||||
public abstract class AbsPreferenceActivity extends PreferenceActivity {
|
||||
|
||||
@@ -50,9 +48,4 @@ public abstract class AbsPreferenceActivity extends PreferenceActivity {
|
||||
if (Config.getAllowAnalyics())
|
||||
EasyTracker.getInstance(this).activityStop(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(Context newBase) {
|
||||
super.attachBaseContext(VectorContext.wrapContext(newBase));
|
||||
}
|
||||
}
|
||||
@@ -1,612 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.vectorold.animation;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ArgbEvaluator;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.TypeEvaluator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.Resources.NotFoundException;
|
||||
import android.content.res.TypedArray;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.util.Xml;
|
||||
import android.view.InflateException;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.vectorold.util.PathParser;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* This class is used to instantiate animator XML files into Animator objects.
|
||||
* <p>
|
||||
* For performance reasons, inflation relies heavily on pre-processing of
|
||||
* XML files that is done at build time. Therefore, it is not currently possible
|
||||
* to use this inflater with an XmlPullParser over a plain XML file at runtime;
|
||||
* it only works with an XmlPullParser returned from a compiled resource (R.
|
||||
* <em>something</em> file.)
|
||||
*/
|
||||
public class AnimatorInflater {
|
||||
private static final String TAG = "AnimatorInflater";
|
||||
/**
|
||||
* These flags are used when parsing AnimatorSet objects
|
||||
*/
|
||||
private static final int TOGETHER = 0;
|
||||
private static final int SEQUENTIALLY = 1;
|
||||
|
||||
/**
|
||||
* Enum values used in XML attributes to indicate the value for mValueType
|
||||
*/
|
||||
private static final int VALUE_TYPE_FLOAT = 0;
|
||||
private static final int VALUE_TYPE_INT = 1;
|
||||
private static final int VALUE_TYPE_PATH = 2;
|
||||
private static final int VALUE_TYPE_COLOR = 4;
|
||||
private static final int VALUE_TYPE_CUSTOM = 5;
|
||||
|
||||
private static final boolean DBG_ANIMATOR_INFLATER = false;
|
||||
|
||||
private static final ArgbEvaluator ARGB_EVALUATOR = new ArgbEvaluator();
|
||||
|
||||
/**
|
||||
* Loads an {@link android.animation.Animator} object from a resource
|
||||
*
|
||||
* @param context Application context used to access resources
|
||||
* @param id The resource id of the animation to load
|
||||
* @return The animator object reference by the specified id
|
||||
* @throws android.content.res.Resources.NotFoundException when the animation cannot be loaded
|
||||
*/
|
||||
public static Animator loadAnimator(Context context, int id)
|
||||
throws NotFoundException {
|
||||
return loadAnimator(context, id, 1);
|
||||
}
|
||||
|
||||
public static Animator loadAnimator(Context context, int id, float pathErrorScale) {
|
||||
Resources resources = context.getResources();
|
||||
XmlResourceParser parser = null;
|
||||
try {
|
||||
parser = resources.getAnimation(id);
|
||||
return createAnimatorFromXml(context, parser, pathErrorScale);
|
||||
} catch (XmlPullParserException ex) {
|
||||
NotFoundException rnf =
|
||||
new NotFoundException("Can't load animation resource ID #0x" +
|
||||
Integer.toHexString(id));
|
||||
rnf.initCause(ex);
|
||||
throw rnf;
|
||||
} catch (IOException ex) {
|
||||
NotFoundException rnf =
|
||||
new NotFoundException("Can't load animation resource ID #0x" +
|
||||
Integer.toHexString(id));
|
||||
rnf.initCause(ex);
|
||||
throw rnf;
|
||||
} finally {
|
||||
if (parser != null) parser.close();
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO Not support StateListAnimator
|
||||
public static StateListAnimator loadStateListAnimator(Context context, int id)
|
||||
throws NotFoundException {
|
||||
XmlResourceParser parser = null;
|
||||
try {
|
||||
parser = context.getResources().getAnimation(id);
|
||||
return createStateListAnimatorFromXml(context, parser, Xml.asAttributeSet(parser));
|
||||
} catch (XmlPullParserException ex) {
|
||||
NotFoundException rnf =
|
||||
new NotFoundException(
|
||||
"Can't load state list animator resource ID #0x" +
|
||||
Integer.toHexString(id)
|
||||
);
|
||||
rnf.initCause(ex);
|
||||
throw rnf;
|
||||
} catch (IOException ex) {
|
||||
NotFoundException rnf =
|
||||
new NotFoundException(
|
||||
"Can't load state list animator resource ID #0x" +
|
||||
Integer.toHexString(id)
|
||||
);
|
||||
rnf.initCause(ex);
|
||||
throw rnf;
|
||||
} finally {
|
||||
if (parser != null) {
|
||||
parser.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/* TODO Not support StateListAnimator
|
||||
private static StateListAnimator createStateListAnimatorFromXml(Context context,
|
||||
XmlPullParser parser, AttributeSet attributeSet)
|
||||
throws IOException, XmlPullParserException {
|
||||
int type;
|
||||
StateListAnimator stateListAnimator = new StateListAnimator();
|
||||
|
||||
while (true) {
|
||||
type = parser.next();
|
||||
switch (type) {
|
||||
case XmlPullParser.END_DOCUMENT:
|
||||
case XmlPullParser.END_TAG:
|
||||
return stateListAnimator;
|
||||
|
||||
case XmlPullParser.START_TAG:
|
||||
// parse item
|
||||
Animator animator = null;
|
||||
if ("item".equals(parser.getName())) {
|
||||
int attributeCount = parser.getAttributeCount();
|
||||
int[] states = new int[attributeCount];
|
||||
int stateIndex = 0;
|
||||
for (int i = 0; i < attributeCount; i++) {
|
||||
int attrName = attributeSet.getAttributeNameResource(i);
|
||||
if (attrName == R.attr.animation) {
|
||||
animator = loadAnimator(context,
|
||||
attributeSet.getAttributeResourceValue(i, 0));
|
||||
} else {
|
||||
states[stateIndex++] =
|
||||
attributeSet.getAttributeBooleanValue(i, false) ?
|
||||
attrName : -attrName;
|
||||
}
|
||||
|
||||
}
|
||||
if (animator == null) {
|
||||
animator = createAnimatorFromXml(context, parser, 1f);
|
||||
}
|
||||
|
||||
if (animator == null) {
|
||||
throw new NotFoundException(
|
||||
"animation state item must have a valid animation");
|
||||
}
|
||||
stateListAnimator
|
||||
.addState(StateSet.trimStateSet(states, stateIndex), animator);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* PathDataEvaluator is used to interpolate between two paths which are
|
||||
* represented in the same format but different control points' values.
|
||||
* The path is represented as an array of PathDataNode here, which is
|
||||
* fundamentally an array of floating point numbers.
|
||||
*/
|
||||
private static class PathDataEvaluator implements TypeEvaluator<PathParser.PathDataNode[]> {
|
||||
private PathParser.PathDataNode[] mNodeArray;
|
||||
|
||||
/**
|
||||
* Create a PathParser.PathDataNode[] that does not reuse the animated value.
|
||||
* Care must be taken when using this option because on every evaluation
|
||||
* a new <code>PathParser.PathDataNode[]</code> will be allocated.
|
||||
*/
|
||||
private PathDataEvaluator() {}
|
||||
|
||||
/**
|
||||
* Create a PathDataEvaluator that reuses <code>nodeArray</code> for every evaluate() call.
|
||||
* Caution must be taken to ensure that the value returned from
|
||||
* {@link android.animation.ValueAnimator#getAnimatedValue()} is not cached, modified, or
|
||||
* used across threads. The value will be modified on each <code>evaluate()</code> call.
|
||||
*
|
||||
* @param nodeArray The array to modify and return from <code>evaluate</code>.
|
||||
*/
|
||||
public PathDataEvaluator(PathParser.PathDataNode[] nodeArray) {
|
||||
mNodeArray = nodeArray;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathParser.PathDataNode[] evaluate(float fraction,
|
||||
PathParser.PathDataNode[] startPathData,
|
||||
PathParser.PathDataNode[] endPathData) {
|
||||
if (!PathParser.canMorph(startPathData, endPathData)) {
|
||||
throw new IllegalArgumentException("Can't interpolate between"
|
||||
+ " two incompatible pathData");
|
||||
}
|
||||
|
||||
if (mNodeArray == null || !PathParser.canMorph(mNodeArray, startPathData)) {
|
||||
mNodeArray = PathParser.deepCopyNodes(startPathData);
|
||||
}
|
||||
|
||||
for (int i = 0; i < startPathData.length; i++) {
|
||||
mNodeArray[i].interpolatePathDataNode(startPathData[i],
|
||||
endPathData[i], fraction);
|
||||
}
|
||||
|
||||
return mNodeArray;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param anim The animator, must not be null
|
||||
* @param arrayAnimator Incoming typed array for Animator's attributes.
|
||||
* @param arrayObjectAnimator Incoming typed array for Object Animator's
|
||||
* attributes.
|
||||
* @param pixelSize The relative pixel size, used to calculate the
|
||||
* maximum error for path animations.
|
||||
*/
|
||||
private static void parseAnimatorFromTypeArray(ValueAnimator anim,
|
||||
TypedArray arrayAnimator, TypedArray arrayObjectAnimator, float pixelSize) {
|
||||
long duration = arrayAnimator.getInt(R.styleable.Animator_duration, 300);
|
||||
|
||||
long startDelay = arrayAnimator.getInt(R.styleable.Animator_startOffset, 0);
|
||||
|
||||
int valueType = arrayAnimator.getInt(R.styleable.Animator_valueType,
|
||||
VALUE_TYPE_FLOAT);
|
||||
|
||||
TypeEvaluator evaluator = null;
|
||||
|
||||
boolean getFloats = (valueType == VALUE_TYPE_FLOAT);
|
||||
|
||||
TypedValue tvFrom = arrayAnimator.peekValue(R.styleable.Animator_valueFrom);
|
||||
boolean hasFrom = (tvFrom != null);
|
||||
int fromType = hasFrom ? tvFrom.type : 0;
|
||||
TypedValue tvTo = arrayAnimator.peekValue(R.styleable.Animator_valueTo);
|
||||
boolean hasTo = (tvTo != null);
|
||||
int toType = hasTo ? tvTo.type : 0;
|
||||
|
||||
// TODO: Further clean up this part of code into 4 types : path, color,
|
||||
// integer and float.
|
||||
if (valueType == VALUE_TYPE_PATH) {
|
||||
evaluator = setupAnimatorForPath(anim, arrayAnimator);
|
||||
} else {
|
||||
// Integer and float value types are handled here.
|
||||
if ((hasFrom && (fromType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
|
||||
(fromType <= TypedValue.TYPE_LAST_COLOR_INT)) ||
|
||||
(hasTo && (toType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
|
||||
(toType <= TypedValue.TYPE_LAST_COLOR_INT))) {
|
||||
// special case for colors: ignore valueType and get ints
|
||||
getFloats = false;
|
||||
evaluator = ARGB_EVALUATOR;
|
||||
}
|
||||
setupValues(anim, arrayAnimator, getFloats, hasFrom, fromType, hasTo, toType);
|
||||
}
|
||||
|
||||
anim.setDuration(duration);
|
||||
anim.setStartDelay(startDelay);
|
||||
|
||||
if (arrayAnimator.hasValue(R.styleable.Animator_repeatCount)) {
|
||||
anim.setRepeatCount(
|
||||
arrayAnimator.getInt(R.styleable.Animator_repeatCount, 0));
|
||||
}
|
||||
if (arrayAnimator.hasValue(R.styleable.Animator_repeatMode)) {
|
||||
anim.setRepeatMode(
|
||||
arrayAnimator.getInt(R.styleable.Animator_repeatMode,
|
||||
ValueAnimator.RESTART));
|
||||
}
|
||||
if (evaluator != null) {
|
||||
anim.setEvaluator(evaluator);
|
||||
}
|
||||
|
||||
if (arrayObjectAnimator != null) {
|
||||
setupObjectAnimator(anim, arrayObjectAnimator, getFloats, pixelSize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the Animator to achieve path morphing.
|
||||
*
|
||||
* @param anim The target Animator which will be updated.
|
||||
* @param arrayAnimator TypedArray for the ValueAnimator.
|
||||
* @return the PathDataEvaluator.
|
||||
*/
|
||||
private static TypeEvaluator setupAnimatorForPath(ValueAnimator anim,
|
||||
TypedArray arrayAnimator) {
|
||||
TypeEvaluator evaluator = null;
|
||||
String fromString = arrayAnimator.getString(R.styleable.Animator_valueFrom);
|
||||
String toString = arrayAnimator.getString(R.styleable.Animator_valueTo);
|
||||
PathParser.PathDataNode[] nodesFrom = PathParser.createNodesFromPathData(fromString);
|
||||
PathParser.PathDataNode[] nodesTo = PathParser.createNodesFromPathData(toString);
|
||||
|
||||
if (nodesFrom != null) {
|
||||
if (nodesTo != null) {
|
||||
anim.setObjectValues(nodesFrom, nodesTo);
|
||||
if (!PathParser.canMorph(nodesFrom, nodesTo)) {
|
||||
throw new InflateException(arrayAnimator.getPositionDescription()
|
||||
+ " Can't morph from " + fromString + " to " + toString);
|
||||
}
|
||||
} else {
|
||||
anim.setObjectValues((Object)nodesFrom);
|
||||
}
|
||||
evaluator = new PathDataEvaluator(PathParser.deepCopyNodes(nodesFrom));
|
||||
} else if (nodesTo != null) {
|
||||
anim.setObjectValues((Object)nodesTo);
|
||||
evaluator = new PathDataEvaluator(PathParser.deepCopyNodes(nodesTo));
|
||||
}
|
||||
|
||||
if (DBG_ANIMATOR_INFLATER && evaluator != null) {
|
||||
Log.v(TAG, "create a new PathDataEvaluator here");
|
||||
}
|
||||
|
||||
return evaluator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup ObjectAnimator's property or values from pathData.
|
||||
*
|
||||
* @param anim The target Animator which will be updated.
|
||||
* @param arrayObjectAnimator TypedArray for the ObjectAnimator.
|
||||
* @param getFloats True if the value type is float.
|
||||
* @param pixelSize The relative pixel size, used to calculate the
|
||||
* maximum error for path animations.
|
||||
*/
|
||||
private static void setupObjectAnimator(ValueAnimator anim, TypedArray arrayObjectAnimator,
|
||||
boolean getFloats, float pixelSize) {
|
||||
ObjectAnimator oa = (ObjectAnimator) anim;
|
||||
String pathData = arrayObjectAnimator.getString(R.styleable.PropertyAnimator_pathData);
|
||||
|
||||
// Note that if there is a pathData defined in the Object Animator,
|
||||
// valueFrom / valueTo will be ignored.
|
||||
if (pathData != null) {
|
||||
throw new IllegalStateException("Not support PropertyAnimator_pathData");
|
||||
/* TODO Not support pathData
|
||||
String propertyXName =
|
||||
arrayObjectAnimator.getString(R.styleable.PropertyAnimator_propertyXName);
|
||||
String propertyYName =
|
||||
arrayObjectAnimator.getString(R.styleable.PropertyAnimator_propertyYName);
|
||||
|
||||
if (propertyXName == null && propertyYName == null) {
|
||||
throw new InflateException(arrayObjectAnimator.getPositionDescription()
|
||||
+ " propertyXName or propertyYName is needed for PathData");
|
||||
} else {
|
||||
JPath path = JPathParser.createPathFromPathData(pathData);
|
||||
float error = 0.5f * pixelSize; // max half a pixel error
|
||||
PathKeyframes keyframeSet = new PathKeyframes(path, error);
|
||||
Keyframes xKeyframes;
|
||||
Keyframes yKeyframes;
|
||||
if (getFloats) {
|
||||
xKeyframes = keyframeSet.createXFloatKeyframes();
|
||||
yKeyframes = keyframeSet.createYFloatKeyframes();
|
||||
} else {
|
||||
xKeyframes = keyframeSet.createXIntKeyframes();
|
||||
yKeyframes = keyframeSet.createYIntKeyframes();
|
||||
}
|
||||
PropertyValuesHolder x = null;
|
||||
PropertyValuesHolder y = null;
|
||||
if (propertyXName != null) {
|
||||
x = PropertyValuesHolder.ofKeyframes(propertyXName, xKeyframes);
|
||||
}
|
||||
if (propertyYName != null) {
|
||||
y = PropertyValuesHolder.ofKeyframes(propertyYName, yKeyframes);
|
||||
}
|
||||
if (x == null) {
|
||||
oa.setValues(y);
|
||||
} else if (y == null) {
|
||||
oa.setValues(x);
|
||||
} else {
|
||||
oa.setValues(x, y);
|
||||
}
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
String propertyName =
|
||||
arrayObjectAnimator.getString(R.styleable.PropertyAnimator_propertyName);
|
||||
oa.setPropertyName(propertyName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup ValueAnimator's values.
|
||||
* This will handle all of the integer, float and color types.
|
||||
*
|
||||
* @param anim The target Animator which will be updated.
|
||||
* @param arrayAnimator TypedArray for the ValueAnimator.
|
||||
* @param getFloats True if the value type is float.
|
||||
* @param hasFrom True if "valueFrom" exists.
|
||||
* @param fromType The type of "valueFrom".
|
||||
* @param hasTo True if "valueTo" exists.
|
||||
* @param toType The type of "valueTo".
|
||||
*/
|
||||
private static void setupValues(ValueAnimator anim, TypedArray arrayAnimator,
|
||||
boolean getFloats, boolean hasFrom, int fromType, boolean hasTo, int toType) {
|
||||
int valueFromIndex = R.styleable.Animator_valueFrom;
|
||||
int valueToIndex = R.styleable.Animator_valueTo;
|
||||
if (getFloats) {
|
||||
float valueFrom;
|
||||
float valueTo;
|
||||
if (hasFrom) {
|
||||
if (fromType == TypedValue.TYPE_DIMENSION) {
|
||||
valueFrom = arrayAnimator.getDimension(valueFromIndex, 0f);
|
||||
} else {
|
||||
valueFrom = arrayAnimator.getFloat(valueFromIndex, 0f);
|
||||
}
|
||||
if (hasTo) {
|
||||
if (toType == TypedValue.TYPE_DIMENSION) {
|
||||
valueTo = arrayAnimator.getDimension(valueToIndex, 0f);
|
||||
} else {
|
||||
valueTo = arrayAnimator.getFloat(valueToIndex, 0f);
|
||||
}
|
||||
anim.setFloatValues(valueFrom, valueTo);
|
||||
} else {
|
||||
anim.setFloatValues(valueFrom);
|
||||
}
|
||||
} else {
|
||||
if (toType == TypedValue.TYPE_DIMENSION) {
|
||||
valueTo = arrayAnimator.getDimension(valueToIndex, 0f);
|
||||
} else {
|
||||
valueTo = arrayAnimator.getFloat(valueToIndex, 0f);
|
||||
}
|
||||
anim.setFloatValues(valueTo);
|
||||
}
|
||||
} else {
|
||||
int valueFrom;
|
||||
int valueTo;
|
||||
if (hasFrom) {
|
||||
if (fromType == TypedValue.TYPE_DIMENSION) {
|
||||
valueFrom = (int) arrayAnimator.getDimension(valueFromIndex, 0f);
|
||||
} else if ((fromType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
|
||||
(fromType <= TypedValue.TYPE_LAST_COLOR_INT)) {
|
||||
valueFrom = arrayAnimator.getColor(valueFromIndex, 0);
|
||||
} else {
|
||||
valueFrom = arrayAnimator.getInt(valueFromIndex, 0);
|
||||
}
|
||||
if (hasTo) {
|
||||
if (toType == TypedValue.TYPE_DIMENSION) {
|
||||
valueTo = (int) arrayAnimator.getDimension(valueToIndex, 0f);
|
||||
} else if ((toType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
|
||||
(toType <= TypedValue.TYPE_LAST_COLOR_INT)) {
|
||||
valueTo = arrayAnimator.getColor(valueToIndex, 0);
|
||||
} else {
|
||||
valueTo = arrayAnimator.getInt(valueToIndex, 0);
|
||||
}
|
||||
anim.setIntValues(valueFrom, valueTo);
|
||||
} else {
|
||||
anim.setIntValues(valueFrom);
|
||||
}
|
||||
} else {
|
||||
if (hasTo) {
|
||||
if (toType == TypedValue.TYPE_DIMENSION) {
|
||||
valueTo = (int) arrayAnimator.getDimension(valueToIndex, 0f);
|
||||
} else if ((toType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
|
||||
(toType <= TypedValue.TYPE_LAST_COLOR_INT)) {
|
||||
valueTo = arrayAnimator.getColor(valueToIndex, 0);
|
||||
} else {
|
||||
valueTo = arrayAnimator.getInt(valueToIndex, 0);
|
||||
}
|
||||
anim.setIntValues(valueTo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Animator createAnimatorFromXml(Context context, XmlPullParser parser,
|
||||
float pixelSize)
|
||||
throws XmlPullParserException, IOException {
|
||||
return createAnimatorFromXml(context, parser, Xml.asAttributeSet(parser), null, 0,
|
||||
pixelSize);
|
||||
}
|
||||
|
||||
private static Animator createAnimatorFromXml(Context context, XmlPullParser parser,
|
||||
AttributeSet attrs, AnimatorSet parent, int sequenceOrdering, float pixelSize)
|
||||
throws XmlPullParserException, IOException {
|
||||
|
||||
Animator anim = null;
|
||||
ArrayList<Animator> childAnims = null;
|
||||
|
||||
// Make sure we are on a start tag.
|
||||
int type;
|
||||
int depth = parser.getDepth();
|
||||
|
||||
while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
|
||||
&& type != XmlPullParser.END_DOCUMENT) {
|
||||
|
||||
if (type != XmlPullParser.START_TAG) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String name = parser.getName();
|
||||
|
||||
if (name.equals("objectAnimator")) {
|
||||
anim = loadObjectAnimator(context, attrs, pixelSize);
|
||||
} else if (name.equals("animator")) {
|
||||
anim = loadAnimator(context, attrs, null, pixelSize);
|
||||
} else if (name.equals("set")) {
|
||||
anim = new AnimatorSet();
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AnimatorSet);
|
||||
int ordering = a.getInt(R.styleable.AnimatorSet_ordering,
|
||||
TOGETHER);
|
||||
createAnimatorFromXml(context, parser, attrs, (AnimatorSet) anim, ordering,
|
||||
pixelSize);
|
||||
a.recycle();
|
||||
} else {
|
||||
throw new RuntimeException("Unknown animator name: " + parser.getName());
|
||||
}
|
||||
|
||||
if (parent != null) {
|
||||
if (childAnims == null) {
|
||||
childAnims = new ArrayList<>();
|
||||
}
|
||||
childAnims.add(anim);
|
||||
}
|
||||
}
|
||||
if (parent != null && childAnims != null) {
|
||||
Animator[] animsArray = new Animator[childAnims.size()];
|
||||
int index = 0;
|
||||
for (Animator a : childAnims) {
|
||||
animsArray[index++] = a;
|
||||
}
|
||||
if (sequenceOrdering == TOGETHER) {
|
||||
parent.playTogether(animsArray);
|
||||
} else {
|
||||
parent.playSequentially(animsArray);
|
||||
}
|
||||
}
|
||||
|
||||
return anim;
|
||||
|
||||
}
|
||||
|
||||
private static ObjectAnimator loadObjectAnimator(Context context, AttributeSet attrs,
|
||||
float pathErrorScale) throws NotFoundException {
|
||||
ObjectAnimator anim = new ObjectAnimator();
|
||||
|
||||
loadAnimator(context, attrs, anim, pathErrorScale);
|
||||
|
||||
return anim;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new animation whose parameters come from the specified context
|
||||
* and attributes set.
|
||||
*
|
||||
* @param context the context
|
||||
* @param attrs The set of attributes holding the animation parameters
|
||||
* @param anim Null if this is a ValueAnimator, otherwise this is an
|
||||
* ObjectAnimator
|
||||
*/
|
||||
private static ValueAnimator loadAnimator(Context context, AttributeSet attrs,
|
||||
ValueAnimator anim, float pathErrorScale)
|
||||
throws NotFoundException {
|
||||
|
||||
TypedArray arrayAnimator = context.obtainStyledAttributes(attrs, R.styleable.Animator);
|
||||
TypedArray arrayObjectAnimator = null;
|
||||
|
||||
// If anim is not null, then it is an object animator.
|
||||
if (anim != null) {
|
||||
arrayObjectAnimator = context.obtainStyledAttributes(attrs,
|
||||
R.styleable.PropertyAnimator);
|
||||
}
|
||||
|
||||
if (anim == null) {
|
||||
anim = new ValueAnimator();
|
||||
}
|
||||
|
||||
parseAnimatorFromTypeArray(anim, arrayAnimator, arrayObjectAnimator, pathErrorScale);
|
||||
|
||||
final int resID =
|
||||
arrayAnimator.getResourceId(R.styleable.Animator_interpolator, 0);
|
||||
if (resID > 0) {
|
||||
anim.setInterpolator(InterpolatorInflater.loadInterpolator(context, resID));
|
||||
}
|
||||
|
||||
arrayAnimator.recycle();
|
||||
if (arrayObjectAnimator != null) {
|
||||
arrayObjectAnimator.recycle();
|
||||
}
|
||||
|
||||
return anim;
|
||||
}
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.vectorold.animation;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Xml;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
import android.view.animation.AccelerateInterpolator;
|
||||
import android.view.animation.AnticipateInterpolator;
|
||||
import android.view.animation.AnticipateOvershootInterpolator;
|
||||
import android.view.animation.BounceInterpolator;
|
||||
import android.view.animation.CycleInterpolator;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.view.animation.OvershootInterpolator;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class InterpolatorInflater {
|
||||
|
||||
/**
|
||||
* Loads an {@link Interpolator} object from a resource
|
||||
*
|
||||
* @param context The Context
|
||||
* @param id The resource id of the animation to load
|
||||
* @return The interpolator object reference by the specified id
|
||||
* @throws Resources.NotFoundException
|
||||
*/
|
||||
public static Interpolator loadInterpolator(Context context, int id) throws Resources.NotFoundException {
|
||||
XmlResourceParser parser = null;
|
||||
try {
|
||||
parser = context.getResources().getAnimation(id);
|
||||
return createInterpolatorFromXml(context, parser);
|
||||
} catch (XmlPullParserException ex) {
|
||||
Resources.NotFoundException rnf = new Resources.NotFoundException("Can't load animation resource ID #0x" +
|
||||
Integer.toHexString(id));
|
||||
rnf.initCause(ex);
|
||||
throw rnf;
|
||||
} catch (IOException ex) {
|
||||
Resources.NotFoundException rnf = new Resources.NotFoundException("Can't load animation resource ID #0x" +
|
||||
Integer.toHexString(id));
|
||||
rnf.initCause(ex);
|
||||
throw rnf;
|
||||
} finally {
|
||||
if (parser != null)
|
||||
parser.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Interpolator createInterpolatorFromXml(Context context, XmlPullParser parser)
|
||||
throws XmlPullParserException, IOException {
|
||||
|
||||
Interpolator interpolator = null;
|
||||
|
||||
// Make sure we are on a start tag.
|
||||
int type;
|
||||
int depth = parser.getDepth();
|
||||
|
||||
while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
|
||||
&& type != XmlPullParser.END_DOCUMENT) {
|
||||
|
||||
if (type != XmlPullParser.START_TAG) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||
|
||||
String name = parser.getName();
|
||||
|
||||
if (name.equals("linearInterpolator")) {
|
||||
interpolator = new LinearInterpolator();
|
||||
} else if (name.equals("accelerateInterpolator")) {
|
||||
interpolator = new AccelerateInterpolator(context, attrs);
|
||||
} else if (name.equals("decelerateInterpolator")) {
|
||||
interpolator = new DecelerateInterpolator(context, attrs);
|
||||
} else if (name.equals("accelerateDecelerateInterpolator")) {
|
||||
interpolator = new AccelerateDecelerateInterpolator();
|
||||
} else if (name.equals("cycleInterpolator")) {
|
||||
interpolator = new CycleInterpolator(context, attrs);
|
||||
} else if (name.equals("anticipateInterpolator")) {
|
||||
interpolator = new AnticipateInterpolator(context, attrs);
|
||||
} else if (name.equals("overshootInterpolator")) {
|
||||
interpolator = new OvershootInterpolator(context, attrs);
|
||||
} else if (name.equals("anticipateOvershootInterpolator")) {
|
||||
interpolator = new AnticipateOvershootInterpolator(context, attrs);
|
||||
} else if (name.equals("bounceInterpolator")) {
|
||||
interpolator = new BounceInterpolator();
|
||||
} else if (name.equals("pathInterpolator")) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
interpolator = new PathInterpolator(context, attrs);
|
||||
} else {
|
||||
interpolator = new android.view.animation.PathInterpolator(context, attrs);
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Unknown interpolator name: " + parser.getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return interpolator;
|
||||
}
|
||||
}
|
||||
@@ -1,219 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.vectorold.animation;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.Resources.Theme;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PathMeasure;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.InflateException;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.vectorold.util.PathParser;
|
||||
|
||||
/**
|
||||
* An interpolator that can traverse a Path that extends from <code>Point</code>
|
||||
* <code>(0, 0)</code> to <code>(1, 1)</code>. The x coordinate along the <code>Path</code>
|
||||
* is the input value and the output is the y coordinate of the line at that point.
|
||||
* This means that the Path must conform to a function <code>y = f(x)</code>.
|
||||
*
|
||||
* <p>The <code>Path</code> must not have gaps in the x direction and must not
|
||||
* loop back on itself such that there can be two points sharing the same x coordinate.
|
||||
* It is alright to have a disjoint line in the vertical direction:</p>
|
||||
* <p><blockquote><pre>
|
||||
* Path path = new Path();
|
||||
* path.lineTo(0.25f, 0.25f);
|
||||
* path.moveTo(0.25f, 0.5f);
|
||||
* path.lineTo(1f, 1f);
|
||||
* </pre></blockquote></p>
|
||||
*/
|
||||
public class PathInterpolator implements Interpolator {
|
||||
|
||||
// This governs how accurate the approximation of the Path is.
|
||||
private static final float PRECISION = 0.002f;
|
||||
|
||||
private float[] mX; // x coordinates in the line
|
||||
|
||||
private float[] mY; // y coordinates in the line
|
||||
|
||||
/**
|
||||
* Create an interpolator for an arbitrary <code>Path</code>. The <code>Path</code>
|
||||
* must begin at <code>(0, 0)</code> and end at <code>(1, 1)</code>.
|
||||
*
|
||||
* @param path The <code>Path</code> to use to make the line representing the interpolator.
|
||||
*/
|
||||
public PathInterpolator(Path path) {
|
||||
initPath(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an interpolator for a quadratic Bezier curve. The end points
|
||||
* <code>(0, 0)</code> and <code>(1, 1)</code> are assumed.
|
||||
*
|
||||
* @param controlX The x coordinate of the quadratic Bezier control point.
|
||||
* @param controlY The y coordinate of the quadratic Bezier control point.
|
||||
*/
|
||||
public PathInterpolator(float controlX, float controlY) {
|
||||
initQuad(controlX, controlY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an interpolator for a cubic Bezier curve. The end points
|
||||
* <code>(0, 0)</code> and <code>(1, 1)</code> are assumed.
|
||||
*
|
||||
* @param controlX1 The x coordinate of the first control point of the cubic Bezier.
|
||||
* @param controlY1 The y coordinate of the first control point of the cubic Bezier.
|
||||
* @param controlX2 The x coordinate of the second control point of the cubic Bezier.
|
||||
* @param controlY2 The y coordinate of the second control point of the cubic Bezier.
|
||||
*/
|
||||
public PathInterpolator(float controlX1, float controlY1, float controlX2, float controlY2) {
|
||||
initCubic(controlX1, controlY1, controlX2, controlY2);
|
||||
}
|
||||
|
||||
public PathInterpolator(Context context, AttributeSet attrs) {
|
||||
this(context.getResources(), context.getTheme(), attrs);
|
||||
}
|
||||
|
||||
public PathInterpolator(Resources res, Theme theme, AttributeSet attrs) {
|
||||
TypedArray a;
|
||||
if (theme != null) {
|
||||
a = theme.obtainStyledAttributes(attrs, R.styleable.PathInterpolator, 0, 0);
|
||||
} else {
|
||||
a = res.obtainAttributes(attrs, R.styleable.PathInterpolator);
|
||||
}
|
||||
parseInterpolatorFromTypeArray(a);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
private void parseInterpolatorFromTypeArray(TypedArray a) {
|
||||
// If there is pathData defined in the xml file, then the controls points
|
||||
// will be all coming from pathData.
|
||||
if (a.hasValue(R.styleable.PathInterpolator_pathData)) {
|
||||
String pathData = a.getString(R.styleable.PathInterpolator_pathData);
|
||||
Path path = PathParser.createPathFromPathData(pathData);
|
||||
if (path == null) {
|
||||
throw new InflateException("The path is null, which is created"
|
||||
+ " from " + pathData);
|
||||
}
|
||||
initPath(path);
|
||||
} else {
|
||||
if (!a.hasValue(R.styleable.PathInterpolator_controlX1)) {
|
||||
throw new InflateException("pathInterpolator requires the controlX1 attribute");
|
||||
} else if (!a.hasValue(R.styleable.PathInterpolator_controlY1)) {
|
||||
throw new InflateException("pathInterpolator requires the controlY1 attribute");
|
||||
}
|
||||
float x1 = a.getFloat(R.styleable.PathInterpolator_controlX1, 0);
|
||||
float y1 = a.getFloat(R.styleable.PathInterpolator_controlY1, 0);
|
||||
|
||||
boolean hasX2 = a.hasValue(R.styleable.PathInterpolator_controlX2);
|
||||
boolean hasY2 = a.hasValue(R.styleable.PathInterpolator_controlY2);
|
||||
|
||||
if (hasX2 != hasY2) {
|
||||
throw new InflateException(
|
||||
"pathInterpolator requires both controlX2 and controlY2 for cubic Beziers.");
|
||||
}
|
||||
|
||||
if (!hasX2) {
|
||||
initQuad(x1, y1);
|
||||
} else {
|
||||
float x2 = a.getFloat(R.styleable.PathInterpolator_controlX2, 0);
|
||||
float y2 = a.getFloat(R.styleable.PathInterpolator_controlY2, 0);
|
||||
initCubic(x1, y1, x2, y2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initQuad(float controlX, float controlY) {
|
||||
Path path = new Path();
|
||||
path.moveTo(0, 0);
|
||||
path.quadTo(controlX, controlY, 1f, 1f);
|
||||
initPath(path);
|
||||
}
|
||||
|
||||
private void initCubic(float x1, float y1, float x2, float y2) {
|
||||
Path path = new Path();
|
||||
path.moveTo(0, 0);
|
||||
path.cubicTo(x1, y1, x2, y2, 1f, 1f);
|
||||
initPath(path);
|
||||
}
|
||||
|
||||
private void initPath(Path path) {
|
||||
final PathMeasure pathMeasure = new PathMeasure(path, false /* forceClosed */);
|
||||
|
||||
final float pathLength = pathMeasure.getLength();
|
||||
final int numPoints = (int) (pathLength / PRECISION) + 1;
|
||||
|
||||
mX = new float[numPoints];
|
||||
mY = new float[numPoints];
|
||||
|
||||
final float[] position = new float[2];
|
||||
for (int i = 0; i < numPoints; ++i) {
|
||||
final float distance = (i * pathLength) / (numPoints - 1);
|
||||
pathMeasure.getPosTan(distance, position, null /* tangent */);
|
||||
|
||||
mX[i] = position[0];
|
||||
mY[i] = position[1];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Using the line in the Path in this interpolator that can be described as
|
||||
* <code>y = f(x)</code>, finds the y coordinate of the line given <code>t</code>
|
||||
* as the x coordinate. Values less than 0 will always return 0 and values greater
|
||||
* than 1 will always return 1.
|
||||
*
|
||||
* @param t Treated as the x coordinate along the line.
|
||||
* @return The y coordinate of the Path along the line where x = <code>t</code>.
|
||||
* @see Interpolator#getInterpolation(float)
|
||||
*/
|
||||
@Override
|
||||
public float getInterpolation(float t) {
|
||||
if (t <= 0) {
|
||||
return 0;
|
||||
} else if (t >= 1) {
|
||||
return 1;
|
||||
}
|
||||
// Do a binary search for the correct x to interpolate between.
|
||||
int startIndex = 0;
|
||||
int endIndex = mX.length - 1;
|
||||
|
||||
while (endIndex - startIndex > 1) {
|
||||
int midIndex = (startIndex + endIndex) / 2;
|
||||
if (t < mX[midIndex]) {
|
||||
endIndex = midIndex;
|
||||
} else {
|
||||
startIndex = midIndex;
|
||||
}
|
||||
}
|
||||
|
||||
float xRange = mX[endIndex] - mX[startIndex];
|
||||
if (xRange == 0) {
|
||||
return mY[startIndex];
|
||||
}
|
||||
|
||||
float tInRange = t - mX[startIndex];
|
||||
float fraction = tInRange / xRange;
|
||||
|
||||
float startY = mY[startIndex];
|
||||
float endY = mY[endIndex];
|
||||
return startY + (fraction * (endY - startY));
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.vectorold.content;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.VectorResources;
|
||||
import android.os.Build;
|
||||
|
||||
public class VectorContext extends ContextWrapper {
|
||||
|
||||
private VectorResources mVectorResources;
|
||||
|
||||
public VectorContext(Context base) {
|
||||
super(base);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resources getResources() {
|
||||
final Resources superResources = super.getResources();
|
||||
if (mVectorResources == null || mVectorResources.isBase(superResources)) {
|
||||
mVectorResources = new VectorResources(this, superResources);
|
||||
}
|
||||
return mVectorResources;
|
||||
}
|
||||
|
||||
/**
|
||||
* In {@link android.content.ContextWrapper#attachBaseContext(Context)},
|
||||
* do <code>super.attachBaseContext(Vector.wrapContext(newBase));</code>.
|
||||
*
|
||||
* @param context the context
|
||||
* @return new context
|
||||
*/
|
||||
public static Context wrapContext(Context context) {
|
||||
return Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP ? new VectorContext(context) : context;
|
||||
}
|
||||
}
|
||||
@@ -1,430 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.hippo.vectorold.drawable;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Animatable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.v4.util.ArrayMap;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
|
||||
import com.hippo.vectorold.animation.AnimatorInflater;
|
||||
import com.hippo.ehviewer.R;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* This class uses {@link android.animation.ObjectAnimator} and
|
||||
* {@link android.animation.AnimatorSet} to animate the properties of a
|
||||
* {@link android.graphics.drawable.VectorDrawable} to create an animated drawable.
|
||||
* <p>
|
||||
* AnimatedVectorDrawable are normally defined as 3 separate XML files.
|
||||
* </p>
|
||||
* <p>
|
||||
* First is the XML file for {@link android.graphics.drawable.VectorDrawable}.
|
||||
* Note that we allow the animation happen on the group's attributes and path's
|
||||
* attributes, which requires they are uniquely named in this xml file. Groups
|
||||
* and paths without animations do not need names.
|
||||
* </p>
|
||||
* <li>Here is a simple VectorDrawable in this vectordrawable.xml file.
|
||||
* <pre>
|
||||
* <vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
* android:height="64dp"
|
||||
* android:width="64dp"
|
||||
* android:viewportHeight="600"
|
||||
* android:viewportWidth="600" >
|
||||
* <group
|
||||
* android:name="rotationGroup"
|
||||
* android:pivotX="300.0"
|
||||
* android:pivotY="300.0"
|
||||
* android:rotation="45.0" >
|
||||
* <path
|
||||
* android:name="v"
|
||||
* android:fillColor="#000000"
|
||||
* android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
|
||||
* </group>
|
||||
* </vector>
|
||||
* </pre></li>
|
||||
* <p>
|
||||
* Second is the AnimatedVectorDrawable's xml file, which defines the target
|
||||
* VectorDrawable, the target paths and groups to animate, the properties of the
|
||||
* path and group to animate and the animations defined as the ObjectAnimators
|
||||
* or AnimatorSets.
|
||||
* </p>
|
||||
* <li>Here is a simple AnimatedVectorDrawable defined in this avd.xml file.
|
||||
* Note how we use the names to refer to the groups and paths in the vectordrawable.xml.
|
||||
* <pre>
|
||||
* <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
* android:drawable="@drawable/vectordrawable" >
|
||||
* <target
|
||||
* android:name="rotationGroup"
|
||||
* android:animation="@anim/rotation" />
|
||||
* <target
|
||||
* android:name="v"
|
||||
* android:animation="@anim/path_morph" />
|
||||
* </animated-vector>
|
||||
* </pre></li>
|
||||
* <p>
|
||||
* Last is the Animator xml file, which is the same as a normal ObjectAnimator
|
||||
* or AnimatorSet.
|
||||
* To complete this example, here are the 2 animator files used in avd.xml:
|
||||
* rotation.xml and path_morph.xml.
|
||||
* </p>
|
||||
* <li>Here is the rotation.xml, which will rotate the target group for 360 degrees.
|
||||
* <pre>
|
||||
* <objectAnimator
|
||||
* android:duration="6000"
|
||||
* android:propertyName="rotation"
|
||||
* android:valueFrom="0"
|
||||
* android:valueTo="360" />
|
||||
* </pre></li>
|
||||
* <li>Here is the path_morph.xml, which will morph the path from one shape to
|
||||
* the other. Note that the paths must be compatible for morphing.
|
||||
* In more details, the paths should have exact same length of commands , and
|
||||
* exact same length of parameters for each commands.
|
||||
* Note that the path string are better stored in strings.xml for reusing.
|
||||
* <pre>
|
||||
* <set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
* <objectAnimator
|
||||
* android:duration="3000"
|
||||
* android:propertyName="pathData"
|
||||
* android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z"
|
||||
* android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z"
|
||||
* android:valueType="pathType"/>
|
||||
* </set>
|
||||
* </pre></li>
|
||||
*
|
||||
* @attr ref android.R.styleable#AnimatedVectorDrawable_drawable
|
||||
* @attr ref android.R.styleable#AnimatedVectorDrawableTarget_name
|
||||
* @attr ref android.R.styleable#AnimatedVectorDrawableTarget_animation
|
||||
*/
|
||||
public class AnimatedVectorDrawable extends Drawable implements Animatable {
|
||||
private static final String LOGTAG = AnimatedVectorDrawable.class.getSimpleName();
|
||||
|
||||
private static final String ANIMATED_VECTOR = "animated-vector";
|
||||
private static final String TARGET = "target";
|
||||
|
||||
private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false;
|
||||
|
||||
private AnimatedVectorDrawableState mAnimatedVectorState;
|
||||
|
||||
private boolean mMutated;
|
||||
|
||||
public AnimatedVectorDrawable() {
|
||||
mAnimatedVectorState = new AnimatedVectorDrawableState(null);
|
||||
}
|
||||
|
||||
private AnimatedVectorDrawable(AnimatedVectorDrawableState state, Resources res) {
|
||||
mAnimatedVectorState = new AnimatedVectorDrawableState(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable mutate() {
|
||||
if (!mMutated && super.mutate() == this) {
|
||||
mAnimatedVectorState.mVectorDrawable.mutate();
|
||||
mMutated = true;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstantState getConstantState() {
|
||||
mAnimatedVectorState.mChangingConfigurations = getChangingConfigurations();
|
||||
return mAnimatedVectorState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChangingConfigurations() {
|
||||
return super.getChangingConfigurations() | mAnimatedVectorState.mChangingConfigurations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
mAnimatedVectorState.mVectorDrawable.draw(canvas);
|
||||
if (isStarted()) {
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBoundsChange(Rect bounds) {
|
||||
mAnimatedVectorState.mVectorDrawable.setBounds(bounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onStateChange(int[] state) {
|
||||
return mAnimatedVectorState.mVectorDrawable.setState(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onLevelChange(int level) {
|
||||
return mAnimatedVectorState.mVectorDrawable.setLevel(level);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAlpha() {
|
||||
return mAnimatedVectorState.mVectorDrawable.getAlpha();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
mAnimatedVectorState.mVectorDrawable.setAlpha(alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter colorFilter) {
|
||||
mAnimatedVectorState.mVectorDrawable.setColorFilter(colorFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTintList(ColorStateList tint) {
|
||||
mAnimatedVectorState.mVectorDrawable.setTintList(tint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTintMode(PorterDuff.Mode tintMode) {
|
||||
mAnimatedVectorState.mVectorDrawable.setTintMode(tintMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setVisible(boolean visible, boolean restart) {
|
||||
mAnimatedVectorState.mVectorDrawable.setVisible(visible, restart);
|
||||
return super.setVisible(visible, restart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStateful() {
|
||||
return mAnimatedVectorState.mVectorDrawable.isStateful();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return mAnimatedVectorState.mVectorDrawable.getOpacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
return mAnimatedVectorState.mVectorDrawable.getIntrinsicWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
return mAnimatedVectorState.mVectorDrawable.getIntrinsicHeight();
|
||||
}
|
||||
|
||||
public void inflate(Context context, XmlPullParser parser, AttributeSet attrs)
|
||||
throws XmlPullParserException, IOException {
|
||||
Resources res = context.getResources();
|
||||
int eventType = parser.getEventType();
|
||||
float pathErrorScale = 1;
|
||||
while (eventType != XmlPullParser.END_DOCUMENT) {
|
||||
if (eventType == XmlPullParser.START_TAG) {
|
||||
final String tagName = parser.getName();
|
||||
if (ANIMATED_VECTOR.equals(tagName)) {
|
||||
final TypedArray a = res.obtainAttributes(attrs,
|
||||
R.styleable.AnimatedVectorDrawable);
|
||||
int drawableRes = a.getResourceId(
|
||||
R.styleable.AnimatedVectorDrawable_drawable, 0);
|
||||
if (drawableRes != 0) {
|
||||
VectorDrawable vectorDrawable =(VectorDrawable) res.getDrawable(
|
||||
drawableRes).mutate();
|
||||
vectorDrawable.setAllowCaching(false);
|
||||
pathErrorScale = vectorDrawable.getPixelSize();
|
||||
mAnimatedVectorState.mVectorDrawable = vectorDrawable;
|
||||
}
|
||||
a.recycle();
|
||||
} else if (TARGET.equals(tagName)) {
|
||||
final TypedArray a = res.obtainAttributes(attrs,
|
||||
R.styleable.AnimatedVectorDrawableTarget);
|
||||
final String target = a.getString(
|
||||
R.styleable.AnimatedVectorDrawableTarget_name);
|
||||
|
||||
int id = a.getResourceId(
|
||||
R.styleable.AnimatedVectorDrawableTarget_animation, 0);
|
||||
if (id != 0) {
|
||||
Animator objectAnimator = AnimatorInflater.loadAnimator(context, id, pathErrorScale);
|
||||
setupAnimatorsForTarget(target, objectAnimator);
|
||||
}
|
||||
a.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
eventType = parser.next();
|
||||
}
|
||||
}
|
||||
|
||||
private static class AnimatedVectorDrawableState extends ConstantState {
|
||||
int mChangingConfigurations;
|
||||
VectorDrawable mVectorDrawable;
|
||||
ArrayList<Animator> mAnimators;
|
||||
ArrayMap<Animator, String> mTargetNameMap;
|
||||
|
||||
public AnimatedVectorDrawableState(AnimatedVectorDrawableState copy) {
|
||||
if (copy != null) {
|
||||
mChangingConfigurations = copy.mChangingConfigurations;
|
||||
if (copy.mVectorDrawable != null) {
|
||||
mVectorDrawable = (VectorDrawable) copy.mVectorDrawable.getConstantState().newDrawable();
|
||||
mVectorDrawable.mutate();
|
||||
mVectorDrawable.setAllowCaching(false);
|
||||
mVectorDrawable.setBounds(copy.mVectorDrawable.getBounds());
|
||||
}
|
||||
if (copy.mAnimators != null) {
|
||||
final int numAnimators = copy.mAnimators.size();
|
||||
mAnimators = new ArrayList<>(numAnimators);
|
||||
mTargetNameMap = new ArrayMap<>(numAnimators);
|
||||
for (int i = 0; i < numAnimators; ++i) {
|
||||
Animator anim = copy.mAnimators.get(i);
|
||||
Animator animClone = anim.clone();
|
||||
String targetName = copy.mTargetNameMap.get(anim);
|
||||
Object targetObject = mVectorDrawable.getTargetByName(targetName);
|
||||
animClone.setTarget(targetObject);
|
||||
mAnimators.add(animClone);
|
||||
mTargetNameMap.put(animClone, targetName);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mVectorDrawable = new VectorDrawable();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable newDrawable() {
|
||||
return new AnimatedVectorDrawable(this, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable newDrawable(Resources res) {
|
||||
return new AnimatedVectorDrawable(this, res);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChangingConfigurations() {
|
||||
return mChangingConfigurations;
|
||||
}
|
||||
}
|
||||
|
||||
private void setupAnimatorsForTarget(String name, Animator animator) {
|
||||
Object target = mAnimatedVectorState.mVectorDrawable.getTargetByName(name);
|
||||
animator.setTarget(target);
|
||||
if (mAnimatedVectorState.mAnimators == null) {
|
||||
mAnimatedVectorState.mAnimators = new ArrayList<>();
|
||||
mAnimatedVectorState.mTargetNameMap = new ArrayMap<>();
|
||||
}
|
||||
mAnimatedVectorState.mAnimators.add(animator);
|
||||
mAnimatedVectorState.mTargetNameMap.put(animator, name);
|
||||
if (DBG_ANIMATION_VECTOR_DRAWABLE) {
|
||||
Log.v(LOGTAG, "add animator for target " + name + " " + animator);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
|
||||
final int size = animators.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final Animator animator = animators.get(i);
|
||||
if (animator.isRunning()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isStarted() {
|
||||
final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
|
||||
final int size = animators.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final Animator animator = animators.get(i);
|
||||
if (animator.isStarted()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
|
||||
final int size = animators.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final Animator animator = animators.get(i);
|
||||
if (!animator.isStarted()) {
|
||||
animator.start();
|
||||
}
|
||||
}
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
|
||||
final int size = animators.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final Animator animator = animators.get(i);
|
||||
animator.end();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverses ongoing animations or starts pending animations in reverse.
|
||||
* <p>
|
||||
* NOTE: Only works of all animations are ValueAnimators.
|
||||
* @hide
|
||||
*/
|
||||
/*
|
||||
public void reverse() {
|
||||
final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
|
||||
final int size = animators.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final Animator animator = animators.get(i);
|
||||
if (animator.canReverse()) {
|
||||
animator.reverse();
|
||||
} else {
|
||||
Log.w(LOGTAG, "AnimatedVectorDrawable can't reverse()");
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
/*
|
||||
public boolean canReverse() {
|
||||
final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
|
||||
final int size = animators.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final Animator animator = animators.get(i);
|
||||
if (!animator.canReverse()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -1,240 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<!-- Makes the TextView be exactly this many pixels tall.
|
||||
You could get the same effect by specifying this number in the
|
||||
layout parameters. -->
|
||||
<attr name="height" />
|
||||
|
||||
<!-- ========================== -->
|
||||
<!-- VectorDrawable class -->
|
||||
<!-- ========================== -->
|
||||
<eat-comment />
|
||||
|
||||
<!-- Drawable used to draw vector paths. -->
|
||||
<declare-styleable name="VectorDrawable">
|
||||
<!-- If set, specifies the color to apply to the drawable as a tint. By default,
|
||||
no tint is applied. May be a color state list. -->
|
||||
<attr name="tint" format="color"/>
|
||||
<!-- When a tint color is set, specifies its Porter-Duff blending mode. The
|
||||
default value is src_in, which treats the drawable as an alpha mask. -->
|
||||
<attr name="tintMode">
|
||||
<!-- The tint is drawn on top of the drawable.
|
||||
[Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] -->
|
||||
<enum name="src_over" value="3"/>
|
||||
<!-- The tint is masked by the alpha channel of the drawable. The drawable’s
|
||||
color channels are thrown out. [Sa * Da, Sc * Da] -->
|
||||
<enum name="src_in" value="5"/>
|
||||
<!-- The tint is drawn above the drawable, but with the drawable’s alpha
|
||||
channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] -->
|
||||
<enum name="src_atop" value="9"/>
|
||||
<!-- Multiplies the color and alpha channels of the drawable with those of
|
||||
the tint. [Sa * Da, Sc * Dc] -->
|
||||
<enum name="multiply" value="14"/>
|
||||
<!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -->
|
||||
<enum name="screen" value="15"/>
|
||||
<!-- Combines the tint and drawable color and alpha channels, clamping the
|
||||
result to valid color values. Saturate(S + D) -->
|
||||
<enum name="add" value="16"/>
|
||||
</attr>
|
||||
<!-- Indicates if the drawable needs to be mirrored when its layout direction is
|
||||
RTL (right-to-left). -->
|
||||
<attr name="autoMirrored" format="boolean"/>
|
||||
<!-- The intrinsic width of the Vector Drawable. -->
|
||||
<attr name="width" format="dimension"/>
|
||||
<!-- The intrinsic height of the Vector Drawable. -->
|
||||
<attr name="height"/>
|
||||
<!-- The width of the canvas the drawing is on. -->
|
||||
<attr name="viewportWidth" format="float"/>
|
||||
<!-- The height of the canvas the drawing is on. -->
|
||||
<attr name="viewportHeight" format="float"/>
|
||||
<!-- The name of this vector drawable -->
|
||||
<attr name="name" format="string"/>
|
||||
<!-- The opacity of the whole vector drawable, as a value between 0
|
||||
(completely transparent) and 1 (completely opaque). -->
|
||||
<attr name="alpha" format="float"/>
|
||||
</declare-styleable>
|
||||
|
||||
<!-- Defines the group used in VectorDrawables. -->
|
||||
<declare-styleable name="VectorDrawableGroup">
|
||||
<!-- The name of this group -->
|
||||
<attr name="name"/>
|
||||
<!-- The amount to rotate the group -->
|
||||
<attr name="rotation" format="float"/>
|
||||
<!-- The X coordinate of the center of rotation of a group -->
|
||||
<attr name="pivotX" format="float|fraction"/>
|
||||
<!-- The Y coordinate of the center of rotation of a group -->
|
||||
<attr name="pivotY" format="float|fraction"/>
|
||||
<!-- The amount to translate the group on X coordinate -->
|
||||
<attr name="translateX" format="float"/>
|
||||
<!-- The amount to translate the group on Y coordinate -->
|
||||
<attr name="translateY" format="float"/>
|
||||
<!-- The amount to scale the group on X coordinate -->
|
||||
<attr name="scaleX" format="float"/>
|
||||
<!-- The amount to scale the group on Y coordinate -->
|
||||
<attr name="scaleY" format="float"/>
|
||||
</declare-styleable>
|
||||
|
||||
<!-- Defines the path used in VectorDrawables. -->
|
||||
<declare-styleable name="VectorDrawablePath">
|
||||
<!-- The name of this path -->
|
||||
<attr name="name" />
|
||||
<!-- The width a path stroke -->
|
||||
<attr name="strokeWidth" format="float" />
|
||||
<!-- The color to stroke the path if not defined implies no stroke-->
|
||||
<attr name="strokeColor" format="color" />
|
||||
<!-- The opacity of a path stroke, as a value between 0 (completely transparent)
|
||||
and 1 (completely opaque) -->
|
||||
<attr name="strokeAlpha" format="float" />
|
||||
<!-- The color to fill the path if not defined implies no fill-->
|
||||
<attr name="fillColor" format="color" />
|
||||
<!-- The alpha of the path fill, as a value between 0 (completely transparent)
|
||||
and 1 (completely opaque)-->
|
||||
<attr name="fillAlpha" format="float" />
|
||||
<!-- The specification of the operations that define the path -->
|
||||
<attr name="pathData" format="string" />
|
||||
<!-- The fraction of the path to trim from the start from 0 to 1 -->
|
||||
<attr name="trimPathStart" format="float" />
|
||||
<!-- The fraction of the path to trim from the end from 0 to 1 -->
|
||||
<attr name="trimPathEnd" format="float" />
|
||||
<!-- Shift trim region (allows visible region to include the start and end) from 0 to 1 -->
|
||||
<attr name="trimPathOffset" format="float" />
|
||||
<!-- sets the linecap for a stroked path -->
|
||||
<attr name="strokeLineCap" format="enum">
|
||||
<enum name="butt" value="0"/>
|
||||
<enum name="round" value="1"/>
|
||||
<enum name="square" value="2"/>
|
||||
</attr>
|
||||
<!-- sets the lineJoin for a stroked path -->
|
||||
<attr name="strokeLineJoin" format="enum">
|
||||
<enum name="miter" value="0"/>
|
||||
<enum name="round" value="1"/>
|
||||
<enum name="bevel" value="2"/>
|
||||
</attr>
|
||||
<!-- sets the Miter limit for a stroked path -->
|
||||
<attr name="strokeMiterLimit" format="float"/>
|
||||
</declare-styleable>
|
||||
|
||||
<!-- Defines the clip path used in VectorDrawables. -->
|
||||
<declare-styleable name="VectorDrawableClipPath">
|
||||
<!-- The Name of this path -->
|
||||
<attr name="name"/>
|
||||
<!-- The specification of the operations that define the path -->
|
||||
<attr name="pathData"/>
|
||||
</declare-styleable>
|
||||
|
||||
<!-- ========================== -->
|
||||
<!-- AnimatedVectorDrawable class -->
|
||||
<!-- ========================== -->
|
||||
<eat-comment />
|
||||
|
||||
<!-- Define the AnimatedVectorDrawable. -->
|
||||
<declare-styleable name="AnimatedVectorDrawable">
|
||||
<!-- The static vector drawable. -->
|
||||
<attr name="drawable" format="reference"/>
|
||||
</declare-styleable>
|
||||
|
||||
<!-- Defines the target used in the AnimatedVectorDrawable. -->
|
||||
<declare-styleable name="AnimatedVectorDrawableTarget">
|
||||
<!-- The name of the target path, group or vector drawable -->
|
||||
<attr name="name"/>
|
||||
<!-- The animation for the target path, group or vector drawable -->
|
||||
<attr name="animation" format="reference"/>
|
||||
</declare-styleable>
|
||||
|
||||
<!-- ========================== -->
|
||||
<!-- ValueAnimator class attributes -->
|
||||
<!-- ========================== -->
|
||||
<eat-comment />
|
||||
|
||||
<declare-styleable name="Animator">
|
||||
<!-- Defines the interpolator used to smooth the animation movement in time. -->
|
||||
<attr name="interpolator" format="reference"/>
|
||||
<!-- Amount of time (in milliseconds) for the animation to run. -->
|
||||
<attr name="duration" format="integer"/>
|
||||
<!-- Delay in milliseconds before the animation runs, once start time is reached. -->
|
||||
<attr name="startOffset" format="integer"/>
|
||||
<!-- Defines how many times the animation should repeat. The default value is 0. -->
|
||||
<attr name="repeatCount" format="integer">
|
||||
<enum name="infinite" value="-1"/>
|
||||
</attr>
|
||||
<!-- Defines the animation behavior when it reaches the end and the repeat count is
|
||||
greater than 0 or infinite. The default value is restart. -->
|
||||
<attr name="repeatMode">
|
||||
<!-- The animation starts again from the beginning. -->
|
||||
<enum name="restart" value="1" />
|
||||
<!-- The animation plays backward. -->
|
||||
<enum name="reverse" value="2" />
|
||||
</attr>
|
||||
<!-- Value the animation starts from. -->
|
||||
<attr name="valueFrom" format="float|integer|color|dimension|string"/>
|
||||
<!-- Value the animation animates to. -->
|
||||
<attr name="valueTo" format="float|integer|color|dimension|string"/>
|
||||
<!-- The type of valueFrom and valueTo. -->
|
||||
<attr name="valueType">
|
||||
<!-- valueFrom and valueTo are floats. This is the default value is valueType is
|
||||
unspecified. Note that if either valueFrom or valueTo represent colors
|
||||
(beginning with "#"), then this attribute is ignored and the color values are
|
||||
interpreted as integers. -->
|
||||
<enum name="floatType" value="0" />
|
||||
<!-- valueFrom and valueTo are integers. -->
|
||||
<enum name="intType" value="1" />
|
||||
<!-- valueFrom and valueTo are paths defined as strings.
|
||||
This type is used for path morphing in AnimatedVectorDrawable. -->
|
||||
<enum name="pathType" value="2" />
|
||||
</attr>
|
||||
</declare-styleable>
|
||||
|
||||
<!-- ========================== -->
|
||||
<!-- ObjectAnimator class attributes -->
|
||||
<!-- ========================== -->
|
||||
<eat-comment />
|
||||
|
||||
<declare-styleable name="PropertyAnimator">
|
||||
<!-- Name of the property being animated. -->
|
||||
<attr name="propertyName" format="string"/>
|
||||
<!-- Name of the property being animated as the X coordinate of the pathData. -->
|
||||
<attr name="propertyXName" format="string"/>
|
||||
<!-- Name of the property being animated as the Y coordinate of the pathData. -->
|
||||
<attr name="propertyYName" format="string"/>
|
||||
<!-- The path used to animate the properties in the ObjectAnimator -->
|
||||
<attr name="pathData"/>
|
||||
</declare-styleable>
|
||||
|
||||
|
||||
<!-- ========================== -->
|
||||
<!-- AnimatorSet class attributes -->
|
||||
<!-- ========================== -->
|
||||
<eat-comment />
|
||||
|
||||
<declare-styleable name="AnimatorSet">
|
||||
<!-- Name of the property being animated. -->
|
||||
<attr name="ordering">
|
||||
<!-- child animations should be played together. -->
|
||||
<enum name="together" value="0" />
|
||||
<!-- child animations should be played sequentially, in the same order as the xml. -->
|
||||
<enum name="sequentially" value="1" />
|
||||
</attr>
|
||||
</declare-styleable>
|
||||
|
||||
<!-- ========================== -->
|
||||
<!-- PathInterpolator attributes -->
|
||||
<!-- ========================== -->
|
||||
<eat-comment />
|
||||
|
||||
<declare-styleable name="PathInterpolator">
|
||||
<!-- The x coordinate of the first control point of the cubic Bezier -->
|
||||
<attr name="controlX1" format="float" />
|
||||
<!-- The y coordinate of the first control point of the cubic Bezier -->
|
||||
<attr name="controlY1" format="float" />
|
||||
<!-- The x coordinate of the second control point of the cubic Bezier -->
|
||||
<attr name="controlX2" format="float" />
|
||||
<!-- The y coordinate of the second control point of the cubic Bezier -->
|
||||
<attr name="controlY2" format="float" />
|
||||
<!-- The control points defined as a path.
|
||||
When pathData is defined, then both of the control points of the
|
||||
cubic Bezier will be ignored. -->
|
||||
<attr name="pathData"/>
|
||||
</declare-styleable>
|
||||
|
||||
</resources>
|
||||
+1
-1
@@ -5,7 +5,7 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:1.3.0-beta2'
|
||||
classpath 'com.android.tools.build:gradle:1.3.1'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
include ':app'
|
||||
include ':app', ':vector'
|
||||
@@ -0,0 +1 @@
|
||||
/build
|
||||
@@ -0,0 +1,24 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion "23.0.1"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 23
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile 'com.android.support:support-v4:22.2.1'
|
||||
}
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in E:\Android\android-sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.hippo.vector;
|
||||
|
||||
import android.app.Application;
|
||||
import android.test.ApplicationTestCase;
|
||||
|
||||
/**
|
||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||
*/
|
||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||
public ApplicationTest() {
|
||||
super(Application.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<manifest package="com.hippo.vector">
|
||||
|
||||
<application>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
+69
-31
@@ -1,18 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.vectorold.util;
|
||||
package com.hippo.vector;
|
||||
|
||||
import android.graphics.Path;
|
||||
import android.util.Log;
|
||||
@@ -20,9 +22,6 @@ import android.util.Log;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public class PathParser {
|
||||
static final String LOGTAG = PathParser.class.getSimpleName();
|
||||
|
||||
@@ -34,7 +33,11 @@ public class PathParser {
|
||||
Path path = new Path();
|
||||
PathDataNode[] nodes = createNodesFromPathData(pathData);
|
||||
if (nodes != null) {
|
||||
PathDataNode.nodesToPath(nodes, path);
|
||||
try {
|
||||
PathDataNode.nodesToPath(nodes, path);
|
||||
} catch (RuntimeException e) {
|
||||
throw new RuntimeException("Error in parsing " + pathData, e);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
return null;
|
||||
@@ -128,7 +131,12 @@ public class PathParser {
|
||||
|
||||
while (end < s.length()) {
|
||||
c = s.charAt(end);
|
||||
if (((c - 'A') * (c - 'Z') <= 0) || (((c - 'a') * (c - 'z') <= 0))) {
|
||||
// Note that 'e' or 'E' are not valid path commands, but could be
|
||||
// used for floating point numbers' scientific notation.
|
||||
// Therefore, when searching for next command, we should ignore 'e'
|
||||
// and 'E'.
|
||||
if ((((c - 'A') * (c - 'Z') <= 0) || ((c - 'a') * (c - 'z') <= 0))
|
||||
&& c != 'e' && c != 'E') {
|
||||
return end;
|
||||
}
|
||||
end++;
|
||||
@@ -142,9 +150,9 @@ public class PathParser {
|
||||
|
||||
private static class ExtractFloatResult {
|
||||
// We need to return the position of the next separator and whether the
|
||||
// next float starts with a '-'.
|
||||
// next float starts with a '-' or a '.'.
|
||||
int mEndPosition;
|
||||
boolean mEndWithNegSign;
|
||||
boolean mEndWithNegOrDot;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,7 +163,7 @@ public class PathParser {
|
||||
* @return array of floats
|
||||
*/
|
||||
private static float[] getFloats(String s) {
|
||||
if (s.charAt(0) == 'z' | s.charAt(0) == 'Z') {
|
||||
if (s.charAt(0) == 'z' || s.charAt(0) == 'Z') {
|
||||
return new float[0];
|
||||
}
|
||||
try {
|
||||
@@ -179,8 +187,8 @@ public class PathParser {
|
||||
s.substring(startPosition, endPosition));
|
||||
}
|
||||
|
||||
if (result.mEndWithNegSign) {
|
||||
// Keep the '-' sign with next number.
|
||||
if (result.mEndWithNegOrDot) {
|
||||
// Keep the '-' or '.' sign with next number.
|
||||
startPosition = endPosition;
|
||||
} else {
|
||||
startPosition = endPosition + 1;
|
||||
@@ -188,8 +196,7 @@ public class PathParser {
|
||||
}
|
||||
return Arrays.copyOf(results, count);
|
||||
} catch (NumberFormatException e) {
|
||||
Log.e(LOGTAG, "error in parsing \"" + s + "\"");
|
||||
throw e;
|
||||
throw new RuntimeException("error in parsing \"" + s + "\"", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,11 +208,15 @@ public class PathParser {
|
||||
* the starting position of next number, whether it is ending with a '-'.
|
||||
*/
|
||||
private static void extract(String s, int start, ExtractFloatResult result) {
|
||||
// Now looking for ' ', ',' or '-' from the start.
|
||||
// Now looking for ' ', ',', '.' or '-' from the start.
|
||||
int currentIndex = start;
|
||||
boolean foundSeparator = false;
|
||||
result.mEndWithNegSign = false;
|
||||
result.mEndWithNegOrDot = false;
|
||||
boolean secondDot = false;
|
||||
boolean isExponential = false;
|
||||
for (; currentIndex < s.length(); currentIndex++) {
|
||||
boolean isPrevExponential = isExponential;
|
||||
isExponential = false;
|
||||
char currentChar = s.charAt(currentIndex);
|
||||
switch (currentChar) {
|
||||
case ' ':
|
||||
@@ -213,11 +224,25 @@ public class PathParser {
|
||||
foundSeparator = true;
|
||||
break;
|
||||
case '-':
|
||||
if (currentIndex != start) {
|
||||
// The negative sign following a 'e' or 'E' is not a separator.
|
||||
if (currentIndex != start && !isPrevExponential) {
|
||||
foundSeparator = true;
|
||||
result.mEndWithNegSign = true;
|
||||
result.mEndWithNegOrDot = true;
|
||||
}
|
||||
break;
|
||||
case '.':
|
||||
if (!secondDot) {
|
||||
secondDot = true;
|
||||
} else {
|
||||
// This is the second dot, and it is considered as a separator.
|
||||
foundSeparator = true;
|
||||
result.mEndWithNegOrDot = true;
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
case 'E':
|
||||
isExponential = true;
|
||||
break;
|
||||
}
|
||||
if (foundSeparator) {
|
||||
break;
|
||||
@@ -254,7 +279,7 @@ public class PathParser {
|
||||
* @param path The target Path object.
|
||||
*/
|
||||
public static void nodesToPath(PathDataNode[] node, Path path) {
|
||||
float[] current = new float[4];
|
||||
float[] current = new float[6];
|
||||
char previousCommand = 'm';
|
||||
for (int i = 0; i < node.length; i++) {
|
||||
addCommand(path, current, previousCommand, node[i].mType, node[i].mParams);
|
||||
@@ -287,6 +312,8 @@ public class PathParser {
|
||||
float currentY = current[1];
|
||||
float ctrlPointX = current[2];
|
||||
float ctrlPointY = current[3];
|
||||
float currentSegmentStartX = current[4];
|
||||
float currentSegmentStartY = current[5];
|
||||
float reflectiveCtrlPointX;
|
||||
float reflectiveCtrlPointY;
|
||||
|
||||
@@ -294,7 +321,15 @@ public class PathParser {
|
||||
case 'z':
|
||||
case 'Z':
|
||||
path.close();
|
||||
return;
|
||||
// Path is closed here, but we need to move the pen to the
|
||||
// closed position. So we cache the segment's starting position,
|
||||
// and restore it here.
|
||||
currentX = currentSegmentStartX;
|
||||
currentY = currentSegmentStartY;
|
||||
ctrlPointX = currentSegmentStartX;
|
||||
ctrlPointY = currentSegmentStartY;
|
||||
path.moveTo(currentX, currentY);
|
||||
break;
|
||||
case 'm':
|
||||
case 'M':
|
||||
case 'l':
|
||||
@@ -324,17 +359,22 @@ public class PathParser {
|
||||
incr = 7;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int k = 0; k < val.length; k += incr) {
|
||||
switch (cmd) {
|
||||
case 'm': // moveto - Start a new sub-path (relative)
|
||||
path.rMoveTo(val[k + 0], val[k + 1]);
|
||||
currentX += val[k + 0];
|
||||
currentY += val[k + 1];
|
||||
currentSegmentStartX = currentX;
|
||||
currentSegmentStartY = currentY;
|
||||
break;
|
||||
case 'M': // moveto - Start a new sub-path
|
||||
path.moveTo(val[k + 0], val[k + 1]);
|
||||
currentX = val[k + 0];
|
||||
currentY = val[k + 1];
|
||||
currentSegmentStartX = currentX;
|
||||
currentSegmentStartY = currentY;
|
||||
break;
|
||||
case 'l': // lineto - Draw a line from the current point (relative)
|
||||
path.rLineTo(val[k + 0], val[k + 1]);
|
||||
@@ -346,10 +386,6 @@ public class PathParser {
|
||||
currentX = val[k + 0];
|
||||
currentY = val[k + 1];
|
||||
break;
|
||||
case 'z': // closepath - Close the current subpath
|
||||
case 'Z': // closepath - Close the current subpath
|
||||
path.close();
|
||||
break;
|
||||
case 'h': // horizontal lineto - Draws a horizontal line (relative)
|
||||
path.rLineTo(val[k + 0], 0);
|
||||
currentX += val[k + 0];
|
||||
@@ -500,6 +536,8 @@ public class PathParser {
|
||||
current[1] = currentY;
|
||||
current[2] = ctrlPointX;
|
||||
current[3] = ctrlPointY;
|
||||
current[4] = currentSegmentStartX;
|
||||
current[5] = currentSegmentStartY;
|
||||
}
|
||||
|
||||
private static void drawArc(Path p,
|
||||
+6
-9
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Hippo Seven
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.vectorold.util;
|
||||
package com.hippo.vector;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Color;
|
||||
@@ -22,17 +22,14 @@ import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
public class DrawableUtils {
|
||||
|
||||
public static final PorterDuff.Mode DEFAULT_TINT_MODE = PorterDuff.Mode.SRC_IN;
|
||||
public class Utils {
|
||||
|
||||
/**
|
||||
* Ensures the tint filter is consistent with the current tint color and
|
||||
* mode.
|
||||
*/
|
||||
public static PorterDuffColorFilter updateTintFilter(Drawable drawable,
|
||||
PorterDuffColorFilter tintFilter, ColorStateList tint,
|
||||
PorterDuff.Mode tintMode) {
|
||||
public static PorterDuffColorFilter updateTintFilter(Drawable drawable, PorterDuffColorFilter tintFilter,
|
||||
ColorStateList tint, PorterDuff.Mode tintMode) {
|
||||
if (tint == null || tintMode == null) {
|
||||
return null;
|
||||
}
|
||||
+257
-101
@@ -1,19 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
* Copyright 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.vectorold.drawable;
|
||||
package com.hippo.vector;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
@@ -29,6 +32,7 @@ import android.graphics.PixelFormat;
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Region;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.annotation.NonNull;
|
||||
@@ -37,10 +41,6 @@ import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.Xml;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.vectorold.util.DrawableUtils;
|
||||
import com.hippo.vectorold.util.PathParser;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
@@ -183,6 +183,8 @@ import java.util.Stack;
|
||||
public class VectorDrawable extends Drawable {
|
||||
private static final String LOGTAG = VectorDrawable.class.getSimpleName();
|
||||
|
||||
private static final Mode DEFAULT_TINT_MODE = Mode.SRC_IN;
|
||||
|
||||
private static final String SHAPE_CLIP_PATH = "clip-path";
|
||||
private static final String SHAPE_GROUP = "group";
|
||||
private static final String SHAPE_PATH = "path";
|
||||
@@ -213,9 +215,9 @@ public class VectorDrawable extends Drawable {
|
||||
mVectorState = new VectorDrawableState();
|
||||
}
|
||||
|
||||
private VectorDrawable(@NonNull VectorDrawableState state, Resources res) {
|
||||
private VectorDrawable(@NonNull VectorDrawableState state) {
|
||||
mVectorState = state;
|
||||
mTintFilter = DrawableUtils.updateTintFilter(this, mTintFilter, state.mTint, state.mTintMode);
|
||||
mTintFilter = Utils.updateTintFilter(this, mTintFilter, state.mTint, state.mTintMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -227,7 +229,7 @@ public class VectorDrawable extends Drawable {
|
||||
return this;
|
||||
}
|
||||
|
||||
Object getTargetByName(String name) {
|
||||
public Object getTargetByName(String name) {
|
||||
return mVectorState.mVPathRenderer.mVGTargetsMap.get(name);
|
||||
}
|
||||
|
||||
@@ -238,7 +240,7 @@ public class VectorDrawable extends Drawable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
public void draw(@NonNull Canvas canvas) {
|
||||
final Rect bounds = getBounds();
|
||||
if (bounds.width() == 0 || bounds.height() == 0) {
|
||||
// too small to draw
|
||||
@@ -246,13 +248,8 @@ public class VectorDrawable extends Drawable {
|
||||
}
|
||||
|
||||
final int saveCount = canvas.save();
|
||||
final boolean needMirroring = needMirroring();
|
||||
|
||||
canvas.translate(bounds.left, bounds.top);
|
||||
if (needMirroring) {
|
||||
canvas.translate(bounds.width(), 0);
|
||||
canvas.scale(-1.0f, 1.0f);
|
||||
}
|
||||
|
||||
// Color filters always override tint filters.
|
||||
final ColorFilter colorFilter = mColorFilter == null ? mTintFilter : mColorFilter;
|
||||
@@ -304,17 +301,17 @@ public class VectorDrawable extends Drawable {
|
||||
final VectorDrawableState state = mVectorState;
|
||||
if (state.mTint != tint) {
|
||||
state.mTint = tint;
|
||||
mTintFilter = DrawableUtils.updateTintFilter(this, mTintFilter, tint, state.mTintMode);
|
||||
mTintFilter = Utils.updateTintFilter(this, mTintFilter, tint, state.mTintMode);
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTintMode(Mode tintMode) {
|
||||
public void setTintMode(@NonNull Mode tintMode) {
|
||||
final VectorDrawableState state = mVectorState;
|
||||
if (state.mTintMode != tintMode) {
|
||||
state.mTintMode = tintMode;
|
||||
mTintFilter = DrawableUtils.updateTintFilter(this, mTintFilter, state.mTint, tintMode);
|
||||
mTintFilter = Utils.updateTintFilter(this, mTintFilter, state.mTint, tintMode);
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
@@ -329,7 +326,7 @@ public class VectorDrawable extends Drawable {
|
||||
protected boolean onStateChange(int[] stateSet) {
|
||||
final VectorDrawableState state = mVectorState;
|
||||
if (state.mTint != null && state.mTintMode != null) {
|
||||
mTintFilter = DrawableUtils.updateTintFilter(this, mTintFilter, state.mTint, state.mTintMode);
|
||||
mTintFilter = Utils.updateTintFilter(this, mTintFilter, state.mTint, state.mTintMode);
|
||||
invalidateSelf();
|
||||
return true;
|
||||
}
|
||||
@@ -372,10 +369,9 @@ public class VectorDrawable extends Drawable {
|
||||
return Math.min(scaleX, scaleY);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static VectorDrawable create(Resources resources, int rid) {
|
||||
public static VectorDrawable create(Context context, int rid) {
|
||||
try {
|
||||
final XmlPullParser parser = resources.getXml(rid);
|
||||
final XmlPullParser parser = context.getResources().getXml(rid);
|
||||
final AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||
int type;
|
||||
while ((type=parser.next()) != XmlPullParser.START_TAG &&
|
||||
@@ -386,16 +382,20 @@ public class VectorDrawable extends Drawable {
|
||||
throw new XmlPullParserException("No start tag found");
|
||||
}
|
||||
|
||||
final String name = parser.getName();
|
||||
if (!"vector".equals(name)) {
|
||||
throw new IllegalStateException("It is not vector");
|
||||
}
|
||||
|
||||
final VectorDrawable drawable = new VectorDrawable();
|
||||
drawable.inflate(resources, parser, attrs);
|
||||
drawable.inflate(context, parser, attrs);
|
||||
|
||||
return drawable;
|
||||
} catch (XmlPullParserException e) {
|
||||
Log.e(LOGTAG, "parser error", e);
|
||||
throw new IllegalStateException("parser error", e);
|
||||
} catch (IOException e) {
|
||||
Log.e(LOGTAG, "parser error", e);
|
||||
throw new IllegalStateException("parser error", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int applyAlpha(int color, float alpha) {
|
||||
@@ -405,21 +405,19 @@ public class VectorDrawable extends Drawable {
|
||||
return color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs)
|
||||
public void inflate(Context context, XmlPullParser parser, AttributeSet attrs)
|
||||
throws XmlPullParserException, IOException {
|
||||
final VectorDrawableState state = mVectorState;
|
||||
final VPathRenderer pathRenderer = new VPathRenderer();
|
||||
state.mVPathRenderer = pathRenderer;
|
||||
state.mVPathRenderer = new VPathRenderer();
|
||||
|
||||
final TypedArray a = res.obtainAttributes(attrs, R.styleable.VectorDrawable);
|
||||
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.VectorDrawable);
|
||||
updateStateFromTypedArray(a);
|
||||
a.recycle();
|
||||
|
||||
state.mCacheDirty = true;
|
||||
inflateInternal(res, parser, attrs);
|
||||
inflateInternal(context, parser, attrs);
|
||||
|
||||
mTintFilter = DrawableUtils.updateTintFilter(this, mTintFilter, state.mTint, state.mTintMode);
|
||||
mTintFilter = Utils.updateTintFilter(this, mTintFilter, state.mTint, state.mTintMode);
|
||||
}
|
||||
|
||||
private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException {
|
||||
@@ -431,7 +429,7 @@ public class VectorDrawable extends Drawable {
|
||||
|
||||
final int tintMode = a.getInt(R.styleable.VectorDrawable_tintMode, -1);
|
||||
if (tintMode != -1) {
|
||||
state.mTintMode = DrawableUtils.parseTintMode(tintMode, Mode.SRC_IN);
|
||||
state.mTintMode = Utils.parseTintMode(tintMode, Mode.SRC_IN);
|
||||
}
|
||||
|
||||
final ColorStateList tint = a.getColorStateList(R.styleable.VectorDrawable_tint);
|
||||
@@ -439,8 +437,7 @@ public class VectorDrawable extends Drawable {
|
||||
state.mTint = tint;
|
||||
}
|
||||
|
||||
state.mAutoMirrored = a.getBoolean(
|
||||
R.styleable.VectorDrawable_autoMirrored, state.mAutoMirrored);
|
||||
setAllowCaching(a.getBoolean(R.styleable.VectorDrawable_allowCaching, true));
|
||||
|
||||
pathRenderer.mViewportWidth = a.getFloat(
|
||||
R.styleable.VectorDrawable_viewportWidth, pathRenderer.mViewportWidth);
|
||||
@@ -479,7 +476,7 @@ public class VectorDrawable extends Drawable {
|
||||
}
|
||||
}
|
||||
|
||||
private void inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs)
|
||||
private void inflateInternal(Context context, XmlPullParser parser, AttributeSet attrs)
|
||||
throws XmlPullParserException, IOException {
|
||||
final VectorDrawableState state = mVectorState;
|
||||
final VPathRenderer pathRenderer = state.mVPathRenderer;
|
||||
@@ -498,7 +495,7 @@ public class VectorDrawable extends Drawable {
|
||||
|
||||
if (SHAPE_PATH.equals(tagName)) {
|
||||
final VFullPath path = new VFullPath();
|
||||
path.inflate(res, attrs);
|
||||
path.inflate(context, attrs);
|
||||
currentGroup.mChildren.add(path);
|
||||
if (path.getPathName() != null) {
|
||||
pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
|
||||
@@ -507,7 +504,7 @@ public class VectorDrawable extends Drawable {
|
||||
state.mChangingConfigurations |= path.mChangingConfigurations;
|
||||
} else if (SHAPE_CLIP_PATH.equals(tagName)) {
|
||||
final VClipPath path = new VClipPath();
|
||||
path.inflate(res, attrs);
|
||||
path.inflate(context, attrs);
|
||||
currentGroup.mChildren.add(path);
|
||||
if (path.getPathName() != null) {
|
||||
pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
|
||||
@@ -515,7 +512,7 @@ public class VectorDrawable extends Drawable {
|
||||
state.mChangingConfigurations |= path.mChangingConfigurations;
|
||||
} else if (SHAPE_GROUP.equals(tagName)) {
|
||||
VGroup newChildGroup = new VGroup();
|
||||
newChildGroup.inflate(res, attrs);
|
||||
newChildGroup.inflate(context, attrs);
|
||||
currentGroup.mChildren.add(newChildGroup);
|
||||
groupStack.push(newChildGroup);
|
||||
if (newChildGroup.getGroupName() != null) {
|
||||
@@ -573,39 +570,20 @@ public class VectorDrawable extends Drawable {
|
||||
return super.getChangingConfigurations() | mVectorState.mChangingConfigurations;
|
||||
}
|
||||
|
||||
void setAllowCaching(boolean allowCaching) {
|
||||
public void setAllowCaching(boolean allowCaching) {
|
||||
mAllowCaching = allowCaching;
|
||||
}
|
||||
|
||||
private boolean needMirroring() {
|
||||
return isAutoMirrored();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAutoMirrored(boolean mirrored) {
|
||||
if (mVectorState.mAutoMirrored != mirrored) {
|
||||
mVectorState.mAutoMirrored = mirrored;
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAutoMirrored() {
|
||||
return mVectorState.mAutoMirrored;
|
||||
}
|
||||
|
||||
private static class VectorDrawableState extends ConstantState {
|
||||
int mChangingConfigurations;
|
||||
VPathRenderer mVPathRenderer;
|
||||
ColorStateList mTint = null;
|
||||
Mode mTintMode = DrawableUtils.DEFAULT_TINT_MODE;
|
||||
boolean mAutoMirrored;
|
||||
Mode mTintMode = DEFAULT_TINT_MODE;
|
||||
|
||||
Bitmap mCachedBitmap;
|
||||
ColorStateList mCachedTint;
|
||||
Mode mCachedTintMode;
|
||||
int mCachedRootAlpha;
|
||||
boolean mCachedAutoMirrored;
|
||||
boolean mCacheDirty;
|
||||
|
||||
/** Temporary paint object used to draw cached bitmaps. */
|
||||
@@ -624,7 +602,6 @@ public class VectorDrawable extends Drawable {
|
||||
}
|
||||
mTint = copy.mTint;
|
||||
mTintMode = copy.mTintMode;
|
||||
mAutoMirrored = copy.mAutoMirrored;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -683,7 +660,6 @@ public class VectorDrawable extends Drawable {
|
||||
if (!mCacheDirty
|
||||
&& mCachedTint == mTint
|
||||
&& mCachedTintMode == mTintMode
|
||||
&& mCachedAutoMirrored == mAutoMirrored
|
||||
&& mCachedRootAlpha == mVPathRenderer.getRootAlpha()) {
|
||||
return true;
|
||||
}
|
||||
@@ -696,7 +672,6 @@ public class VectorDrawable extends Drawable {
|
||||
mCachedTint = mTint;
|
||||
mCachedTintMode = mTintMode;
|
||||
mCachedRootAlpha = mVPathRenderer.getRootAlpha();
|
||||
mCachedAutoMirrored = mAutoMirrored;
|
||||
mCacheDirty = false;
|
||||
}
|
||||
|
||||
@@ -704,14 +679,16 @@ public class VectorDrawable extends Drawable {
|
||||
mVPathRenderer = new VPathRenderer();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Drawable newDrawable() {
|
||||
return new VectorDrawable(this, null);
|
||||
return new VectorDrawable(this);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Drawable newDrawable(Resources res) {
|
||||
return new VectorDrawable(this, res);
|
||||
return new VectorDrawable(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -737,7 +714,6 @@ public class VectorDrawable extends Drawable {
|
||||
// is no need for deep copying.
|
||||
private final Path mPath;
|
||||
private final Path mRenderPath;
|
||||
private static final Matrix IDENTITY_MATRIX = new Matrix();
|
||||
private final Matrix mFinalPathMatrix = new Matrix();
|
||||
|
||||
private Paint mStrokePaint;
|
||||
@@ -755,7 +731,7 @@ public class VectorDrawable extends Drawable {
|
||||
int mRootAlpha = 0xFF;
|
||||
String mRootName = null;
|
||||
|
||||
final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<String, Object>();
|
||||
final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<>();
|
||||
|
||||
public VPathRenderer() {
|
||||
mRootGroup = new VGroup();
|
||||
@@ -915,7 +891,7 @@ public class VectorDrawable extends Drawable {
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Variables below need to be copied (deep copy if applicable) for mutation.
|
||||
final ArrayList<Object> mChildren = new ArrayList<Object>();
|
||||
final ArrayList<Object> mChildren = new ArrayList<>();
|
||||
|
||||
private float mRotate = 0;
|
||||
private float mPivotX = 0;
|
||||
@@ -954,7 +930,7 @@ public class VectorDrawable extends Drawable {
|
||||
VGroup copyGroup = (VGroup) copyChild;
|
||||
mChildren.add(new VGroup(copyGroup, targetsMap));
|
||||
} else {
|
||||
VPath newPath = null;
|
||||
VPath newPath;
|
||||
if (copyChild instanceof VFullPath) {
|
||||
newPath = new VFullPath((VFullPath) copyChild);
|
||||
} else if (copyChild instanceof VClipPath) {
|
||||
@@ -981,8 +957,8 @@ public class VectorDrawable extends Drawable {
|
||||
return mLocalMatrix;
|
||||
}
|
||||
|
||||
public void inflate(Resources res, AttributeSet attrs) {
|
||||
final TypedArray a = res.obtainAttributes(attrs,
|
||||
public void inflate(Context context, AttributeSet attrs) {
|
||||
final TypedArray a = context.obtainStyledAttributes(attrs,
|
||||
R.styleable.VectorDrawableGroup);
|
||||
updateStateFromTypedArray(a);
|
||||
a.recycle();
|
||||
@@ -1173,8 +1149,8 @@ public class VectorDrawable extends Drawable {
|
||||
super(copy);
|
||||
}
|
||||
|
||||
public void inflate(Resources r, AttributeSet attrs) {
|
||||
final TypedArray a = r.obtainAttributes(attrs,
|
||||
public void inflate(Context context, AttributeSet attrs) {
|
||||
final TypedArray a = context.obtainStyledAttributes(attrs,
|
||||
R.styleable.VectorDrawableClipPath);
|
||||
updateStateFromTypedArray(a);
|
||||
a.recycle();
|
||||
@@ -1204,7 +1180,7 @@ public class VectorDrawable extends Drawable {
|
||||
/**
|
||||
* Normal path, which contains all the fill / paint information.
|
||||
*/
|
||||
private static class VFullPath extends VPath {
|
||||
public static class VFullPath extends VPath {
|
||||
/////////////////////////////////////////////////////
|
||||
// Variables below need to be copied (deep copy if applicable) for mutation.
|
||||
int mStrokeColor = Color.TRANSPARENT;
|
||||
@@ -1228,7 +1204,6 @@ public class VectorDrawable extends Drawable {
|
||||
|
||||
public VFullPath(VFullPath copy) {
|
||||
super(copy);
|
||||
|
||||
mStrokeColor = copy.mStrokeColor;
|
||||
mStrokeWidth = copy.mStrokeWidth;
|
||||
mStrokeAlpha = copy.mStrokeAlpha;
|
||||
@@ -1270,8 +1245,8 @@ public class VectorDrawable extends Drawable {
|
||||
}
|
||||
}
|
||||
|
||||
public void inflate(Resources r, AttributeSet attrs) {
|
||||
final TypedArray a = r.obtainAttributes(attrs,
|
||||
public void inflate(Context context, AttributeSet attrs) {
|
||||
final TypedArray a = context.obtainStyledAttributes(attrs,
|
||||
R.styleable.VectorDrawablePath);
|
||||
updateStateFromTypedArray(a);
|
||||
a.recycle();
|
||||
@@ -1317,83 +1292,264 @@ public class VectorDrawable extends Drawable {
|
||||
|
||||
/* Setters and Getters, used by animator from AnimatedVectorDrawable. */
|
||||
@SuppressWarnings("unused")
|
||||
int getStrokeColor() {
|
||||
public int getStrokeColor() {
|
||||
return mStrokeColor;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
void setStrokeColor(int strokeColor) {
|
||||
public void setStrokeColor(int strokeColor) {
|
||||
mStrokeColor = strokeColor;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
float getStrokeWidth() {
|
||||
public float getStrokeWidth() {
|
||||
return mStrokeWidth;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
void setStrokeWidth(float strokeWidth) {
|
||||
public void setStrokeWidth(float strokeWidth) {
|
||||
mStrokeWidth = strokeWidth;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
float getStrokeAlpha() {
|
||||
public float getStrokeAlpha() {
|
||||
return mStrokeAlpha;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
void setStrokeAlpha(float strokeAlpha) {
|
||||
public void setStrokeAlpha(float strokeAlpha) {
|
||||
mStrokeAlpha = strokeAlpha;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
int getFillColor() {
|
||||
public int getFillColor() {
|
||||
return mFillColor;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
void setFillColor(int fillColor) {
|
||||
public void setFillColor(int fillColor) {
|
||||
mFillColor = fillColor;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
float getFillAlpha() {
|
||||
public float getFillAlpha() {
|
||||
return mFillAlpha;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
void setFillAlpha(float fillAlpha) {
|
||||
public void setFillAlpha(float fillAlpha) {
|
||||
mFillAlpha = fillAlpha;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
float getTrimPathStart() {
|
||||
public float getTrimPathStart() {
|
||||
return mTrimPathStart;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
void setTrimPathStart(float trimPathStart) {
|
||||
public void setTrimPathStart(float trimPathStart) {
|
||||
mTrimPathStart = trimPathStart;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
float getTrimPathEnd() {
|
||||
public float getTrimPathEnd() {
|
||||
return mTrimPathEnd;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
void setTrimPathEnd(float trimPathEnd) {
|
||||
public void setTrimPathEnd(float trimPathEnd) {
|
||||
mTrimPathEnd = trimPathEnd;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
float getTrimPathOffset() {
|
||||
public float getTrimPathOffset() {
|
||||
return mTrimPathOffset;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
void setTrimPathOffset(float trimPathOffset) {
|
||||
public void setTrimPathOffset(float trimPathOffset) {
|
||||
mTrimPathOffset = trimPathOffset;
|
||||
}
|
||||
}
|
||||
|
||||
public final static Matrix IDENTITY_MATRIX = new Matrix() {
|
||||
void oops() {
|
||||
throw new IllegalStateException("Matrix can not be modified");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(Matrix src) {
|
||||
oops();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
oops();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTranslate(float dx, float dy) {
|
||||
oops();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScale(float sx, float sy, float px, float py) {
|
||||
oops();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScale(float sx, float sy) {
|
||||
oops();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRotate(float degrees, float px, float py) {
|
||||
oops();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRotate(float degrees) {
|
||||
oops();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSinCos(float sinValue, float cosValue, float px, float py) {
|
||||
oops();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSinCos(float sinValue, float cosValue) {
|
||||
oops();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkew(float kx, float ky, float px, float py) {
|
||||
oops();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkew(float kx, float ky) {
|
||||
oops();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setConcat(@NonNull Matrix a, @NonNull Matrix b) {
|
||||
oops();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preTranslate(float dx, float dy) {
|
||||
oops();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preScale(float sx, float sy, float px, float py) {
|
||||
oops();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preScale(float sx, float sy) {
|
||||
oops();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preRotate(float degrees, float px, float py) {
|
||||
oops();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preRotate(float degrees) {
|
||||
oops();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preSkew(float kx, float ky, float px, float py) {
|
||||
oops();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preSkew(float kx, float ky) {
|
||||
oops();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preConcat(@NonNull Matrix other) {
|
||||
oops();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean postTranslate(float dx, float dy) {
|
||||
oops();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean postScale(float sx, float sy, float px, float py) {
|
||||
oops();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean postScale(float sx, float sy) {
|
||||
oops();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean postRotate(float degrees, float px, float py) {
|
||||
oops();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean postRotate(float degrees) {
|
||||
oops();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean postSkew(float kx, float ky, float px, float py) {
|
||||
oops();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean postSkew(float kx, float ky) {
|
||||
oops();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean postConcat(@NonNull Matrix other) {
|
||||
oops();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setRectToRect(@NonNull RectF src, @NonNull RectF dst, @NonNull ScaleToFit stf) {
|
||||
oops();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setPolyToPoly(@NonNull float[] src, int srcIndex, @NonNull float[] dst, int dstIndex,
|
||||
int pointCount) {
|
||||
oops();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValues(@NonNull float[] values) {
|
||||
oops();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright 2015 Hippo Seven
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<attr name="height"/>
|
||||
|
||||
<!-- ========================== -->
|
||||
<!-- VectorDrawable class -->
|
||||
<!-- ========================== -->
|
||||
<eat-comment/>
|
||||
|
||||
<!-- Drawable used to draw vector paths. -->
|
||||
<declare-styleable name="VectorDrawable">
|
||||
<!-- If set, specifies the color to apply to the drawable as a tint. By default,
|
||||
no tint is applied. May be a color state list. -->
|
||||
<attr name="tint" format="color"/>
|
||||
<!-- When a tint color is set, specifies its Porter-Duff blending mode. The
|
||||
default value is src_in, which treats the drawable as an alpha mask. -->
|
||||
<attr name="tintMode">
|
||||
<!-- The tint is drawn on top of the drawable.
|
||||
[Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] -->
|
||||
<enum name="src_over" value="3" />
|
||||
<!-- The tint is masked by the alpha channel of the drawable. The drawable’s
|
||||
color channels are thrown out. [Sa * Da, Sc * Da] -->
|
||||
<enum name="src_in" value="5" />
|
||||
<!-- The tint is drawn above the drawable, but with the drawable’s alpha
|
||||
channel masking the result. [Da, Sc * Da + (1 - Sa) * Dc] -->
|
||||
<enum name="src_atop" value="9" />
|
||||
<!-- Multiplies the color and alpha channels of the drawable with those of
|
||||
the tint. [Sa * Da, Sc * Dc] -->
|
||||
<enum name="multiply" value="14" />
|
||||
<!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -->
|
||||
<enum name="screen" value="15" />
|
||||
<!-- Combines the tint and drawable color and alpha channels, clamping the
|
||||
result to valid color values. Saturate(S + D) -->
|
||||
<enum name="add" value="16" />
|
||||
</attr>
|
||||
<!-- The intrinsic width of the Vector Drawable. -->
|
||||
<attr name="width" format="dimension"/>
|
||||
<!-- The intrinsic height of the Vector Drawable. -->
|
||||
<attr name="height"/>
|
||||
<!-- The width of the canvas the drawing is on. -->
|
||||
<attr name="viewportWidth" format="float"/>
|
||||
<!-- The height of the canvas the drawing is on. -->
|
||||
<attr name="viewportHeight" format="float"/>
|
||||
<!-- The name of this vector drawable -->
|
||||
<attr name="name" format="string"/>
|
||||
<!-- The opacity of the whole vector drawable, as a value between 0
|
||||
(completely transparent) and 1 (completely opaque). -->
|
||||
<attr name="alpha" format="float"/>
|
||||
|
||||
<attr name="allowCaching" format="boolean"/>
|
||||
</declare-styleable>
|
||||
|
||||
<!-- Defines the group used in VectorDrawables. -->
|
||||
<declare-styleable name="VectorDrawableGroup">
|
||||
<!-- The name of this group -->
|
||||
<attr name="name"/>
|
||||
<!-- The amount to rotate the group -->
|
||||
<attr name="rotation" format="float"/>
|
||||
<!-- The X coordinate of the center of rotation of a group -->
|
||||
<attr name="pivotX" format="float|fraction"/>
|
||||
<!-- The Y coordinate of the center of rotation of a group -->
|
||||
<attr name="pivotY" format="float|fraction"/>
|
||||
<!-- The amount to translate the group on X coordinate -->
|
||||
<attr name="translateX" format="float"/>
|
||||
<!-- The amount to translate the group on Y coordinate -->
|
||||
<attr name="translateY" format="float"/>
|
||||
<!-- The amount to scale the group on X coordinate -->
|
||||
<attr name="scaleX" format="float"/>
|
||||
<!-- The amount to scale the group on X coordinate -->
|
||||
<attr name="scaleY" format="float"/>
|
||||
</declare-styleable>
|
||||
|
||||
<!-- Defines the path used in VectorDrawables. -->
|
||||
<declare-styleable name="VectorDrawablePath">
|
||||
<!-- The name of this path -->
|
||||
<attr name="name"/>
|
||||
<!-- The width a path stroke -->
|
||||
<attr name="strokeWidth" format="float"/>
|
||||
<!-- The color to stroke the path if not defined implies no stroke-->
|
||||
<attr name="strokeColor" format="color"/>
|
||||
<!-- The opacity of a path stroke, as a value between 0 (completely transparent)
|
||||
and 1 (completely opaque) -->
|
||||
<attr name="strokeAlpha" format="float"/>
|
||||
<!-- The color to fill the path if not defined implies no fill-->
|
||||
<attr name="fillColor" format="color"/>
|
||||
<!-- The alpha of the path fill, as a value between 0 (completely transparent)
|
||||
and 1 (completely opaque)-->
|
||||
<attr name="fillAlpha" format="float"/>
|
||||
<!-- The specification of the operations that define the path -->
|
||||
<attr name="pathData" format="string"/>
|
||||
<!-- The fraction of the path to trim from the start from 0 to 1 -->
|
||||
<attr name="trimPathStart" format="float"/>
|
||||
<!-- The fraction of the path to trim from the end from 0 to 1 -->
|
||||
<attr name="trimPathEnd" format="float"/>
|
||||
<!-- Shift trim region (allows visible region to include the start and end) from 0 to 1 -->
|
||||
<attr name="trimPathOffset" format="float"/>
|
||||
<!-- sets the linecap for a stroked path -->
|
||||
<attr name="strokeLineCap" format="enum">
|
||||
<enum name="butt" value="0"/>
|
||||
<enum name="round" value="1"/>
|
||||
<enum name="square" value="2"/>
|
||||
</attr>
|
||||
<!-- sets the lineJoin for a stroked path -->
|
||||
<attr name="strokeLineJoin" format="enum">
|
||||
<enum name="miter" value="0"/>
|
||||
<enum name="round" value="1"/>
|
||||
<enum name="bevel" value="2"/>
|
||||
</attr>
|
||||
<!-- sets the Miter limit for a stroked path -->
|
||||
<attr name="strokeMiterLimit" format="float"/>
|
||||
</declare-styleable>
|
||||
|
||||
<!-- Defines the clip path used in VectorDrawables. -->
|
||||
<declare-styleable name="VectorDrawableClipPath">
|
||||
<!-- The Name of this path -->
|
||||
<attr name="name"/>
|
||||
<!-- The specification of the operations that define the path -->
|
||||
<attr name="pathData"/>
|
||||
</declare-styleable>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.hippo.vector;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* To work on unit tests, switch the Test Artifact in the Build Variants view.
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() throws Exception {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.id=":vector" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="EhViewer" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="android-gradle" name="Android-Gradle">
|
||||
<configuration>
|
||||
<option name="GRADLE_PROJECT_PATH" value=":vector" />
|
||||
</configuration>
|
||||
</facet>
|
||||
<facet type="android" name="Android">
|
||||
<configuration>
|
||||
<option name="SELECTED_BUILD_VARIANT" value="debug" />
|
||||
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
|
||||
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
|
||||
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
|
||||
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
|
||||
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
|
||||
<afterSyncTasks>
|
||||
<task>generateDebugAndroidTestSources</task>
|
||||
<task>generateDebugSources</task>
|
||||
</afterSyncTasks>
|
||||
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
||||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
|
||||
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
|
||||
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
|
||||
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
|
||||
<option name="LIBRARY_PROJECT" value="true" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
|
||||
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
|
||||
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" exported="" name="support-v4-22.2.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="support-annotations-22.2.1" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
Reference in new issue
Block a user