├── app
├── .gitignore
├── src
│ └── main
│ │ ├── res
│ │ ├── values
│ │ │ ├── strings.xml
│ │ │ ├── dimens.xml
│ │ │ ├── arrays.xml
│ │ │ ├── colors.xml
│ │ │ └── styles.xml
│ │ ├── drawable
│ │ │ ├── image.png
│ │ │ └── ic_edit_black_24dp.xml
│ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ └── layout
│ │ │ ├── activity_sample.xml
│ │ │ └── fragment_bottom_sheet.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── vpaliy
│ │ └── chipview
│ │ ├── SampleActivity.java
│ │ └── BottomSheet.java
├── proguard-rules.pro
└── build.gradle
├── chips-lover
├── .gitignore
├── src
│ └── main
│ │ ├── res
│ │ ├── values
│ │ │ ├── strings.xml
│ │ │ ├── integers.xml
│ │ │ ├── ids.xml
│ │ │ ├── dimens.xml
│ │ │ ├── colors.xml
│ │ │ └── attrs.xml
│ │ └── drawable
│ │ │ └── ic_close.xml
│ │ ├── java
│ │ └── com
│ │ │ └── vpaliy
│ │ │ └── chips_lover
│ │ │ ├── OnEndIconEventClick.java
│ │ │ ├── OnFrontIconEventClick.java
│ │ │ ├── ChipBuilder.java
│ │ │ ├── ChipsLayout.java
│ │ │ └── ChipView.java
│ │ └── AndroidManifest.xml
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── .idea
├── copyright
│ └── profiles_settings.xml
├── modules.xml
├── runConfigurations.xml
├── gradle.xml
├── compiler.xml
└── misc.xml
├── art
├── ezgif.com-video-to-gif(8).gif
└── ezgif.com-video-to-gif(9).gif
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── gradle.properties
├── gradlew.bat
├── README.md
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/chips-lover/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':chips-lover'
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ChipView
3 |
4 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/art/ezgif.com-video-to-gif(8).gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vpaliy/android-chip/HEAD/art/ezgif.com-video-to-gif(8).gif
--------------------------------------------------------------------------------
/art/ezgif.com-video-to-gif(9).gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vpaliy/android-chip/HEAD/art/ezgif.com-video-to-gif(9).gif
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vpaliy/android-chip/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/drawable/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vpaliy/android-chip/HEAD/app/src/main/res/drawable/image.png
--------------------------------------------------------------------------------
/chips-lover/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | chips-lover
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vpaliy/android-chip/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vpaliy/android-chip/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vpaliy/android-chip/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vpaliy/android-chip/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vpaliy/android-chip/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vpaliy/android-chip/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vpaliy/android-chip/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vpaliy/android-chip/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vpaliy/android-chip/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vpaliy/android-chip/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/chips-lover/src/main/res/values/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 300
4 |
--------------------------------------------------------------------------------
/chips-lover/src/main/java/com/vpaliy/chips_lover/OnEndIconEventClick.java:
--------------------------------------------------------------------------------
1 | package com.vpaliy.chips_lover;
2 |
3 | import android.view.View;
4 |
5 | public interface OnEndIconEventClick {
6 | void onClick(View view);
7 | }
8 |
--------------------------------------------------------------------------------
/chips-lover/src/main/java/com/vpaliy/chips_lover/OnFrontIconEventClick.java:
--------------------------------------------------------------------------------
1 | package com.vpaliy.chips_lover;
2 |
3 |
4 | import android.view.View;
5 |
6 | public interface OnFrontIconEventClick {
7 | void onClick(View view);
8 | }
9 |
--------------------------------------------------------------------------------
/chips-lover/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Jun 17 19:40:08 EDT 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/chips-lover/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 8dp
4 | 5dp
5 | 16dp
6 | 400dp
7 |
8 | 8dp
9 | 16dp
10 |
--------------------------------------------------------------------------------
/chips-lover/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 32dp
4 | 32dp
5 | 24dp
6 | 12dp
7 | 8dp
8 | 4dp
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - Background
5 | - SelectedBackground
6 | - Text
7 | - SelectedText
8 | - FrontIconColor
9 | - RearIconColor
10 | - SelectedRearIconColor
11 | - SelectedFrontIconColor
12 |
13 |
--------------------------------------------------------------------------------
/chips-lover/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #e0e0e0
4 | #424242
5 | #F5F5F5
6 | #F5F5F5
7 | #424242
8 | #F5F5F5
9 | #757575
10 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_edit_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 | #FFF
8 | #565656
9 | #90A4AE
10 | #455a64
11 | #37474F
12 | #ff5722
13 |
14 |
--------------------------------------------------------------------------------
/chips-lover/src/main/res/drawable/ic_close.xml:
--------------------------------------------------------------------------------
1 |
6 |
11 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
13 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/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 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/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 /home/vpaliy/Android/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 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/chips-lover/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 /home/vpaliy/Android/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 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "25.0.2"
6 | defaultConfig {
7 | applicationId "com.vpaliy.chipview"
8 | minSdkVersion 14
9 | targetSdkVersion 25
10 | versionCode 1
11 | versionName "1.0"
12 | vectorDrawables.useSupportLibrary = true
13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
14 | }
15 | buildTypes {
16 | release {
17 | minifyEnabled false
18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19 | }
20 | }
21 | }
22 |
23 | dependencies {
24 | compile project(':chips-lover')
25 | compile 'com.github.QuadFlask:colorpicker:0.0.13'
26 | compile 'com.android.support:appcompat-v7:25.3.1'
27 | compile 'com.android.support:design:25.3.1'
28 | compile 'com.android.support.constraint:constraint-layout:1.0.2'
29 | compile 'com.jakewharton:butterknife:8.6.0'
30 | annotationProcessor 'com.jakewharton:butterknife-compiler:8.6.0'
31 | }
32 |
--------------------------------------------------------------------------------
/chips-lover/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "25.0.2"
6 |
7 |
8 |
9 | defaultConfig {
10 | minSdkVersion 13
11 | targetSdkVersion 25
12 | versionCode 1
13 | versionName "1.0"
14 | vectorDrawables.useSupportLibrary = true
15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
16 |
17 | }
18 | buildTypes {
19 | release {
20 | minifyEnabled false
21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
22 | }
23 | }
24 | }
25 |
26 | dependencies {
27 | compile fileTree(dir: 'libs', include: ['*.jar'])
28 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
29 | exclude group: 'com.android.support', module: 'support-annotations'
30 | })
31 | compile 'com.android.support:appcompat-v7:25.3.1'
32 | compile 'com.android.support:design:25.3.1'
33 | testCompile 'junit:junit:4.12'
34 | compile 'de.hdodenhof:circleimageview:2.1.0'
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/com/vpaliy/chipview/SampleActivity.java:
--------------------------------------------------------------------------------
1 | package com.vpaliy.chipview;
2 |
3 | import android.support.design.widget.FloatingActionButton;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.os.Bundle;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | import com.vpaliy.chips_lover.ChipBuilder;
10 | import com.vpaliy.chips_lover.ChipsLayout;
11 | import java.util.Arrays;
12 |
13 | import butterknife.BindView;
14 | import butterknife.ButterKnife;
15 |
16 | public class SampleActivity extends AppCompatActivity
17 | implements BottomSheet.OnUpdateChipsListener{
18 |
19 | @BindView(R.id.chips)
20 | protected ChipsLayout chipsLayout;
21 |
22 | @BindView(R.id.fab)
23 | protected FloatingActionButton fab;
24 |
25 | @BindView(R.id.root)
26 | protected ViewGroup root;
27 |
28 | @Override
29 | protected void onCreate(Bundle savedInstanceState) {
30 | super.onCreate(savedInstanceState);
31 | setContentView(R.layout.activity_sample);
32 | ButterKnife.bind(this);
33 | chipsLayout.setTags(Arrays.asList("Ch.Dickson","E.Farmer","M.Phil","J. White","L. Frazier","Iliana Ho",
34 | "Hugo Horne","Cesar Quinn","Seth Pugh","Valentina Green","Ayla Carney","Kyleigh Steele"));
35 | }
36 |
37 | @Override
38 | public void onUpdate(ChipBuilder builder) {
39 | chipsLayout.updateChipColors(builder);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_sample.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
25 |
26 |
27 |
36 |
37 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/chips-lover/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_bottom_sheet.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
27 |
28 |
42 |
43 |
51 |
52 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ChipsLover
2 |
3 | [](https://jitpack.io/#vpaliyX/ChipsLover)
4 |
5 | This repository provides an implementation of a material chip. Chips represent complex entities in small blocks, such as a contact. Also it could be used to represent a category or a simple tag.
6 |
7 | I followed the guidelines from the [Material Design](https://material.io/guidelines/components/chips.html#) website during the implementation of this library.
8 | However, I have also added additional functionality such as a `ChipsLayout`, default animations, selections, color customization, text appearance, etc.
9 |
10 | Take a glance at the demo:
11 |
12 | .gif)
13 |
14 | Also I've created the customization sheet in the sample, so go ahead and download the sample, and you'll get a chance to poke around in the library a little bit:
15 |
16 | .gif)
17 |
18 | ## How to use? ##
19 |
20 | Check out all properties you can set to the `ChipView` as well as `ChipsLayout` [here](https://github.com/vpaliyX/ChipsLover/blob/master/chips-lover/src/main/res/values/attrs.xml). They should be intuitive, well, at least I tried to make them so; if it's not the case then I failed miserably.
21 |
22 | ### Note! ###
23 | If you are going to use the `ChipsLayout` view, you may find yourself in a situation where the chips have completely occupied the screen, so in this case you will not be able to scroll your layout. The solution is to wrap the `ChipsLayout` up into a `ScrollView` or `NestedScrollView` (if you're using a `CoordinatorLayout`).
24 |
25 | Check out these XML examples:
26 |
27 | ```XML
28 |
43 |
44 | ```
45 |
46 | Another one:
47 |
48 | ```XML
49 |
63 |
64 | ```
65 |
66 | ## How to download? ##
67 |
68 | ### Step 1 ###
69 |
70 | Add it in your root build.gradle at the end of repositories:
71 |
72 | ``` gradle
73 | allprojects {
74 | repositories {
75 | maven { url 'https://jitpack.io' }
76 | }
77 | }
78 |
79 | ```
80 | ### Step 2 ###
81 |
82 | Add the dependency
83 |
84 | ``` gradle
85 | dependencies {
86 | compile 'com.github.vpaliyX:ChipsLover:v1.2'
87 | }
88 |
89 | ```
90 | You're good to go!
91 |
92 |
93 | ``````
94 | MIT License
95 |
96 | Copyright (c) 2017 Vasyl Paliy
97 |
98 | Permission is hereby granted, free of charge, to any person obtaining a copy
99 | of this software and associated documentation files (the "Software"), to deal
100 | in the Software without restriction, including without limitation the rights
101 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
102 | copies of the Software, and to permit persons to whom the Software is
103 | furnished to do so, subject to the following conditions:
104 |
105 | The above copyright notice and this permission notice shall be included in all
106 | copies or substantial portions of the Software.
107 |
108 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
109 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
110 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
111 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
112 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
113 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
114 | SOFTWARE.
115 | ``````
116 |
--------------------------------------------------------------------------------
/app/src/main/java/com/vpaliy/chipview/BottomSheet.java:
--------------------------------------------------------------------------------
1 | package com.vpaliy.chipview;
2 |
3 | import android.graphics.Color;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.design.widget.BottomSheetDialogFragment;
7 | import android.support.v4.content.ContextCompat;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import com.flask.colorpicker.ColorPickerView;
12 | import com.flask.colorpicker.OnColorChangedListener;
13 | import com.flask.colorpicker.slider.LightnessSlider;
14 | import com.vpaliy.chips_lover.ChipBuilder;
15 | import com.vpaliy.chips_lover.ChipView;
16 | import com.vpaliy.chips_lover.ChipsLayout;
17 | import java.util.List;
18 | import butterknife.BindView;
19 | import butterknife.ButterKnife;
20 | import butterknife.OnClick;
21 |
22 | public class BottomSheet extends BottomSheetDialogFragment {
23 |
24 | @BindView(R.id.chips_config)
25 | protected ChipsLayout chipsLayout;
26 |
27 | @BindView(R.id.lightness_bar)
28 | protected LightnessSlider lightnessSlider;
29 |
30 | @BindView(R.id.color_picker_view)
31 | protected ColorPickerView pickerView;
32 |
33 | private ChipBuilder builder;
34 | private int selection=-1;
35 |
36 | private OnUpdateChipsListener updateChipsListener;
37 |
38 | public BottomSheet setUpdateListener(OnUpdateChipsListener updateListener){
39 | this.updateChipsListener=updateListener;
40 | return this;
41 | }
42 |
43 | public static BottomSheet newInstance(){
44 | return new BottomSheet();
45 | }
46 |
47 | @Nullable
48 | @Override
49 | public View onCreateView(LayoutInflater inflater,
50 | @Nullable ViewGroup container,
51 | @Nullable Bundle savedInstanceState) {
52 | setRetainInstance(true);
53 | View root=inflater.inflate(R.layout.fragment_bottom_sheet,container,false);
54 | ButterKnife.bind(this,root);
55 | return root;
56 | }
57 |
58 | @Override
59 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
60 | super.onViewCreated(view, savedInstanceState);
61 | if(view!=null){
62 | lightnessSlider.setColorPicker(pickerView);
63 | final List chips=chipsLayout.getChips();
64 | builder=ChipBuilder.create(getContext());
65 | pickerView.addOnColorChangedListener(new OnColorChangedListener() {
66 | @Override
67 | public void onColorChanged(int color) {
68 | ChipView chipView=chips.get(selection);
69 | chipView.setSelectedBackgroundColor(color);
70 | chipView.setBackgroundColor(color);
71 | switch (selection){
72 | case 0:
73 | builder.setBackgroundColor(color);
74 | break;
75 | case 1:
76 | builder.setSelectedBackgroundColor(color);
77 | break;
78 | case 2:
79 | builder.setTextColor(color);
80 | break;
81 | case 3:
82 | builder.setSelectedTextColor(color);
83 | break;
84 | case 4:
85 | builder.setFrontIconColor(color);
86 | break;
87 | case 5:
88 | builder.setEndIconColor(color);
89 | break;
90 | case 6:
91 | builder.setSelectedEndColor(color);
92 | break;
93 | case 7:
94 | builder.setSelectedFrontColor(color);
95 | break;
96 | }
97 | }
98 | });
99 | selection=0;
100 | chips.get(selection).select();
101 | final int color= ContextCompat.getColor(getContext(),R.color.colorSelectedChipBackground);
102 | chipsLayout.setClickListenerToAll(new View.OnClickListener() {
103 | @Override
104 | public void onClick(View view) {
105 | selection=chips.indexOf(view);
106 | ChipView chipView=chips.get(selection);
107 | if(chipView.getSelectedBackgroundColor()!=color) {
108 | pickerView.setColor(chipView.getSelectedBackgroundColor(), false);
109 | }else{
110 | pickerView.setColor(Color.WHITE,false);
111 | }
112 | lightnessSlider.setColor(Color.WHITE);
113 |
114 | }
115 | });
116 | }
117 | }
118 |
119 | @OnClick(R.id.submit_chip)
120 | public void submit(){
121 | updateChipsListener.onUpdate(builder);
122 | }
123 |
124 | @Override
125 | public void onPause() {
126 | super.onPause();
127 | updateChipsListener.onUpdate(builder);
128 | }
129 |
130 | public interface OnUpdateChipsListener{
131 | void onUpdate(ChipBuilder builder);
132 | }
133 |
134 | }
135 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/chips-lover/src/main/java/com/vpaliy/chips_lover/ChipBuilder.java:
--------------------------------------------------------------------------------
1 | package com.vpaliy.chips_lover;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.drawable.Drawable;
6 | import android.support.v4.content.ContextCompat;
7 |
8 | public class ChipBuilder {
9 |
10 | String text;
11 | Drawable endIconDrawable;
12 | Drawable frontIconDrawable;
13 | int frontIconColor=-1;
14 | int endIconColor=-1;
15 | boolean selectable;
16 | boolean closeable;
17 | boolean isDefaultAnimation;
18 | int textStyle=-1;
19 | int backgroundColor;
20 | int textColor;
21 | int elevation;
22 | int selectedBackgroundColor;
23 | int selectedTextColor;
24 | int selectedEndColor;
25 | int selectedFrontColor;
26 | private Context context;
27 |
28 | private ChipBuilder(Context context, TypedArray array){
29 | this(context);
30 | if(array!=null){
31 | text=array.getString(R.styleable.ChipView_chip_text);
32 | backgroundColor=array.getColor(R.styleable.ChipView_chip_backgroundColor,backgroundColor);
33 | textColor=array.getColor(R.styleable.ChipView_chipTextColor,textColor);
34 | textStyle=array.getResourceId(R.styleable.ChipView_chipTextStyle,textStyle);
35 | endIconColor=array.getColor(R.styleable.ChipView_chipEndIconColor,endIconColor);
36 | frontIconColor=array.getColor(R.styleable.ChipView_chipFrontIconColor,frontIconColor);
37 | isDefaultAnimation=array.getBoolean(R.styleable.ChipView_chipDefaultAnimation,false);
38 | selectedEndColor=array.getColor(R.styleable.ChipView_chip_selectedEndColor,selectedEndColor);
39 | closeable=array.getBoolean(R.styleable.ChipView_chipCloseable,false);
40 | selectedFrontColor=array.getColor(R.styleable.ChipView_chip_selectedFrontColor,selectedFrontColor);
41 | selectable=array.getBoolean(R.styleable.ChipView_chipSelectable,false);
42 | elevation=(int)array.getDimension(R.styleable.ChipView_chip_elevation,0);
43 | selectedBackgroundColor=array.getColor(R.styleable.ChipView_chip_selectedBackgroundColor,selectedBackgroundColor);
44 | selectedTextColor=array.getColor(R.styleable.ChipView_chip_selectedTextColor, selectedTextColor);
45 | int icon=array.getResourceId(R.styleable.ChipView_chipFrontIcon,-1);
46 | if(icon!=-1) {
47 | frontIconDrawable = ContextCompat.getDrawable(context, icon);
48 | }
49 | icon=array.getResourceId(R.styleable.ChipView_chipEndIcon,-1);
50 | if(icon!=-1) {
51 | endIconDrawable = ContextCompat.getDrawable(context,icon);
52 | }else if(closeable){
53 | endIconColor=ContextCompat.getColor(context,R.color.colorChipCloseInactive);
54 | endIconDrawable=ContextCompat.getDrawable(context,R.drawable.ic_close);
55 | }
56 | }
57 | }
58 |
59 | private void init(){
60 | textColor=ContextCompat.getColor(context,R.color.colorChipText);
61 | textStyle=-1;
62 | backgroundColor=ContextCompat.getColor(context,R.color.colorChipBackground);
63 | endIconColor=-1;
64 | frontIconColor=-1;
65 | selectedEndColor=ContextCompat.getColor(context,R.color.colorSelectedEndIcon);
66 | selectedFrontColor=ContextCompat.getColor(context,R.color.colorSelectedFrontIcon);
67 | selectedBackgroundColor=ContextCompat.getColor(context,R.color.colorSelectedChipBackground);
68 | selectedTextColor=ContextCompat.getColor(context,R.color.colorChipTextSelected);
69 | }
70 |
71 | private ChipBuilder(Context context){
72 | this.context=context;
73 | init();
74 | }
75 |
76 | public ChipBuilder setTextStyle(int textStyle) {
77 | this.textStyle = textStyle;
78 | return this;
79 | }
80 |
81 | public ChipBuilder setTextColor(int textColor) {
82 | this.textColor = textColor;
83 | return this;
84 | }
85 |
86 | public ChipBuilder setBackgroundColor(int backgroundColor) {
87 | this.backgroundColor = backgroundColor;
88 | return this;
89 | }
90 |
91 | public ChipBuilder setCloseable(boolean closeable) {
92 | this.closeable = closeable;
93 | return this;
94 | }
95 |
96 | public ChipBuilder setDefaultAnimation(boolean defaultAnimation) {
97 | isDefaultAnimation = defaultAnimation;
98 | return this;
99 | }
100 |
101 | public ChipBuilder setEndIconColor(int endIconColor) {
102 | this.endIconColor = endIconColor;
103 | return this;
104 | }
105 |
106 | public ChipBuilder setEndIconDrawable(Drawable endIconDrawable) {
107 | this.endIconDrawable = endIconDrawable;
108 | return this;
109 | }
110 |
111 | public ChipBuilder setFrontIconColor(int frontIconColor) {
112 | this.frontIconColor = frontIconColor;
113 | return this;
114 | }
115 |
116 | public ChipBuilder setFrontIconDrawable(Drawable frontIconDrawable) {
117 | this.frontIconDrawable = frontIconDrawable;
118 | return this;
119 | }
120 |
121 | public ChipBuilder setSelectable(boolean selectable) {
122 | this.selectable = selectable;
123 | return this;
124 | }
125 |
126 | public ChipBuilder setSelectedBackgroundColor(int selectedBackgroundColor) {
127 | this.selectedBackgroundColor = selectedBackgroundColor;
128 | return this;
129 | }
130 |
131 | public ChipBuilder setSelectedEndColor(int selectedEndColor) {
132 | this.selectedEndColor = selectedEndColor;
133 | return this;
134 | }
135 |
136 | public ChipBuilder setSelectedFrontColor(int selectedFrontColor) {
137 | this.selectedFrontColor = selectedFrontColor;
138 | return this;
139 | }
140 |
141 | public ChipBuilder setSelectedTextColor(int selectedTextColor) {
142 | this.selectedTextColor = selectedTextColor;
143 | return this;
144 | }
145 |
146 | public ChipBuilder setText(String text) {
147 | this.text = text;
148 | return this;
149 | }
150 |
151 | public static ChipBuilder create(Context context,TypedArray array){
152 | return new ChipBuilder(context,array);
153 | }
154 |
155 | public static ChipBuilder create(Context context){
156 | return new ChipBuilder(context);
157 | }
158 |
159 | public ChipView build(){
160 | return new ChipView(context,this );
161 | }
162 | }
--------------------------------------------------------------------------------
/chips-lover/src/main/java/com/vpaliy/chips_lover/ChipsLayout.java:
--------------------------------------------------------------------------------
1 | package com.vpaliy.chips_lover;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.os.Build;
6 | import android.text.TextUtils;
7 | import android.transition.Transition;
8 | import android.transition.TransitionInflater;
9 | import android.transition.TransitionManager;
10 | import android.util.AttributeSet;
11 | import android.view.MotionEvent;
12 | import android.view.View;
13 | import android.view.ViewGroup;
14 | import java.util.ArrayList;
15 | import java.util.Arrays;
16 | import java.util.List;
17 |
18 | public class ChipsLayout extends ViewGroup
19 | implements ChipView.OnChipChangeListener{
20 |
21 | private List chips;
22 | private int lineHeight;
23 | private int horizontalSpacing;
24 | private int verticalSpacing;
25 | private ChipBuilder chipBuilder;
26 | private boolean deleteAnimationEnabled;
27 | private int removeAnimationRes;
28 | private boolean removeChipTouch;
29 | public ChipsLayout(Context context){
30 | this(context,null,0);
31 | }
32 |
33 | public ChipsLayout(Context context, AttributeSet attrs){
34 | this(context,attrs,0);
35 | }
36 |
37 | public ChipsLayout(Context context, AttributeSet attrs, int defStyle){
38 | super(context,attrs,defStyle);
39 | initAttrs(attrs);
40 | }
41 |
42 | private void initAttrs(AttributeSet attrs){
43 | if(attrs!=null){
44 | TypedArray array=getContext().obtainStyledAttributes(attrs,R.styleable.ChipsLayout);
45 | chipBuilder=ChipBuilder.create(getContext(),array);
46 | horizontalSpacing=(int)(array.getDimension(R.styleable.ChipsLayout_chip_layout_horizontal_margin,1));
47 | verticalSpacing=(int)(array.getDimension(R.styleable.ChipsLayout_chip_layout_vertical_margin,1));
48 | deleteAnimationEnabled=array.getBoolean(R.styleable.ChipsLayout_remove_anim_enabled,true);
49 | removeAnimationRes=array.getInteger(R.styleable.ChipsLayout_remove_anim,-1);
50 | removeChipTouch=array.getBoolean(R.styleable.ChipsLayout_remove_chips_touch,false);
51 | int arrayRes=array.getResourceId(R.styleable.ChipsLayout_chips_array,-1);
52 | if(arrayRes!=-1){
53 | String[] textArray=getResources().getStringArray(arrayRes);
54 | setTags(Arrays.asList(textArray));
55 | }
56 | array.recycle();
57 | return;
58 | }
59 | chipBuilder=ChipBuilder.create(getContext());
60 | }
61 |
62 | private static class LayoutParams extends ViewGroup.LayoutParams {
63 |
64 | final int horizontalSpacing;
65 | final int verticalSpacing;
66 |
67 | LayoutParams(int horizontalSpacing, int verticalSpacing) {
68 | super(0, 0);
69 | this.horizontalSpacing = horizontalSpacing;
70 | this.verticalSpacing = verticalSpacing;
71 | }
72 | }
73 |
74 | @Override
75 | protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
76 | return new LayoutParams(horizontalSpacing, verticalSpacing);
77 | }
78 |
79 | @Override
80 | protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
81 | return new LayoutParams(horizontalSpacing, verticalSpacing);
82 | }
83 |
84 | @Override
85 | protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
86 | return p instanceof LayoutParams;
87 | }
88 |
89 | public void updateChipColors(ChipBuilder chipBuilder) {
90 | this.chipBuilder = chipBuilder;
91 | if(chips!=null){
92 | for(ChipView chipView:chips){
93 | chipView.setSelectedTextColor(chipBuilder.selectedTextColor);
94 | chipView.setSelectedFrontColor(chipBuilder.selectedFrontColor);
95 | chipView.setSelectedEndColor(chipBuilder.selectedEndColor);
96 | chipView.setSelectedBackgroundColor(chipBuilder.selectedBackgroundColor);
97 | chipView.setFrontIconColor(chipBuilder.frontIconColor);
98 | chipView.setEndIconColor(chipBuilder.endIconColor);
99 | chipView.setTextColor(chipBuilder.textColor);
100 | chipView.setBackgroundColor(chipBuilder.backgroundColor);
101 | }
102 | }
103 | }
104 |
105 | public ChipBuilder getChipBuilder() {
106 | return chipBuilder;
107 | }
108 |
109 | @Override
110 | protected void onLayout(boolean changed, int l, int t, int r, int b) {
111 | final int count = getChildCount();
112 | final int width = r - l;
113 | int xPos = getPaddingLeft();
114 | int yPos = getPaddingTop();
115 |
116 | for (int i = 0; i < count; i++) {
117 | final View child = getChildAt(i);
118 | if (child.getVisibility() != GONE) {
119 | final int childWidth = child.getMeasuredWidth();
120 | final int childHeight = child.getMeasuredHeight();
121 | final LayoutParams lp = (LayoutParams) child.getLayoutParams();
122 | if (xPos + childWidth > width) {
123 | xPos = getPaddingLeft();
124 | yPos += lineHeight;
125 | }
126 | child.layout(xPos, yPos, xPos + childWidth, yPos + childHeight);
127 | xPos += childWidth + lp.horizontalSpacing;
128 | }
129 | }
130 | }
131 |
132 | @Override
133 | public void onScaleChanged(ChipView chipView) {
134 | requestLayout();
135 | }
136 |
137 | @Override
138 | public void onRemove(ChipView chipView) {
139 | if(chips.contains(chipView)) {
140 | if (Build.VERSION.SDK_INT >= 19 && deleteAnimationEnabled) {
141 | if(removeAnimationRes!=-1) {
142 | Transition transition=TransitionInflater.from(getContext()).inflateTransition(removeAnimationRes);
143 | TransitionManager.beginDelayedTransition(this,transition);
144 | }else {
145 | TransitionManager.beginDelayedTransition(this);
146 | }
147 | }
148 | removeView(chipView);
149 | }
150 | }
151 |
152 | public void setHorizontalSpacing(int horizontalSpacing) {
153 | this.horizontalSpacing = horizontalSpacing;
154 | }
155 |
156 | public void setVerticalSpacing(int verticalSpacing) {
157 | this.verticalSpacing = verticalSpacing;
158 | }
159 |
160 | public int getVerticalSpacing() {
161 | return verticalSpacing;
162 | }
163 |
164 | public int getHorizontalSpacing() {
165 | return horizontalSpacing;
166 | }
167 |
168 | public List getChips() {
169 | return chips;
170 | }
171 |
172 | @Override
173 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
174 | int width = View.MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
175 | int height = View.MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom();
176 | int count = getChildCount();
177 | int lineHeight = 0;
178 |
179 | int xPos = getPaddingLeft();
180 | int yPos = getPaddingTop();
181 |
182 | int childHeightMeasureSpec;
183 | if (View.MeasureSpec.getMode(heightMeasureSpec) == View.MeasureSpec.AT_MOST) {
184 | childHeightMeasureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST);
185 | } else {
186 | childHeightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
187 | }
188 |
189 | for (int i = 0; i < count; i++) {
190 | final View child = getChildAt(i);
191 | if (child.getVisibility() != GONE) {
192 | final LayoutParams lp = (LayoutParams) child.getLayoutParams();
193 | child.measure(View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.AT_MOST), childHeightMeasureSpec);
194 | final int childWidth = child.getMeasuredWidth();
195 | lineHeight = Math.max(lineHeight, child.getMeasuredHeight() + lp.verticalSpacing);
196 |
197 | if (xPos + childWidth> width) {
198 | xPos = getPaddingLeft();
199 | yPos += lineHeight;
200 | }
201 | xPos += childWidth + lp.horizontalSpacing;
202 | }
203 | }
204 | this.lineHeight = lineHeight;
205 | if (View.MeasureSpec.getMode(heightMeasureSpec) == View.MeasureSpec.UNSPECIFIED) {
206 | height = yPos + lineHeight;
207 |
208 | } else if (View.MeasureSpec.getMode(heightMeasureSpec) == View.MeasureSpec.AT_MOST) {
209 | if (yPos + lineHeight < height) {
210 | height = yPos + lineHeight;
211 | }
212 | }
213 | setMeasuredDimension(width, height);
214 | }
215 |
216 | public void setTags(List tags){
217 | if(tags==null||tags.isEmpty()) return;
218 | if(chips==null){
219 | chips=new ArrayList<>(tags.size());
220 | }
221 | if(tags.size()>chips.size()){
222 | int diff=tags.size()-chips.size();
223 | for(int index=0;index chipViews){
276 | if(chipViews!=null){
277 | for(ChipView chip:chipViews){
278 | if(!chips.contains(chip)){
279 | chips.add(chip);
280 | addView(chip);
281 | }
282 | }
283 | }
284 | }
285 |
286 | }
287 |
--------------------------------------------------------------------------------
/chips-lover/src/main/java/com/vpaliy/chips_lover/ChipView.java:
--------------------------------------------------------------------------------
1 | package com.vpaliy.chips_lover;
2 |
3 |
4 | import android.content.Context;
5 | import android.content.res.TypedArray;
6 | import android.graphics.drawable.Drawable;
7 | import android.graphics.drawable.PaintDrawable;
8 | import android.os.Build;
9 | import android.support.annotation.DimenRes;
10 | import android.support.annotation.Nullable;
11 | import android.support.v4.content.ContextCompat;
12 | import android.support.v4.graphics.drawable.DrawableCompat;
13 | import android.support.v4.view.ViewCompat;
14 | import android.support.v4.view.ViewPropertyAnimatorListenerAdapter;
15 | import android.util.AttributeSet;
16 | import android.view.View;
17 | import android.widget.ImageView;
18 | import android.widget.RelativeLayout;
19 | import android.widget.TextView;
20 | import de.hdodenhof.circleimageview.CircleImageView;
21 | import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
22 |
23 | public class ChipView extends RelativeLayout{
24 |
25 | private static final float SCALE_BY=1.03F;
26 |
27 | private TextView chipTextView;
28 | private CircleImageView frontIcon;
29 | private ImageView endIcon;
30 | private String text;
31 | private Drawable endIconDrawable;
32 | private Drawable frontIconDrawable;
33 | private boolean selectable;
34 | private boolean closeable;
35 | private boolean isPressAnimation;
36 | private boolean isSelected;
37 | private int frontIconColor;
38 | private int endIconColor;
39 | private int textStyle;
40 | private int elevation;
41 | private int backgroundColor;
42 | private int textColor;
43 | private int selectedBackgroundColor;
44 | private int selectedTextColor;
45 | private int selectedEndColor;
46 | private int selectedFrontColor;
47 |
48 | private OnChipChangeListener chipChangeListener;
49 | private OnFrontIconEventClick frontIconClickEvent;
50 | private OnEndIconEventClick endIconEventClick;
51 | private OnClickListener selfClickListener;
52 | private OnClickListener externalClickListener;
53 |
54 | public ChipView(Context context) {
55 | this(context, null, 0);
56 | }
57 |
58 | public ChipView(Context context, ChipBuilder builder){
59 | super(context);
60 | init(builder);
61 | }
62 |
63 | public ChipView(Context context, AttributeSet attrs) {
64 | this(context, attrs, 0);
65 | }
66 |
67 | public ChipView(Context context, AttributeSet attrs, int defStyleAttr) {
68 | super(context, attrs, defStyleAttr);
69 | if(attrs!=null){
70 | TypedArray array=getContext().obtainStyledAttributes(attrs,R.styleable.ChipView);
71 | init(ChipBuilder.create(getContext(),array));
72 | array.recycle();
73 | }else {
74 | init(ChipBuilder.create(getContext()));
75 | }
76 | }
77 |
78 | void init(ChipBuilder builder){
79 | text=builder.text;
80 | endIconDrawable=builder.endIconDrawable;
81 | frontIconDrawable=builder.frontIconDrawable;
82 | elevation=builder.elevation;
83 | frontIconColor=builder.frontIconColor;
84 | endIconColor=builder.endIconColor;
85 | selectable=builder.selectable;
86 | closeable=builder.closeable;
87 | isPressAnimation =builder.isDefaultAnimation;
88 | textStyle=builder.textStyle;
89 | backgroundColor=builder.backgroundColor;
90 | textColor=builder.textColor;
91 | selectedBackgroundColor=builder.selectedBackgroundColor;
92 | selectedTextColor=builder.selectedTextColor;
93 | selectedEndColor=builder.selectedEndColor;
94 | selectedFrontColor=builder.selectedFrontColor;
95 | setUp();
96 | }
97 |
98 | private int dimens(@DimenRes int dimen){
99 | return (int)getResources().getDimension(dimen);
100 | }
101 |
102 | @Override
103 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
104 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
105 | getLayoutParams().height=dimens(R.dimen.chip_height);
106 | getLayoutParams().width=WRAP_CONTENT;
107 | if(elevation>0){
108 | ViewCompat.setElevation(this,elevation);
109 | }
110 | }
111 |
112 | private void setUp(){
113 | initBackgroundColor();
114 | initTextView();
115 | initEndIcon();
116 | initFrontIcon();
117 | selfClickListener=new OnClickListener() {
118 | @Override
119 | public void onClick(View v) {
120 | triggerSelection();
121 | }
122 | };
123 | setOnClickListener(selfClickListener);
124 | }
125 |
126 | private void triggerSelection(){
127 | if(selectable){
128 | isSelected=!isSelected;
129 | initBackgroundColor();
130 | setFrontIcon();
131 | setEndIcon();
132 | setTextColor();
133 | if(isPressAnimation) {
134 | ViewCompat.animate(this)
135 | .scaleX(isSelected?SCALE_BY: 1)
136 | .scaleY(isSelected?SCALE_BY: 1)
137 | .setDuration(getResources().getInteger(R.integer.default_anim_duration))
138 | .setListener(new ViewPropertyAnimatorListenerAdapter(){
139 | @Override
140 | public void onAnimationEnd(View view) {
141 | super.onAnimationEnd(view);
142 | if(chipChangeListener!=null){
143 | chipChangeListener.onScaleChanged(ChipView.this);
144 | }
145 | }
146 | })
147 | .start();
148 | }
149 | }
150 | if(externalClickListener!=null){
151 | externalClickListener.onClick(this);
152 | }
153 | }
154 |
155 | private void initTextView() {
156 | chipTextView= new TextView(getContext());
157 | RelativeLayout.LayoutParams chipTextParams = new RelativeLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
158 | if(endIconDrawable!=null||frontIconDrawable!=null){
159 | chipTextParams.addRule(RIGHT_OF,R.id.chip_front_icon);
160 | chipTextParams.addRule(CENTER_VERTICAL);
161 | }else {
162 | chipTextParams.addRule(CENTER_IN_PARENT);
163 | }
164 | int left=frontIconDrawable!=null?dimens(R.dimen.chip_text_icon_margin):dimens(R.dimen.chip_text_margin);
165 | int right=endIconDrawable!=null?0 :dimens(R.dimen.chip_text_margin);
166 |
167 | chipTextParams.setMargins(left,0,right,0);
168 | chipTextView.setLayoutParams(chipTextParams);
169 | chipTextView.setId(R.id.chip_text);
170 | chipTextView.setText(text);
171 | if(textColor!=-1){
172 | chipTextView.setTextColor(textColor);
173 | }
174 | if(textStyle!=-1){
175 | if(Build.VERSION.SDK_INT>=23){
176 | chipTextView.setTextAppearance(textStyle);
177 | }
178 | }
179 | this.addView(chipTextView);
180 | }
181 |
182 | public void setSelectedBackgroundColor(int selectedBackgroundColor) {
183 | this.selectedBackgroundColor = selectedBackgroundColor;
184 | if(isSelected){
185 | initBackgroundColor();
186 | }
187 | }
188 |
189 | private Drawable makeCopyIfPossible(Drawable drawable){
190 | if(drawable.getConstantState()!=null){
191 | return drawable.getConstantState().newDrawable().mutate();
192 | }
193 | return drawable;
194 | }
195 | private void initFrontIcon(){
196 | if(frontIconDrawable!=null) {
197 | frontIconDrawable=makeCopyIfPossible(frontIconDrawable);
198 | frontIcon = new CircleImageView(getContext());
199 | LayoutParams params = new LayoutParams(dimens(R.dimen.chip_front_icon_size), dimens(R.dimen.chip_front_icon_size));
200 | params.addRule(ALIGN_PARENT_LEFT);
201 | params.addRule(CENTER_VERTICAL);
202 | frontIcon.setLayoutParams(params);
203 | frontIcon.setId(R.id.chip_front_icon);
204 | setFrontIcon();
205 | frontIcon.setOnClickListener(new OnClickListener() {
206 | @Override
207 | public void onClick(View v) {
208 | if(frontIconClickEvent!=null){
209 | frontIconClickEvent.onClick(v);
210 | }
211 | }
212 | });
213 | addView(frontIcon);
214 | }
215 | }
216 |
217 | public void setChipChangeListener(OnChipChangeListener chipChangeListener) {
218 | this.chipChangeListener = chipChangeListener;
219 | }
220 |
221 | private void initEndIcon(){
222 | if(closeable||endIconDrawable!=null){
223 | endIconDrawable=makeCopyIfPossible(endIconDrawable);
224 | endIcon=new CircleImageView(getContext());
225 | LayoutParams params=new LayoutParams(dimens(R.dimen.chip_end_icon_size), dimens(R.dimen.chip_end_icon_size));
226 | params.addRule(RIGHT_OF, R.id.chip_text);
227 | params.addRule(CENTER_VERTICAL);
228 | params.setMargins(dimens(R.dimen.chip_close_margin),0, dimens(R.dimen.chip_close_margin),0);
229 | endIcon.setLayoutParams(params);
230 | endIcon.setId(R.id.chip_end_icon);
231 | setEndIcon();
232 | endIcon.setOnClickListener(new OnClickListener() {
233 | @Override
234 | public void onClick(View v) {
235 | if(endIconEventClick!=null){
236 | endIconEventClick.onClick(v);
237 | }
238 |
239 | if(closeable){
240 | chipChangeListener.onRemove(ChipView.this);
241 | }
242 | }
243 | });
244 | addView(endIcon);
245 | }
246 | }
247 |
248 | @Override
249 | public void setOnClickListener(@Nullable OnClickListener listener) {
250 | if(listener==selfClickListener) {
251 | super.setOnClickListener(listener);
252 | }else{
253 | this.externalClickListener=listener;
254 | }
255 | }
256 |
257 | public void select(){
258 | triggerSelection();
259 | }
260 |
261 | private void setTextColor(){
262 | if(chipTextView!=null){
263 | chipTextView.setTextColor(isSelected?selectedTextColor:textColor);
264 | }
265 | }
266 |
267 | private void setFrontIcon(){
268 | if(frontIcon!=null){
269 | if(isSelected){
270 | if(selectedFrontColor!=-1) {
271 | DrawableCompat.setTint(frontIconDrawable, selectedFrontColor);
272 | }
273 | }else if(frontIconColor!=-1){
274 | DrawableCompat.setTint(frontIconDrawable,frontIconColor);
275 | }
276 | frontIcon.setImageDrawable(frontIconDrawable);
277 | }
278 | }
279 |
280 | private void setEndIcon(){
281 | if(endIcon!=null){
282 | if(isSelected) {
283 | DrawableCompat.setTint(endIconDrawable, selectedEndColor);
284 | }else if(endIconColor!=-1){
285 | DrawableCompat.setTint(endIconDrawable,endIconColor);
286 | }
287 | endIcon.setImageDrawable(endIconDrawable);
288 | }
289 | }
290 |
291 | public void setFrontIconClickEvent(OnFrontIconEventClick frontIconClickEvent) {
292 | this.frontIconClickEvent = frontIconClickEvent;
293 | }
294 |
295 | public void setEndIconEventClick(OnEndIconEventClick endIconEventClick) {
296 | this.endIconEventClick = endIconEventClick;
297 | }
298 |
299 | private void initBackgroundColor() {
300 | PaintDrawable bgDrawable = new PaintDrawable(isSelected?selectedBackgroundColor:backgroundColor);
301 | bgDrawable.setCornerRadius(dimens(R.dimen.chip_height)/2);
302 | setBackgroundDrawable(bgDrawable);
303 | }
304 |
305 | @Override
306 | public void setBackgroundColor(int backgroundColor) {
307 | this.backgroundColor = backgroundColor;
308 | initBackgroundColor();
309 | }
310 |
311 | public void setSelectedTextColor(int selectedTextColor) {
312 | this.selectedTextColor = selectedTextColor;
313 | if(isSelected){
314 | setTextColor();
315 | }
316 | }
317 |
318 | public void setSelectedEndColor(int selectedEndColor) {
319 | this.selectedEndColor = selectedEndColor;
320 | if(isSelected){
321 | setEndIconColor(selectedEndColor);
322 | }
323 | }
324 |
325 | public void setText(String text) {
326 | this.text = text;
327 | chipTextView.setText(text);
328 | }
329 |
330 | public void setCloseable(boolean closeable) {
331 | this.closeable = closeable;
332 | if(closeable){
333 | endIconColor=ContextCompat.getColor(getContext(),R.color.colorChipCloseInactive);
334 | endIconDrawable=ContextCompat.getDrawable(getContext(),R.drawable.ic_close);
335 | setEndIconColor(endIconColor);
336 | }
337 | }
338 |
339 | public void setEndIconDrawable(Drawable endIconDrawable) {
340 | this.endIconDrawable = endIconDrawable;
341 | if(endIconDrawable!=null){
342 | if(endIcon!=null){
343 | endIcon.setImageDrawable(endIconDrawable);
344 | }else{
345 | initEndIcon();
346 | }
347 | }
348 | }
349 |
350 | public void setFrontIconColor(int frontIconColor) {
351 | this.frontIconColor = frontIconColor;
352 | setFrontIcon();
353 | }
354 |
355 | public void setFrontIconDrawable(Drawable frontIconDrawable) {
356 | this.frontIconDrawable = frontIconDrawable;
357 | if(frontIconDrawable!=null){
358 | if(frontIcon!=null){
359 | frontIcon.setImageDrawable(frontIconDrawable);
360 | }else{
361 | initFrontIcon();
362 | }
363 | }
364 | }
365 |
366 | public void setPressAnimation(boolean pressAnimation) {
367 | isPressAnimation = pressAnimation;
368 | }
369 |
370 | public void setSelectable(boolean selectable) {
371 | this.selectable = selectable;
372 | }
373 |
374 | public void setEndIconColor(int endIconColor) {
375 | this.endIconColor = endIconColor;
376 | setEndIcon();
377 | }
378 |
379 | public void setSelectedFrontColor(int selectedFrontColor) {
380 | this.selectedFrontColor = selectedFrontColor;
381 | setFrontIcon();
382 | }
383 |
384 | public void setTextStyle(int textStyle) {
385 | this.textStyle = textStyle;
386 | if(chipTextView!=null){
387 | if(Build.VERSION.SDK_INT>=23) {
388 | chipTextView.setTextAppearance(textStyle);
389 | }
390 | }
391 | }
392 |
393 | public void setTextColor(int textColor) {
394 | this.textColor = textColor;
395 | setTextColor();
396 | }
397 |
398 | public void setChipText(String chipText) {
399 | this.text=chipText;
400 | chipTextView.setText(chipText);
401 | }
402 |
403 | public int getBackgroundColor() {
404 | return backgroundColor;
405 | }
406 |
407 | public int getTextColor() {
408 | return textColor;
409 | }
410 |
411 | public int getSelectedEndColor() {
412 | return selectedEndColor;
413 | }
414 |
415 | public int getEndIconColor() {
416 | return endIconColor;
417 | }
418 |
419 | public int getFrontIconColor() {
420 | return frontIconColor;
421 | }
422 |
423 | public int getSelectedBackgroundColor() {
424 | return selectedBackgroundColor;
425 | }
426 |
427 | public int getSelectedFrontColor() {
428 | return selectedFrontColor;
429 | }
430 |
431 | public int getSelectedTextColor() {
432 | return selectedTextColor;
433 | }
434 |
435 |
436 | public interface OnChipChangeListener{
437 | void onScaleChanged(ChipView chipView);
438 | void onRemove(ChipView chipView);
439 | }
440 |
441 | public String getChipText() {
442 | return text;
443 | }
444 | }
445 |
--------------------------------------------------------------------------------