├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── jaouan │ │ └── viewsfrom │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── jaouan │ │ │ └── viewsfrom │ │ │ └── example │ │ │ └── ExampleActivity.java │ └── res │ │ ├── anim │ │ └── fadein.xml │ │ ├── layout │ │ └── activity_example.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── jaouan │ └── viewsfrom │ └── ExampleUnitTest.java ├── art └── demo.gif ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── viewsfrom ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src ├── androidTest └── java │ └── com │ └── jaouan │ └── viewsfrom │ └── ViewsTest.java ├── main ├── AndroidManifest.xml ├── java │ └── com │ │ └── jaouan │ │ └── viewsfrom │ │ ├── AnimationProvider.java │ │ ├── FunctionUtils.java │ │ ├── ViewIteration.java │ │ ├── Views.java │ │ ├── ViewsAnimator.java │ │ ├── ViewsFinder.java │ │ ├── ViewsHelper.java │ │ └── filters │ │ ├── AbstractEqualsViewFilter.java │ │ ├── AbstractRegexViewFilter.java │ │ ├── AggregatedViewFilters.java │ │ ├── ComplementedViewFilter.java │ │ ├── ExcluderViewFilter.java │ │ ├── FilterHelper.java │ │ ├── IdViewFilter.java │ │ ├── TagRegexViewFilter.java │ │ ├── TagViewFilter.java │ │ ├── TypeViewFilter.java │ │ ├── ViewFilter.java │ │ └── VisibilityViewFilter.java └── res │ └── values │ └── strings.xml └── test └── java └── com └── jaouan └── viewsfrom └── ExampleUnitTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Android ViewsFrom 2 | ======== 3 | [![Release](https://jitpack.io/v/Jaouan/ViewsFrom.svg)](https://jitpack.io/#Jaouan/ViewsFrom) [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-ViewsFrom-green.svg?style=true)](https://android-arsenal.com/details/1/4040) [![API](https://img.shields.io/badge/API-14%2B-brightgreen.svg?style=flat)](https://android-arsenal.com/api?level=14) 4 | 5 | ViewsFrom is an android librarie that allows you to easily find and animate child views from one or multiple ViewGroups using their tag, type, visibility and much more. 6 | This librairie is Android 14+ compatible. 7 | 8 | ![demo](art/demo.gif) 9 | 10 | Installation 11 | -------- 12 | Gradle 13 | 14 | ```java 15 | repositories { 16 | maven { url "https://jitpack.io" } 17 | } 18 | ``` 19 | 20 | ```java 21 | compile 'com.github.jaouan:viewsfrom:1.0.0' 22 | ``` 23 | 24 | Usage 25 | -------- 26 | Use **Views** class as entry point, and let the librarie guides you. 27 | 28 | First example : Animate all visible views from rootView. 29 | ```java 30 | Views.from(rootView) 31 | .withVisibility(View.VISIBLE) 32 | .animateWith(context, R.anim.my_awesome_animation) 33 | .start(); 34 | ``` 35 | 36 | Second example : Show all EditText with tags "example" from two group views. 37 | ```java 38 | Views.from(myFirstLinearLayout, mySecondLinearLayout) 39 | .withType(EditText.class) 40 | .withTag("example") 41 | .forEach((view, index, count) -> { 42 | view.setVisibility(View.VISIBLE); 43 | }); 44 | ``` 45 | 46 | A bit more complete example that shows what you can do : 47 | ```java 48 | // Defines root views of your views finder. 49 | Views.from(groupView1 /*, groupView2, ...*/) 50 | 51 | // Basics filters. 52 | .withTag("abc" /*, "efg", ...*/) 53 | .withTagRegex("[a-z]*" /*, "anotherRegex", ...*/) 54 | .withId(R.id.my_wonderful_id, /*, R.id.my_another_id, ...*/) 55 | .withType(TextView.class /*, EditText.class, ...*/) 56 | .withVisibility(View.GONE /*, View.INVISIBLE, ...*/) 57 | 58 | // Negate "with*" filters by prefixing with "not" method. 59 | not().withId(R.id.one_more_id /*, R.id.gimme_more_id*/) 60 | 61 | // Custom filter. 62 | .filteredWith((view) -> { 63 | return /* your own filter */; 64 | }) 65 | 66 | // Exclude views. 67 | .excludeView(myView1 /*, myViews2, ... */) 68 | 69 | // Options. 70 | .includingFromViews() 71 | .excludingChildsFromFilteredGroupViews() 72 | 73 | // Concate with a new views finder, with its own filters and options. 74 | .andFrom(group2) 75 | .withTag("xyz") 76 | 77 | // Order views. 78 | .orderedBy((view1, view2) -> { 79 | return /* your own comparator */; 80 | } 81 | 82 | // And animate them all ! 83 | .animateWith(context, R.anim.my_awesome_animation) 84 | .withDelayBetweenEachChild(250) 85 | .withViewsVisibilityBeforeAnimation(View.INVISIBLE) 86 | .withEndAction(() -> { 87 | Log.i("ViewsFromLibExample", "It's finally over."); 88 | }) 89 | .start(); 90 | ``` 91 | 92 | 93 | You have 3 end points : **Find**, **iterate** and **animate**. 94 | 95 | ###### Find 96 | Returns a views list. 97 | ```java 98 | Views.from(groupView) 99 | .find(); 100 | ``` 101 | 102 | 103 | ###### Iterate 104 | Iterates all views. 105 | ```java 106 | Views.from(groupView) 107 | .forEach((view, index, count) -> {}); 108 | ``` 109 | 110 | ###### Animate 111 | ```java 112 | Views.from(groupView) 113 | .animateWith(() -> { 114 | return /* your animation instance */; 115 | }) 116 | // or 117 | // .animateWith(context, R.anim.my_awesome_animation) 118 | .withDelayBetweenEachChild(250) 119 | .withViewsVisibilityBeforeAnimation(View.INVISIBLE) 120 | .withEndAction(() -> {}) 121 | .start(); 122 | ``` 123 | 124 | Views animator 125 | -------- 126 | If you know which views has to be animated, you can still use **ViewsAnimator** as below : 127 | ```java 128 | new ViewsAnimator(context, viewsIWantToAnimate, R.anim.my_smooth_animation) 129 | .withDelayBetweenEachChild(250) 130 | .withViewsVisibilityBeforeAnimation(View.INVISIBLE) 131 | .withEndAction(() -> {}) 132 | .start(); 133 | ``` 134 | 135 | ViewsAnimator's **start()** method can be called multiple times if you want. 136 | ```java 137 | // First call. 138 | ViewsAnimator viewsAnimator = Views.from(groupView) 139 | .animateWith(context, R.anim.my_awesome_animation) 140 | .start(); 141 | 142 | // Second call. 143 | myButton.setOnClickListener((view) -> { 144 | viewsAnimator.start(); 145 | }); 146 | ``` 147 | 148 | Note 149 | -------- 150 | Be aware that when an end point is called, every child views are iterated in order to find which satisfies filters. 151 | If your layout is very complex, prefer using multiple little group views instead of one big root view. 152 | 153 | 154 | License 155 | ======== 156 | 157 | [Apache License Version 2.0](LICENSE) 158 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.2" 6 | 7 | defaultConfig { 8 | applicationId "com.jaouan.viewsfrom.example" 9 | minSdkVersion 14 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:23.4.0' 26 | compile project(':viewsfrom') 27 | } 28 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\Maxence\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/jaouan/viewsfrom/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/jaouan/viewsfrom/example/ExampleActivity.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom.example; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.util.Log; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.Toast; 9 | 10 | import com.jaouan.viewsfrom.ViewIteration; 11 | import com.jaouan.viewsfrom.Views; 12 | 13 | import java.util.List; 14 | 15 | public class ExampleActivity extends AppCompatActivity { 16 | 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity_example); 21 | 22 | final ViewGroup group1 = (ViewGroup) findViewById(R.id.group1); 23 | final ViewGroup group2 = (ViewGroup) findViewById(R.id.group2); 24 | 25 | // List views. 26 | List views = Views.from(group1) 27 | .includingFromViews() 28 | .find(); 29 | Toast.makeText(this, "Count : " + views.size(), Toast.LENGTH_LONG).show(); 30 | 31 | // Iterate views. 32 | Views.from(group1) 33 | .includingFromViews() 34 | .andFrom(group2) 35 | .forEach(new ViewIteration() { 36 | @Override 37 | public void onView(final View view, final int viewIndex, final int viewsCount) { 38 | Log.i("ViewsFromLibExample", (viewIndex + 1) + " of " + viewsCount + " : " + view.getClass().getSimpleName()); 39 | } 40 | }); 41 | 42 | // Animate views. 43 | Views.from(group1, group2) 44 | .withVisibility(View.VISIBLE) 45 | .includingFromViews() 46 | .animateWith(ExampleActivity.this, R.anim.fadein) 47 | .withDelayBetweenEachChild(250) 48 | .withViewsVisibilityBeforeAnimation(View.INVISIBLE) 49 | .withEndAction(new Runnable() { 50 | @Override 51 | public void run() { 52 | Log.i("ViewsFromLibExample", "It's finally over."); 53 | } 54 | }) 55 | .start(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/res/anim/fadein.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_example.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 21 | 22 | 27 | 28 | 33 | 34 | 39 | 40 | 45 | 46 | 51 | 52 | 53 | 54 | 61 | 62 | 67 | 68 | 73 | 74 | 79 | 80 | 85 | 86 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jaouan/ViewsFrom/6ed412683908157b973b7d5c881db47c8819a72d/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jaouan/ViewsFrom/6ed412683908157b973b7d5c881db47c8819a72d/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jaouan/ViewsFrom/6ed412683908157b973b7d5c881db47c8819a72d/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jaouan/ViewsFrom/6ed412683908157b973b7d5c881db47c8819a72d/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jaouan/ViewsFrom/6ed412683908157b973b7d5c881db47c8819a72d/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ViewsFrom Librarie 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/com/jaouan/viewsfrom/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /art/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jaouan/ViewsFrom/6ed412683908157b973b7d5c881db47c8819a72d/art/demo.gif -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.1.2' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | 21 | task clean(type: Delete) { 22 | delete rootProject.buildDir 23 | } 24 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jaouan/ViewsFrom/6ed412683908157b973b7d5c881db47c8819a72d/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Dec 28 10:00:20 PST 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':viewsfrom' 2 | -------------------------------------------------------------------------------- /viewsfrom/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /viewsfrom/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.2" 6 | 7 | defaultConfig { 8 | minSdkVersion 14 9 | targetSdkVersion 23 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile fileTree(dir: 'libs', include: ['*.jar']) 23 | testCompile 'junit:junit:4.12' 24 | compile 'com.android.support:appcompat-v7:23.4.0' 25 | } 26 | -------------------------------------------------------------------------------- /viewsfrom/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\Maxence\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /viewsfrom/src/androidTest/java/com/jaouan/viewsfrom/ViewsTest.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | import android.test.suitebuilder.annotation.MediumTest; 6 | import android.test.suitebuilder.annotation.SmallTest; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.Button; 10 | import android.widget.EditText; 11 | import android.widget.FrameLayout; 12 | import android.widget.LinearLayout; 13 | import android.widget.TextView; 14 | 15 | import com.jaouan.viewsfrom.filters.ViewFilter; 16 | 17 | import java.util.Comparator; 18 | import java.util.List; 19 | 20 | /** 21 | * Tests {@link Views} 22 | */ 23 | public class ViewsTest extends ApplicationTestCase { 24 | 25 | /** 26 | * All views. 27 | * Views hierarchy : 28 | * RootView 29 | * |- textView1 (tag: textView_1) 30 | * |- viewGroup1 31 | * | |- textView2 (tag: textView_2) 32 | * | |- button1 (invisible) 33 | * |- viewGroup2 34 | * | |- button2 35 | * | |- viewGroup3 (gone) 36 | * | | |- button3 37 | */ 38 | private ViewGroup rootView; 39 | private ViewGroup viewGroup1; 40 | private ViewGroup viewGroup2; 41 | private ViewGroup viewGroup3; 42 | private View textView1; 43 | private View textView2; 44 | private View button1; 45 | private View button2; 46 | private View button3; 47 | 48 | public ViewsTest() { 49 | super(Application.class); 50 | } 51 | 52 | @Override 53 | protected void setUp() throws Exception { 54 | super.setUp(); 55 | generateView(); 56 | } 57 | 58 | /** 59 | * Assert views find. 60 | * 61 | * @param views Views find. 62 | * @param expectedViews Expected views. 63 | */ 64 | private void assertViews(final List views, final View... expectedViews) { 65 | assertEquals("It should have " + expectedViews.length + " views.", expectedViews.length, views.size()); 66 | 67 | for (int expectedViewsIndex = 0; expectedViewsIndex < expectedViews.length; expectedViewsIndex++) { 68 | final View expectedView = expectedViews[expectedViewsIndex]; 69 | assertTrue("It should contain " + expectedView.getClass().getSimpleName() + " at position " + expectedViewsIndex + ".", views.get(expectedViewsIndex) == expectedView); 70 | } 71 | } 72 | 73 | @SmallTest 74 | public void testListAllChildsFromRootView() { 75 | final List views = Views.from(rootView).find(); 76 | assertViews(views, textView1, viewGroup1, textView2, button1, viewGroup2, button2, viewGroup3, button3); 77 | } 78 | 79 | @SmallTest 80 | public void testListAllChildsFromRootViewIncludingRootView() { 81 | final List views = Views.from(rootView).includingFromViews().find(); 82 | assertViews(views, rootView, textView1, viewGroup1, textView2, button1, viewGroup2, button2, viewGroup3, button3); 83 | } 84 | 85 | @SmallTest 86 | public void testListAllChildsFromMultiplesViewGroups() { 87 | final List views = Views.from(viewGroup1, viewGroup2).find(); 88 | assertViews(views, textView2, button1, button2, viewGroup3, button3); 89 | } 90 | 91 | @SmallTest 92 | public void testListFromViewGroupAndFromAnotherViewGroup() { 93 | final List views = Views.from(viewGroup1).includingFromViews().andFrom(viewGroup2).find(); 94 | assertViews(views, viewGroup1, textView2, button1, button2, viewGroup3, button3); 95 | } 96 | 97 | @SmallTest 98 | public void testExcludeView() { 99 | final List views = Views.from(rootView).excludeView(button3).find(); 100 | assertViews(views, textView1, viewGroup1, textView2, button1, viewGroup2, button2, viewGroup3); 101 | } 102 | 103 | @SmallTest 104 | public void testExcludeChildsFromFilteredGroupView() { 105 | final List views = Views.from(rootView).excludeView(viewGroup3).excludingChildsFromFilteredGroupViews().find(); 106 | assertViews(views, textView1, viewGroup1, textView2, button1, viewGroup2, button2); 107 | } 108 | 109 | @SmallTest 110 | public void testFilter() { 111 | final List views = Views.from(rootView).filteredWith(new ViewFilter() { 112 | @Override 113 | public boolean filter(View view) { 114 | return view == button1; 115 | } 116 | }).find(); 117 | assertViews(views, button1); 118 | } 119 | 120 | @SmallTest 121 | public void testWithType() { 122 | final List views = Views.from(rootView).withType(TextView.class, EditText.class).find(); 123 | assertViews(views, textView1, textView2); 124 | } 125 | 126 | @SmallTest 127 | public void testWithId() { 128 | final List views = Views.from(rootView).withId(android.R.id.button1, android.R.id.text1).find(); 129 | assertViews(views, textView1, button1); 130 | } 131 | 132 | @SmallTest 133 | public void testWithTag() { 134 | final List views = Views.from(rootView).withTag("textView_1", "textView_2").find(); 135 | assertViews(views, textView1, textView2); 136 | } 137 | 138 | @SmallTest 139 | public void testWithTagRegex() { 140 | final List views = Views.from(rootView).withTagRegex("textView_[1-9]+", "abc").find(); 141 | assertViews(views, textView1, textView2); 142 | } 143 | 144 | @SmallTest 145 | public void testWithVisibility() { 146 | final List views = Views.from(rootView).withVisibility(View.GONE).find(); 147 | assertViews(views, viewGroup3); 148 | } 149 | 150 | @SmallTest 151 | public void testNot() { 152 | final List views = Views.from(rootView).not().withVisibility(View.GONE).find(); 153 | assertViews(views, textView1, viewGroup1, textView2, button1, viewGroup2, button2, button3); 154 | } 155 | 156 | @SmallTest 157 | public void testCheckParameterIsNotNull() { 158 | try { 159 | Views.from(null).find(); 160 | } catch(final IllegalArgumentException illegalArgumentException){ 161 | assertNotNull(illegalArgumentException.getMessage()); 162 | } 163 | } 164 | 165 | @SmallTest 166 | public void testOrderedBy() { 167 | final List views = Views.from(rootView) 168 | .withTag("textView_1", "textView_2") 169 | .orderedBy(new Comparator() { 170 | @Override 171 | public int compare(final View view1, final View view2) { 172 | return ((String) view2.getTag()).compareTo((String) view1.getTag()); 173 | } 174 | }) 175 | .find(); 176 | 177 | assertViews(views, textView2, textView1); 178 | } 179 | 180 | @MediumTest 181 | public void testMultipleFilters1() { 182 | final List views = Views.from(rootView) 183 | .includingFromViews() 184 | .not().withId(android.R.id.text1) 185 | .withVisibility(View.VISIBLE) 186 | .excludeView(viewGroup3) 187 | .excludingChildsFromFilteredGroupViews() 188 | .find(); 189 | 190 | assertViews(views, rootView, viewGroup1, textView2, viewGroup2, button2); 191 | } 192 | 193 | @MediumTest 194 | public void testMultipleFilters2() { 195 | final List views = Views.from(viewGroup1) 196 | .includingFromViews() 197 | .withVisibility(View.VISIBLE) 198 | .andFrom(viewGroup2) 199 | .withId(android.R.id.button2, android.R.id.button3) 200 | .excludeView(viewGroup3) 201 | .excludingChildsFromFilteredGroupViews() 202 | .find(); 203 | 204 | assertViews(views, viewGroup1, textView2, button2); 205 | } 206 | 207 | /** 208 | * Generate view. 209 | */ 210 | private void generateView() { 211 | rootView = new FrameLayout(getContext()); 212 | 213 | // TextView in rootView. 214 | textView1 = new TextView(getContext()); 215 | textView1.setId(android.R.id.text1); 216 | textView1.setTag("textView_1"); 217 | rootView.addView(textView1); 218 | 219 | // viewGroup1 in rootView. 220 | viewGroup1 = new LinearLayout(getContext()); 221 | rootView.addView(viewGroup1); 222 | 223 | // TextView in viewGroup1. 224 | textView2 = new TextView(getContext()); 225 | textView2.setId(android.R.id.text2); 226 | textView2.setTag("textView_2"); 227 | viewGroup1.addView(textView2); 228 | 229 | // Button in viewGroup1. 230 | button1 = new Button(getContext()); 231 | button1.setId(android.R.id.button1); 232 | button1.setVisibility(View.INVISIBLE); 233 | viewGroup1.addView(button1); 234 | 235 | // viewGroup2 in rootView. 236 | viewGroup2 = new LinearLayout(getContext()); 237 | rootView.addView(viewGroup2); 238 | 239 | // Button in viewGroup2. 240 | button2 = new Button(getContext()); 241 | button2.setId(android.R.id.button2); 242 | viewGroup2.addView(button2); 243 | 244 | // viewGroup3 in viewGroup2. 245 | viewGroup3 = new LinearLayout(getContext()); 246 | viewGroup3.setVisibility(View.GONE); 247 | viewGroup2.addView(viewGroup3); 248 | 249 | // Button in viewGroup3, in viewGroup2. 250 | button3 = new Button(getContext()); 251 | button3.setId(android.R.id.button3); 252 | viewGroup3.addView(button3); 253 | } 254 | 255 | } -------------------------------------------------------------------------------- /viewsfrom/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /viewsfrom/src/main/java/com/jaouan/viewsfrom/AnimationProvider.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom; 2 | 3 | import android.view.animation.Animation; 4 | 5 | /** 6 | * Animation provider. 7 | */ 8 | public interface AnimationProvider { 9 | 10 | /** 11 | * Provides a new animation instance. 12 | * @return New animation instance. 13 | */ 14 | Animation provide(); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /viewsfrom/src/main/java/com/jaouan/viewsfrom/FunctionUtils.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom; 2 | 3 | /** 4 | * Utils for function. 5 | */ 6 | final class FunctionUtils { 7 | 8 | 9 | /** 10 | * Private constructor to disallow instantiation. 11 | */ 12 | private FunctionUtils() { 13 | } 14 | 15 | /** 16 | * Checks that an array does not contain null reference. 17 | * 18 | * @param parameterName Parameter name. 19 | * @param parameterValues Parameter values. 20 | * @param Parameter type. 21 | */ 22 | static void checkParameterArrayIsNotNull(final String parameterName, final ParameterType[] parameterValues) { 23 | // - Check array. 24 | checkParameterIsNotNull(parameterName, parameterValues); 25 | 26 | // - Check array size. 27 | if (parameterValues.length == 0) { 28 | throw new IllegalArgumentException(parameterName + " cannot be empty."); 29 | } 30 | 31 | // - Check array values. 32 | for (final ParameterType parameterValue : parameterValues) { 33 | if (parameterValue == null) { 34 | throw new IllegalArgumentException(parameterName + " cannot contain null."); 35 | } 36 | } 37 | } 38 | 39 | /** 40 | * Checks that an array does not contain null reference. 41 | * 42 | * @param parameterName Parameter name. 43 | * @param parameterValues Parameter values. 44 | */ 45 | static void checkParameterArrayIsNotNull(final String parameterName, final int[] parameterValues) { 46 | // - Check array. 47 | checkParameterIsNotNull(parameterName, parameterValues); 48 | 49 | // - Check array size. 50 | if (parameterValues.length == 0) { 51 | throw new IllegalArgumentException(parameterName + " cannot be empty."); 52 | } 53 | } 54 | 55 | /** 56 | * Checks that a parameter is not null. 57 | * 58 | * @param parameterName Parameter name. 59 | * @param parameterValue Parameter value. 60 | */ 61 | static void checkParameterIsNotNull(final String parameterName, final Object parameterValue) { 62 | // - Check array. 63 | if (parameterValue == null) { 64 | throw new IllegalArgumentException(parameterName + " cannot be null."); 65 | } 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /viewsfrom/src/main/java/com/jaouan/viewsfrom/ViewIteration.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom; 2 | 3 | import android.view.View; 4 | 5 | /** 6 | * View iteration. 7 | */ 8 | public interface ViewIteration { 9 | 10 | /** 11 | * View iteration. 12 | * @param view Found view. 13 | * @param viewIndex View index in views find. 14 | * @param viewsCount Views find count. 15 | */ 16 | void onView(View view, int viewIndex, int viewsCount); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /viewsfrom/src/main/java/com/jaouan/viewsfrom/Views.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.view.ViewGroup; 5 | 6 | /** 7 | * Views librarie entry point. 8 | */ 9 | public final class Views { 10 | 11 | /** 12 | * Helps to find child views. 13 | * @param rootViews Root views. 14 | * @return Views finder. 15 | */ 16 | public static ViewsFinder from(@NonNull final ViewGroup... rootViews){ 17 | return new ViewsFinder(rootViews); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /viewsfrom/src/main/java/com/jaouan/viewsfrom/ViewsAnimator.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.AnimRes; 5 | import android.support.annotation.NonNull; 6 | import android.view.View; 7 | import android.view.animation.Animation; 8 | import android.view.animation.AnimationUtils; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * Views animator. 14 | */ 15 | public final class ViewsAnimator { 16 | 17 | /** 18 | * Context. 19 | */ 20 | private Context context; 21 | 22 | /** 23 | * Animation provider. 24 | * It provides by default the animation ressource id. 25 | */ 26 | private AnimationProvider animationProvider = new AnimationProvider() { 27 | @Override 28 | public Animation provide() { 29 | return AnimationUtils.loadAnimation(context, animResId); 30 | } 31 | }; 32 | 33 | /** 34 | * Views finder. (ignored if views list is defined) 35 | */ 36 | private ViewsFinder viewsFinder; 37 | 38 | /** 39 | * Views list. 40 | */ 41 | private List views; 42 | 43 | /** 44 | * Animation ressource id. 45 | */ 46 | private int animResId; 47 | 48 | 49 | /** 50 | * Delay between each child animation. 51 | */ 52 | private int delayBetweenEachChild; 53 | 54 | /** 55 | * End action. 56 | */ 57 | private Runnable endAction; 58 | 59 | 60 | /** 61 | * Views visibility before animation. NULL if nothing to change. 62 | */ 63 | private Integer viewsVisibilityBeforeAnimation; 64 | 65 | /** 66 | * ViewsAnimator's constructor. 67 | * 68 | * @param context Context. 69 | * @param viewsFinder Views finder. 70 | * @param animResId Animation ressource id. 71 | */ 72 | public ViewsAnimator(@NonNull final Context context, @NonNull final ViewsFinder viewsFinder, @AnimRes final int animResId) { 73 | FunctionUtils.checkParameterIsNotNull("context", context); 74 | FunctionUtils.checkParameterIsNotNull("viewsFinder", viewsFinder); 75 | this.context = context; 76 | this.viewsFinder = viewsFinder; 77 | this.animResId = animResId; 78 | } 79 | 80 | /** 81 | * ViewsAnimator's constructor. 82 | * 83 | * @param context Context. 84 | * @param views Views. 85 | * @param animResId Animation ressource id. 86 | */ 87 | public ViewsAnimator(@NonNull final Context context, @NonNull final List views, @AnimRes final int animResId) { 88 | FunctionUtils.checkParameterIsNotNull("context", context); 89 | FunctionUtils.checkParameterIsNotNull("views", views); 90 | this.context = context; 91 | this.views = views; 92 | this.animResId = animResId; 93 | } 94 | 95 | /** 96 | * ViewAnimator's constructor. 97 | * 98 | * @param viewsFinder Views finder. 99 | * @param animationProvider Animation provider. 100 | */ 101 | public ViewsAnimator(@NonNull final ViewsFinder viewsFinder, @NonNull final AnimationProvider animationProvider) { 102 | FunctionUtils.checkParameterIsNotNull("viewsFinder", viewsFinder); 103 | FunctionUtils.checkParameterIsNotNull("animationProvider", animationProvider); 104 | this.viewsFinder = viewsFinder; 105 | this.animationProvider = animationProvider; 106 | } 107 | 108 | /** 109 | * ViewAnimator's constructor. 110 | * 111 | * @param views Views list. 112 | * @param animationProvider Animation provider. 113 | */ 114 | public ViewsAnimator(@NonNull final List views, @NonNull final AnimationProvider animationProvider) { 115 | FunctionUtils.checkParameterIsNotNull("views", views); 116 | FunctionUtils.checkParameterIsNotNull("animationProvider", animationProvider); 117 | this.views = views; 118 | this.animationProvider = animationProvider; 119 | } 120 | 121 | 122 | /** 123 | * Defines delay between each child animation. 124 | * 125 | * @param delayBetweenEachChild Delay between each child animation. 126 | * @return Views animator. 127 | */ 128 | public ViewsAnimator withDelayBetweenEachChild(final int delayBetweenEachChild) { 129 | this.delayBetweenEachChild = delayBetweenEachChild; 130 | return this; 131 | } 132 | 133 | /** 134 | * Defines end action callback. 135 | * 136 | * @param endAction End action callback. 137 | * @return Views animator. 138 | */ 139 | public ViewsAnimator withEndAction(@NonNull final Runnable endAction) { 140 | FunctionUtils.checkParameterIsNotNull("endAction", endAction); 141 | this.endAction = endAction; 142 | return this; 143 | } 144 | 145 | /** 146 | * Defines if views visibility before animation. 147 | * 148 | * @param viewsVisibilityBeforeAnimation Views visibility before animation. 149 | * @return Views animator. 150 | */ 151 | public ViewsAnimator withViewsVisibilityBeforeAnimation(final int viewsVisibilityBeforeAnimation) { 152 | this.viewsVisibilityBeforeAnimation = viewsVisibilityBeforeAnimation; 153 | return this; 154 | } 155 | 156 | /** 157 | * Let's animate ! 158 | * @return Views animator for future animation. 159 | */ 160 | public ViewsAnimator start() { 161 | // - Find viewsToAnimate from viewsFinder if necessary. 162 | List viewsToAnimate = this.views; 163 | if (viewsToAnimate == null) { 164 | viewsToAnimate = viewsFinder.find(); 165 | } 166 | 167 | // - Update viewsToAnimate visibility before animation if necessary. 168 | if (viewsVisibilityBeforeAnimation != null) { 169 | for (final View view : viewsToAnimate) { 170 | view.setVisibility(viewsVisibilityBeforeAnimation); 171 | } 172 | } 173 | 174 | // - Animate all viewsToAnimate. 175 | Animation animation = null; 176 | for (int viewIndex = 0; viewIndex < viewsToAnimate.size(); viewIndex++) { 177 | animation = animationProvider.provide(); 178 | animation.setStartOffset(animation.getStartOffset() + delayBetweenEachChild * viewIndex); 179 | viewsToAnimate.get(viewIndex).startAnimation(animation); 180 | } 181 | 182 | // - Call end action on last animation end. 183 | if (animation != null) { 184 | animation.setAnimationListener(new Animation.AnimationListener() { 185 | @Override 186 | public void onAnimationEnd(Animation animation) { 187 | if (endAction != null) { 188 | endAction.run(); 189 | } 190 | } 191 | 192 | @Override 193 | public void onAnimationStart(Animation animation) { 194 | } 195 | 196 | @Override 197 | public void onAnimationRepeat(Animation animation) { 198 | } 199 | }); 200 | } 201 | 202 | return this; 203 | } 204 | 205 | } 206 | -------------------------------------------------------------------------------- /viewsfrom/src/main/java/com/jaouan/viewsfrom/ViewsFinder.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.AnimRes; 5 | import android.support.annotation.IdRes; 6 | import android.support.annotation.NonNull; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | 10 | import com.jaouan.viewsfrom.filters.AggregatedViewFilters; 11 | import com.jaouan.viewsfrom.filters.ComplementedViewFilter; 12 | import com.jaouan.viewsfrom.filters.ExcluderViewFilter; 13 | import com.jaouan.viewsfrom.filters.IdViewFilter; 14 | import com.jaouan.viewsfrom.filters.TagRegexViewFilter; 15 | import com.jaouan.viewsfrom.filters.TagViewFilter; 16 | import com.jaouan.viewsfrom.filters.TypeViewFilter; 17 | import com.jaouan.viewsfrom.filters.ViewFilter; 18 | import com.jaouan.viewsfrom.filters.VisibilityViewFilter; 19 | 20 | import java.util.ArrayList; 21 | import java.util.Collections; 22 | import java.util.Comparator; 23 | import java.util.List; 24 | 25 | /** 26 | * Views utils that helps to find views by id, tags, type, ... 27 | */ 28 | public final class ViewsFinder { 29 | 30 | /** 31 | * Root view. 32 | */ 33 | private ViewGroup[] rootViews; 34 | 35 | /** 36 | * Nested views finder when {@see andFrom} is used. 37 | */ 38 | private ViewsFinder nestedViewsFinder; 39 | 40 | /** 41 | * Including root view. 42 | */ 43 | 44 | /** 45 | * View filters. 46 | */ 47 | private List viewFilters = new ArrayList<>(); 48 | 49 | /** 50 | * Include root view to views find. 51 | */ 52 | private boolean includeRootView; 53 | 54 | /** 55 | * Complement next "with" filter. 56 | */ 57 | private boolean complementNextWithFilter; 58 | 59 | /** 60 | * View comparator. 61 | */ 62 | private Comparator viewComparator; 63 | 64 | /** 65 | * Add childs from filtered group views. 66 | */ 67 | private boolean addChildsFromFilteredGroupViews = true; 68 | 69 | /** 70 | * ViewsFinder's constructor. 71 | * 72 | * @param rootViews Root view. 73 | */ 74 | ViewsFinder(@NonNull final ViewGroup... rootViews) { 75 | FunctionUtils.checkParameterArrayIsNotNull("rootViews", rootViews); 76 | this.rootViews = rootViews; 77 | } 78 | 79 | 80 | /** 81 | * ViewsFinder's constructor with nested views finder. 82 | * 83 | * @param nestedViewsFinder Nested views finder. 84 | * @param rootViews Root view. 85 | */ 86 | private ViewsFinder(@NonNull ViewsFinder nestedViewsFinder, @NonNull final ViewGroup... rootViews) { 87 | this(rootViews); 88 | FunctionUtils.checkParameterIsNotNull("nestedViewsFinder", nestedViewsFinder); 89 | this.nestedViewsFinder = nestedViewsFinder; 90 | } 91 | 92 | /** 93 | * Specifies to include from views. 94 | * 95 | * @return View finder. 96 | */ 97 | public ViewsFinder includingFromViews() { 98 | this.includeRootView = true; 99 | return this; 100 | } 101 | 102 | /** 103 | * Specifies to exclude childs from filtered group views. 104 | * 105 | * @return View finder. 106 | */ 107 | public ViewsFinder excludingChildsFromFilteredGroupViews() { 108 | this.addChildsFromFilteredGroupViews = false; 109 | return this; 110 | } 111 | 112 | /** 113 | * Concates current views finder with a new one. 114 | * 115 | * @param rootViews Root views. 116 | * @return View finder. 117 | */ 118 | public ViewsFinder andFrom(final ViewGroup... rootViews) { 119 | FunctionUtils.checkParameterIsNotNull("rootViews", rootViews); 120 | return new ViewsFinder(this, rootViews); 121 | } 122 | 123 | /** 124 | * Finds and lists all found views. 125 | */ 126 | public List find() { 127 | final List views = new ArrayList<>(); 128 | 129 | // - Add all views from nested views finder. 130 | if (nestedViewsFinder != null) { 131 | views.addAll(nestedViewsFinder.find()); 132 | } 133 | 134 | // - For each root view. 135 | for (final ViewGroup rootView : rootViews) { 136 | // - Include root view to views find if necessary. 137 | if (includeRootView) { 138 | views.add(rootView); 139 | } 140 | // - Find all childs. 141 | ViewsHelper.findChilds(rootView, views, new AggregatedViewFilters(viewFilters), addChildsFromFilteredGroupViews); 142 | } 143 | 144 | // - Sort views if necessary. 145 | if (viewComparator != null) { 146 | Collections.sort(views, viewComparator); 147 | } 148 | 149 | return views; 150 | } 151 | 152 | /** 153 | * Iterates all found views. 154 | * 155 | * @param viewIteration View iteration. 156 | */ 157 | public void forEach(final ViewIteration viewIteration) { 158 | FunctionUtils.checkParameterIsNotNull("viewIteration", viewIteration); 159 | final List views = find(); 160 | final int viewCount = views.size(); 161 | for (int viewIndex = 0; viewIndex < viewCount; viewIndex++) { 162 | viewIteration.onView(views.get(viewIndex), viewIndex, viewCount); 163 | } 164 | } 165 | 166 | /** 167 | * Animates all found views. 168 | * 169 | * @param context Context. 170 | * @param animResId Animation ressource id. 171 | * @return Views animator. 172 | */ 173 | public ViewsAnimator animateWith(@NonNull final Context context, @AnimRes final int animResId) { 174 | FunctionUtils.checkParameterIsNotNull("context", context); 175 | return new ViewsAnimator(context, this, animResId); 176 | } 177 | 178 | /** 179 | * Animates all found views. 180 | * 181 | * @param animationProvider Animation provider. 182 | * @return Views animator. 183 | */ 184 | public ViewsAnimator animateWith(final AnimationProvider animationProvider) { 185 | FunctionUtils.checkParameterIsNotNull("animationProvider", animationProvider); 186 | return new ViewsAnimator(this, animationProvider); 187 | } 188 | 189 | /** 190 | * Orders views with specific comparator. 191 | * 192 | * @param viewComparator View comparator. 193 | * @return View finder. 194 | */ 195 | public ViewsFinder orderedBy(@NonNull final Comparator viewComparator) { 196 | FunctionUtils.checkParameterIsNotNull("viewComparator", viewComparator); 197 | this.viewComparator = viewComparator; 198 | return this; 199 | } 200 | 201 | /** 202 | * Filters views. 203 | * 204 | * @param viewFilter View filter. 205 | * @return View finder. 206 | */ 207 | public ViewsFinder filteredWith(@NonNull final ViewFilter viewFilter) { 208 | FunctionUtils.checkParameterIsNotNull("viewFilter", viewFilter); 209 | viewFilters.add(viewFilter); 210 | return this; 211 | } 212 | 213 | /** 214 | * Complements next "with" filter. Only works with "with*" method. 215 | * 216 | * @return View finder. 217 | */ 218 | public ViewsFinder not() { 219 | this.complementNextWithFilter = true; 220 | return this; 221 | } 222 | 223 | /** 224 | * Filters view's visibility. Can be used with {@see not}. 225 | * 226 | * @param viewVisibilities View's visibilites to allow. 227 | * @return View finder. 228 | */ 229 | public ViewsFinder withVisibility(final int... viewVisibilities) { 230 | FunctionUtils.checkParameterArrayIsNotNull("viewVisibilities", viewVisibilities); 231 | viewFilters.add(complementFilterIfNecessary(new VisibilityViewFilter(viewVisibilities))); 232 | return this; 233 | } 234 | 235 | /** 236 | * Filters view's tag. Can be used with {@see not}. 237 | * 238 | * @param tags View's tags to allow. 239 | * @return View finder. 240 | */ 241 | public ViewsFinder withTag(final String... tags) { 242 | FunctionUtils.checkParameterIsNotNull("tags", tags); 243 | viewFilters.add(complementFilterIfNecessary(new TagViewFilter(tags))); 244 | return this; 245 | } 246 | 247 | /** 248 | * Filters view's tag using regex. Can be used with {@see not}. 249 | * 250 | * @param tagRegexes View's tag regexes to allow. 251 | * @return View finder. 252 | */ 253 | public ViewsFinder withTagRegex(final String... tagRegexes) { 254 | FunctionUtils.checkParameterArrayIsNotNull("tagRegexes", tagRegexes); 255 | viewFilters.add(complementFilterIfNecessary(new TagRegexViewFilter(tagRegexes))); 256 | return this; 257 | } 258 | 259 | /** 260 | * Filters view's tag. Can be used with {@see not}. 261 | * 262 | * @param identifiers View's identifiers to allow. 263 | * @return View finder. 264 | */ 265 | public ViewsFinder withId(@IdRes final int... identifiers) { 266 | FunctionUtils.checkParameterArrayIsNotNull("identifiers", identifiers); 267 | viewFilters.add(complementFilterIfNecessary(new IdViewFilter(identifiers))); 268 | return this; 269 | } 270 | 271 | /** 272 | * Filters view's type. Can be used with {@see not}. 273 | * 274 | * @param types View's types to allow. 275 | * @return View finder. 276 | */ 277 | @SafeVarargs 278 | public final ViewsFinder withType(final Class... types) { 279 | FunctionUtils.checkParameterArrayIsNotNull("types", types); 280 | viewFilters.add(complementFilterIfNecessary(new TypeViewFilter(types))); 281 | return this; 282 | } 283 | 284 | /** 285 | * Complements filter if necessary. 286 | * 287 | * @param viewFilter View filter. 288 | * @return View filter. 289 | */ 290 | private ViewFilter complementFilterIfNecessary(final ViewFilter viewFilter) { 291 | FunctionUtils.checkParameterIsNotNull("viewFilter", viewFilter); 292 | if (complementNextWithFilter) { 293 | complementNextWithFilter = false; 294 | return new ComplementedViewFilter(viewFilter); 295 | } 296 | return viewFilter; 297 | } 298 | 299 | /** 300 | * Excludes views. 301 | * 302 | * @param views Views to exclude. 303 | * @return View finder. 304 | */ 305 | public ViewsFinder excludeView(final View... views) { 306 | FunctionUtils.checkParameterArrayIsNotNull("views", views); 307 | viewFilters.add(new ExcluderViewFilter(views)); 308 | return this; 309 | } 310 | 311 | } 312 | -------------------------------------------------------------------------------- /viewsfrom/src/main/java/com/jaouan/viewsfrom/ViewsHelper.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | 7 | import com.jaouan.viewsfrom.filters.ViewFilter; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * Views helper. 13 | */ 14 | final class ViewsHelper { 15 | 16 | /** 17 | * Private constructor to disallow instantiation. 18 | */ 19 | private ViewsHelper() { 20 | } 21 | 22 | /** 23 | * Helps to find recursivly all childs in a view group. 24 | * 25 | * @param viewGroup View group. 26 | * @param ordoredChilds Childs find where visible childs will be added. 27 | * @param viewFilter View filter. 28 | * @param addChildsFromFilteredGroupViews Add childs from filtered group views. 29 | * @return Childs find. 30 | */ 31 | static List findChilds(@NonNull final ViewGroup viewGroup, @NonNull final List ordoredChilds, @NonNull final ViewFilter viewFilter, final boolean addChildsFromFilteredGroupViews) { 32 | for (int childViewIndex = 0; childViewIndex < viewGroup.getChildCount(); childViewIndex++) { 33 | final View childView = viewGroup.getChildAt(childViewIndex); 34 | final boolean isNotFiltered = viewFilter.filter(childView); 35 | if (isNotFiltered) { 36 | ordoredChilds.add(childView); 37 | } 38 | if (childView instanceof ViewGroup && (isNotFiltered || addChildsFromFilteredGroupViews)) { 39 | findChilds((ViewGroup) childView, ordoredChilds, viewFilter, addChildsFromFilteredGroupViews); 40 | } 41 | } 42 | return ordoredChilds; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /viewsfrom/src/main/java/com/jaouan/viewsfrom/filters/AbstractEqualsViewFilter.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom.filters; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.view.View; 5 | 6 | /** 7 | * Abstract equals filter. 8 | */ 9 | public abstract class AbstractEqualsViewFilter implements ViewFilter { 10 | 11 | /** 12 | * Texts. 13 | */ 14 | private final TypeOfObject[] objects; 15 | 16 | /** 17 | * Text filter's contructor. 18 | * 19 | * @param objects Objects. 20 | */ 21 | public AbstractEqualsViewFilter(@NonNull final TypeOfObject[] objects) { 22 | this.objects = objects; 23 | } 24 | 25 | @Override 26 | public boolean filter(final View view) { 27 | return FilterHelper.arrayContains(objects, getObjectToMatch(view)); 28 | } 29 | 30 | /** 31 | * Get object to match. 32 | * 33 | * @param view View. 34 | * @return Object to match. 35 | */ 36 | protected abstract Object getObjectToMatch(View view); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /viewsfrom/src/main/java/com/jaouan/viewsfrom/filters/AbstractRegexViewFilter.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom.filters; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.view.View; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.regex.Pattern; 9 | 10 | /** 11 | * Abstract regex filter. 12 | */ 13 | public abstract class AbstractRegexViewFilter implements ViewFilter { 14 | 15 | /** 16 | * Regex patterns. 17 | */ 18 | private final List patterns; 19 | 20 | /** 21 | * Visibility filter's contructor. 22 | * 23 | * @param regexes View's regexes. 24 | */ 25 | public AbstractRegexViewFilter(@NonNull final String[] regexes) { 26 | patterns = new ArrayList<>(regexes.length); 27 | for (final String regex : regexes) { 28 | patterns.add(Pattern.compile(regex)); 29 | } 30 | } 31 | 32 | @Override 33 | public boolean filter(final View view) { 34 | final String textToMatch = getTextToMatch(view); 35 | if (textToMatch != null) { 36 | for (final Pattern pattern : patterns) { 37 | if (pattern.matcher(textToMatch).find()) { 38 | return true; 39 | } 40 | } 41 | } 42 | return false; 43 | } 44 | 45 | /** 46 | * Get text to match. 47 | * 48 | * @param view View. 49 | * @return Text to match. 50 | */ 51 | protected abstract String getTextToMatch(View view); 52 | 53 | } 54 | -------------------------------------------------------------------------------- /viewsfrom/src/main/java/com/jaouan/viewsfrom/filters/AggregatedViewFilters.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom.filters; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.view.View; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Global filter that aggregate multiples filters. 10 | */ 11 | public class AggregatedViewFilters implements ViewFilter { 12 | 13 | /** 14 | * View filters. 15 | */ 16 | private final List viewFilters; 17 | 18 | /** 19 | * AggregatedViewFilters's constructor. 20 | * 21 | * @param viewFilters View filter to onView. 22 | */ 23 | public AggregatedViewFilters(@NonNull final List viewFilters) { 24 | this.viewFilters = viewFilters; 25 | } 26 | 27 | @Override 28 | public boolean filter(final View view) { 29 | // - Apply all filters. 30 | for (final ViewFilter viewFilter : viewFilters) { 31 | if (!viewFilter.filter(view)) { 32 | return false; 33 | } 34 | } 35 | return true; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /viewsfrom/src/main/java/com/jaouan/viewsfrom/filters/ComplementedViewFilter.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom.filters; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.view.View; 5 | 6 | /** 7 | * Complemented view filter. 8 | */ 9 | public class ComplementedViewFilter implements ViewFilter { 10 | 11 | /** 12 | * View filter to complement. 13 | */ 14 | private final ViewFilter viewFilter; 15 | 16 | /** 17 | * Complemented view filter's constructor. 18 | * @param viewFilter View filter to complement. 19 | */ 20 | public ComplementedViewFilter(@NonNull final ViewFilter viewFilter) { 21 | this.viewFilter = viewFilter; 22 | } 23 | 24 | @Override 25 | public boolean filter(final View view) { 26 | return !viewFilter.filter(view); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /viewsfrom/src/main/java/com/jaouan/viewsfrom/filters/ExcluderViewFilter.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom.filters; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.view.View; 5 | 6 | /** 7 | * Excluder view filter. 8 | */ 9 | public class ExcluderViewFilter implements ViewFilter { 10 | 11 | /** 12 | * Views to exclude. 13 | */ 14 | private final View[] views; 15 | 16 | /** 17 | * Excluder view filter's constructor. 18 | * 19 | * @param views Views to exclude. 20 | */ 21 | public ExcluderViewFilter(@NonNull final View[] views) { 22 | this.views = views; 23 | } 24 | 25 | @Override 26 | public boolean filter(final View view) { 27 | return !FilterHelper.arrayContains(views, view); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /viewsfrom/src/main/java/com/jaouan/viewsfrom/filters/FilterHelper.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom.filters; 2 | 3 | /** 4 | * Filter helper. 5 | */ 6 | final class FilterHelper { 7 | 8 | /** 9 | * Private constructor to disallow instantiation. 10 | */ 11 | private FilterHelper() { 12 | } 13 | 14 | /** 15 | * Check if array contains a value. 16 | * 17 | * @param array Array. 18 | * @param value Value. 19 | * @return TRUE if array contains value. 20 | */ 21 | static boolean arrayContains(final TypeOfValue[] array, final TypeOfValue value) { 22 | for (final TypeOfValue arrayValue : array) { 23 | if (arrayValue == value || (arrayValue != null && arrayValue.equals(value))) { 24 | return true; 25 | } 26 | } 27 | return false; 28 | } 29 | 30 | /** 31 | * Check if array contains a value. 32 | * 33 | * @param array Array. 34 | * @param value Value. 35 | * @return TRUE if array contains value. 36 | */ 37 | static boolean arrayContains(final int[] array, final int value) { 38 | for (final int arrayValue : array) { 39 | if (arrayValue == value) { 40 | return true; 41 | } 42 | } 43 | 44 | return false; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /viewsfrom/src/main/java/com/jaouan/viewsfrom/filters/IdViewFilter.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom.filters; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.view.View; 5 | 6 | /** 7 | * Identifier filter. 8 | */ 9 | public class IdViewFilter implements ViewFilter { 10 | /** 11 | * View's identifiers. 12 | */ 13 | private final int[] viewIdentifiers; 14 | 15 | /** 16 | * Identifier filter's contructor. 17 | * 18 | * @param viewIdentifiers View's visibilities. 19 | */ 20 | public IdViewFilter(@NonNull final int[] viewIdentifiers) { 21 | this.viewIdentifiers = viewIdentifiers; 22 | } 23 | 24 | @Override 25 | public boolean filter(final View view) { 26 | return FilterHelper.arrayContains(viewIdentifiers, view.getId()); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /viewsfrom/src/main/java/com/jaouan/viewsfrom/filters/TagRegexViewFilter.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom.filters; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.view.View; 5 | 6 | /** 7 | * Tag regex filter. 8 | */ 9 | public class TagRegexViewFilter extends AbstractRegexViewFilter { 10 | 11 | /** 12 | * Tag regex filter's contructor. 13 | * 14 | * @param viewTagRegexes View's tags regexes. 15 | */ 16 | public TagRegexViewFilter(@NonNull final String[] viewTagRegexes) { 17 | super(viewTagRegexes); 18 | } 19 | 20 | @Override 21 | protected String getTextToMatch(final View view) { 22 | if (view.getTag() == null || !(view.getTag() instanceof String)) { 23 | return null; 24 | } 25 | return (String) view.getTag(); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /viewsfrom/src/main/java/com/jaouan/viewsfrom/filters/TagViewFilter.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom.filters; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.view.View; 5 | 6 | /** 7 | * Tag filter. 8 | */ 9 | public class TagViewFilter extends AbstractEqualsViewFilter { 10 | 11 | /** 12 | * Tag filter's contructor. 13 | * 14 | * @param viewTags View's tags. 15 | */ 16 | public TagViewFilter(@NonNull final String[] viewTags) { 17 | super(viewTags); 18 | } 19 | 20 | @Override 21 | protected Object getObjectToMatch(final View view) { 22 | return view.getTag(); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /viewsfrom/src/main/java/com/jaouan/viewsfrom/filters/TypeViewFilter.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom.filters; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.view.View; 5 | 6 | /** 7 | * Type filter. 8 | */ 9 | public class TypeViewFilter extends AbstractEqualsViewFilter> { 10 | 11 | /** 12 | * Type filter's contructor. 13 | * 14 | * @param viewTypes View's types. 15 | */ 16 | public TypeViewFilter(@NonNull Class[] viewTypes) { 17 | super(viewTypes); 18 | } 19 | 20 | @Override 21 | protected Object getObjectToMatch(final View view) { 22 | return view.getClass(); 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /viewsfrom/src/main/java/com/jaouan/viewsfrom/filters/ViewFilter.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom.filters; 2 | 3 | import android.view.View; 4 | 5 | 6 | /** 7 | * View filter. 8 | */ 9 | public interface ViewFilter { 10 | 11 | /** 12 | * Check if view satisfies the filter. 13 | * 14 | * @param view View. 15 | * @return TRUE if the view satisfies the filter and must be kept in find. 16 | */ 17 | boolean filter(View view); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /viewsfrom/src/main/java/com/jaouan/viewsfrom/filters/VisibilityViewFilter.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom.filters; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.view.View; 5 | 6 | /** 7 | * Visibility filter. 8 | */ 9 | public class VisibilityViewFilter implements ViewFilter { 10 | 11 | /** 12 | * View's visibilities. 13 | */ 14 | private final int[] viewVisibilities; 15 | 16 | /** 17 | * Visibility filter's contructor. 18 | * 19 | * @param viewVisibilities View's visibilities. 20 | */ 21 | public VisibilityViewFilter(@NonNull final int[] viewVisibilities) { 22 | this.viewVisibilities = viewVisibilities; 23 | } 24 | 25 | @Override 26 | public boolean filter(final View view) { 27 | return FilterHelper.arrayContains(viewVisibilities, view.getVisibility()); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /viewsfrom/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /viewsfrom/src/test/java/com/jaouan/viewsfrom/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.jaouan.viewsfrom; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } --------------------------------------------------------------------------------