├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── flask
│ │ └── colorpicker
│ │ └── sample
│ │ └── ApplicationTest.java
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── flask
│ │ └── colorpicker
│ │ └── sample
│ │ ├── PrefsActivity.java
│ │ ├── SampleActivity.java
│ │ ├── SampleActivity2.java
│ │ └── SampleActivity3.java
│ └── res
│ ├── drawable-hdpi
│ ├── ic_github_circle_black_24dp.png
│ └── ic_launcher.png
│ ├── drawable-mdpi
│ ├── ic_github_circle_black_24dp.png
│ └── ic_launcher.png
│ ├── drawable-xhdpi
│ ├── ic_github_circle_black_24dp.png
│ └── ic_launcher.png
│ ├── drawable-xxhdpi
│ ├── ic_github_circle_black_24dp.png
│ └── ic_launcher.png
│ ├── drawable-xxxhdpi
│ ├── ic_github_circle_black_24dp.png
│ └── ic_launcher.png
│ ├── drawable
│ ├── background.xml
│ ├── ic_launcher.png
│ └── tile.png
│ ├── layout-land
│ └── fragment_adapted_dialog.xml
│ ├── layout
│ ├── activity_sample.xml
│ ├── activity_sample2.xml
│ ├── activity_sample3.xml
│ ├── fragment_adapted_dialog.xml
│ └── fragment_sample_activity3.xml
│ ├── menu
│ └── menu_sample_activity3.xml
│ ├── values-w820dp
│ └── dimens.xml
│ ├── values
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
│ └── xml
│ └── prefs.xml
├── build.gradle
├── gradle
├── local.properties
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── library
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── flask
│ │ └── colorpicker
│ │ └── ApplicationTest.java
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── flask
│ │ └── colorpicker
│ │ ├── ColorCircle.java
│ │ ├── ColorCircleDrawable.java
│ │ ├── ColorPickerPreference.java
│ │ ├── ColorPickerView.java
│ │ ├── OnColorChangedListener.java
│ │ ├── OnColorSelectedListener.java
│ │ ├── Utils.java
│ │ ├── builder
│ │ ├── ColorPickerClickListener.java
│ │ ├── ColorPickerDialogBuilder.java
│ │ ├── ColorWheelRendererBuilder.java
│ │ └── PaintBuilder.java
│ │ ├── renderer
│ │ ├── AbsColorWheelRenderer.java
│ │ ├── ColorWheelRenderOption.java
│ │ ├── ColorWheelRenderer.java
│ │ ├── FlowerColorWheelRenderer.java
│ │ └── SimpleColorWheelRenderer.java
│ │ └── slider
│ │ ├── AbsCustomSlider.java
│ │ ├── AlphaSlider.java
│ │ ├── LightnessSlider.java
│ │ └── OnValueChangedListener.java
│ └── res
│ ├── layout
│ ├── color_edit.xml
│ ├── color_preview.xml
│ ├── color_selector.xml
│ └── color_widget.xml
│ └── values
│ ├── attrs.xml
│ ├── dimens.xml
│ └── styles.xml
├── screenshot
├── screenshot.png
├── screenshot2.png
├── screenshot3.png
└── screenshot4.png
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/
5 | .DS_Store
6 | /build
7 | /captures
8 | gradle.properties
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: android
2 |
3 | sudo: false
4 |
5 | android:
6 | components:
7 | - build-tools-26.0.2
8 | - android-26
9 | - extra-google-m2repository
10 | - extra-android-m2repository
11 |
12 | licenses:
13 | - android-sdk-license-.+
14 |
15 | script: ./gradlew clean build --info
16 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | CHANGELOG
2 | ------------
3 |
4 | - some performance improvement
5 | - add ColorPickerPerference for Preference xml
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Color Picker
2 | -------------
3 | [](http://android-arsenal.com/details/1/1693)
4 | 
5 |
6 | 
7 |
8 | simple android color picker with color wheel and lightness bar.
9 |
10 | [Play Store link](https://play.google.com/store/apps/details?id=com.flask.colorpicker.sample)
11 |
12 | ## Demo video
13 |
14 | [Youtube](https://youtu.be/MwWi9X7eqNI)
15 |
16 |
17 | ## Screenshot
18 |
19 | ### WHEEL_TYPE.FLOWER
20 | 
21 |
22 | ### WHEEL_TYPE.CIRCLE
23 | 
24 |
25 |
26 | ## How to add dependency?
27 |
28 | This library is not released in Maven Central, but instead you can use [JitPack](https://jitpack.io)
29 |
30 | add remote maven url in `allprojects.repositories`
31 |
32 | ```groovy
33 | allprojects {
34 | repositories {
35 | maven { url "https://jitpack.io" }
36 | }
37 | }
38 | ```
39 |
40 | then add a library dependency
41 |
42 | ```groovy
43 | dependencies {
44 | implementation 'com.github.QuadFlask:colorpicker:0.0.15'
45 | }
46 | ```
47 |
48 | or, you can manually download `aar` and put into your project's `libs` directory.
49 |
50 | and add dependency
51 |
52 | ```groovy
53 | dependencies {
54 | compile(name:'[arrFileName]', ext:'aar')
55 | }
56 | ```
57 |
58 | > check out latest version at [releases](https://github.com/QuadFlask/colorpicker/releases)
59 |
60 | ## Usage
61 | As a dialog
62 | ```java
63 | ColorPickerDialogBuilder
64 | .with(context)
65 | .setTitle("Choose color")
66 | .initialColor(currentBackgroundColor)
67 | .wheelType(ColorPickerView.WHEEL_TYPE.FLOWER)
68 | .density(12)
69 | .setOnColorSelectedListener(new OnColorSelectedListener() {
70 | @Override
71 | public void onColorSelected(int selectedColor) {
72 | toast("onColorSelected: 0x" + Integer.toHexString(selectedColor));
73 | }
74 | })
75 | .setPositiveButton("ok", new ColorPickerClickListener() {
76 | @Override
77 | public void onClick(DialogInterface dialog, int selectedColor, Integer[] allColors) {
78 | changeBackgroundColor(selectedColor);
79 | }
80 | })
81 | .setNegativeButton("cancel", new DialogInterface.OnClickListener() {
82 | @Override
83 | public void onClick(DialogInterface dialog, int which) {
84 | }
85 | })
86 | .build()
87 | .show();
88 | ```
89 | As a widget
90 | ```xml
91 |
102 |
103 |
108 |
109 |
114 | ```
115 |
116 |
117 | ## To do
118 |
119 | * gradle support
120 | * performance improvement
121 | * refactoring
122 |
123 |
124 | ## License
125 |
126 | ```
127 | Copyright 2014-2017 QuadFlask
128 |
129 | Licensed under the Apache License, Version 2.0 (the "License");
130 | you may not use this file except in compliance with the License.
131 | You may obtain a copy of the License at
132 |
133 | http://www.apache.org/licenses/LICENSE-2.0
134 |
135 | Unless required by applicable law or agreed to in writing, software
136 | distributed under the License is distributed on an "AS IS" BASIS,
137 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138 | See the License for the specific language governing permissions and
139 | limitations under the License.
140 | ```
141 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 29
5 | buildToolsVersion "29.0.0"
6 |
7 | defaultConfig {
8 | applicationId "com.flask.colorpicker.sample"
9 | minSdkVersion 14
10 | targetSdkVersion 29
11 | versionCode 10
12 | versionName "1.0.10"
13 |
14 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
15 | }
16 | // signingConfigs {
17 | // release {
18 | // storeFile file(RELEASE_STORE_FILE)
19 | // storePassword RELEASE_STORE_PASSWORD
20 | // keyAlias RELEASE_KEY_ALIAS
21 | // keyPassword RELEASE_KEY_PASSWORD
22 | // }
23 | // }
24 | // buildTypes {
25 | // release {
26 | // minifyEnabled false
27 | // proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
28 | // signingConfig signingConfigs.release
29 | // }
30 | // }
31 | }
32 |
33 | dependencies {
34 | implementation fileTree(dir: 'libs', include: ['*.jar'])
35 | implementation project(":library")
36 | implementation 'androidx.appcompat:appcompat:1.1.0'
37 | implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta3'
38 | implementation 'com.google.android.material:material:1.0.0'
39 | }
40 |
--------------------------------------------------------------------------------
/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 /Users/flask/Documents/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 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/flask/colorpicker/sample/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker.sample;
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 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/flask/colorpicker/sample/PrefsActivity.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker.sample;
2 |
3 | import android.os.Bundle;
4 | import android.preference.PreferenceActivity;
5 |
6 | public class PrefsActivity extends PreferenceActivity {
7 | @Override
8 | public void onCreate(Bundle savedInstanceState) {
9 | super.onCreate(savedInstanceState);
10 |
11 | addPreferencesFromResource(R.xml.prefs);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/flask/colorpicker/sample/SampleActivity.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker.sample;
2 |
3 | import android.content.Context;
4 | import android.content.DialogInterface;
5 | import android.content.Intent;
6 | import android.net.Uri;
7 | import android.os.Bundle;
8 | import androidx.annotation.Nullable;
9 | import androidx.fragment.app.DialogFragment;
10 | import androidx.core.content.ContextCompat;
11 | import androidx.appcompat.app.AppCompatActivity;
12 | import androidx.appcompat.app.AppCompatDialogFragment;
13 | import android.util.Log;
14 | import android.view.LayoutInflater;
15 | import android.view.View;
16 | import android.view.ViewGroup;
17 | import android.widget.Toast;
18 |
19 | import com.flask.colorpicker.ColorPickerView;
20 | import com.flask.colorpicker.OnColorChangedListener;
21 | import com.flask.colorpicker.OnColorSelectedListener;
22 | import com.flask.colorpicker.builder.ColorPickerClickListener;
23 | import com.flask.colorpicker.builder.ColorPickerDialogBuilder;
24 |
25 | public class SampleActivity extends AppCompatActivity {
26 | private View root;
27 | private int currentBackgroundColor = 0xffffffff;
28 |
29 | @Override
30 | protected void onCreate(Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | setContentView(R.layout.activity_sample);
33 | root = findViewById(R.id.color_screen);
34 | changeBackgroundColor(currentBackgroundColor);
35 |
36 | findViewById(R.id.btn_dialog).setOnClickListener(new View.OnClickListener() {
37 | @Override
38 | public void onClick(View v) {
39 | final Context context = SampleActivity.this;
40 |
41 | ColorPickerDialogBuilder
42 | .with(context)
43 | .setTitle(R.string.color_dialog_title)
44 | .initialColor(currentBackgroundColor)
45 | .wheelType(ColorPickerView.WHEEL_TYPE.FLOWER)
46 | .density(12)
47 | .setOnColorChangedListener(new OnColorChangedListener() {
48 | @Override
49 | public void onColorChanged(int selectedColor) {
50 | // Handle on color change
51 | Log.d("ColorPicker", "onColorChanged: 0x" + Integer.toHexString(selectedColor));
52 | }
53 | })
54 | .setOnColorSelectedListener(new OnColorSelectedListener() {
55 | @Override
56 | public void onColorSelected(int selectedColor) {
57 | toast("onColorSelected: 0x" + Integer.toHexString(selectedColor));
58 | }
59 | })
60 | .setPositiveButton("ok", new ColorPickerClickListener() {
61 | @Override
62 | public void onClick(DialogInterface dialog, int selectedColor, Integer[] allColors) {
63 | changeBackgroundColor(selectedColor);
64 | if (allColors != null) {
65 | StringBuilder sb = null;
66 |
67 | for (Integer color : allColors) {
68 | if (color == null)
69 | continue;
70 | if (sb == null)
71 | sb = new StringBuilder("Color List:");
72 | sb.append("\r\n#" + Integer.toHexString(color).toUpperCase());
73 | }
74 |
75 | if (sb != null)
76 | Toast.makeText(getApplicationContext(), sb.toString(), Toast.LENGTH_SHORT).show();
77 | }
78 | }
79 | })
80 | .setNegativeButton("cancel", new DialogInterface.OnClickListener() {
81 | @Override
82 | public void onClick(DialogInterface dialog, int which) {
83 | }
84 | })
85 | .showColorEdit(true)
86 | .setColorEditTextColor(ContextCompat.getColor(SampleActivity.this, android.R.color.holo_blue_bright))
87 | .build()
88 | .show();
89 | }
90 | });
91 | findViewById(R.id.btn_adapted_dialog).setOnClickListener(new View.OnClickListener() {
92 | @Override
93 | public void onClick(View v) {
94 | DialogFragment dialogFragment = new AdaptedDialogFragment();
95 | dialogFragment.show(getSupportFragmentManager(), "adapted_dialog");
96 | }
97 | });
98 | findViewById(R.id.btn_prefs).setOnClickListener(new View.OnClickListener() {
99 | @Override
100 | public void onClick(View v) {
101 | startActivity(new Intent(SampleActivity.this, PrefsActivity.class));
102 | }
103 | });
104 | findViewById(R.id.btn_view).setOnClickListener(new View.OnClickListener() {
105 | @Override
106 | public void onClick(View v) {
107 | Intent intent = new Intent(SampleActivity.this, SampleActivity2.class);
108 | startActivity(intent);
109 | }
110 | });
111 | findViewById(R.id.btn_github).setOnClickListener(new View.OnClickListener() {
112 | @Override
113 | public void onClick(View v) {
114 | String url = "https://github.com/QuadFlask/colorpicker";
115 | Intent intent = new Intent(Intent.ACTION_VIEW);
116 | intent.setData(Uri.parse(url));
117 | startActivity(intent);
118 | }
119 | });
120 | findViewById(R.id.btn_fragment).setOnClickListener(new View.OnClickListener() {
121 | @Override
122 | public void onClick(View view) {
123 | final Intent intent = new Intent(SampleActivity.this, SampleActivity3.class);
124 | startActivity(intent);
125 | }
126 | });
127 | }
128 |
129 | private void changeBackgroundColor(int selectedColor) {
130 | currentBackgroundColor = selectedColor;
131 | root.setBackgroundColor(selectedColor);
132 | }
133 |
134 | private void toast(String text) {
135 | Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
136 | }
137 |
138 | public static class AdaptedDialogFragment extends AppCompatDialogFragment {
139 | public AdaptedDialogFragment() {
140 | }
141 |
142 | @Nullable
143 | @Override
144 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
145 | return inflater.inflate(R.layout.fragment_adapted_dialog, container);
146 | }
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/app/src/main/java/com/flask/colorpicker/sample/SampleActivity2.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker.sample;
2 |
3 | import android.os.Bundle;
4 | import androidx.appcompat.app.AppCompatActivity;
5 | import android.util.Log;
6 | import android.widget.Toast;
7 |
8 | import com.flask.colorpicker.ColorPickerView;
9 | import com.flask.colorpicker.OnColorChangedListener;
10 | import com.flask.colorpicker.OnColorSelectedListener;
11 |
12 | public class SampleActivity2 extends AppCompatActivity {
13 |
14 | @Override
15 | protected void onCreate(Bundle savedInstanceState) {
16 | super.onCreate(savedInstanceState);
17 | setContentView(R.layout.activity_sample2);
18 |
19 | ColorPickerView colorPickerView = findViewById(R.id.color_picker_view);
20 | colorPickerView.addOnColorChangedListener(new OnColorChangedListener() {
21 | @Override public void onColorChanged(int selectedColor) {
22 | // Handle on color change
23 | Log.d("ColorPicker", "onColorChanged: 0x" + Integer.toHexString(selectedColor));
24 | }
25 | });
26 | colorPickerView.addOnColorSelectedListener(new OnColorSelectedListener() {
27 | @Override
28 | public void onColorSelected(int selectedColor) {
29 | Toast.makeText(
30 | SampleActivity2.this,
31 | "selectedColor: " + Integer.toHexString(selectedColor).toUpperCase(),
32 | Toast.LENGTH_SHORT).show();
33 | }
34 | });
35 | }
36 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/flask/colorpicker/sample/SampleActivity3.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker.sample;
2 |
3 | import android.os.Bundle;
4 | import androidx.fragment.app.Fragment;
5 | import androidx.fragment.app.FragmentManager;
6 | import androidx.fragment.app.FragmentPagerAdapter;
7 | import androidx.fragment.app.FragmentStatePagerAdapter;
8 | import androidx.viewpager.widget.PagerAdapter;
9 | import androidx.viewpager.widget.ViewPager;
10 | import androidx.appcompat.app.AppCompatActivity;
11 | import androidx.appcompat.widget.Toolbar;
12 | import android.view.LayoutInflater;
13 | import android.view.Menu;
14 | import android.view.MenuItem;
15 | import android.view.View;
16 | import android.view.ViewGroup;
17 | import android.widget.TextView;
18 |
19 | public class SampleActivity3 extends AppCompatActivity {
20 |
21 | /**
22 | * The {@link PagerAdapter} that will provide
23 | * fragments for each of the sections. We use a
24 | * {@link FragmentPagerAdapter} derivative, which will keep every
25 | * loaded fragment in memory. If this becomes too memory intensive, it
26 | * may be best to switch to a
27 | * {@link FragmentStatePagerAdapter}.
28 | */
29 | private SectionsPagerAdapter mSectionsPagerAdapter;
30 |
31 | /**
32 | * The {@link ViewPager} that will host the section contents.
33 | */
34 | private ViewPager mViewPager;
35 |
36 | @Override
37 | protected void onCreate(Bundle savedInstanceState) {
38 | super.onCreate(savedInstanceState);
39 | setContentView(R.layout.activity_sample3);
40 |
41 | Toolbar toolbar = findViewById(R.id.toolbar);
42 | setSupportActionBar(toolbar);
43 | // Create the adapter that will return a fragment for each of the three
44 | // primary sections of the activity.
45 | mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
46 |
47 | // Set up the ViewPager with the sections adapter.
48 | mViewPager = findViewById(R.id.container);
49 | mViewPager.setAdapter(mSectionsPagerAdapter);
50 | }
51 |
52 | @Override
53 | public boolean onCreateOptionsMenu(Menu menu) {
54 | // Inflate the menu; this adds items to the action bar if it is present.
55 | getMenuInflater().inflate(R.menu.menu_sample_activity3, menu);
56 | return true;
57 | }
58 |
59 | @Override
60 | public boolean onOptionsItemSelected(MenuItem item) {
61 | // Handle action bar item clicks here. The action bar will
62 | // automatically handle clicks on the Home/Up button, so long
63 | // as you specify a parent activity in AndroidManifest.xml.
64 | int id = item.getItemId();
65 |
66 | //noinspection SimplifiableIfStatement
67 | if (id == R.id.action_settings) {
68 | return true;
69 | }
70 |
71 | return super.onOptionsItemSelected(item);
72 | }
73 |
74 | /**
75 | * A placeholder fragment containing a simple view.
76 | */
77 | public static class PlaceholderFragment extends Fragment {
78 | /**
79 | * The fragment argument representing the section number for this
80 | * fragment.
81 | */
82 | private static final String ARG_SECTION_NUMBER = "section_number";
83 |
84 | public PlaceholderFragment() {
85 | }
86 |
87 | /**
88 | * Returns a new instance of this fragment for the given section
89 | * number.
90 | */
91 | public static PlaceholderFragment newInstance(int sectionNumber) {
92 | PlaceholderFragment fragment = new PlaceholderFragment();
93 | Bundle args = new Bundle();
94 | args.putInt(ARG_SECTION_NUMBER, sectionNumber);
95 | fragment.setArguments(args);
96 | return fragment;
97 | }
98 |
99 | @Override
100 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
101 | Bundle savedInstanceState) {
102 | View rootView = inflater.inflate(R.layout.fragment_sample_activity3, container, false);
103 | TextView textView = rootView.findViewById(R.id.section_label);
104 | textView.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
105 | return rootView;
106 | }
107 | }
108 |
109 | /**
110 | * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
111 | * one of the sections/tabs/pages.
112 | */
113 | public class SectionsPagerAdapter extends FragmentPagerAdapter {
114 |
115 | public SectionsPagerAdapter(FragmentManager fm) {
116 | super(fm);
117 | }
118 |
119 | @Override
120 | public Fragment getItem(int position) {
121 | // getItem is called to instantiate the fragment for the given page.
122 | // Return a PlaceholderFragment (defined as a static inner class below).
123 | return PlaceholderFragment.newInstance(position + 1);
124 | }
125 |
126 | @Override
127 | public int getCount() {
128 | // Show 3 total pages.
129 | return 3;
130 | }
131 |
132 | @Override
133 | public CharSequence getPageTitle(int position) {
134 | switch (position) {
135 | case 0:
136 | return "SECTION 1";
137 | case 1:
138 | return "SECTION 2";
139 | case 2:
140 | return "SECTION 3";
141 | }
142 | return null;
143 | }
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_github_circle_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuadFlask/colorpicker/ef73ced2172b37f0cbc3259eefd5770b67635b6b/app/src/main/res/drawable-hdpi/ic_github_circle_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuadFlask/colorpicker/ef73ced2172b37f0cbc3259eefd5770b67635b6b/app/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_github_circle_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuadFlask/colorpicker/ef73ced2172b37f0cbc3259eefd5770b67635b6b/app/src/main/res/drawable-mdpi/ic_github_circle_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuadFlask/colorpicker/ef73ced2172b37f0cbc3259eefd5770b67635b6b/app/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_github_circle_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuadFlask/colorpicker/ef73ced2172b37f0cbc3259eefd5770b67635b6b/app/src/main/res/drawable-xhdpi/ic_github_circle_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuadFlask/colorpicker/ef73ced2172b37f0cbc3259eefd5770b67635b6b/app/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_github_circle_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuadFlask/colorpicker/ef73ced2172b37f0cbc3259eefd5770b67635b6b/app/src/main/res/drawable-xxhdpi/ic_github_circle_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuadFlask/colorpicker/ef73ced2172b37f0cbc3259eefd5770b67635b6b/app/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_github_circle_black_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuadFlask/colorpicker/ef73ced2172b37f0cbc3259eefd5770b67635b6b/app/src/main/res/drawable-xxxhdpi/ic_github_circle_black_24dp.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuadFlask/colorpicker/ef73ced2172b37f0cbc3259eefd5770b67635b6b/app/src/main/res/drawable-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/background.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuadFlask/colorpicker/ef73ced2172b37f0cbc3259eefd5770b67635b6b/app/src/main/res/drawable/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/tile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuadFlask/colorpicker/ef73ced2172b37f0cbc3259eefd5770b67635b6b/app/src/main/res/drawable/tile.png
--------------------------------------------------------------------------------
/app/src/main/res/layout-land/fragment_adapted_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
18 |
19 |
24 |
25 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_sample.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
14 |
15 |
23 |
24 |
31 |
37 |
43 |
49 |
55 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_sample2.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
20 |
21 |
26 |
27 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_sample3.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
18 |
19 |
26 |
27 |
28 |
29 |
30 |
31 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_adapted_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
18 |
19 |
23 |
24 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_sample_activity3.xml:
--------------------------------------------------------------------------------
1 |
13 |
14 |
18 |
19 |
30 |
31 |
36 |
37 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_sample_activity3.xml:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 16dp
6 | 8dp
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ColorPicker
3 | Choose color
4 | SampleActivity3
5 | Settings
6 | Hello World from section: %1$d
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/prefs.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
14 |
22 |
30 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | google()
7 | }
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.5.2'
10 |
11 | // NOTE: Do not place your application dependencies here; they belong
12 | // in the individual module build.gradle files
13 | }
14 | }
15 |
16 | allprojects {
17 | repositories {
18 | jcenter()
19 | google()
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/gradle/local.properties:
--------------------------------------------------------------------------------
1 | ## This file is automatically generated by Android Studio.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must *NOT* be checked into Version Control Systems,
5 | # as it contains information specific to your local configuration.
6 | #
7 | # Location of the SDK. This is only used by Gradle.
8 | # For customization when using a Version Control System, please read the
9 | # header note.
10 | #Tue Mar 24 18:54:39 KST 2015
11 | sdk.dir=/Users/flask/Library/Android/sdk
12 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuadFlask/colorpicker/ef73ced2172b37f0cbc3259eefd5770b67635b6b/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Nov 07 22:59:21 KST 2019
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-5.4.1-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 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/library/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/library/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 29
5 | buildToolsVersion "29.0.0"
6 |
7 | defaultConfig {
8 | minSdkVersion 14
9 | targetSdkVersion 29
10 | versionCode 17
11 | versionName "0.0.15"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | implementation fileTree(dir: 'libs', include: ['*.jar'])
23 | implementation 'androidx.appcompat:appcompat:1.1.0'
24 | }
25 |
--------------------------------------------------------------------------------
/library/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/flask/Documents/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 |
--------------------------------------------------------------------------------
/library/src/androidTest/java/com/flask/colorpicker/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker;
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 | }
--------------------------------------------------------------------------------
/library/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/library/src/main/java/com/flask/colorpicker/ColorCircle.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker;
2 |
3 | import android.graphics.Color;
4 |
5 | public class ColorCircle {
6 | private float x, y;
7 | private float[] hsv = new float[3];
8 | private float[] hsvClone;
9 | private int color;
10 |
11 | public ColorCircle(float x, float y, float[] hsv) {
12 | set(x, y, hsv);
13 | }
14 |
15 | public double sqDist(float x, float y) {
16 | double dx = this.x - x;
17 | double dy = this.y - y;
18 | return dx * dx + dy * dy;
19 | }
20 |
21 | public float getX() {
22 | return x;
23 | }
24 |
25 | public float getY() {
26 | return y;
27 | }
28 |
29 | public float[] getHsv() {
30 | return hsv;
31 | }
32 |
33 | public float[] getHsvWithLightness(float lightness) {
34 | if (hsvClone == null)
35 | hsvClone = hsv.clone();
36 | hsvClone[0] = hsv[0];
37 | hsvClone[1] = hsv[1];
38 | hsvClone[2] = lightness;
39 | return hsvClone;
40 | }
41 |
42 | public void set(float x, float y, float[] hsv) {
43 | this.x = x;
44 | this.y = y;
45 | this.hsv[0] = hsv[0];
46 | this.hsv[1] = hsv[1];
47 | this.hsv[2] = hsv[2];
48 | this.color = Color.HSVToColor(this.hsv);
49 | }
50 |
51 | public int getColor() {
52 | return color;
53 | }
54 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/flask/colorpicker/ColorCircleDrawable.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import android.graphics.drawable.ColorDrawable;
6 |
7 | import com.flask.colorpicker.builder.PaintBuilder;
8 |
9 | public class ColorCircleDrawable extends ColorDrawable {
10 | private float strokeWidth;
11 | private Paint strokePaint = PaintBuilder.newPaint().style(Paint.Style.STROKE).stroke(strokeWidth).color(0xff9e9e9e).build();
12 | private Paint fillPaint = PaintBuilder.newPaint().style(Paint.Style.FILL).color(0).build();
13 | private Paint fillBackPaint = PaintBuilder.newPaint().shader(PaintBuilder.createAlphaPatternShader(26)).build();
14 |
15 | public ColorCircleDrawable(int color) {
16 | super(color);
17 | }
18 |
19 | @Override
20 | public void draw(Canvas canvas) {
21 | canvas.drawColor(0);
22 |
23 | int width = canvas.getWidth();
24 | float radius = width / 2f;
25 | strokeWidth = radius / 8f;
26 |
27 | this.strokePaint.setStrokeWidth(strokeWidth);
28 | this.fillPaint.setColor(getColor());
29 | canvas.drawCircle(radius, radius, radius - strokeWidth, fillBackPaint);
30 | canvas.drawCircle(radius, radius, radius - strokeWidth, fillPaint);
31 | canvas.drawCircle(radius, radius, radius - strokeWidth, strokePaint);
32 | }
33 |
34 | @Override
35 | public void setColor(int color) {
36 | super.setColor(color);
37 | invalidateSelf();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/library/src/main/java/com/flask/colorpicker/ColorPickerPreference.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker;
2 |
3 | import android.content.Context;
4 | import android.content.DialogInterface;
5 | import android.content.res.TypedArray;
6 | import android.graphics.Color;
7 | import android.graphics.drawable.Drawable;
8 | import android.preference.Preference;
9 | import androidx.annotation.NonNull;
10 | import android.util.AttributeSet;
11 | import android.view.View;
12 | import android.widget.ImageView;
13 |
14 | import com.flask.colorpicker.builder.ColorPickerClickListener;
15 | import com.flask.colorpicker.builder.ColorPickerDialogBuilder;
16 |
17 | public class ColorPickerPreference extends Preference {
18 |
19 | protected boolean alphaSlider;
20 | protected boolean lightSlider;
21 | protected boolean border;
22 |
23 | protected int selectedColor = 0;
24 |
25 | protected ColorPickerView.WHEEL_TYPE wheelType;
26 | protected int density;
27 |
28 | private boolean pickerColorEdit;
29 | private String pickerTitle;
30 | private String pickerButtonCancel;
31 | private String pickerButtonOk;
32 |
33 | protected ImageView colorIndicator;
34 |
35 | public ColorPickerPreference(Context context) {
36 | super(context);
37 | }
38 |
39 | public ColorPickerPreference(Context context, AttributeSet attrs) {
40 | super(context, attrs);
41 | initWith(context, attrs);
42 | }
43 |
44 | public ColorPickerPreference(Context context, AttributeSet attrs, int defStyleAttr) {
45 | super(context, attrs, defStyleAttr);
46 | initWith(context, attrs);
47 | }
48 |
49 | private void initWith(Context context, AttributeSet attrs) {
50 | final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ColorPickerPreference);
51 |
52 | try {
53 | alphaSlider = typedArray.getBoolean(R.styleable.ColorPickerPreference_alphaSlider, false);
54 | lightSlider = typedArray.getBoolean(R.styleable.ColorPickerPreference_lightnessSlider, false);
55 | border = typedArray.getBoolean(R.styleable.ColorPickerPreference_border, true);
56 |
57 | density = typedArray.getInt(R.styleable.ColorPickerPreference_density, 8);
58 | wheelType = ColorPickerView.WHEEL_TYPE.indexOf(typedArray.getInt(R.styleable.ColorPickerPreference_wheelType, 0));
59 |
60 | selectedColor = typedArray.getInt(R.styleable.ColorPickerPreference_initialColor, 0xffffffff);
61 |
62 | pickerColorEdit = typedArray.getBoolean(R.styleable.ColorPickerPreference_pickerColorEdit, true);
63 | pickerTitle = typedArray.getString(R.styleable.ColorPickerPreference_pickerTitle);
64 | if (pickerTitle==null)
65 | pickerTitle = "Choose color";
66 |
67 | pickerButtonCancel = typedArray.getString(R.styleable.ColorPickerPreference_pickerButtonCancel);
68 | if (pickerButtonCancel==null)
69 | pickerButtonCancel = "cancel";
70 |
71 | pickerButtonOk = typedArray.getString(R.styleable.ColorPickerPreference_pickerButtonOk);
72 | if (pickerButtonOk==null)
73 | pickerButtonOk = "ok";
74 |
75 | } finally {
76 | typedArray.recycle();
77 | }
78 |
79 | setWidgetLayoutResource(R.layout.color_widget);
80 | }
81 |
82 |
83 | @Override
84 | protected void onBindView(@NonNull View view) {
85 | super.onBindView(view);
86 |
87 | int tmpColor = isEnabled()
88 | ? selectedColor
89 | : darken(selectedColor, .5f);
90 |
91 | colorIndicator = (ImageView) view.findViewById(R.id.color_indicator);
92 |
93 | ColorCircleDrawable colorChoiceDrawable = null;
94 | Drawable currentDrawable = colorIndicator.getDrawable();
95 | if (currentDrawable != null && currentDrawable instanceof ColorCircleDrawable)
96 | colorChoiceDrawable = (ColorCircleDrawable) currentDrawable;
97 |
98 | if (colorChoiceDrawable == null)
99 | colorChoiceDrawable = new ColorCircleDrawable(tmpColor);
100 |
101 | colorIndicator.setImageDrawable(colorChoiceDrawable);
102 | }
103 |
104 | public void setValue(int value) {
105 | if (callChangeListener(value)) {
106 | selectedColor = value;
107 | persistInt(value);
108 | notifyChanged();
109 | }
110 | }
111 |
112 | @Override
113 | protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
114 | setValue(restoreValue ? getPersistedInt(0) : (Integer) defaultValue);
115 | }
116 |
117 | @Override
118 | protected void onClick() {
119 | ColorPickerDialogBuilder builder = ColorPickerDialogBuilder
120 | .with(getContext())
121 | .setTitle(pickerTitle)
122 | .initialColor(selectedColor)
123 | .showBorder(border)
124 | .wheelType(wheelType)
125 | .density(density)
126 | .showColorEdit(pickerColorEdit)
127 | .setPositiveButton(pickerButtonOk, new ColorPickerClickListener() {
128 | @Override
129 | public void onClick(DialogInterface dialog, int selectedColorFromPicker, Integer[] allColors) {
130 | setValue(selectedColorFromPicker);
131 | }
132 | })
133 | .setNegativeButton(pickerButtonCancel, null);
134 |
135 | if (!alphaSlider && !lightSlider) builder.noSliders();
136 | else if (!alphaSlider) builder.lightnessSliderOnly();
137 | else if (!lightSlider) builder.alphaSliderOnly();
138 |
139 | builder
140 | .build()
141 | .show();
142 | }
143 |
144 | public static int darken(int color, float factor) {
145 | int a = Color.alpha(color);
146 | int r = Color.red(color);
147 | int g = Color.green(color);
148 | int b = Color.blue(color);
149 |
150 | return Color.argb(a,
151 | Math.max((int)(r * factor), 0),
152 | Math.max((int)(g * factor), 0),
153 | Math.max((int)(b * factor), 0));
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/library/src/main/java/com/flask/colorpicker/ColorPickerView.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.Context;
5 | import android.content.res.TypedArray;
6 | import android.graphics.Bitmap;
7 | import android.graphics.Canvas;
8 | import android.graphics.Color;
9 | import android.graphics.Paint;
10 | import android.graphics.PorterDuff;
11 | import android.text.Editable;
12 | import android.text.TextWatcher;
13 | import android.util.AttributeSet;
14 | import android.view.MotionEvent;
15 | import android.view.View;
16 | import android.widget.EditText;
17 | import android.widget.ImageView;
18 | import android.widget.LinearLayout;
19 |
20 | import com.flask.colorpicker.builder.ColorWheelRendererBuilder;
21 | import com.flask.colorpicker.builder.PaintBuilder;
22 | import com.flask.colorpicker.renderer.ColorWheelRenderOption;
23 | import com.flask.colorpicker.renderer.ColorWheelRenderer;
24 | import com.flask.colorpicker.slider.AlphaSlider;
25 | import com.flask.colorpicker.slider.LightnessSlider;
26 |
27 | import java.util.ArrayList;
28 |
29 | public class ColorPickerView extends View {
30 | private static final float STROKE_RATIO = 1.5f;
31 |
32 | private Bitmap colorWheel;
33 | private Canvas colorWheelCanvas;
34 | private Bitmap currentColor;
35 | private Canvas currentColorCanvas;
36 | private boolean showBorder;
37 | private int density = 8;
38 |
39 | private float lightness = 1;
40 | private float alpha = 1;
41 | private int backgroundColor = 0x00000000;
42 |
43 | private Integer initialColors[] = new Integer[]{null, null, null, null, null};
44 | private int colorSelection = 0;
45 | private Integer initialColor;
46 | private Integer pickerColorEditTextColor;
47 | private Paint colorWheelFill = PaintBuilder.newPaint().color(0).build();
48 | private Paint selectorStroke = PaintBuilder.newPaint().color(0).build();
49 | private Paint alphaPatternPaint = PaintBuilder.newPaint().build();
50 | private ColorCircle currentColorCircle;
51 |
52 | private ArrayList colorChangedListeners = new ArrayList<>();
53 | private ArrayList listeners = new ArrayList<>();
54 |
55 | private LightnessSlider lightnessSlider;
56 | private AlphaSlider alphaSlider;
57 | private EditText colorEdit;
58 | private TextWatcher colorTextChange = new TextWatcher() {
59 | @Override
60 | public void beforeTextChanged(CharSequence s, int start, int count, int after) {
61 | }
62 |
63 | @Override
64 | public void onTextChanged(CharSequence s, int start, int before, int count) {
65 | try {
66 | int color = Color.parseColor(s.toString());
67 |
68 | // set the color without changing the edit text preventing stack overflow
69 | setColor(color, false);
70 | } catch (Exception e) {
71 | e.printStackTrace();
72 | }
73 | }
74 |
75 | @Override
76 | public void afterTextChanged(Editable s) {
77 | }
78 | };
79 | private LinearLayout colorPreview;
80 |
81 | private ColorWheelRenderer renderer;
82 |
83 | private int alphaSliderViewId, lightnessSliderViewId;
84 |
85 | public ColorPickerView(Context context) {
86 | super(context);
87 | initWith(context, null);
88 | }
89 |
90 | public ColorPickerView(Context context, AttributeSet attrs) {
91 | super(context, attrs);
92 | initWith(context, attrs);
93 | }
94 |
95 | public ColorPickerView(Context context, AttributeSet attrs, int defStyleAttr) {
96 | super(context, attrs, defStyleAttr);
97 | initWith(context, attrs);
98 | }
99 |
100 | @TargetApi(21)
101 | public ColorPickerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
102 | super(context, attrs, defStyleAttr, defStyleRes);
103 | initWith(context, attrs);
104 | }
105 |
106 | private void initWith(Context context, AttributeSet attrs) {
107 | final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ColorPickerPreference);
108 |
109 | density = typedArray.getInt(R.styleable.ColorPickerPreference_density, 10);
110 | initialColor = typedArray.getInt(R.styleable.ColorPickerPreference_initialColor, 0xffffffff);
111 |
112 | pickerColorEditTextColor = typedArray.getInt(R.styleable.ColorPickerPreference_pickerColorEditTextColor, 0xffffffff);
113 |
114 | WHEEL_TYPE wheelType = WHEEL_TYPE.indexOf(typedArray.getInt(R.styleable.ColorPickerPreference_wheelType, 0));
115 | ColorWheelRenderer renderer = ColorWheelRendererBuilder.getRenderer(wheelType);
116 |
117 | alphaSliderViewId = typedArray.getResourceId(R.styleable.ColorPickerPreference_alphaSliderView, 0);
118 | lightnessSliderViewId = typedArray.getResourceId(R.styleable.ColorPickerPreference_lightnessSliderView, 0);
119 |
120 | setRenderer(renderer);
121 | setDensity(density);
122 | setInitialColor(initialColor, true);
123 |
124 | typedArray.recycle();
125 | }
126 |
127 | @Override
128 | public void onWindowFocusChanged(boolean hasWindowFocus) {
129 | super.onWindowFocusChanged(hasWindowFocus);
130 | updateColorWheel();
131 | currentColorCircle = findNearestByColor(initialColor);
132 | }
133 |
134 | @Override
135 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
136 | super.onLayout(changed, left, top, right, bottom);
137 |
138 | if (alphaSliderViewId != 0)
139 | setAlphaSlider((AlphaSlider) getRootView().findViewById(alphaSliderViewId));
140 | if (lightnessSliderViewId != 0)
141 | setLightnessSlider((LightnessSlider) getRootView().findViewById(lightnessSliderViewId));
142 |
143 | updateColorWheel();
144 | currentColorCircle = findNearestByColor(initialColor);
145 | }
146 |
147 | @Override
148 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
149 | super.onSizeChanged(w, h, oldw, oldh);
150 | updateColorWheel();
151 | }
152 |
153 | private void updateColorWheel() {
154 | int width = getMeasuredWidth();
155 | int height = getMeasuredHeight();
156 |
157 | if (height < width)
158 | width = height;
159 | if (width <= 0)
160 | return;
161 | if (colorWheel == null || colorWheel.getWidth() != width) {
162 | colorWheel = Bitmap.createBitmap(width, width, Bitmap.Config.ARGB_8888);
163 | colorWheelCanvas = new Canvas(colorWheel);
164 | alphaPatternPaint.setShader(PaintBuilder.createAlphaPatternShader(26));
165 | }
166 | if (currentColor == null || currentColor.getWidth() != width) {
167 | currentColor = Bitmap.createBitmap(width, width, Bitmap.Config.ARGB_8888);
168 | currentColorCanvas = new Canvas(currentColor);
169 | }
170 | drawColorWheel();
171 | invalidate();
172 | }
173 |
174 | private void drawColorWheel() {
175 | colorWheelCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
176 | currentColorCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
177 |
178 | if (renderer == null) return;
179 |
180 | float half = colorWheelCanvas.getWidth() / 2f;
181 | float strokeWidth = STROKE_RATIO * (1f + ColorWheelRenderer.GAP_PERCENTAGE);
182 | float maxRadius = half - strokeWidth - half / density;
183 | float cSize = maxRadius / (density - 1) / 2;
184 |
185 | ColorWheelRenderOption colorWheelRenderOption = renderer.getRenderOption();
186 | colorWheelRenderOption.density = this.density;
187 | colorWheelRenderOption.maxRadius = maxRadius;
188 | colorWheelRenderOption.cSize = cSize;
189 | colorWheelRenderOption.strokeWidth = strokeWidth;
190 | colorWheelRenderOption.alpha = alpha;
191 | colorWheelRenderOption.lightness = lightness;
192 | colorWheelRenderOption.targetCanvas = colorWheelCanvas;
193 |
194 | renderer.initWith(colorWheelRenderOption);
195 | renderer.draw();
196 | }
197 |
198 | @Override
199 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
200 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
201 | int widthMode = MeasureSpec.getMode(widthMeasureSpec);
202 | int width = 0;
203 | if (widthMode == MeasureSpec.UNSPECIFIED)
204 | width = widthMeasureSpec;
205 | else if (widthMode == MeasureSpec.AT_MOST)
206 | width = MeasureSpec.getSize(widthMeasureSpec);
207 | else if (widthMode == MeasureSpec.EXACTLY)
208 | width = MeasureSpec.getSize(widthMeasureSpec);
209 |
210 | int heightMode = MeasureSpec.getMode(heightMeasureSpec);
211 | int height = 0;
212 | if (heightMode == MeasureSpec.UNSPECIFIED)
213 | height = heightMeasureSpec;
214 | else if (heightMode == MeasureSpec.AT_MOST)
215 | height = MeasureSpec.getSize(heightMeasureSpec);
216 | else if (heightMode == MeasureSpec.EXACTLY)
217 | height = MeasureSpec.getSize(heightMeasureSpec);
218 | int squareDimen = width;
219 | if (height < width)
220 | squareDimen = height;
221 | setMeasuredDimension(squareDimen, squareDimen);
222 | }
223 |
224 | @Override
225 | public boolean onTouchEvent(MotionEvent event) {
226 | switch (event.getAction()) {
227 | case MotionEvent.ACTION_DOWN:
228 | case MotionEvent.ACTION_MOVE: {
229 | int lastSelectedColor = getSelectedColor();
230 | currentColorCircle = findNearestByPosition(event.getX(), event.getY());
231 | int selectedColor = getSelectedColor();
232 |
233 | callOnColorChangedListeners(lastSelectedColor, selectedColor);
234 |
235 | initialColor = selectedColor;
236 | setColorToSliders(selectedColor);
237 | updateColorWheel();
238 | invalidate();
239 | break;
240 | }
241 | case MotionEvent.ACTION_UP: {
242 | int selectedColor = getSelectedColor();
243 | if (listeners != null) {
244 | for (OnColorSelectedListener listener : listeners) {
245 | try {
246 | listener.onColorSelected(selectedColor);
247 | } catch (Exception e) {
248 | e.printStackTrace();
249 | }
250 | }
251 | }
252 | setColorToSliders(selectedColor);
253 | setColorText(selectedColor);
254 | setColorPreviewColor(selectedColor);
255 | invalidate();
256 | break;
257 | }
258 | }
259 | return true;
260 | }
261 |
262 | protected void callOnColorChangedListeners(int oldColor, int newColor) {
263 | if (colorChangedListeners != null && oldColor != newColor) {
264 | for (OnColorChangedListener listener : colorChangedListeners) {
265 | try {
266 | listener.onColorChanged(newColor);
267 | } catch (Exception e) {
268 | e.printStackTrace();
269 | }
270 | }
271 | }
272 | }
273 |
274 | @Override
275 | protected void onDraw(Canvas canvas) {
276 | super.onDraw(canvas);
277 | canvas.drawColor(backgroundColor);
278 |
279 | float maxRadius = canvas.getWidth() / (1f + ColorWheelRenderer.GAP_PERCENTAGE);
280 | float size = maxRadius / density / 2;
281 | if (colorWheel != null && currentColorCircle != null) {
282 | colorWheelFill.setColor(Color.HSVToColor(currentColorCircle.getHsvWithLightness(this.lightness)));
283 | colorWheelFill.setAlpha((int) (alpha * 0xff));
284 |
285 | // a separate canvas is used to erase an issue with the alpha pattern around the edges
286 | // draw circle slightly larger than it needs to be, then erase edges to proper dimensions
287 | currentColorCanvas.drawCircle(currentColorCircle.getX(), currentColorCircle.getY(), size + 4, alphaPatternPaint);
288 | currentColorCanvas.drawCircle(currentColorCircle.getX(), currentColorCircle.getY(), size + 4, colorWheelFill);
289 |
290 | selectorStroke = PaintBuilder.newPaint().color(0xffffffff).style(Paint.Style.STROKE).stroke(size * (STROKE_RATIO - 1)).xPerMode(PorterDuff.Mode.CLEAR).build();
291 |
292 | if (showBorder) colorWheelCanvas.drawCircle(currentColorCircle.getX(), currentColorCircle.getY(), size + (selectorStroke.getStrokeWidth() / 2f), selectorStroke);
293 | canvas.drawBitmap(colorWheel, 0, 0, null);
294 |
295 | currentColorCanvas.drawCircle(currentColorCircle.getX(), currentColorCircle.getY(), size + (selectorStroke.getStrokeWidth() / 2f), selectorStroke);
296 | canvas.drawBitmap(currentColor, 0, 0, null);
297 | }
298 | }
299 |
300 | private ColorCircle findNearestByPosition(float x, float y) {
301 | ColorCircle near = null;
302 | double minDist = Double.MAX_VALUE;
303 |
304 | for (ColorCircle colorCircle : renderer.getColorCircleList()) {
305 | double dist = colorCircle.sqDist(x, y);
306 | if (minDist > dist) {
307 | minDist = dist;
308 | near = colorCircle;
309 | }
310 | }
311 |
312 | return near;
313 | }
314 |
315 | private ColorCircle findNearestByColor(int color) {
316 | float[] hsv = new float[3];
317 | Color.colorToHSV(color, hsv);
318 | ColorCircle near = null;
319 | double minDiff = Double.MAX_VALUE;
320 | double x = hsv[1] * Math.cos(hsv[0] * Math.PI / 180);
321 | double y = hsv[1] * Math.sin(hsv[0] * Math.PI / 180);
322 |
323 | for (ColorCircle colorCircle : renderer.getColorCircleList()) {
324 | float[] hsv1 = colorCircle.getHsv();
325 | double x1 = hsv1[1] * Math.cos(hsv1[0] * Math.PI / 180);
326 | double y1 = hsv1[1] * Math.sin(hsv1[0] * Math.PI / 180);
327 | double dx = x - x1;
328 | double dy = y - y1;
329 | double dist = dx * dx + dy * dy;
330 | if (dist < minDiff) {
331 | minDiff = dist;
332 | near = colorCircle;
333 | }
334 | }
335 |
336 | return near;
337 | }
338 |
339 | public int getSelectedColor() {
340 | int color = 0;
341 | if (currentColorCircle != null)
342 | color = Utils.colorAtLightness(currentColorCircle.getColor(), this.lightness);
343 | return Utils.adjustAlpha(this.alpha, color);
344 | }
345 |
346 | public Integer[] getAllColors() {
347 | return initialColors;
348 | }
349 |
350 | public void setInitialColors(Integer[] colors, int selectedColor) {
351 | this.initialColors = colors;
352 | this.colorSelection = selectedColor;
353 | Integer initialColor = this.initialColors[this.colorSelection];
354 | if (initialColor == null) initialColor = 0xffffffff;
355 | setInitialColor(initialColor, true);
356 | }
357 |
358 | public void setInitialColor(int color, boolean updateText) {
359 | float[] hsv = new float[3];
360 | Color.colorToHSV(color, hsv);
361 |
362 | this.alpha = Utils.getAlphaPercent(color);
363 | this.lightness = hsv[2];
364 | this.initialColors[this.colorSelection] = color;
365 | this.initialColor = color;
366 | setColorPreviewColor(color);
367 | setColorToSliders(color);
368 | if (this.colorEdit != null && updateText)
369 | setColorText(color);
370 | currentColorCircle = findNearestByColor(color);
371 | }
372 |
373 | public void setLightness(float lightness) {
374 | int lastSelectedColor = getSelectedColor();
375 |
376 | this.lightness = lightness;
377 | if (currentColorCircle != null) {
378 | this.initialColor = Color.HSVToColor(Utils.alphaValueAsInt(this.alpha), currentColorCircle.getHsvWithLightness(lightness));
379 | if (this.colorEdit != null)
380 | this.colorEdit.setText(Utils.getHexString(this.initialColor, this.alphaSlider != null));
381 | if (this.alphaSlider != null && this.initialColor != null)
382 | this.alphaSlider.setColor(this.initialColor);
383 |
384 | callOnColorChangedListeners(lastSelectedColor, this.initialColor);
385 |
386 | updateColorWheel();
387 | invalidate();
388 | }
389 | }
390 |
391 | public void setColor(int color, boolean updateText) {
392 | setInitialColor(color, updateText);
393 | updateColorWheel();
394 | invalidate();
395 | }
396 |
397 | public void setAlphaValue(float alpha) {
398 | int lastSelectedColor = getSelectedColor();
399 |
400 | this.alpha = alpha;
401 | this.initialColor = Color.HSVToColor(Utils.alphaValueAsInt(this.alpha), currentColorCircle.getHsvWithLightness(this.lightness));
402 | if (this.colorEdit != null)
403 | this.colorEdit.setText(Utils.getHexString(this.initialColor, this.alphaSlider != null));
404 | if (this.lightnessSlider != null && this.initialColor != null)
405 | this.lightnessSlider.setColor(this.initialColor);
406 |
407 | callOnColorChangedListeners(lastSelectedColor, this.initialColor);
408 |
409 | updateColorWheel();
410 | invalidate();
411 | }
412 |
413 | public void addOnColorChangedListener(OnColorChangedListener listener) {
414 | this.colorChangedListeners.add(listener);
415 | }
416 |
417 | public void addOnColorSelectedListener(OnColorSelectedListener listener) {
418 | this.listeners.add(listener);
419 | }
420 |
421 | public void setLightnessSlider(LightnessSlider lightnessSlider) {
422 | this.lightnessSlider = lightnessSlider;
423 | if (lightnessSlider != null) {
424 | this.lightnessSlider.setColorPicker(this);
425 | this.lightnessSlider.setColor(getSelectedColor());
426 | }
427 | }
428 |
429 | public void setAlphaSlider(AlphaSlider alphaSlider) {
430 | this.alphaSlider = alphaSlider;
431 | if (alphaSlider != null) {
432 | this.alphaSlider.setColorPicker(this);
433 | this.alphaSlider.setColor(getSelectedColor());
434 | }
435 | }
436 |
437 | public void setColorEdit(EditText colorEdit) {
438 | this.colorEdit = colorEdit;
439 | if (this.colorEdit != null) {
440 | this.colorEdit.setVisibility(View.VISIBLE);
441 | this.colorEdit.addTextChangedListener(colorTextChange);
442 | setColorEditTextColor(pickerColorEditTextColor);
443 | }
444 | }
445 |
446 | public void setColorEditTextColor(int argb) {
447 | this.pickerColorEditTextColor = argb;
448 | if (colorEdit != null)
449 | colorEdit.setTextColor(argb);
450 | }
451 |
452 | public void setDensity(int density) {
453 | this.density = Math.max(2, density);
454 | invalidate();
455 | }
456 |
457 | public void setRenderer(ColorWheelRenderer renderer) {
458 | this.renderer = renderer;
459 | invalidate();
460 | }
461 |
462 | public void setColorPreview(LinearLayout colorPreview, Integer selectedColor) {
463 | if (colorPreview == null)
464 | return;
465 | this.colorPreview = colorPreview;
466 | if (selectedColor == null)
467 | selectedColor = 0;
468 | int children = colorPreview.getChildCount();
469 | if (children == 0 || colorPreview.getVisibility() != View.VISIBLE)
470 | return;
471 |
472 | for (int i = 0; i < children; i++) {
473 | View childView = colorPreview.getChildAt(i);
474 | if (!(childView instanceof LinearLayout))
475 | continue;
476 | LinearLayout childLayout = (LinearLayout) childView;
477 | if (i == selectedColor) {
478 | childLayout.setBackgroundColor(Color.WHITE);
479 | }
480 | ImageView childImage = (ImageView) childLayout.findViewById(R.id.image_preview);
481 | childImage.setClickable(true);
482 | childImage.setTag(i);
483 | childImage.setOnClickListener(new OnClickListener() {
484 | @Override
485 | public void onClick(View v) {
486 | if (v == null)
487 | return;
488 | Object tag = v.getTag();
489 | if (tag == null || !(tag instanceof Integer))
490 | return;
491 | setSelectedColor((int) tag);
492 | }
493 | });
494 | }
495 | }
496 |
497 | public void setSelectedColor(int previewNumber) {
498 | if (initialColors == null || initialColors.length < previewNumber)
499 | return;
500 | this.colorSelection = previewNumber;
501 | setHighlightedColor(previewNumber);
502 | Integer color = initialColors[previewNumber];
503 | if (color == null)
504 | return;
505 | setColor(color, true);
506 | }
507 |
508 | public void setShowBorder(boolean showBorder) {
509 | this.showBorder = showBorder;
510 | }
511 |
512 | private void setHighlightedColor(int previewNumber) {
513 | int children = colorPreview.getChildCount();
514 | if (children == 0 || colorPreview.getVisibility() != View.VISIBLE)
515 | return;
516 |
517 | for (int i = 0; i < children; i++) {
518 | View childView = colorPreview.getChildAt(i);
519 | if (!(childView instanceof LinearLayout))
520 | continue;
521 | LinearLayout childLayout = (LinearLayout) childView;
522 | if (i == previewNumber) {
523 | childLayout.setBackgroundColor(Color.WHITE);
524 | } else {
525 | childLayout.setBackgroundColor(Color.TRANSPARENT);
526 | }
527 | }
528 | }
529 |
530 | private void setColorPreviewColor(int newColor) {
531 | if (colorPreview == null || initialColors == null || colorSelection > initialColors.length || initialColors[colorSelection] == null)
532 | return;
533 |
534 | int children = colorPreview.getChildCount();
535 | if (children == 0 || colorPreview.getVisibility() != View.VISIBLE)
536 | return;
537 |
538 | View childView = colorPreview.getChildAt(colorSelection);
539 | if (!(childView instanceof LinearLayout))
540 | return;
541 | LinearLayout childLayout = (LinearLayout) childView;
542 | ImageView childImage = (ImageView) childLayout.findViewById(R.id.image_preview);
543 | childImage.setImageDrawable(new ColorCircleDrawable(newColor));
544 | }
545 |
546 | private void setColorText(int argb) {
547 | if (colorEdit == null)
548 | return;
549 | colorEdit.setText(Utils.getHexString(argb, this.alphaSlider != null));
550 | }
551 |
552 | private void setColorToSliders(int selectedColor) {
553 | if (lightnessSlider != null)
554 | lightnessSlider.setColor(selectedColor);
555 | if (alphaSlider != null)
556 | alphaSlider.setColor(selectedColor);
557 | }
558 |
559 | public enum WHEEL_TYPE {
560 | FLOWER, CIRCLE;
561 |
562 | public static WHEEL_TYPE indexOf(int index) {
563 | switch (index) {
564 | case 0:
565 | return FLOWER;
566 | case 1:
567 | return CIRCLE;
568 | }
569 | return FLOWER;
570 | }
571 | }
572 | }
573 |
--------------------------------------------------------------------------------
/library/src/main/java/com/flask/colorpicker/OnColorChangedListener.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker;
2 |
3 | public interface OnColorChangedListener {
4 | void onColorChanged(int selectedColor);
5 | }
6 |
--------------------------------------------------------------------------------
/library/src/main/java/com/flask/colorpicker/OnColorSelectedListener.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker;
2 |
3 | public interface OnColorSelectedListener {
4 | void onColorSelected(int selectedColor);
5 | }
6 |
--------------------------------------------------------------------------------
/library/src/main/java/com/flask/colorpicker/Utils.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker;
2 |
3 | import android.graphics.Color;
4 |
5 | /**
6 | * Created by Charles Andersons on 4/17/15.
7 | */
8 | public class Utils {
9 | public static float getAlphaPercent(int argb) {
10 | return Color.alpha(argb) / 255f;
11 | }
12 |
13 | public static int alphaValueAsInt(float alpha) {
14 | return Math.round(alpha * 255);
15 | }
16 |
17 | public static int adjustAlpha(float alpha, int color) {
18 | return alphaValueAsInt(alpha) << 24 | (0x00ffffff & color);
19 | }
20 |
21 | public static int colorAtLightness(int color, float lightness) {
22 | float[] hsv = new float[3];
23 | Color.colorToHSV(color, hsv);
24 | hsv[2] = lightness;
25 | return Color.HSVToColor(hsv);
26 | }
27 |
28 | public static float lightnessOfColor(int color) {
29 | float[] hsv = new float[3];
30 | Color.colorToHSV(color, hsv);
31 | return hsv[2];
32 | }
33 |
34 | public static String getHexString(int color, boolean showAlpha) {
35 | int base = showAlpha ? 0xFFFFFFFF : 0xFFFFFF;
36 | String format = showAlpha ? "#%08X" : "#%06X";
37 | return String.format(format, (base & color)).toUpperCase();
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/library/src/main/java/com/flask/colorpicker/builder/ColorPickerClickListener.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker.builder;
2 |
3 | import android.content.DialogInterface;
4 |
5 | /**
6 | * Created by Charles Anderson on 4/17/15.
7 | */
8 | public interface ColorPickerClickListener {
9 | void onClick(DialogInterface d, int lastSelectedColor, Integer[] allColors);
10 | }
11 |
--------------------------------------------------------------------------------
/library/src/main/java/com/flask/colorpicker/builder/ColorPickerDialogBuilder.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker.builder;
2 |
3 | import androidx.appcompat.app.AlertDialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.graphics.Color;
7 | import android.graphics.drawable.ColorDrawable;
8 | import android.text.InputFilter;
9 | import android.view.Gravity;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 | import android.widget.EditText;
13 | import android.widget.ImageView;
14 | import android.widget.LinearLayout;
15 |
16 | import com.flask.colorpicker.ColorPickerView;
17 | import com.flask.colorpicker.OnColorChangedListener;
18 | import com.flask.colorpicker.OnColorSelectedListener;
19 | import com.flask.colorpicker.R;
20 | import com.flask.colorpicker.Utils;
21 | import com.flask.colorpicker.renderer.ColorWheelRenderer;
22 | import com.flask.colorpicker.slider.AlphaSlider;
23 | import com.flask.colorpicker.slider.LightnessSlider;
24 |
25 | public class ColorPickerDialogBuilder {
26 | private AlertDialog.Builder builder;
27 | private LinearLayout pickerContainer;
28 | private ColorPickerView colorPickerView;
29 | private LightnessSlider lightnessSlider;
30 | private AlphaSlider alphaSlider;
31 | private EditText colorEdit;
32 | private LinearLayout colorPreview;
33 |
34 | private boolean isLightnessSliderEnabled = true;
35 | private boolean isAlphaSliderEnabled = true;
36 | private boolean isBorderEnabled = true;
37 | private boolean isColorEditEnabled = false;
38 | private boolean isPreviewEnabled = false;
39 | private int pickerCount = 1;
40 | private int defaultMargin = 0;
41 | private int defaultMarginTop = 0;
42 | private Integer[] initialColor = new Integer[]{null, null, null, null, null};
43 |
44 | private ColorPickerDialogBuilder(Context context) {
45 | this(context, 0);
46 | }
47 |
48 | private ColorPickerDialogBuilder(Context context, int theme) {
49 | defaultMargin = getDimensionAsPx(context, R.dimen.default_slider_margin);
50 | defaultMarginTop = getDimensionAsPx(context, R.dimen.default_margin_top);
51 |
52 | builder = new AlertDialog.Builder(context, theme);
53 | pickerContainer = new LinearLayout(context);
54 | pickerContainer.setOrientation(LinearLayout.VERTICAL);
55 | pickerContainer.setGravity(Gravity.CENTER_HORIZONTAL);
56 | pickerContainer.setPadding(defaultMargin, defaultMarginTop, defaultMargin, 0);
57 |
58 | LinearLayout.LayoutParams layoutParamsForColorPickerView = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0);
59 | layoutParamsForColorPickerView.weight = 1;
60 | colorPickerView = new ColorPickerView(context);
61 |
62 | pickerContainer.addView(colorPickerView, layoutParamsForColorPickerView);
63 |
64 | builder.setView(pickerContainer);
65 | }
66 |
67 | public static ColorPickerDialogBuilder with(Context context) {
68 | return new ColorPickerDialogBuilder(context);
69 | }
70 |
71 | public static ColorPickerDialogBuilder with(Context context, int theme) {
72 | return new ColorPickerDialogBuilder(context, theme);
73 | }
74 |
75 | public ColorPickerDialogBuilder setTitle(String title) {
76 | builder.setTitle(title);
77 | return this;
78 | }
79 |
80 | public ColorPickerDialogBuilder setTitle(int titleId) {
81 | builder.setTitle(titleId);
82 | return this;
83 | }
84 |
85 | public ColorPickerDialogBuilder initialColor(int initialColor) {
86 | this.initialColor[0] = initialColor;
87 | return this;
88 | }
89 |
90 | public ColorPickerDialogBuilder initialColors(int[] initialColor) {
91 | for (int i = 0; i < initialColor.length && i < this.initialColor.length; i++) {
92 | this.initialColor[i] = initialColor[i];
93 | }
94 | return this;
95 | }
96 |
97 | public ColorPickerDialogBuilder wheelType(ColorPickerView.WHEEL_TYPE wheelType) {
98 | ColorWheelRenderer renderer = ColorWheelRendererBuilder.getRenderer(wheelType);
99 | colorPickerView.setRenderer(renderer);
100 | return this;
101 | }
102 |
103 | public ColorPickerDialogBuilder density(int density) {
104 | colorPickerView.setDensity(density);
105 | return this;
106 | }
107 |
108 | public ColorPickerDialogBuilder setOnColorChangedListener(OnColorChangedListener onColorChangedListener) {
109 | colorPickerView.addOnColorChangedListener(onColorChangedListener);
110 | return this;
111 | }
112 |
113 | public ColorPickerDialogBuilder setOnColorSelectedListener(OnColorSelectedListener onColorSelectedListener) {
114 | colorPickerView.addOnColorSelectedListener(onColorSelectedListener);
115 | return this;
116 | }
117 |
118 | public ColorPickerDialogBuilder setPositiveButton(CharSequence text, final ColorPickerClickListener onClickListener) {
119 | builder.setPositiveButton(text, new DialogInterface.OnClickListener() {
120 | @Override
121 | public void onClick(DialogInterface dialog, int which) {
122 | positiveButtonOnClick(dialog, onClickListener);
123 | }
124 | });
125 | return this;
126 | }
127 |
128 | public ColorPickerDialogBuilder setPositiveButton(int textId, final ColorPickerClickListener onClickListener) {
129 | builder.setPositiveButton(textId, new DialogInterface.OnClickListener() {
130 | @Override
131 | public void onClick(DialogInterface dialog, int which) {
132 | positiveButtonOnClick(dialog, onClickListener);
133 | }
134 | });
135 | return this;
136 | }
137 |
138 | public ColorPickerDialogBuilder setNegativeButton(CharSequence text, DialogInterface.OnClickListener onClickListener) {
139 | builder.setNegativeButton(text, onClickListener);
140 | return this;
141 | }
142 |
143 | public ColorPickerDialogBuilder setNegativeButton(int textId, DialogInterface.OnClickListener onClickListener) {
144 | builder.setNegativeButton(textId, onClickListener);
145 | return this;
146 | }
147 |
148 | public ColorPickerDialogBuilder noSliders() {
149 | isLightnessSliderEnabled = false;
150 | isAlphaSliderEnabled = false;
151 | return this;
152 | }
153 |
154 | public ColorPickerDialogBuilder alphaSliderOnly() {
155 | isLightnessSliderEnabled = false;
156 | isAlphaSliderEnabled = true;
157 | return this;
158 | }
159 |
160 | public ColorPickerDialogBuilder lightnessSliderOnly() {
161 | isLightnessSliderEnabled = true;
162 | isAlphaSliderEnabled = false;
163 | return this;
164 | }
165 |
166 | public ColorPickerDialogBuilder showAlphaSlider(boolean showAlpha) {
167 | isAlphaSliderEnabled = showAlpha;
168 | return this;
169 | }
170 |
171 | public ColorPickerDialogBuilder showLightnessSlider(boolean showLightness) {
172 | isLightnessSliderEnabled = showLightness;
173 | return this;
174 | }
175 |
176 | public ColorPickerDialogBuilder showBorder(boolean showBorder) {
177 | isBorderEnabled = showBorder;
178 | return this;
179 | }
180 |
181 | public ColorPickerDialogBuilder showColorEdit(boolean showEdit) {
182 | isColorEditEnabled = showEdit;
183 | return this;
184 | }
185 |
186 | public ColorPickerDialogBuilder setColorEditTextColor(int argb) {
187 | colorPickerView.setColorEditTextColor(argb);
188 | return this;
189 | }
190 |
191 | public ColorPickerDialogBuilder showColorPreview(boolean showPreview) {
192 | isPreviewEnabled = showPreview;
193 | if (!showPreview)
194 | pickerCount = 1;
195 | return this;
196 | }
197 |
198 | public ColorPickerDialogBuilder setPickerCount(int pickerCount) throws IndexOutOfBoundsException {
199 | if (pickerCount < 1 || pickerCount > 5)
200 | throw new IndexOutOfBoundsException("Picker Can Only Support 1-5 Colors");
201 | this.pickerCount = pickerCount;
202 | if (this.pickerCount > 1)
203 | this.isPreviewEnabled = true;
204 | return this;
205 | }
206 |
207 | public AlertDialog build() {
208 | Context context = builder.getContext();
209 | colorPickerView.setInitialColors(initialColor, getStartOffset(initialColor));
210 | colorPickerView.setShowBorder(isBorderEnabled);
211 |
212 | if (isLightnessSliderEnabled) {
213 | LinearLayout.LayoutParams layoutParamsForLightnessBar = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getDimensionAsPx(context, R.dimen.default_slider_height));
214 | lightnessSlider = new LightnessSlider(context);
215 | lightnessSlider.setLayoutParams(layoutParamsForLightnessBar);
216 | pickerContainer.addView(lightnessSlider);
217 | colorPickerView.setLightnessSlider(lightnessSlider);
218 | lightnessSlider.setColor(getStartColor(initialColor));
219 | lightnessSlider.setShowBorder(isBorderEnabled);
220 | }
221 | if (isAlphaSliderEnabled) {
222 | LinearLayout.LayoutParams layoutParamsForAlphaBar = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getDimensionAsPx(context, R.dimen.default_slider_height));
223 | alphaSlider = new AlphaSlider(context);
224 | alphaSlider.setLayoutParams(layoutParamsForAlphaBar);
225 | pickerContainer.addView(alphaSlider);
226 | colorPickerView.setAlphaSlider(alphaSlider);
227 | alphaSlider.setColor(getStartColor(initialColor));
228 | alphaSlider.setShowBorder(isBorderEnabled);
229 | }
230 | if (isColorEditEnabled) {
231 | LinearLayout.LayoutParams layoutParamsForColorEdit = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
232 | colorEdit = (EditText) View.inflate(context, R.layout.color_edit, null);
233 | colorEdit.setFilters(new InputFilter[]{new InputFilter.AllCaps()});
234 | colorEdit.setSingleLine();
235 | colorEdit.setVisibility(View.GONE);
236 |
237 | // limit number of characters to hexColors
238 | int maxLength = isAlphaSliderEnabled ? 9 : 7;
239 | colorEdit.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength)});
240 |
241 | pickerContainer.addView(colorEdit, layoutParamsForColorEdit);
242 |
243 | colorEdit.setText(Utils.getHexString(getStartColor(initialColor), isAlphaSliderEnabled));
244 | colorPickerView.setColorEdit(colorEdit);
245 | }
246 | if (isPreviewEnabled) {
247 | colorPreview = (LinearLayout) View.inflate(context, R.layout.color_preview, null);
248 | colorPreview.setVisibility(View.GONE);
249 | pickerContainer.addView(colorPreview);
250 |
251 | if (initialColor.length == 0) {
252 | ImageView colorImage = (ImageView) View.inflate(context, R.layout.color_selector, null);
253 | colorImage.setImageDrawable(new ColorDrawable(Color.WHITE));
254 | } else {
255 | for (int i = 0; i < initialColor.length && i < this.pickerCount; i++) {
256 | if (initialColor[i] == null)
257 | break;
258 | LinearLayout colorLayout = (LinearLayout) View.inflate(context, R.layout.color_selector, null);
259 | ImageView colorImage = (ImageView) colorLayout.findViewById(R.id.image_preview);
260 | colorImage.setImageDrawable(new ColorDrawable(initialColor[i]));
261 | colorPreview.addView(colorLayout);
262 | }
263 | }
264 | colorPreview.setVisibility(View.VISIBLE);
265 | colorPickerView.setColorPreview(colorPreview, getStartOffset(initialColor));
266 | }
267 |
268 | return builder.create();
269 | }
270 |
271 | private Integer getStartOffset(Integer[] colors) {
272 | Integer start = 0;
273 | for (int i = 0; i < colors.length; i++) {
274 | if (colors[i] == null) {
275 | return start;
276 | }
277 | start = (i + 1) / 2;
278 | }
279 | return start;
280 | }
281 |
282 | private int getStartColor(Integer[] colors) {
283 | Integer startColor = getStartOffset(colors);
284 | return startColor == null ? Color.WHITE : colors[startColor];
285 | }
286 |
287 | private static int getDimensionAsPx(Context context, int rid) {
288 | return (int) (context.getResources().getDimension(rid) + .5f);
289 | }
290 |
291 | private void positiveButtonOnClick(DialogInterface dialog, ColorPickerClickListener onClickListener) {
292 | int selectedColor = colorPickerView.getSelectedColor();
293 | Integer[] allColors = colorPickerView.getAllColors();
294 | onClickListener.onClick(dialog, selectedColor, allColors);
295 | }
296 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/flask/colorpicker/builder/ColorWheelRendererBuilder.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker.builder;
2 |
3 | import com.flask.colorpicker.ColorPickerView;
4 | import com.flask.colorpicker.renderer.ColorWheelRenderer;
5 | import com.flask.colorpicker.renderer.FlowerColorWheelRenderer;
6 | import com.flask.colorpicker.renderer.SimpleColorWheelRenderer;
7 |
8 | public class ColorWheelRendererBuilder {
9 | public static ColorWheelRenderer getRenderer(ColorPickerView.WHEEL_TYPE wheelType) {
10 | switch (wheelType) {
11 | case CIRCLE:
12 | return new SimpleColorWheelRenderer();
13 | case FLOWER:
14 | return new FlowerColorWheelRenderer();
15 | }
16 | throw new IllegalArgumentException("wrong WHEEL_TYPE");
17 | }
18 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/flask/colorpicker/builder/PaintBuilder.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker.builder;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.BitmapShader;
5 | import android.graphics.Canvas;
6 | import android.graphics.Paint;
7 | import android.graphics.PorterDuff;
8 | import android.graphics.PorterDuffXfermode;
9 | import android.graphics.Shader;
10 |
11 | public class PaintBuilder {
12 | public static PaintHolder newPaint() {
13 | return new PaintHolder();
14 | }
15 |
16 | public static class PaintHolder {
17 | private Paint paint;
18 |
19 | private PaintHolder() {
20 | this.paint = new Paint(Paint.ANTI_ALIAS_FLAG);
21 | }
22 |
23 | public PaintHolder color(int color) {
24 | this.paint.setColor(color);
25 | return this;
26 | }
27 |
28 | public PaintHolder antiAlias(boolean flag) {
29 | this.paint.setAntiAlias(flag);
30 | return this;
31 | }
32 |
33 | public PaintHolder style(Paint.Style style) {
34 | this.paint.setStyle(style);
35 | return this;
36 | }
37 |
38 | public PaintHolder mode(PorterDuff.Mode mode) {
39 | this.paint.setXfermode(new PorterDuffXfermode(mode));
40 | return this;
41 | }
42 |
43 | public PaintHolder stroke(float width) {
44 | this.paint.setStrokeWidth(width);
45 | return this;
46 | }
47 |
48 | public PaintHolder xPerMode(PorterDuff.Mode mode) {
49 | this.paint.setXfermode(new PorterDuffXfermode(mode));
50 | return this;
51 | }
52 |
53 | public PaintHolder shader(Shader shader) {
54 | this.paint.setShader(shader);
55 | return this;
56 | }
57 |
58 | public Paint build() {
59 | return this.paint;
60 | }
61 | }
62 |
63 | public static Shader createAlphaPatternShader(int size) {
64 | size /= 2;
65 | size = Math.max(8, size * 2);
66 | return new BitmapShader(createAlphaBackgroundPattern(size), Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
67 | }
68 |
69 | private static Bitmap createAlphaBackgroundPattern(int size) {
70 | Paint alphaPatternPaint = PaintBuilder.newPaint().build();
71 | Bitmap bm = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
72 | Canvas c = new Canvas(bm);
73 | int s = Math.round(size / 2f);
74 | for (int i = 0; i < 2; i++)
75 | for (int j = 0; j < 2; j++) {
76 | if ((i + j) % 2 == 0) alphaPatternPaint.setColor(0xffffffff);
77 | else alphaPatternPaint.setColor(0xffd0d0d0);
78 | c.drawRect(i * s, j * s, (i + 1) * s, (j + 1) * s, alphaPatternPaint);
79 | }
80 | return bm;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/library/src/main/java/com/flask/colorpicker/renderer/AbsColorWheelRenderer.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker.renderer;
2 |
3 | import com.flask.colorpicker.ColorCircle;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | public abstract class AbsColorWheelRenderer implements ColorWheelRenderer {
9 | protected ColorWheelRenderOption colorWheelRenderOption;
10 | protected List colorCircleList = new ArrayList<>();
11 |
12 | public void initWith(ColorWheelRenderOption colorWheelRenderOption) {
13 | this.colorWheelRenderOption = colorWheelRenderOption;
14 | this.colorCircleList.clear();
15 | }
16 |
17 | @Override
18 | public ColorWheelRenderOption getRenderOption() {
19 | if (colorWheelRenderOption == null) colorWheelRenderOption = new ColorWheelRenderOption();
20 | return colorWheelRenderOption;
21 | }
22 |
23 | public List getColorCircleList() {
24 | return colorCircleList;
25 | }
26 |
27 | protected int getAlphaValueAsInt() {
28 | return Math.round(colorWheelRenderOption.alpha * 255);
29 | }
30 |
31 | protected int calcTotalCount(float radius, float size) {
32 | return Math.max(1, (int) ((1f - GAP_PERCENTAGE) * Math.PI / (Math.asin(size / radius)) + 0.5f));
33 | }
34 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/flask/colorpicker/renderer/ColorWheelRenderOption.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker.renderer;
2 |
3 | import android.graphics.Canvas;
4 |
5 | public class ColorWheelRenderOption {
6 | public int density;
7 | public float maxRadius;
8 | public float cSize, strokeWidth, alpha, lightness;
9 | public Canvas targetCanvas;
10 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/flask/colorpicker/renderer/ColorWheelRenderer.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker.renderer;
2 |
3 | import com.flask.colorpicker.ColorCircle;
4 |
5 | import java.util.List;
6 |
7 | public interface ColorWheelRenderer {
8 | float GAP_PERCENTAGE = 0.025f;
9 |
10 | void draw();
11 |
12 | ColorWheelRenderOption getRenderOption();
13 |
14 | void initWith(ColorWheelRenderOption colorWheelRenderOption);
15 |
16 | List getColorCircleList();
17 | }
18 |
--------------------------------------------------------------------------------
/library/src/main/java/com/flask/colorpicker/renderer/FlowerColorWheelRenderer.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker.renderer;
2 |
3 | import android.graphics.Color;
4 | import android.graphics.Paint;
5 |
6 | import com.flask.colorpicker.ColorCircle;
7 | import com.flask.colorpicker.builder.PaintBuilder;
8 |
9 | public class FlowerColorWheelRenderer extends AbsColorWheelRenderer {
10 | private Paint selectorFill = PaintBuilder.newPaint().build();
11 | private float[] hsv = new float[3];
12 | private float sizeJitter = 1.2f;
13 |
14 | @Override
15 | public void draw() {
16 | final int setSize = colorCircleList.size();
17 | int currentCount = 0;
18 | float half = colorWheelRenderOption.targetCanvas.getWidth() / 2f;
19 | int density = colorWheelRenderOption.density;
20 | float strokeWidth = colorWheelRenderOption.strokeWidth;
21 | float maxRadius = colorWheelRenderOption.maxRadius;
22 | float cSize = colorWheelRenderOption.cSize;
23 |
24 | for (int i = 0; i < density; i++) {
25 | float p = (float) i / (density - 1); // 0~1
26 | float jitter = (i - density / 2f) / density; // -0.5 ~ 0.5
27 | float radius = maxRadius * p;
28 | float size = Math.max(1.5f + strokeWidth, cSize + (i == 0 ? 0 : cSize * sizeJitter * jitter));
29 | int total = Math.min(calcTotalCount(radius, size), density * 2);
30 |
31 | for (int j = 0; j < total; j++) {
32 | double angle = Math.PI * 2 * j / total + (Math.PI / total) * ((i + 1) % 2);
33 | float x = half + (float) (radius * Math.cos(angle));
34 | float y = half + (float) (radius * Math.sin(angle));
35 | hsv[0] = (float) (angle * 180 / Math.PI);
36 | hsv[1] = radius / maxRadius;
37 | hsv[2] = colorWheelRenderOption.lightness;
38 | selectorFill.setColor(Color.HSVToColor(hsv));
39 | selectorFill.setAlpha(getAlphaValueAsInt());
40 |
41 | colorWheelRenderOption.targetCanvas.drawCircle(x, y, size - strokeWidth, selectorFill);
42 |
43 | if (currentCount >= setSize) {
44 | colorCircleList.add(new ColorCircle(x, y, hsv));
45 | } else colorCircleList.get(currentCount).set(x, y, hsv);
46 | currentCount++;
47 | }
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/flask/colorpicker/renderer/SimpleColorWheelRenderer.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker.renderer;
2 |
3 | import android.graphics.Color;
4 | import android.graphics.Paint;
5 |
6 | import com.flask.colorpicker.ColorCircle;
7 | import com.flask.colorpicker.builder.PaintBuilder;
8 |
9 | public class SimpleColorWheelRenderer extends AbsColorWheelRenderer {
10 | private Paint selectorFill = PaintBuilder.newPaint().build();
11 | private float[] hsv = new float[3];
12 |
13 | @Override
14 | public void draw() {
15 | final int setSize = colorCircleList.size();
16 | int currentCount = 0;
17 | float half = colorWheelRenderOption.targetCanvas.getWidth() / 2f;
18 | int density = colorWheelRenderOption.density;
19 | float maxRadius = colorWheelRenderOption.maxRadius;
20 |
21 | for (int i = 0; i < density; i++) {
22 | float p = (float) i / (density - 1); // 0~1
23 | float radius = maxRadius * p;
24 | float size = colorWheelRenderOption.cSize;
25 | int total = calcTotalCount(radius, size);
26 |
27 | for (int j = 0; j < total; j++) {
28 | double angle = Math.PI * 2 * j / total + (Math.PI / total) * ((i + 1) % 2);
29 | float x = half + (float) (radius * Math.cos(angle));
30 | float y = half + (float) (radius * Math.sin(angle));
31 | hsv[0] = (float) (angle * 180 / Math.PI);
32 | hsv[1] = radius / maxRadius;
33 | hsv[2] = colorWheelRenderOption.lightness;
34 | selectorFill.setColor(Color.HSVToColor(hsv));
35 | selectorFill.setAlpha(getAlphaValueAsInt());
36 |
37 | colorWheelRenderOption.targetCanvas.drawCircle(x, y, size - colorWheelRenderOption.strokeWidth, selectorFill);
38 |
39 | if (currentCount >= setSize)
40 | colorCircleList.add(new ColorCircle(x, y, hsv));
41 | else colorCircleList.get(currentCount).set(x, y, hsv);
42 | currentCount++;
43 | }
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/flask/colorpicker/slider/AbsCustomSlider.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker.slider;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Bitmap;
6 | import android.graphics.Canvas;
7 | import android.graphics.PorterDuff;
8 | import androidx.annotation.DimenRes;
9 | import android.util.AttributeSet;
10 | import android.view.MotionEvent;
11 | import android.view.View;
12 |
13 | import com.flask.colorpicker.R;
14 |
15 | public abstract class AbsCustomSlider extends View {
16 | protected Bitmap bitmap;
17 | protected Canvas bitmapCanvas;
18 | protected Bitmap bar;
19 | protected Canvas barCanvas;
20 | protected OnValueChangedListener onValueChangedListener;
21 | protected int barOffsetX;
22 | protected int handleRadius = 20;
23 | protected int barHeight = 5;
24 | protected float value = 1;
25 | protected boolean showBorder = false;
26 |
27 | private boolean inVerticalOrientation = false;
28 |
29 | public AbsCustomSlider(Context context) {
30 | super(context);
31 | init(context, null);
32 | }
33 |
34 | public AbsCustomSlider(Context context, AttributeSet attrs) {
35 | super(context, attrs);
36 | init(context, attrs);
37 | }
38 |
39 | public AbsCustomSlider(Context context, AttributeSet attrs, int defStyleAttr) {
40 | super(context, attrs, defStyleAttr);
41 | init(context, attrs);
42 | }
43 |
44 | private void init(Context context, AttributeSet attrs) {
45 | TypedArray styledAttrs = context.getTheme().obtainStyledAttributes(
46 | attrs, R.styleable.AbsCustomSlider, 0, 0);
47 | try {
48 | inVerticalOrientation = styledAttrs.getBoolean(
49 | R.styleable.AbsCustomSlider_inVerticalOrientation, inVerticalOrientation);
50 | } finally {
51 | styledAttrs.recycle();
52 | }
53 | }
54 |
55 | protected void updateBar() {
56 | handleRadius = getDimension(R.dimen.default_slider_handler_radius);
57 | barHeight = getDimension(R.dimen.default_slider_bar_height);
58 | barOffsetX = handleRadius;
59 |
60 | if (bar == null)
61 | createBitmaps();
62 | drawBar(barCanvas);
63 | invalidate();
64 | }
65 |
66 | protected void createBitmaps() {
67 | int width;
68 | int height;
69 | if (inVerticalOrientation) {
70 | width = getHeight();
71 | height = getWidth();
72 | } else {
73 | width = getWidth();
74 | height = getHeight();
75 | }
76 |
77 | bar = Bitmap.createBitmap(Math.max(width - barOffsetX * 2, 1), barHeight, Bitmap.Config.ARGB_8888);
78 | barCanvas = new Canvas(bar);
79 |
80 | if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
81 | if (bitmap != null) bitmap.recycle();
82 | bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
83 | bitmapCanvas = new Canvas(bitmap);
84 | }
85 | }
86 |
87 | @Override
88 | protected void onDraw(Canvas canvas) {
89 | super.onDraw(canvas);
90 |
91 | int width;
92 | int height;
93 | if (inVerticalOrientation) {
94 | width = getHeight();
95 | height = getWidth();
96 |
97 | canvas.rotate(-90);
98 | canvas.translate(-width, 0);
99 | } else {
100 | width = getWidth();
101 | height = getHeight();
102 | }
103 |
104 | if (bar != null && bitmapCanvas != null) {
105 | bitmapCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
106 | bitmapCanvas.drawBitmap(bar, barOffsetX, (height - bar.getHeight()) / 2, null);
107 |
108 | float x = handleRadius + value * (width - handleRadius * 2);
109 | float y = height / 2f;
110 | drawHandle(bitmapCanvas, x, y);
111 | canvas.drawBitmap(bitmap, 0, 0, null);
112 | }
113 | }
114 |
115 | protected abstract void drawBar(Canvas barCanvas);
116 |
117 | protected abstract void onValueChanged(float value);
118 |
119 | protected abstract void drawHandle(Canvas canvas, float x, float y);
120 |
121 | @Override
122 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
123 | super.onSizeChanged(w, h, oldw, oldh);
124 | updateBar();
125 | }
126 |
127 | @Override
128 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
129 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
130 | int widthMode = MeasureSpec.getMode(widthMeasureSpec);
131 | int width = 0;
132 | if (widthMode == MeasureSpec.UNSPECIFIED)
133 | width = widthMeasureSpec;
134 | else if (widthMode == MeasureSpec.AT_MOST)
135 | width = MeasureSpec.getSize(widthMeasureSpec);
136 | else if (widthMode == MeasureSpec.EXACTLY)
137 | width = MeasureSpec.getSize(widthMeasureSpec);
138 |
139 | int heightMode = MeasureSpec.getMode(heightMeasureSpec);
140 | int height = 0;
141 | if (heightMode == MeasureSpec.UNSPECIFIED)
142 | height = heightMeasureSpec;
143 | else if (heightMode == MeasureSpec.AT_MOST)
144 | height = MeasureSpec.getSize(heightMeasureSpec);
145 | else if (heightMode == MeasureSpec.EXACTLY)
146 | height = MeasureSpec.getSize(heightMeasureSpec);
147 |
148 | setMeasuredDimension(width, height);
149 | }
150 |
151 | @Override
152 | public boolean onTouchEvent(MotionEvent event) {
153 | switch (event.getAction()) {
154 | case MotionEvent.ACTION_DOWN:
155 | case MotionEvent.ACTION_MOVE: {
156 | if (bar != null) {
157 | if (inVerticalOrientation) {
158 | value = 1 - (event.getY() - barOffsetX) / bar.getWidth();
159 | } else {
160 | value = (event.getX() - barOffsetX) / bar.getWidth();
161 | }
162 | value = Math.max(0, Math.min(value, 1));
163 | onValueChanged(value);
164 | invalidate();
165 | }
166 | break;
167 | }
168 | case MotionEvent.ACTION_UP: {
169 | onValueChanged(value);
170 | if (onValueChangedListener != null)
171 | onValueChangedListener.onValueChanged(value);
172 | invalidate();
173 | }
174 | }
175 | return true;
176 | }
177 |
178 | protected int getDimension(@DimenRes int id) {
179 | return getResources().getDimensionPixelSize(id);
180 | }
181 |
182 | public void setShowBorder(boolean showBorder) {
183 | this.showBorder = showBorder;
184 | }
185 |
186 | public void setOnValueChangedListener(OnValueChangedListener onValueChangedListener) {
187 | this.onValueChangedListener = onValueChangedListener;
188 | }
189 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/flask/colorpicker/slider/AlphaSlider.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker.slider;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.Canvas;
6 | import android.graphics.Paint;
7 | import android.graphics.PorterDuff;
8 | import android.util.AttributeSet;
9 |
10 | import com.flask.colorpicker.ColorPickerView;
11 | import com.flask.colorpicker.Utils;
12 | import com.flask.colorpicker.builder.PaintBuilder;
13 |
14 | public class AlphaSlider extends AbsCustomSlider {
15 | public int color;
16 | private Paint alphaPatternPaint = PaintBuilder.newPaint().build();
17 | private Paint barPaint = PaintBuilder.newPaint().build();
18 | private Paint solid = PaintBuilder.newPaint().build();
19 | private Paint clearingStroke = PaintBuilder.newPaint().color(0xffffffff).xPerMode(PorterDuff.Mode.CLEAR).build();
20 |
21 | private Paint clearStroke = PaintBuilder.newPaint().build();
22 | private Bitmap clearBitmap;
23 | private Canvas clearBitmapCanvas;
24 |
25 | private ColorPickerView colorPicker;
26 |
27 | public AlphaSlider(Context context) {
28 | super(context);
29 | }
30 |
31 | public AlphaSlider(Context context, AttributeSet attrs) {
32 | super(context, attrs);
33 | }
34 |
35 | public AlphaSlider(Context context, AttributeSet attrs, int defStyleAttr) {
36 | super(context, attrs, defStyleAttr);
37 | }
38 |
39 | @Override
40 | protected void createBitmaps() {
41 | super.createBitmaps();
42 | alphaPatternPaint.setShader(PaintBuilder.createAlphaPatternShader(barHeight * 2));
43 | clearBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
44 | clearBitmapCanvas = new Canvas(clearBitmap);
45 | }
46 |
47 | @Override
48 | protected void drawBar(Canvas barCanvas) {
49 | int width = barCanvas.getWidth();
50 | int height = barCanvas.getHeight();
51 |
52 | barCanvas.drawRect(0, 0, width, height, alphaPatternPaint);
53 | int l = Math.max(2, width / 256);
54 | for (int x = 0; x <= width; x += l) {
55 | float alpha = (float) x / (width - 1);
56 | barPaint.setColor(color);
57 | barPaint.setAlpha(Math.round(alpha * 255));
58 | barCanvas.drawRect(x, 0, x + l, height, barPaint);
59 | }
60 | }
61 |
62 | @Override
63 | protected void onValueChanged(float value) {
64 | if (colorPicker != null)
65 | colorPicker.setAlphaValue(value);
66 | }
67 |
68 | @Override
69 | protected void drawHandle(Canvas canvas, float x, float y) {
70 | solid.setColor(color);
71 | solid.setAlpha(Math.round(value * 255));
72 | if (showBorder) canvas.drawCircle(x, y, handleRadius, clearingStroke);
73 | if (value < 1) {
74 | // this fixes the same artifact issue from ColorPickerView
75 | // happens when alpha pattern is drawn underneath a circle with the same size
76 | clearBitmapCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
77 | clearBitmapCanvas.drawCircle(x, y, handleRadius * 0.75f + 4, alphaPatternPaint);
78 | clearBitmapCanvas.drawCircle(x, y, handleRadius * 0.75f + 4, solid);
79 |
80 | clearStroke = PaintBuilder.newPaint().color(0xffffffff).style(Paint.Style.STROKE).stroke(6).xPerMode(PorterDuff.Mode.CLEAR).build();
81 | clearBitmapCanvas.drawCircle(x, y, handleRadius * 0.75f + (clearStroke.getStrokeWidth() / 2), clearStroke);
82 | canvas.drawBitmap(clearBitmap, 0, 0, null);
83 | } else {
84 | canvas.drawCircle(x, y, handleRadius * 0.75f, solid);
85 | }
86 | }
87 |
88 | public void setColorPicker(ColorPickerView colorPicker) {
89 | this.colorPicker = colorPicker;
90 | }
91 |
92 | public void setColor(int color) {
93 | this.color = color;
94 | this.value = Utils.getAlphaPercent(color);
95 | if (bar != null) {
96 | updateBar();
97 | invalidate();
98 | }
99 | }
100 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/flask/colorpicker/slider/LightnessSlider.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker.slider;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Color;
6 | import android.graphics.Paint;
7 | import android.graphics.PorterDuff;
8 | import android.util.AttributeSet;
9 |
10 | import com.flask.colorpicker.ColorPickerView;
11 | import com.flask.colorpicker.Utils;
12 | import com.flask.colorpicker.builder.PaintBuilder;
13 |
14 | public class LightnessSlider extends AbsCustomSlider {
15 | private int color;
16 | private Paint barPaint = PaintBuilder.newPaint().build();
17 | private Paint solid = PaintBuilder.newPaint().build();
18 | private Paint clearingStroke = PaintBuilder.newPaint().color(0xffffffff).xPerMode(PorterDuff.Mode.CLEAR).build();
19 |
20 | private ColorPickerView colorPicker;
21 |
22 | public LightnessSlider(Context context) {
23 | super(context);
24 | }
25 |
26 | public LightnessSlider(Context context, AttributeSet attrs) {
27 | super(context, attrs);
28 | }
29 |
30 | public LightnessSlider(Context context, AttributeSet attrs, int defStyleAttr) {
31 | super(context, attrs, defStyleAttr);
32 | }
33 |
34 | @Override
35 | protected void drawBar(Canvas barCanvas) {
36 | int width = barCanvas.getWidth();
37 | int height = barCanvas.getHeight();
38 |
39 | float[] hsv = new float[3];
40 | Color.colorToHSV(color, hsv);
41 | int l = Math.max(2, width / 256);
42 | for (int x = 0; x <= width; x += l) {
43 | hsv[2] = (float) x / (width - 1);
44 | barPaint.setColor(Color.HSVToColor(hsv));
45 | barCanvas.drawRect(x, 0, x + l, height, barPaint);
46 | }
47 | }
48 |
49 | @Override
50 | protected void onValueChanged(float value) {
51 | if (colorPicker != null)
52 | colorPicker.setLightness(value);
53 | }
54 |
55 | @Override
56 | protected void drawHandle(Canvas canvas, float x, float y) {
57 | solid.setColor(Utils.colorAtLightness(color, value));
58 | if (showBorder) canvas.drawCircle(x, y, handleRadius, clearingStroke);
59 | canvas.drawCircle(x, y, handleRadius * 0.75f, solid);
60 | }
61 |
62 | public void setColorPicker(ColorPickerView colorPicker) {
63 | this.colorPicker = colorPicker;
64 | }
65 |
66 | public void setColor(int color) {
67 | this.color = color;
68 | this.value = Utils.lightnessOfColor(color);
69 | if (bar != null) {
70 | updateBar();
71 | invalidate();
72 | }
73 | }
74 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/flask/colorpicker/slider/OnValueChangedListener.java:
--------------------------------------------------------------------------------
1 | package com.flask.colorpicker.slider;
2 |
3 | public interface OnValueChangedListener {
4 | void onValueChanged(float value);
5 | }
--------------------------------------------------------------------------------
/library/src/main/res/layout/color_edit.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/color_preview.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/color_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
12 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/color_widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/library/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 |
--------------------------------------------------------------------------------
/library/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 | 36dp
3 | 24dp
4 | 4dp
5 | 10dp
6 | 24dp
7 | 40dp
8 | 36dp
9 | 20dp
10 |
11 |
--------------------------------------------------------------------------------
/library/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
--------------------------------------------------------------------------------
/screenshot/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuadFlask/colorpicker/ef73ced2172b37f0cbc3259eefd5770b67635b6b/screenshot/screenshot.png
--------------------------------------------------------------------------------
/screenshot/screenshot2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuadFlask/colorpicker/ef73ced2172b37f0cbc3259eefd5770b67635b6b/screenshot/screenshot2.png
--------------------------------------------------------------------------------
/screenshot/screenshot3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuadFlask/colorpicker/ef73ced2172b37f0cbc3259eefd5770b67635b6b/screenshot/screenshot3.png
--------------------------------------------------------------------------------
/screenshot/screenshot4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/QuadFlask/colorpicker/ef73ced2172b37f0cbc3259eefd5770b67635b6b/screenshot/screenshot4.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':library'
2 |
--------------------------------------------------------------------------------