Use Vector

This commit is contained in:
seven332 committed 2015-10-08 12:22:48 +08:00
1 parent e3134bbea1
commit aeb49f4bb6
38 files changed
+876 -2291

No files matched your search

+22 -23
View File
@@ -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>
+5 -5
View File
@@ -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>
+18 -17
View File
@@ -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
View File
@@ -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
View File
@@ -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>
+45 -32
View File
@@ -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>
+10 -10
View File
@@ -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>
+12
View File
@@ -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>
-5
View File
@@ -1,5 +0,0 @@
<component name="DependencyValidationManager">
<state>
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
</state>
</component>
Generated
+6 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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>
* &lt;vector xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
* android:height=&quot;64dp&quot;
* android:width=&quot;64dp&quot;
* android:viewportHeight=&quot;600&quot;
* android:viewportWidth=&quot;600&quot; &gt;
* &lt;group
* android:name=&quot;rotationGroup&quot;
* android:pivotX=&quot;300.0&quot;
* android:pivotY=&quot;300.0&quot;
* android:rotation=&quot;45.0&quot; &gt;
* &lt;path
* android:name=&quot;v&quot;
* android:fillColor=&quot;#000000&quot;
* android:pathData=&quot;M300,70 l 0,-70 70,70 0,0 -70,70z&quot; /&gt;
* &lt;/group&gt;
* &lt;/vector&gt;
* </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>
* &lt;animated-vector xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
* android:drawable=&quot;@drawable/vectordrawable&quot; &gt;
* &lt;target
* android:name=&quot;rotationGroup&quot;
* android:animation=&quot;@anim/rotation&quot; /&gt;
* &lt;target
* android:name=&quot;v&quot;
* android:animation=&quot;@anim/path_morph&quot; /&gt;
* &lt;/animated-vector&gt;
* </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>
* &lt;objectAnimator
* android:duration=&quot;6000&quot;
* android:propertyName=&quot;rotation&quot;
* android:valueFrom=&quot;0&quot;
* android:valueTo=&quot;360&quot; /&gt;
* </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>
* &lt;set xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;&gt;
* &lt;objectAnimator
* android:duration=&quot;3000&quot;
* android:propertyName=&quot;pathData&quot;
* android:valueFrom=&quot;M300,70 l 0,-70 70,70 0,0 -70,70z&quot;
* android:valueTo=&quot;M300,70 l 0,-70 70,0 0,140 -70,0 z&quot;
* android:valueType=&quot;pathType&quot;/&gt;
* &lt;/set&gt;
* </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;
}
*/
}
-240
View File
@@ -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
View File
@@ -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
View File
@@ -1 +1 @@
include ':app'
include ':app', ':vector'
+1
View File
@@ -0,0 +1 @@
/build
+24
View File
@@ -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'
}
+17
View File
@@ -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);
}
}
+7
View File
@@ -0,0 +1,7 @@
<manifest package="com.hippo.vector">
<application>
</application>
</manifest>
@@ -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,
@@ -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;
}
@@ -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();
}
};
}
+138
View File
@@ -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);
}
}
+95
View File
@@ -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>