修复已知BUG调色器MD3化
This commit is contained in:
parent
c6089ae67c
commit
c5fa00b988
|
@ -24,15 +24,15 @@ android {
|
||||||
keyAlias 'coldmint'
|
keyAlias 'coldmint'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compileSdkVersion 33
|
compileSdk 33
|
||||||
buildToolsVersion "30.0.3"
|
// buildToolsVersion "30.0.3"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.coldmint.rust.pro"
|
applicationId "com.coldmint.rust.pro"
|
||||||
minSdkVersion 23
|
minSdkVersion 23
|
||||||
targetSdkVersion 33
|
targetSdkVersion 33
|
||||||
versionCode 28
|
versionCode 28
|
||||||
versionName "2.1 Bata6(2023-7-20)"
|
versionName "2.1.1 Bata6(2023-7-20)"
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
@ -91,12 +91,15 @@ dependencies {
|
||||||
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib'
|
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
api 'androidx.appcompat:appcompat:1.6.1'
|
||||||
|
api 'com.google.android.material:material:1.9.0'
|
||||||
|
|
||||||
implementation platform('com.google.firebase:firebase-bom:31.1.1')
|
implementation platform('com.google.firebase:firebase-bom:31.1.1')
|
||||||
implementation 'com.google.firebase:firebase-analytics-ktx'
|
implementation 'com.google.firebase:firebase-analytics-ktx'
|
||||||
implementation 'com.google.firebase:firebase-crashlytics-ktx'
|
implementation 'com.google.firebase:firebase-crashlytics-ktx'
|
||||||
implementation 'com.google.firebase:firebase-perf-ktx'
|
implementation 'com.google.firebase:firebase-perf-ktx'
|
||||||
implementation fileTree(dir: 'libs', include: ['*.aar', '*.jar'], exclude: [])
|
// implementation fileTree(dir: 'libs', include: ['*.aar', '*.jar'], exclude: [])
|
||||||
|
api project(path: ':library')
|
||||||
def nav_version = "2.5.1"
|
def nav_version = "2.5.1"
|
||||||
|
|
||||||
// implementation 'com.luolc:emoji-rain:0.1.1'
|
// implementation 'com.luolc:emoji-rain:0.1.1'
|
||||||
|
@ -133,16 +136,10 @@ dependencies {
|
||||||
implementation 'com.github.florent37:glidepalette:2.1.2'
|
implementation 'com.github.florent37:glidepalette:2.1.2'
|
||||||
implementation 'cat.ereza:customactivityoncrash:2.3.0'
|
implementation 'cat.ereza:customactivityoncrash:2.3.0'
|
||||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
|
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
|
||||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
|
||||||
implementation 'dev.rikka.rikkax.appcompat:appcompat:1.6.1'
|
implementation 'dev.rikka.rikkax.appcompat:appcompat:1.6.1'
|
||||||
implementation 'com.google.android.material:material:1.9.0'
|
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||||
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
|
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
|
||||||
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
|
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
|
||||||
implementation 'androidx.preference:preference-ktx:1.2.0'
|
implementation 'androidx.preference:preference-ktx:1.2.0'
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.13.2'
|
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
|
||||||
|
|
||||||
}
|
}
|
Binary file not shown.
|
@ -1,28 +0,0 @@
|
||||||
package com.coldmint.rust.pro;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import androidx.test.platform.app.InstrumentationRegistry;
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 仪器测试,将在Android设备上执行。
|
|
||||||
*
|
|
||||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
|
||||||
*/
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
|
||||||
public class ExampleInstrumentedTest {
|
|
||||||
@Test
|
|
||||||
public void useAppContext() {
|
|
||||||
// 被测试应用程序的上下文。
|
|
||||||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
|
||||||
assertEquals("com.coldmint.rust.pro", appContext.getPackageName());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
package com.coldmint.rust.pro
|
|
||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
|
||||||
import com.coldmint.rust.core.SourceFile
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
import org.junit.Assert.*
|
|
||||||
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
|
||||||
class SourceFileUnitTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testWriteValue() {
|
|
||||||
val sourceFile = SourceFile("[core]\nname:124")
|
|
||||||
//测试修改值
|
|
||||||
sourceFile.writeValue("name", "love")
|
|
||||||
assertEquals("[core]\nname:love", sourceFile.text)
|
|
||||||
//测试修改值2
|
|
||||||
sourceFile.text = "[core]\nname:124\nmsg:ni"
|
|
||||||
sourceFile.writeValue("msg", "happy")
|
|
||||||
sourceFile.writeValue("name", "loveMe")
|
|
||||||
assertEquals("[core]\nname:loveMe\nmsg:happy", sourceFile.text)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testReadValue() {
|
|
||||||
val sourceFile = SourceFile("[core]\n\nname:124\nkey:value2")
|
|
||||||
//测试修改值
|
|
||||||
val value = sourceFile.readValue("name")
|
|
||||||
assertEquals("124", value)
|
|
||||||
//测试修改值2
|
|
||||||
sourceFile.text = "[core]\nname:124\nmsg:ni"
|
|
||||||
val value2 = sourceFile.readValue("msg")
|
|
||||||
assertEquals("ni", value2)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -24,27 +24,28 @@
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.rust.Concept"
|
android:theme="@style/Theme.rust.Concept"
|
||||||
android:usesCleartextTraffic="true">
|
android:usesCleartextTraffic="true"
|
||||||
|
android:screenOrientation="portrait"
|
||||||
|
tools:targetApi="tiramisu">
|
||||||
<activity
|
<activity
|
||||||
android:name=".FeedbackActivity"
|
android:name=".FeedbackActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:screenOrientation="portrait" />
|
android:screenOrientation="portrait"
|
||||||
|
tools:ignore="LockedOrientationActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ChangePasswordActivity"
|
android:name=".ChangePasswordActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:screenOrientation="portrait" />
|
android:screenOrientation="portrait"
|
||||||
|
tools:ignore="LockedOrientationActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".NetworkTemplatePackageDetailsActivity"
|
android:name=".NetworkTemplatePackageDetailsActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".CustomizeEditTextActivity"
|
android:name=".CustomizeEditTextActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".SearchActivity"
|
android:name=".SearchActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
|
@ -68,93 +69,71 @@
|
||||||
android:value="portrait|landscape" /> <!-- Activity注册 -->
|
android:value="portrait|landscape" /> <!-- Activity注册 -->
|
||||||
<activity
|
<activity
|
||||||
android:name=".CreationWizardActivity"
|
android:name=".CreationWizardActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".TurretDesignActivity"
|
android:name=".TurretDesignActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".BrowserActivity"
|
android:name=".BrowserActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:label="@string/built_in_browser"
|
android:label="@string/built_in_browser"/> <!-- 适配全面屏 -->
|
||||||
android:screenOrientation="portrait" /> <!-- 适配全面屏 -->
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".OrderListActivity"
|
android:name=".OrderListActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".SearchResultActivity"
|
android:name=".SearchResultActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".PayActivity"
|
android:name=".PayActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ReviewModActivity"
|
android:name=".ReviewModActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ReportListActivity"
|
android:name=".ReportListActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ErrorInfoActivity"
|
android:name=".ErrorInfoActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".UserListActivity"
|
android:name=".UserListActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActivateActivity"
|
android:name=".ActivateActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ThanksActivity"
|
android:name=".ThanksActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".WorkManagementActivity"
|
android:name=".WorkManagementActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".FullScreenCoverActivity"
|
android:name=".FullScreenCoverActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".TagActivity"
|
android:name=".TagActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ReportActivity"
|
android:name=".ReportActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".EditUserInfoActivity"
|
android:name=".EditUserInfoActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".UserHomePageActivity"
|
android:name=".UserHomePageActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".WebModInfoActivity"
|
android:name=".WebModInfoActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ErrorActivity"
|
android:name=".ErrorActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.yalantis.ucrop.UCropActivity"
|
android:name="com.yalantis.ucrop.UCropActivity"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask">
|
||||||
android:screenOrientation="portrait">
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
@ -167,8 +146,7 @@
|
||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:label="@string/file_importer"
|
android:label="@string/file_importer"
|
||||||
android:maxRecents="3"
|
android:maxRecents="3">
|
||||||
android:screenOrientation="portrait">
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
@ -268,93 +246,69 @@
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".AboutActivity"
|
android:name=".AboutActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ValueTypeActivity"
|
android:name=".ValueTypeActivity"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".GlobalOperationsActivity"
|
android:name=".GlobalOperationsActivity"
|
||||||
android:label="@string/global_operations"
|
android:label="@string/global_operations"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".EditActivity"
|
android:name=".EditActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:label="@string/mod_action1"
|
android:label="@string/mod_action1"
|
||||||
android:screenOrientation="portrait"
|
|
||||||
android:windowSoftInputMode="adjustResize" />
|
android:windowSoftInputMode="adjustResize" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".CreateModActivity"
|
android:name=".CreateModActivity"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".UnitsActivity"
|
android:name=".UnitsActivity"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".OptimizeActivity"
|
android:name=".OptimizeActivity"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".FileManagerActivity"
|
android:name=".FileManagerActivity"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".CreateUnitActivity"
|
android:name=".CreateUnitActivity"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".TemplateParserActivity"
|
android:name=".TemplateParserActivity"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".LibraryActivity"
|
android:name=".LibraryActivity"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".SettingsActivity"
|
android:name=".SettingsActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:label="@string/setting"
|
android:label="@string/setting"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".TemplateMakerActivity"
|
android:name=".TemplateMakerActivity"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".CreateTemplateActivity"
|
android:name=".CreateTemplateActivity"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".CodeTableActivity"
|
android:name=".CodeTableActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".LoginActivity"
|
android:name=".LoginActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".RegisterActivity"
|
android:name=".RegisterActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".EditModInfoActivity"
|
android:name=".EditModInfoActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ApplicationListActivity"
|
android:name=".ApplicationListActivity"
|
||||||
android:exported="false"
|
android:exported="false" />
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".GameCheckActivity"
|
android:name=".GameCheckActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".RecyclingStationActivity"
|
android:name=".RecyclingStationActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".BookmarkManagerActivity"
|
android:name=".BookmarkManagerActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ReleaseModActivity"
|
android:name=".ReleaseModActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".PackActivity"
|
android:name=".PackActivity"
|
||||||
android:exported="false"
|
android:exported="false"/>
|
||||||
android:screenOrientation="portrait" />
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
|
@ -8,7 +8,12 @@ import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.view.*
|
import android.view.KeyEvent
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.SubMenu
|
||||||
|
import android.view.View
|
||||||
import android.widget.PopupMenu
|
import android.widget.PopupMenu
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
|
@ -17,7 +22,6 @@ import androidx.core.view.GravityCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.drawerlayout.widget.DrawerLayout
|
import androidx.drawerlayout.widget.DrawerLayout
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.request.RequestOptions
|
import com.bumptech.glide.request.RequestOptions
|
||||||
|
@ -31,7 +35,6 @@ import com.coldmint.rust.core.database.file.FileDataBase
|
||||||
import com.coldmint.rust.core.tool.AppOperator
|
import com.coldmint.rust.core.tool.AppOperator
|
||||||
import com.coldmint.rust.core.tool.DebugHelper
|
import com.coldmint.rust.core.tool.DebugHelper
|
||||||
import com.coldmint.rust.core.tool.FileOperator
|
import com.coldmint.rust.core.tool.FileOperator
|
||||||
import com.coldmint.rust.core.web.ServerConfiguration
|
|
||||||
import com.coldmint.rust.pro.adapters.FileAdapter
|
import com.coldmint.rust.pro.adapters.FileAdapter
|
||||||
import com.coldmint.rust.pro.base.BaseActivity
|
import com.coldmint.rust.pro.base.BaseActivity
|
||||||
import com.coldmint.rust.pro.databean.ErrorInfo
|
import com.coldmint.rust.pro.databean.ErrorInfo
|
||||||
|
@ -49,23 +52,16 @@ import com.coldmint.rust.pro.viewmodel.EditStartViewModel
|
||||||
import com.coldmint.rust.pro.viewmodel.EditViewModel
|
import com.coldmint.rust.pro.viewmodel.EditViewModel
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.google.firebase.crashlytics.ktx.crashlytics
|
|
||||||
import com.google.firebase.ktx.Firebase
|
|
||||||
import io.github.rosemoe.sora.lang.completion.CompletionPublisher
|
|
||||||
import io.github.rosemoe.sora.text.CharPosition
|
|
||||||
import io.github.rosemoe.sora.text.ContentReference
|
|
||||||
import io.github.rosemoe.sora.widget.EditorSearcher
|
import io.github.rosemoe.sora.widget.EditorSearcher
|
||||||
import io.github.rosemoe.sora.widget.component.EditorAutoCompletion
|
import io.github.rosemoe.sora.widget.component.EditorAutoCompletion
|
||||||
import io.github.rosemoe.sora.widget.schemes.EditorColorScheme
|
import io.github.rosemoe.sora.widget.schemes.EditorColorScheme
|
||||||
import jp.wasabeef.glide.transformations.BlurTransformation
|
import jp.wasabeef.glide.transformations.BlurTransformation
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
|
|
||||||
|
|
||||||
class EditActivity : BaseActivity<ActivityEditBinding>() {
|
class EditActivity : BaseActivity<ActivityEditBinding>() {
|
||||||
private val viewModel by lazy {
|
private val viewModel by lazy {
|
||||||
ViewModelProvider(this).get(EditViewModel::class.java)
|
ViewModelProvider(this)[EditViewModel::class.java]
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var turretCoordinateResults: ActivityResultLauncher<Intent>
|
private lateinit var turretCoordinateResults: ActivityResultLauncher<Intent>
|
||||||
|
|
|
@ -1,27 +1,21 @@
|
||||||
package com.coldmint.rust.pro
|
package com.coldmint.rust.pro
|
||||||
|
|
||||||
import com.coldmint.rust.pro.base.BaseActivity
|
|
||||||
import com.coldmint.rust.pro.tool.BookmarkManager
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import com.coldmint.rust.pro.tool.GlobalMethod
|
|
||||||
import com.google.android.material.snackbar.Snackbar
|
|
||||||
import android.provider.MediaStore
|
|
||||||
import android.provider.DocumentsContract
|
|
||||||
import android.content.ContentUris
|
|
||||||
import android.content.Context
|
|
||||||
import android.database.Cursor
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.*
|
import android.os.Bundle
|
||||||
import android.view.*
|
import android.os.Handler
|
||||||
import android.widget.*
|
import android.os.Looper
|
||||||
import android.widget.Toast.makeText
|
import android.provider.MediaStore
|
||||||
|
import android.view.KeyEvent
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
|
import android.view.MenuItem
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import com.bumptech.glide.Glide
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.coldmint.dialog.CoreDialog
|
import com.coldmint.dialog.CoreDialog
|
||||||
import com.coldmint.dialog.InputDialog
|
import com.coldmint.dialog.InputDialog
|
||||||
import com.coldmint.rust.core.tool.DebugHelper
|
import com.coldmint.rust.core.tool.DebugHelper
|
||||||
|
@ -29,27 +23,20 @@ import com.coldmint.rust.core.tool.FileOperator
|
||||||
import com.coldmint.rust.core.tool.LineParser
|
import com.coldmint.rust.core.tool.LineParser
|
||||||
import com.coldmint.rust.pro.adapters.FileAdapter
|
import com.coldmint.rust.pro.adapters.FileAdapter
|
||||||
import com.coldmint.rust.pro.adapters.FileTabAdapter
|
import com.coldmint.rust.pro.adapters.FileTabAdapter
|
||||||
|
import com.coldmint.rust.pro.base.BaseActivity
|
||||||
import com.coldmint.rust.pro.databean.FileTab
|
import com.coldmint.rust.pro.databean.FileTab
|
||||||
import com.coldmint.rust.pro.databinding.ActivityFileBinding
|
import com.coldmint.rust.pro.databinding.ActivityFileBinding
|
||||||
import com.coldmint.rust.pro.interfaces.BookmarkListener
|
import com.coldmint.rust.pro.interfaces.BookmarkListener
|
||||||
import com.coldmint.rust.pro.tool.AppSettings
|
import com.coldmint.rust.pro.tool.AppSettings
|
||||||
|
import com.coldmint.rust.pro.tool.GlobalMethod
|
||||||
import com.coldmint.rust.pro.ui.StableLinearLayoutManager
|
import com.coldmint.rust.pro.ui.StableLinearLayoutManager
|
||||||
import com.coldmint.rust.pro.viewmodel.FileManagerViewModel
|
import com.coldmint.rust.pro.viewmodel.FileManagerViewModel
|
||||||
import com.google.android.material.chip.Chip
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|
||||||
import com.google.android.material.snackbar.SnackbarContentLayout
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import me.zhanghai.android.fastscroll.FastScrollerBuilder
|
import me.zhanghai.android.fastscroll.FastScrollerBuilder
|
||||||
import java.io.BufferedReader
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStreamReader
|
|
||||||
import java.lang.Exception
|
|
||||||
import java.util.*
|
|
||||||
import java.util.concurrent.Executors
|
|
||||||
import javax.sql.CommonDataSource
|
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
|
|
||||||
class FileManagerActivity : BaseActivity<ActivityFileBinding>() {
|
class FileManagerActivity : BaseActivity<ActivityFileBinding>() {
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,17 @@
|
||||||
package com.coldmint.rust.pro
|
package com.coldmint.rust.pro
|
||||||
|
|
||||||
|
|
||||||
import com.coldmint.rust.pro.base.BaseActivity
|
|
||||||
import com.coldmint.rust.pro.tool.GlobalMethod
|
|
||||||
import android.content.pm.PackageInfo
|
|
||||||
import com.coldmint.rust.pro.tool.AppSettings
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageInfo
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.res.Resources
|
import android.os.Bundle
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import android.os.Handler
|
||||||
import android.os.*
|
import android.os.Looper
|
||||||
import android.util.Log
|
import android.view.KeyEvent
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
import android.widget.Toast
|
import android.view.Menu
|
||||||
|
import android.view.MenuItem
|
||||||
import androidx.appcompat.app.ActionBarDrawerToggle
|
import androidx.appcompat.app.ActionBarDrawerToggle
|
||||||
import androidx.appcompat.widget.Toolbar
|
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
import androidx.core.view.GravityCompat
|
import androidx.core.view.GravityCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
@ -33,16 +30,21 @@ import com.coldmint.rust.core.dataBean.template.TemplateInfo
|
||||||
import com.coldmint.rust.core.debug.LogCat
|
import com.coldmint.rust.core.debug.LogCat
|
||||||
import com.coldmint.rust.core.interfaces.ApiCallBack
|
import com.coldmint.rust.core.interfaces.ApiCallBack
|
||||||
import com.coldmint.rust.core.interfaces.UnzipListener
|
import com.coldmint.rust.core.interfaces.UnzipListener
|
||||||
import com.coldmint.rust.core.tool.*
|
import com.coldmint.rust.core.tool.AppOperator
|
||||||
|
import com.coldmint.rust.core.tool.DebugHelper
|
||||||
|
import com.coldmint.rust.core.tool.FileOperator
|
||||||
import com.coldmint.rust.core.web.AppUpdate
|
import com.coldmint.rust.core.web.AppUpdate
|
||||||
import com.coldmint.rust.core.web.ServerConfiguration
|
import com.coldmint.rust.core.web.ServerConfiguration
|
||||||
|
import com.coldmint.rust.pro.base.BaseActivity
|
||||||
import com.coldmint.rust.pro.databinding.ActivityMainBinding
|
import com.coldmint.rust.pro.databinding.ActivityMainBinding
|
||||||
import com.coldmint.rust.pro.databinding.HeadLayoutBinding
|
import com.coldmint.rust.pro.databinding.HeadLayoutBinding
|
||||||
import com.coldmint.rust.pro.fragments.UserGroupFragment
|
import com.coldmint.rust.pro.tool.AppSettings
|
||||||
import com.coldmint.rust.pro.tool.EventRecord
|
import com.coldmint.rust.pro.tool.EventRecord
|
||||||
|
import com.coldmint.rust.pro.tool.GlobalMethod
|
||||||
import com.coldmint.rust.pro.viewmodel.StartViewModel
|
import com.coldmint.rust.pro.viewmodel.StartViewModel
|
||||||
import com.google.android.material.color.DynamicColors
|
import com.google.android.material.color.DynamicColors
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.google.android.material.tabs.TabLayout
|
import com.google.android.material.tabs.TabLayout
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.gyf.immersionbar.ImmersionBar
|
import com.gyf.immersionbar.ImmersionBar
|
||||||
|
@ -331,7 +333,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||||
intent.putExtra("type", "template")
|
intent.putExtra("type", "template")
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -380,7 +381,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||||
|
|
||||||
menu.findItem(R.id.rust_api).setOnMenuItemClickListener {
|
menu.findItem(R.id.rust_api).setOnMenuItemClickListener {
|
||||||
val thisIntent = Intent(this, BrowserActivity::class.java)
|
val thisIntent = Intent(this, BrowserActivity::class.java)
|
||||||
thisIntent.putExtra("link", "https://rustedwarfareapicode.top/")
|
thisIntent.putExtra("link", "https://git.coldmint.top/")
|
||||||
thisIntent.putExtra("javaScriptEnabled", true)
|
thisIntent.putExtra("javaScriptEnabled", true)
|
||||||
startActivity(thisIntent)
|
startActivity(thisIntent)
|
||||||
false
|
false
|
||||||
|
|
|
@ -1,23 +1,22 @@
|
||||||
package com.coldmint.rust.pro
|
package com.coldmint.rust.pro
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Environment
|
import android.content.pm.ActivityInfo
|
||||||
import android.util.Log
|
import android.os.Bundle
|
||||||
import cat.ereza.customactivityoncrash.config.CaocConfig
|
import cat.ereza.customactivityoncrash.config.CaocConfig
|
||||||
import com.coldmint.rust.core.debug.LogCat
|
import com.coldmint.rust.core.debug.LogCat
|
||||||
import com.coldmint.rust.core.debug.LogCatObserver
|
import com.coldmint.rust.core.debug.LogCatObserver
|
||||||
import com.coldmint.rust.core.web.ServerConfiguration
|
|
||||||
import com.coldmint.rust.pro.tool.AppSettings
|
import com.coldmint.rust.pro.tool.AppSettings
|
||||||
import com.coldmint.rust.pro.tool.CompletionItemConverter
|
|
||||||
import com.coldmint.rust.pro.tool.GlobalMethod
|
|
||||||
import com.google.android.material.color.DynamicColors
|
import com.google.android.material.color.DynamicColors
|
||||||
import com.google.android.material.color.DynamicColorsOptions
|
import com.google.android.material.color.DynamicColorsOptions
|
||||||
import com.google.firebase.crashlytics.ktx.crashlytics
|
import com.google.firebase.crashlytics.ktx.crashlytics
|
||||||
import com.google.firebase.ktx.Firebase
|
import com.google.firebase.ktx.Firebase
|
||||||
import com.hjq.language.MultiLanguages
|
import com.hjq.language.MultiLanguages
|
||||||
import com.youth.banner.BuildConfig
|
import com.youth.banner.BuildConfig
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class RustApplication : Application() {
|
class RustApplication : Application() {
|
||||||
|
|
||||||
|
@ -38,7 +37,7 @@ class RustApplication : Application() {
|
||||||
AppSettings.initAppSettings(this)
|
AppSettings.initAppSettings(this)
|
||||||
//动态颜色
|
//动态颜色
|
||||||
val options = DynamicColorsOptions.Builder()
|
val options = DynamicColorsOptions.Builder()
|
||||||
.setPrecondition { activity, theme ->
|
.setPrecondition { _, _ ->
|
||||||
AppSettings
|
AppSettings
|
||||||
.getValue(
|
.getValue(
|
||||||
AppSettings.Setting.DynamicColor,
|
AppSettings.Setting.DynamicColor,
|
||||||
|
@ -66,8 +65,24 @@ class RustApplication : Application() {
|
||||||
.errorActivity(ErrorActivity::class.java) //default: null (default error activity)
|
.errorActivity(ErrorActivity::class.java) //default: null (default error activity)
|
||||||
.apply()
|
.apply()
|
||||||
|
|
||||||
MultiLanguages.init(this);
|
MultiLanguages.init(this)
|
||||||
|
registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
|
||||||
|
@SuppressLint("SourceLockedOrientationActivity")
|
||||||
|
override fun onActivityCreated(
|
||||||
|
activity: Activity,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
) {
|
||||||
|
// android:screenOrientation="portrait"
|
||||||
|
//全局强制横屏
|
||||||
|
activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||||
|
}
|
||||||
|
override fun onActivityStarted(activity: Activity) {}
|
||||||
|
override fun onActivityResumed(activity: Activity) {}
|
||||||
|
override fun onActivityPaused(activity: Activity) {}
|
||||||
|
override fun onActivityStopped(activity: Activity) {}
|
||||||
|
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
|
||||||
|
override fun onActivityDestroyed(activity: Activity) {}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
package com.coldmint.rust.pro.base
|
package com.coldmint.rust.pro.base
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Configuration
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import com.coldmint.rust.pro.tool.AppSettings
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
|
@ -11,24 +8,15 @@ import android.view.View
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.widget.Toolbar
|
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import androidx.viewbinding.ViewBinding
|
import androidx.viewbinding.ViewBinding
|
||||||
import com.coldmint.dialog.CoreDialog
|
import com.coldmint.dialog.CoreDialog
|
||||||
import com.coldmint.rust.pro.R
|
import com.coldmint.rust.pro.R
|
||||||
import com.google.android.material.appbar.MaterialToolbar
|
import com.google.android.material.appbar.MaterialToolbar
|
||||||
import com.google.android.material.color.DynamicColors
|
|
||||||
import com.google.android.material.color.DynamicColorsOptions
|
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
import com.google.firebase.analytics.FirebaseAnalytics
|
|
||||||
import com.google.firebase.analytics.ktx.analytics
|
|
||||||
import com.google.firebase.ktx.Firebase
|
|
||||||
import com.hjq.language.MultiLanguages
|
import com.hjq.language.MultiLanguages
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/*主活动,所有活动都应该继承于此*/
|
/*主活动,所有活动都应该继承于此*/
|
||||||
abstract class BaseActivity<ViewBingType : ViewBinding> :
|
abstract class BaseActivity<ViewBingType : ViewBinding> :
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.coldmint.rust.pro.edit.autoComplete
|
package com.coldmint.rust.pro.edit.autoComplete
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import com.coldmint.rust.core.SourceFile
|
import com.coldmint.rust.core.SourceFile
|
||||||
import com.coldmint.rust.core.database.code.CodeDao
|
import com.coldmint.rust.core.database.code.CodeDao
|
||||||
import com.coldmint.rust.core.database.code.CodeDataBase
|
import com.coldmint.rust.core.database.code.CodeDataBase
|
||||||
|
@ -8,14 +7,11 @@ import com.coldmint.rust.core.database.file.FileDataBase
|
||||||
import com.coldmint.rust.core.tool.DebugHelper
|
import com.coldmint.rust.core.tool.DebugHelper
|
||||||
import com.coldmint.rust.core.tool.LineParser
|
import com.coldmint.rust.core.tool.LineParser
|
||||||
import com.coldmint.rust.pro.edit.RustAnalyzer
|
import com.coldmint.rust.pro.edit.RustAnalyzer
|
||||||
import com.coldmint.rust.pro.edit.RustAutoComplete
|
|
||||||
import com.coldmint.rust.pro.edit.RustCompletionItem
|
|
||||||
import com.coldmint.rust.pro.tool.AppSettings
|
import com.coldmint.rust.pro.tool.AppSettings
|
||||||
import com.coldmint.rust.pro.tool.CompletionItemConverter
|
import com.coldmint.rust.pro.tool.CompletionItemConverter
|
||||||
import io.github.rosemoe.sora.lang.completion.CompletionPublisher
|
import io.github.rosemoe.sora.lang.completion.CompletionPublisher
|
||||||
import io.github.rosemoe.sora.text.CharPosition
|
import io.github.rosemoe.sora.text.CharPosition
|
||||||
import io.github.rosemoe.sora.text.ContentReference
|
import io.github.rosemoe.sora.text.ContentReference
|
||||||
import io.github.rosemoe.sora.widget.CodeEditor
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 代码自动完成项目(来自数据库)
|
* 代码自动完成项目(来自数据库)
|
||||||
|
|
|
@ -2,11 +2,10 @@ package com.coldmint.rust.pro.fragments
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.coldmint.dialog.CoreDialog
|
import com.coldmint.dialog.CoreDialog
|
||||||
import com.coldmint.rust.core.dataBean.BannerItemDataBean
|
import com.coldmint.rust.core.dataBean.BannerItemDataBean
|
||||||
|
@ -24,13 +23,10 @@ import com.coldmint.rust.pro.databinding.FragmentRecommendedBinding
|
||||||
import com.coldmint.rust.pro.tool.AppSettings
|
import com.coldmint.rust.pro.tool.AppSettings
|
||||||
import com.coldmint.rust.pro.tool.GlobalMethod
|
import com.coldmint.rust.pro.tool.GlobalMethod
|
||||||
import com.coldmint.rust.pro.tool.TextStyleMaker
|
import com.coldmint.rust.pro.tool.TextStyleMaker
|
||||||
import com.coldmint.rust.pro.ui.StableLinearLayoutManager
|
import com.coldmint.rust.pro.ui.ScrollLinearLayoutManager
|
||||||
import com.google.android.material.color.DynamicColors
|
|
||||||
import com.youth.banner.adapter.BannerImageAdapter
|
import com.youth.banner.adapter.BannerImageAdapter
|
||||||
import com.youth.banner.holder.BannerImageHolder
|
import com.youth.banner.holder.BannerImageHolder
|
||||||
import com.youth.banner.indicator.CircleIndicator
|
import com.youth.banner.indicator.CircleIndicator
|
||||||
import com.youth.banner.transformer.AlphaPageTransformer
|
|
||||||
import com.youth.banner.transformer.DepthPageTransformer
|
|
||||||
|
|
||||||
class RecommendedFragment : BaseFragment<FragmentRecommendedBinding>() {
|
class RecommendedFragment : BaseFragment<FragmentRecommendedBinding>() {
|
||||||
|
|
||||||
|
@ -233,10 +229,10 @@ class RecommendedFragment : BaseFragment<FragmentRecommendedBinding>() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun whenViewCreated(inflater: LayoutInflater, savedInstanceState: Bundle?) {
|
override fun whenViewCreated(inflater: LayoutInflater, savedInstanceState: Bundle?) {
|
||||||
viewBinding.latestReleaseView.layoutManager = StableLinearLayoutManager(requireContext())
|
viewBinding.latestReleaseView.layoutManager = ScrollLinearLayoutManager(requireContext())
|
||||||
viewBinding.soleRecommendedRecyclerView.layoutManager =
|
viewBinding.soleRecommendedRecyclerView.layoutManager =
|
||||||
StableLinearLayoutManager(requireContext())
|
ScrollLinearLayoutManager(requireContext())
|
||||||
viewBinding.randomRecommendedView.layoutManager = StableLinearLayoutManager(requireContext())
|
viewBinding.randomRecommendedView.layoutManager = ScrollLinearLayoutManager(requireContext())
|
||||||
loadRandomRecommended()
|
loadRandomRecommended()
|
||||||
viewBinding.changeRandomRecommended.setOnClickListener {
|
viewBinding.changeRandomRecommended.setOnClickListener {
|
||||||
loadRandomRecommended()
|
loadRandomRecommended()
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.coldmint.rust.pro.ui
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 稳定的线性布局管理器
|
||||||
|
*/
|
||||||
|
class ScrollLinearLayoutManager(val context: Context) : LinearLayoutManager(context) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 这里加了try catch防止奔溃
|
||||||
|
*/
|
||||||
|
override fun onLayoutChildren(recycler: RecyclerView.Recycler?, state: RecyclerView.State?) {
|
||||||
|
try {
|
||||||
|
super.onLayoutChildren(recycler, state)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
override fun canScrollVertically(): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,13 +3,10 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center">
|
android:gravity="center">
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
|
||||||
style="@style/Widget.MaterialComponents.Button.TextButton.Dialog"
|
style="@style/Widget.MaterialComponents.Button.TextButton.Dialog"
|
||||||
android:id="@+id/codeTextItemView"
|
android:id="@+id/codeTextItemView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="项目"/>
|
android:text="项目"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -1,6 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<merge>
|
<merge>
|
||||||
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -13,8 +12,7 @@
|
||||||
android:id="@+id/titleView"
|
android:id="@+id/titleView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?android:attr/actionBarSize"
|
android:layout_height="?android:attr/actionBarSize"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true">
|
||||||
app:cardBackgroundColor="?android:windowBackground">
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent">
|
||||||
android:gravity="center"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/progressBar"
|
android:id="@+id/progressBar"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/textview"
|
android:id="@+id/textview"
|
||||||
style="@style/TextAppearance.Material3.HeadlineMedium"
|
style="@style/TextAppearance.Material3.HeadlineMedium"
|
||||||
|
@ -18,27 +18,23 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:text="@string/no_content"
|
android:text="@string/no_content"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
<LinearLayout
|
||||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
android:id="@+id/linearLayout3"
|
||||||
android:id="@+id/swipeRefreshLayout"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginHorizontal="16dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:visibility="gone">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<HorizontalScrollView
|
<HorizontalScrollView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<com.google.android.material.chip.ChipGroup
|
<com.google.android.material.chip.ChipGroup
|
||||||
android:layout_width="match_parent"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:singleLine="true"
|
app:singleLine="true"
|
||||||
app:singleSelection="true">
|
app:singleSelection="true">
|
||||||
|
@ -77,15 +73,16 @@
|
||||||
|
|
||||||
</com.google.android.material.chip.ChipGroup>
|
</com.google.android.material.chip.ChipGroup>
|
||||||
</HorizontalScrollView>
|
</HorizontalScrollView>
|
||||||
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
|
android:id="@+id/swipeRefreshLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:visibility="gone">
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recyclerView"
|
android:id="@+id/recyclerView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent" />
|
||||||
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
|
@ -7,8 +7,6 @@
|
||||||
android:animateLayoutChanges="true"
|
android:animateLayoutChanges="true"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/progressBar"
|
android:id="@+id/progressBar"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -30,7 +28,6 @@
|
||||||
android:layout_marginHorizontal="16dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:visibility="visible">
|
android:visibility="visible">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
@ -75,7 +72,8 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:text="@string/change_random_recommended" />
|
android:text="@string/change_random_recommended"
|
||||||
|
card_view:ignore="RelativeOverlap" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
package com.coldmint.rust.pro;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Example local unit test, which will execute on the development machine (host).
|
|
||||||
*
|
|
||||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
|
||||||
*/
|
|
||||||
public class ExampleUnitTest {
|
|
||||||
@Test
|
|
||||||
public void addition_isCorrect() {
|
|
||||||
assertEquals(4, 2 + 2);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
package com.coldmint.rust.core;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import androidx.test.platform.app.InstrumentationRegistry;
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instrumented test, which will execute on an Android device.
|
|
||||||
*
|
|
||||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
|
||||||
*/
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
|
||||||
public class ExampleInstrumentedTest {
|
|
||||||
@Test
|
|
||||||
public void useAppContext() {
|
|
||||||
// Context of the app under test.
|
|
||||||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
|
||||||
assertEquals("com.coldmint.rust.core.test", appContext.getPackageName());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
package com.coldmint.rust.core;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Example local unit test, which will execute on the development machine (host).
|
|
||||||
*
|
|
||||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
|
||||||
*/
|
|
||||||
public class ExampleUnitTest {
|
|
||||||
@Test
|
|
||||||
public void addition_isCorrect() {
|
|
||||||
assertEquals(4, 2 + 2);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
package com.coldmint.dialog
|
|
||||||
|
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
|
||||||
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
|
|
||||||
import org.junit.Assert.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instrumented test, which will execute on an Android device.
|
|
||||||
*
|
|
||||||
* See [testing documentation](http://d.android.com/tools/testing).
|
|
||||||
*/
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
|
||||||
class ExampleInstrumentedTest {
|
|
||||||
@Test
|
|
||||||
fun useAppContext() {
|
|
||||||
// Context of the app under test.
|
|
||||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
|
||||||
assertEquals("com.coldmint.dialog.test", appContext.packageName)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
package com.coldmint.dialog
|
|
||||||
|
|
||||||
import org.junit.Test
|
|
||||||
|
|
||||||
import org.junit.Assert.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Example local unit test, which will execute on the development machine (host).
|
|
||||||
*
|
|
||||||
* See [testing documentation](http://d.android.com/tools/testing).
|
|
||||||
*/
|
|
||||||
class ExampleUnitTest {
|
|
||||||
@Test
|
|
||||||
fun addition_isCorrect() {
|
|
||||||
assertEquals(4, 2 + 2)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -18,3 +18,4 @@ android.useAndroidX=true
|
||||||
# Automatically convert third-party libraries to use AndroidX
|
# Automatically convert third-party libraries to use AndroidX
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
android.injected.testOnly=false
|
android.injected.testOnly=false
|
||||||
|
android.suppressUnsupportedCompileSdk=32,33
|
||||||
|
|
1
library/.gitignore
vendored
Normal file
1
library/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/build
|
20
library/build.gradle
Normal file
20
library/build.gradle
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdk 32
|
||||||
|
defaultConfig {
|
||||||
|
minSdk 21
|
||||||
|
targetSdk 32
|
||||||
|
}
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||||
|
implementation 'com.google.android.material:material:1.9.0'
|
||||||
|
}
|
17
library/proguard-rules.pro
vendored
Normal file
17
library/proguard-rules.pro
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# By default, the flags in this file are appended to flags specified
|
||||||
|
# in /Users/flask/Documents/android-sdk/tools/proguard/proguard-android.txt
|
||||||
|
# You can edit the include path and order by changing the proguardFiles
|
||||||
|
# directive in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# Add any project specific keep options here:
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
5
library/src/main/AndroidManifest.xml
Normal file
5
library/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<manifest package="com.flask.colorpicker">
|
||||||
|
|
||||||
|
<application/>
|
||||||
|
|
||||||
|
</manifest>
|
54
library/src/main/java/com/flask/colorpicker/ColorCircle.java
Normal file
54
library/src/main/java/com/flask/colorpicker/ColorCircle.java
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
package com.flask.colorpicker;
|
||||||
|
|
||||||
|
import android.graphics.Color;
|
||||||
|
|
||||||
|
public class ColorCircle {
|
||||||
|
private float x, y;
|
||||||
|
private float[] hsv = new float[3];
|
||||||
|
private float[] hsvClone;
|
||||||
|
private int color;
|
||||||
|
|
||||||
|
public ColorCircle(float x, float y, float[] hsv) {
|
||||||
|
set(x, y, hsv);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double sqDist(float x, float y) {
|
||||||
|
double dx = this.x - x;
|
||||||
|
double dy = this.y - y;
|
||||||
|
return dx * dx + dy * dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float[] getHsv() {
|
||||||
|
return hsv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float[] getHsvWithLightness(float lightness) {
|
||||||
|
if (hsvClone == null)
|
||||||
|
hsvClone = hsv.clone();
|
||||||
|
hsvClone[0] = hsv[0];
|
||||||
|
hsvClone[1] = hsv[1];
|
||||||
|
hsvClone[2] = lightness;
|
||||||
|
return hsvClone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(float x, float y, float[] hsv) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.hsv[0] = hsv[0];
|
||||||
|
this.hsv[1] = hsv[1];
|
||||||
|
this.hsv[2] = hsv[2];
|
||||||
|
this.color = Color.HSVToColor(this.hsv);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getColor() {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.flask.colorpicker;
|
||||||
|
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.drawable.ColorDrawable;
|
||||||
|
|
||||||
|
import com.flask.colorpicker.builder.PaintBuilder;
|
||||||
|
|
||||||
|
public class ColorCircleDrawable extends ColorDrawable {
|
||||||
|
private float strokeWidth;
|
||||||
|
private Paint strokePaint = PaintBuilder.newPaint().style(Paint.Style.STROKE).stroke(strokeWidth).color(0xff9e9e9e).build();
|
||||||
|
private Paint fillPaint = PaintBuilder.newPaint().style(Paint.Style.FILL).color(0).build();
|
||||||
|
private Paint fillBackPaint = PaintBuilder.newPaint().shader(PaintBuilder.createAlphaPatternShader(26)).build();
|
||||||
|
|
||||||
|
public ColorCircleDrawable(int color) {
|
||||||
|
super(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(Canvas canvas) {
|
||||||
|
canvas.drawColor(0);
|
||||||
|
|
||||||
|
int width = canvas.getWidth();
|
||||||
|
float radius = width / 2f;
|
||||||
|
strokeWidth = radius / 8f;
|
||||||
|
|
||||||
|
this.strokePaint.setStrokeWidth(strokeWidth);
|
||||||
|
this.fillPaint.setColor(getColor());
|
||||||
|
canvas.drawCircle(radius, radius, radius - strokeWidth, fillBackPaint);
|
||||||
|
canvas.drawCircle(radius, radius, radius - strokeWidth, fillPaint);
|
||||||
|
canvas.drawCircle(radius, radius, radius - strokeWidth, strokePaint);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setColor(int color) {
|
||||||
|
super.setColor(color);
|
||||||
|
invalidateSelf();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,155 @@
|
||||||
|
package com.flask.colorpicker;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.preference.Preference;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import com.flask.colorpicker.builder.ColorPickerClickListener;
|
||||||
|
import com.flask.colorpicker.builder.ColorPickerDialogBuilder;
|
||||||
|
|
||||||
|
public class ColorPickerPreference extends Preference {
|
||||||
|
|
||||||
|
protected boolean alphaSlider;
|
||||||
|
protected boolean lightSlider;
|
||||||
|
protected boolean border;
|
||||||
|
|
||||||
|
protected int selectedColor = 0;
|
||||||
|
|
||||||
|
protected ColorPickerView.WHEEL_TYPE wheelType;
|
||||||
|
protected int density;
|
||||||
|
|
||||||
|
private boolean pickerColorEdit;
|
||||||
|
private String pickerTitle;
|
||||||
|
private String pickerButtonCancel;
|
||||||
|
private String pickerButtonOk;
|
||||||
|
|
||||||
|
protected ImageView colorIndicator;
|
||||||
|
|
||||||
|
public ColorPickerPreference(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerPreference(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
initWith(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
initWith(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initWith(Context context, AttributeSet attrs) {
|
||||||
|
final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ColorPickerPreference);
|
||||||
|
|
||||||
|
try {
|
||||||
|
alphaSlider = typedArray.getBoolean(R.styleable.ColorPickerPreference_alphaSlider, false);
|
||||||
|
lightSlider = typedArray.getBoolean(R.styleable.ColorPickerPreference_lightnessSlider, false);
|
||||||
|
border = typedArray.getBoolean(R.styleable.ColorPickerPreference_border, true);
|
||||||
|
|
||||||
|
density = typedArray.getInt(R.styleable.ColorPickerPreference_density, 8);
|
||||||
|
wheelType = ColorPickerView.WHEEL_TYPE.indexOf(typedArray.getInt(R.styleable.ColorPickerPreference_wheelType, 0));
|
||||||
|
|
||||||
|
selectedColor = typedArray.getInt(R.styleable.ColorPickerPreference_initialColor, 0xffffffff);
|
||||||
|
|
||||||
|
pickerColorEdit = typedArray.getBoolean(R.styleable.ColorPickerPreference_pickerColorEdit, true);
|
||||||
|
pickerTitle = typedArray.getString(R.styleable.ColorPickerPreference_pickerTitle);
|
||||||
|
if (pickerTitle==null)
|
||||||
|
pickerTitle = "Choose color";
|
||||||
|
|
||||||
|
pickerButtonCancel = typedArray.getString(R.styleable.ColorPickerPreference_pickerButtonCancel);
|
||||||
|
if (pickerButtonCancel==null)
|
||||||
|
pickerButtonCancel = "cancel";
|
||||||
|
|
||||||
|
pickerButtonOk = typedArray.getString(R.styleable.ColorPickerPreference_pickerButtonOk);
|
||||||
|
if (pickerButtonOk==null)
|
||||||
|
pickerButtonOk = "ok";
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
typedArray.recycle();
|
||||||
|
}
|
||||||
|
|
||||||
|
setWidgetLayoutResource(R.layout.color_widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onBindView(@NonNull View view) {
|
||||||
|
super.onBindView(view);
|
||||||
|
|
||||||
|
int tmpColor = isEnabled()
|
||||||
|
? selectedColor
|
||||||
|
: darken(selectedColor, .5f);
|
||||||
|
|
||||||
|
colorIndicator = (ImageView) view.findViewById(R.id.color_indicator);
|
||||||
|
|
||||||
|
ColorCircleDrawable colorChoiceDrawable = null;
|
||||||
|
Drawable currentDrawable = colorIndicator.getDrawable();
|
||||||
|
if (currentDrawable != null && currentDrawable instanceof ColorCircleDrawable)
|
||||||
|
colorChoiceDrawable = (ColorCircleDrawable) currentDrawable;
|
||||||
|
|
||||||
|
if (colorChoiceDrawable == null)
|
||||||
|
colorChoiceDrawable = new ColorCircleDrawable(tmpColor);
|
||||||
|
|
||||||
|
colorIndicator.setImageDrawable(colorChoiceDrawable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(int value) {
|
||||||
|
if (callChangeListener(value)) {
|
||||||
|
selectedColor = value;
|
||||||
|
persistInt(value);
|
||||||
|
notifyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
|
||||||
|
setValue(restoreValue ? getPersistedInt(0) : (Integer) defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onClick() {
|
||||||
|
ColorPickerDialogBuilder builder = ColorPickerDialogBuilder
|
||||||
|
.with(getContext())
|
||||||
|
.setTitle(pickerTitle)
|
||||||
|
.initialColor(selectedColor)
|
||||||
|
.showBorder(border)
|
||||||
|
.wheelType(wheelType)
|
||||||
|
.density(density)
|
||||||
|
.showColorEdit(pickerColorEdit)
|
||||||
|
.setPositiveButton(pickerButtonOk, new ColorPickerClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int selectedColorFromPicker, Integer[] allColors) {
|
||||||
|
setValue(selectedColorFromPicker);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton(pickerButtonCancel, null);
|
||||||
|
|
||||||
|
if (!alphaSlider && !lightSlider) builder.noSliders();
|
||||||
|
else if (!alphaSlider) builder.lightnessSliderOnly();
|
||||||
|
else if (!lightSlider) builder.alphaSliderOnly();
|
||||||
|
|
||||||
|
builder
|
||||||
|
.build()
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int darken(int color, float factor) {
|
||||||
|
int a = Color.alpha(color);
|
||||||
|
int r = Color.red(color);
|
||||||
|
int g = Color.green(color);
|
||||||
|
int b = Color.blue(color);
|
||||||
|
|
||||||
|
return Color.argb(a,
|
||||||
|
Math.max((int)(r * factor), 0),
|
||||||
|
Math.max((int)(g * factor), 0),
|
||||||
|
Math.max((int)(b * factor), 0));
|
||||||
|
}
|
||||||
|
}
|
572
library/src/main/java/com/flask/colorpicker/ColorPickerView.java
Normal file
572
library/src/main/java/com/flask/colorpicker/ColorPickerView.java
Normal file
|
@ -0,0 +1,572 @@
|
||||||
|
package com.flask.colorpicker;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import com.flask.colorpicker.builder.ColorWheelRendererBuilder;
|
||||||
|
import com.flask.colorpicker.builder.PaintBuilder;
|
||||||
|
import com.flask.colorpicker.renderer.ColorWheelRenderOption;
|
||||||
|
import com.flask.colorpicker.renderer.ColorWheelRenderer;
|
||||||
|
import com.flask.colorpicker.slider.AlphaSlider;
|
||||||
|
import com.flask.colorpicker.slider.LightnessSlider;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class ColorPickerView extends View {
|
||||||
|
private static final float STROKE_RATIO = 1.5f;
|
||||||
|
|
||||||
|
private Bitmap colorWheel;
|
||||||
|
private Canvas colorWheelCanvas;
|
||||||
|
private Bitmap currentColor;
|
||||||
|
private Canvas currentColorCanvas;
|
||||||
|
private boolean showBorder;
|
||||||
|
private int density = 8;
|
||||||
|
|
||||||
|
private float lightness = 1;
|
||||||
|
private float alpha = 1;
|
||||||
|
private int backgroundColor = 0x00000000;
|
||||||
|
|
||||||
|
private Integer initialColors[] = new Integer[]{null, null, null, null, null};
|
||||||
|
private int colorSelection = 0;
|
||||||
|
private Integer initialColor;
|
||||||
|
private Integer pickerColorEditTextColor;
|
||||||
|
private Paint colorWheelFill = PaintBuilder.newPaint().color(0).build();
|
||||||
|
private Paint selectorStroke = PaintBuilder.newPaint().color(0).build();
|
||||||
|
private Paint alphaPatternPaint = PaintBuilder.newPaint().build();
|
||||||
|
private ColorCircle currentColorCircle;
|
||||||
|
|
||||||
|
private ArrayList<OnColorChangedListener> colorChangedListeners = new ArrayList<>();
|
||||||
|
private ArrayList<OnColorSelectedListener> listeners = new ArrayList<>();
|
||||||
|
|
||||||
|
private LightnessSlider lightnessSlider;
|
||||||
|
private AlphaSlider alphaSlider;
|
||||||
|
private EditText colorEdit;
|
||||||
|
private TextWatcher colorTextChange = new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
|
try {
|
||||||
|
int color = Color.parseColor(s.toString());
|
||||||
|
|
||||||
|
// set the color without changing the edit text preventing stack overflow
|
||||||
|
setColor(color, false);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private LinearLayout colorPreview;
|
||||||
|
|
||||||
|
private ColorWheelRenderer renderer;
|
||||||
|
|
||||||
|
private int alphaSliderViewId, lightnessSliderViewId;
|
||||||
|
|
||||||
|
public ColorPickerView(Context context) {
|
||||||
|
super(context);
|
||||||
|
initWith(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerView(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
initWith(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
initWith(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(21)
|
||||||
|
public ColorPickerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||||
|
super(context, attrs, defStyleAttr, defStyleRes);
|
||||||
|
initWith(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initWith(Context context, AttributeSet attrs) {
|
||||||
|
final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ColorPickerPreference);
|
||||||
|
|
||||||
|
density = typedArray.getInt(R.styleable.ColorPickerPreference_density, 10);
|
||||||
|
initialColor = typedArray.getInt(R.styleable.ColorPickerPreference_initialColor, 0xffffffff);
|
||||||
|
|
||||||
|
pickerColorEditTextColor = typedArray.getInt(R.styleable.ColorPickerPreference_pickerColorEditTextColor, 0xffffffff);
|
||||||
|
|
||||||
|
WHEEL_TYPE wheelType = WHEEL_TYPE.indexOf(typedArray.getInt(R.styleable.ColorPickerPreference_wheelType, 0));
|
||||||
|
ColorWheelRenderer renderer = ColorWheelRendererBuilder.getRenderer(wheelType);
|
||||||
|
|
||||||
|
alphaSliderViewId = typedArray.getResourceId(R.styleable.ColorPickerPreference_alphaSliderView, 0);
|
||||||
|
lightnessSliderViewId = typedArray.getResourceId(R.styleable.ColorPickerPreference_lightnessSliderView, 0);
|
||||||
|
|
||||||
|
setRenderer(renderer);
|
||||||
|
setDensity(density);
|
||||||
|
setInitialColor(initialColor, true);
|
||||||
|
|
||||||
|
typedArray.recycle();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWindowFocusChanged(boolean hasWindowFocus) {
|
||||||
|
super.onWindowFocusChanged(hasWindowFocus);
|
||||||
|
updateColorWheel();
|
||||||
|
currentColorCircle = findNearestByColor(initialColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||||
|
super.onLayout(changed, left, top, right, bottom);
|
||||||
|
|
||||||
|
if (alphaSliderViewId != 0)
|
||||||
|
setAlphaSlider((AlphaSlider) getRootView().findViewById(alphaSliderViewId));
|
||||||
|
if (lightnessSliderViewId != 0)
|
||||||
|
setLightnessSlider((LightnessSlider) getRootView().findViewById(lightnessSliderViewId));
|
||||||
|
|
||||||
|
updateColorWheel();
|
||||||
|
currentColorCircle = findNearestByColor(initialColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||||
|
super.onSizeChanged(w, h, oldw, oldh);
|
||||||
|
updateColorWheel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateColorWheel() {
|
||||||
|
int width = getMeasuredWidth();
|
||||||
|
int height = getMeasuredHeight();
|
||||||
|
|
||||||
|
if (height < width)
|
||||||
|
width = height;
|
||||||
|
if (width <= 0)
|
||||||
|
return;
|
||||||
|
if (colorWheel == null || colorWheel.getWidth() != width) {
|
||||||
|
colorWheel = Bitmap.createBitmap(width, width, Bitmap.Config.ARGB_8888);
|
||||||
|
colorWheelCanvas = new Canvas(colorWheel);
|
||||||
|
alphaPatternPaint.setShader(PaintBuilder.createAlphaPatternShader(26));
|
||||||
|
}
|
||||||
|
if (currentColor == null || currentColor.getWidth() != width) {
|
||||||
|
currentColor = Bitmap.createBitmap(width, width, Bitmap.Config.ARGB_8888);
|
||||||
|
currentColorCanvas = new Canvas(currentColor);
|
||||||
|
}
|
||||||
|
drawColorWheel();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawColorWheel() {
|
||||||
|
colorWheelCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
|
||||||
|
currentColorCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
|
||||||
|
|
||||||
|
if (renderer == null) return;
|
||||||
|
|
||||||
|
float half = colorWheelCanvas.getWidth() / 2f;
|
||||||
|
float strokeWidth = STROKE_RATIO * (1f + ColorWheelRenderer.GAP_PERCENTAGE);
|
||||||
|
float maxRadius = half - strokeWidth - half / density;
|
||||||
|
float cSize = maxRadius / (density - 1) / 2;
|
||||||
|
|
||||||
|
ColorWheelRenderOption colorWheelRenderOption = renderer.getRenderOption();
|
||||||
|
colorWheelRenderOption.density = this.density;
|
||||||
|
colorWheelRenderOption.maxRadius = maxRadius;
|
||||||
|
colorWheelRenderOption.cSize = cSize;
|
||||||
|
colorWheelRenderOption.strokeWidth = strokeWidth;
|
||||||
|
colorWheelRenderOption.alpha = alpha;
|
||||||
|
colorWheelRenderOption.lightness = lightness;
|
||||||
|
colorWheelRenderOption.targetCanvas = colorWheelCanvas;
|
||||||
|
|
||||||
|
renderer.initWith(colorWheelRenderOption);
|
||||||
|
renderer.draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||||
|
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||||
|
int width = 0;
|
||||||
|
if (widthMode == MeasureSpec.UNSPECIFIED)
|
||||||
|
width = widthMeasureSpec;
|
||||||
|
else if (widthMode == MeasureSpec.AT_MOST)
|
||||||
|
width = MeasureSpec.getSize(widthMeasureSpec);
|
||||||
|
else if (widthMode == MeasureSpec.EXACTLY)
|
||||||
|
width = MeasureSpec.getSize(widthMeasureSpec);
|
||||||
|
|
||||||
|
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||||
|
int height = 0;
|
||||||
|
if (heightMode == MeasureSpec.UNSPECIFIED)
|
||||||
|
height = heightMeasureSpec;
|
||||||
|
else if (heightMode == MeasureSpec.AT_MOST)
|
||||||
|
height = MeasureSpec.getSize(heightMeasureSpec);
|
||||||
|
else if (heightMode == MeasureSpec.EXACTLY)
|
||||||
|
height = MeasureSpec.getSize(heightMeasureSpec);
|
||||||
|
int squareDimen = width;
|
||||||
|
if (height < width)
|
||||||
|
squareDimen = height;
|
||||||
|
setMeasuredDimension(squareDimen, squareDimen);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
|
switch (event.getAction()) {
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
case MotionEvent.ACTION_MOVE: {
|
||||||
|
int lastSelectedColor = getSelectedColor();
|
||||||
|
currentColorCircle = findNearestByPosition(event.getX(), event.getY());
|
||||||
|
int selectedColor = getSelectedColor();
|
||||||
|
|
||||||
|
callOnColorChangedListeners(lastSelectedColor, selectedColor);
|
||||||
|
|
||||||
|
initialColor = selectedColor;
|
||||||
|
setColorToSliders(selectedColor);
|
||||||
|
updateColorWheel();
|
||||||
|
invalidate();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MotionEvent.ACTION_UP: {
|
||||||
|
int selectedColor = getSelectedColor();
|
||||||
|
if (listeners != null) {
|
||||||
|
for (OnColorSelectedListener listener : listeners) {
|
||||||
|
try {
|
||||||
|
listener.onColorSelected(selectedColor);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setColorToSliders(selectedColor);
|
||||||
|
setColorText(selectedColor);
|
||||||
|
setColorPreviewColor(selectedColor);
|
||||||
|
invalidate();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void callOnColorChangedListeners(int oldColor, int newColor) {
|
||||||
|
if (colorChangedListeners != null && oldColor != newColor) {
|
||||||
|
for (OnColorChangedListener listener : colorChangedListeners) {
|
||||||
|
try {
|
||||||
|
listener.onColorChanged(newColor);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDraw(Canvas canvas) {
|
||||||
|
super.onDraw(canvas);
|
||||||
|
canvas.drawColor(backgroundColor);
|
||||||
|
|
||||||
|
float maxRadius = canvas.getWidth() / (1f + ColorWheelRenderer.GAP_PERCENTAGE);
|
||||||
|
float size = maxRadius / density / 2;
|
||||||
|
if (colorWheel != null && currentColorCircle != null) {
|
||||||
|
colorWheelFill.setColor(Color.HSVToColor(currentColorCircle.getHsvWithLightness(this.lightness)));
|
||||||
|
colorWheelFill.setAlpha((int) (alpha * 0xff));
|
||||||
|
|
||||||
|
// a separate canvas is used to erase an issue with the alpha pattern around the edges
|
||||||
|
// draw circle slightly larger than it needs to be, then erase edges to proper dimensions
|
||||||
|
currentColorCanvas.drawCircle(currentColorCircle.getX(), currentColorCircle.getY(), size + 4, alphaPatternPaint);
|
||||||
|
currentColorCanvas.drawCircle(currentColorCircle.getX(), currentColorCircle.getY(), size + 4, colorWheelFill);
|
||||||
|
|
||||||
|
selectorStroke = PaintBuilder.newPaint().color(0xffffffff).style(Paint.Style.STROKE).stroke(size * (STROKE_RATIO - 1)).xPerMode(PorterDuff.Mode.CLEAR).build();
|
||||||
|
|
||||||
|
if (showBorder) colorWheelCanvas.drawCircle(currentColorCircle.getX(), currentColorCircle.getY(), size + (selectorStroke.getStrokeWidth() / 2f), selectorStroke);
|
||||||
|
canvas.drawBitmap(colorWheel, 0, 0, null);
|
||||||
|
|
||||||
|
currentColorCanvas.drawCircle(currentColorCircle.getX(), currentColorCircle.getY(), size + (selectorStroke.getStrokeWidth() / 2f), selectorStroke);
|
||||||
|
canvas.drawBitmap(currentColor, 0, 0, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ColorCircle findNearestByPosition(float x, float y) {
|
||||||
|
ColorCircle near = null;
|
||||||
|
double minDist = Double.MAX_VALUE;
|
||||||
|
|
||||||
|
for (ColorCircle colorCircle : renderer.getColorCircleList()) {
|
||||||
|
double dist = colorCircle.sqDist(x, y);
|
||||||
|
if (minDist > dist) {
|
||||||
|
minDist = dist;
|
||||||
|
near = colorCircle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return near;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ColorCircle findNearestByColor(int color) {
|
||||||
|
float[] hsv = new float[3];
|
||||||
|
Color.colorToHSV(color, hsv);
|
||||||
|
ColorCircle near = null;
|
||||||
|
double minDiff = Double.MAX_VALUE;
|
||||||
|
double x = hsv[1] * Math.cos(hsv[0] * Math.PI / 180);
|
||||||
|
double y = hsv[1] * Math.sin(hsv[0] * Math.PI / 180);
|
||||||
|
|
||||||
|
for (ColorCircle colorCircle : renderer.getColorCircleList()) {
|
||||||
|
float[] hsv1 = colorCircle.getHsv();
|
||||||
|
double x1 = hsv1[1] * Math.cos(hsv1[0] * Math.PI / 180);
|
||||||
|
double y1 = hsv1[1] * Math.sin(hsv1[0] * Math.PI / 180);
|
||||||
|
double dx = x - x1;
|
||||||
|
double dy = y - y1;
|
||||||
|
double dist = dx * dx + dy * dy;
|
||||||
|
if (dist < minDiff) {
|
||||||
|
minDiff = dist;
|
||||||
|
near = colorCircle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return near;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSelectedColor() {
|
||||||
|
int color = 0;
|
||||||
|
if (currentColorCircle != null)
|
||||||
|
color = Utils.colorAtLightness(currentColorCircle.getColor(), this.lightness);
|
||||||
|
return Utils.adjustAlpha(this.alpha, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer[] getAllColors() {
|
||||||
|
return initialColors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInitialColors(Integer[] colors, int selectedColor) {
|
||||||
|
this.initialColors = colors;
|
||||||
|
this.colorSelection = selectedColor;
|
||||||
|
Integer initialColor = this.initialColors[this.colorSelection];
|
||||||
|
if (initialColor == null) initialColor = 0xffffffff;
|
||||||
|
setInitialColor(initialColor, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInitialColor(int color, boolean updateText) {
|
||||||
|
float[] hsv = new float[3];
|
||||||
|
Color.colorToHSV(color, hsv);
|
||||||
|
|
||||||
|
this.alpha = Utils.getAlphaPercent(color);
|
||||||
|
this.lightness = hsv[2];
|
||||||
|
this.initialColors[this.colorSelection] = color;
|
||||||
|
this.initialColor = color;
|
||||||
|
setColorPreviewColor(color);
|
||||||
|
setColorToSliders(color);
|
||||||
|
if (this.colorEdit != null && updateText)
|
||||||
|
setColorText(color);
|
||||||
|
currentColorCircle = findNearestByColor(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLightness(float lightness) {
|
||||||
|
int lastSelectedColor = getSelectedColor();
|
||||||
|
|
||||||
|
this.lightness = lightness;
|
||||||
|
if (currentColorCircle != null) {
|
||||||
|
this.initialColor = Color.HSVToColor(Utils.alphaValueAsInt(this.alpha), currentColorCircle.getHsvWithLightness(lightness));
|
||||||
|
if (this.colorEdit != null)
|
||||||
|
this.colorEdit.setText(Utils.getHexString(this.initialColor, this.alphaSlider != null));
|
||||||
|
if (this.alphaSlider != null && this.initialColor != null)
|
||||||
|
this.alphaSlider.setColor(this.initialColor);
|
||||||
|
|
||||||
|
callOnColorChangedListeners(lastSelectedColor, this.initialColor);
|
||||||
|
|
||||||
|
updateColorWheel();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(int color, boolean updateText) {
|
||||||
|
setInitialColor(color, updateText);
|
||||||
|
updateColorWheel();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlphaValue(float alpha) {
|
||||||
|
int lastSelectedColor = getSelectedColor();
|
||||||
|
|
||||||
|
this.alpha = alpha;
|
||||||
|
this.initialColor = Color.HSVToColor(Utils.alphaValueAsInt(this.alpha), currentColorCircle.getHsvWithLightness(this.lightness));
|
||||||
|
if (this.colorEdit != null)
|
||||||
|
this.colorEdit.setText(Utils.getHexString(this.initialColor, this.alphaSlider != null));
|
||||||
|
if (this.lightnessSlider != null && this.initialColor != null)
|
||||||
|
this.lightnessSlider.setColor(this.initialColor);
|
||||||
|
|
||||||
|
callOnColorChangedListeners(lastSelectedColor, this.initialColor);
|
||||||
|
|
||||||
|
updateColorWheel();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addOnColorChangedListener(OnColorChangedListener listener) {
|
||||||
|
this.colorChangedListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addOnColorSelectedListener(OnColorSelectedListener listener) {
|
||||||
|
this.listeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLightnessSlider(LightnessSlider lightnessSlider) {
|
||||||
|
this.lightnessSlider = lightnessSlider;
|
||||||
|
if (lightnessSlider != null) {
|
||||||
|
this.lightnessSlider.setColorPicker(this);
|
||||||
|
this.lightnessSlider.setColor(getSelectedColor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlphaSlider(AlphaSlider alphaSlider) {
|
||||||
|
this.alphaSlider = alphaSlider;
|
||||||
|
if (alphaSlider != null) {
|
||||||
|
this.alphaSlider.setColorPicker(this);
|
||||||
|
this.alphaSlider.setColor(getSelectedColor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColorEdit(EditText colorEdit) {
|
||||||
|
this.colorEdit = colorEdit;
|
||||||
|
if (this.colorEdit != null) {
|
||||||
|
this.colorEdit.setVisibility(View.VISIBLE);
|
||||||
|
this.colorEdit.addTextChangedListener(colorTextChange);
|
||||||
|
setColorEditTextColor(pickerColorEditTextColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColorEditTextColor(int argb) {
|
||||||
|
this.pickerColorEditTextColor = argb;
|
||||||
|
if (colorEdit != null)
|
||||||
|
colorEdit.setTextColor(argb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDensity(int density) {
|
||||||
|
this.density = Math.max(2, density);
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRenderer(ColorWheelRenderer renderer) {
|
||||||
|
this.renderer = renderer;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColorPreview(LinearLayout colorPreview, Integer selectedColor) {
|
||||||
|
if (colorPreview == null)
|
||||||
|
return;
|
||||||
|
this.colorPreview = colorPreview;
|
||||||
|
if (selectedColor == null)
|
||||||
|
selectedColor = 0;
|
||||||
|
int children = colorPreview.getChildCount();
|
||||||
|
if (children == 0 || colorPreview.getVisibility() != View.VISIBLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < children; i++) {
|
||||||
|
View childView = colorPreview.getChildAt(i);
|
||||||
|
if (!(childView instanceof LinearLayout))
|
||||||
|
continue;
|
||||||
|
LinearLayout childLayout = (LinearLayout) childView;
|
||||||
|
if (i == selectedColor) {
|
||||||
|
childLayout.setBackgroundColor(Color.WHITE);
|
||||||
|
}
|
||||||
|
ImageView childImage = (ImageView) childLayout.findViewById(R.id.image_preview);
|
||||||
|
childImage.setClickable(true);
|
||||||
|
childImage.setTag(i);
|
||||||
|
childImage.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (v == null)
|
||||||
|
return;
|
||||||
|
Object tag = v.getTag();
|
||||||
|
if (tag == null || !(tag instanceof Integer))
|
||||||
|
return;
|
||||||
|
setSelectedColor((int) tag);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectedColor(int previewNumber) {
|
||||||
|
if (initialColors == null || initialColors.length < previewNumber)
|
||||||
|
return;
|
||||||
|
this.colorSelection = previewNumber;
|
||||||
|
setHighlightedColor(previewNumber);
|
||||||
|
Integer color = initialColors[previewNumber];
|
||||||
|
if (color == null)
|
||||||
|
return;
|
||||||
|
setColor(color, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShowBorder(boolean showBorder) {
|
||||||
|
this.showBorder = showBorder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setHighlightedColor(int previewNumber) {
|
||||||
|
int children = colorPreview.getChildCount();
|
||||||
|
if (children == 0 || colorPreview.getVisibility() != View.VISIBLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < children; i++) {
|
||||||
|
View childView = colorPreview.getChildAt(i);
|
||||||
|
if (!(childView instanceof LinearLayout))
|
||||||
|
continue;
|
||||||
|
LinearLayout childLayout = (LinearLayout) childView;
|
||||||
|
if (i == previewNumber) {
|
||||||
|
childLayout.setBackgroundColor(Color.WHITE);
|
||||||
|
} else {
|
||||||
|
childLayout.setBackgroundColor(Color.TRANSPARENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setColorPreviewColor(int newColor) {
|
||||||
|
if (colorPreview == null || initialColors == null || colorSelection > initialColors.length || initialColors[colorSelection] == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int children = colorPreview.getChildCount();
|
||||||
|
if (children == 0 || colorPreview.getVisibility() != View.VISIBLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
View childView = colorPreview.getChildAt(colorSelection);
|
||||||
|
if (!(childView instanceof LinearLayout))
|
||||||
|
return;
|
||||||
|
LinearLayout childLayout = (LinearLayout) childView;
|
||||||
|
ImageView childImage = (ImageView) childLayout.findViewById(R.id.image_preview);
|
||||||
|
childImage.setImageDrawable(new ColorCircleDrawable(newColor));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setColorText(int argb) {
|
||||||
|
if (colorEdit == null)
|
||||||
|
return;
|
||||||
|
colorEdit.setText(Utils.getHexString(argb, this.alphaSlider != null));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setColorToSliders(int selectedColor) {
|
||||||
|
if (lightnessSlider != null)
|
||||||
|
lightnessSlider.setColor(selectedColor);
|
||||||
|
if (alphaSlider != null)
|
||||||
|
alphaSlider.setColor(selectedColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum WHEEL_TYPE {
|
||||||
|
FLOWER, CIRCLE;
|
||||||
|
|
||||||
|
public static WHEEL_TYPE indexOf(int index) {
|
||||||
|
switch (index) {
|
||||||
|
case 0:
|
||||||
|
return FLOWER;
|
||||||
|
case 1:
|
||||||
|
return CIRCLE;
|
||||||
|
}
|
||||||
|
return FLOWER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.flask.colorpicker;
|
||||||
|
|
||||||
|
public interface OnColorChangedListener {
|
||||||
|
void onColorChanged(int selectedColor);
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.flask.colorpicker;
|
||||||
|
|
||||||
|
public interface OnColorSelectedListener {
|
||||||
|
void onColorSelected(int selectedColor);
|
||||||
|
}
|
40
library/src/main/java/com/flask/colorpicker/Utils.java
Normal file
40
library/src/main/java/com/flask/colorpicker/Utils.java
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
package com.flask.colorpicker;
|
||||||
|
|
||||||
|
import android.graphics.Color;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Charles Andersons on 4/17/15.
|
||||||
|
*/
|
||||||
|
public class Utils {
|
||||||
|
public static float getAlphaPercent(int argb) {
|
||||||
|
return Color.alpha(argb) / 255f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int alphaValueAsInt(float alpha) {
|
||||||
|
return Math.round(alpha * 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int adjustAlpha(float alpha, int color) {
|
||||||
|
return alphaValueAsInt(alpha) << 24 | (0x00ffffff & color);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int colorAtLightness(int color, float lightness) {
|
||||||
|
float[] hsv = new float[3];
|
||||||
|
Color.colorToHSV(color, hsv);
|
||||||
|
hsv[2] = lightness;
|
||||||
|
return Color.HSVToColor(hsv);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float lightnessOfColor(int color) {
|
||||||
|
float[] hsv = new float[3];
|
||||||
|
Color.colorToHSV(color, hsv);
|
||||||
|
return hsv[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getHexString(int color, boolean showAlpha) {
|
||||||
|
int base = showAlpha ? 0xFFFFFFFF : 0xFFFFFF;
|
||||||
|
String format = showAlpha ? "#%08X" : "#%06X";
|
||||||
|
return String.format(format, (base & color)).toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.flask.colorpicker.builder;
|
||||||
|
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Charles Anderson on 4/17/15.
|
||||||
|
*/
|
||||||
|
public interface ColorPickerClickListener {
|
||||||
|
void onClick(DialogInterface d, int lastSelectedColor, Integer[] allColors);
|
||||||
|
}
|
|
@ -0,0 +1,294 @@
|
||||||
|
package com.flask.colorpicker.builder;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.drawable.ColorDrawable;
|
||||||
|
import android.text.InputFilter;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import com.flask.colorpicker.ColorPickerView;
|
||||||
|
import com.flask.colorpicker.OnColorChangedListener;
|
||||||
|
import com.flask.colorpicker.OnColorSelectedListener;
|
||||||
|
import com.flask.colorpicker.R;
|
||||||
|
import com.flask.colorpicker.Utils;
|
||||||
|
import com.flask.colorpicker.renderer.ColorWheelRenderer;
|
||||||
|
import com.flask.colorpicker.slider.AlphaSlider;
|
||||||
|
import com.flask.colorpicker.slider.LightnessSlider;
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
|
public class ColorPickerDialogBuilder {
|
||||||
|
private MaterialAlertDialogBuilder builder;
|
||||||
|
private LinearLayout pickerContainer;
|
||||||
|
private ColorPickerView colorPickerView;
|
||||||
|
private LightnessSlider lightnessSlider;
|
||||||
|
private AlphaSlider alphaSlider;
|
||||||
|
private EditText colorEdit;
|
||||||
|
private LinearLayout colorPreview;
|
||||||
|
|
||||||
|
private boolean isLightnessSliderEnabled = true;
|
||||||
|
private boolean isAlphaSliderEnabled = true;
|
||||||
|
private boolean isBorderEnabled = true;
|
||||||
|
private boolean isColorEditEnabled = false;
|
||||||
|
private boolean isPreviewEnabled = false;
|
||||||
|
private int pickerCount = 1;
|
||||||
|
private int defaultMargin = 0;
|
||||||
|
private int defaultMarginTop = 0;
|
||||||
|
private Integer[] initialColor = new Integer[]{null, null, null, null, null};
|
||||||
|
|
||||||
|
private ColorPickerDialogBuilder(Context context) {
|
||||||
|
this(context, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ColorPickerDialogBuilder(Context context, int theme) {
|
||||||
|
defaultMargin = getDimensionAsPx(context, R.dimen.default_slider_margin);
|
||||||
|
defaultMarginTop = getDimensionAsPx(context, R.dimen.default_margin_top);
|
||||||
|
|
||||||
|
builder = new MaterialAlertDialogBuilder(context, theme);
|
||||||
|
pickerContainer = new LinearLayout(context);
|
||||||
|
pickerContainer.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
pickerContainer.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||||
|
pickerContainer.setPadding(defaultMargin, defaultMarginTop, defaultMargin, 0);
|
||||||
|
|
||||||
|
LinearLayout.LayoutParams layoutParamsForColorPickerView = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0);
|
||||||
|
layoutParamsForColorPickerView.weight = 1;
|
||||||
|
colorPickerView = new ColorPickerView(context);
|
||||||
|
|
||||||
|
pickerContainer.addView(colorPickerView, layoutParamsForColorPickerView);
|
||||||
|
|
||||||
|
builder.setView(pickerContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ColorPickerDialogBuilder with(Context context) {
|
||||||
|
return new ColorPickerDialogBuilder(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ColorPickerDialogBuilder with(Context context, int theme) {
|
||||||
|
return new ColorPickerDialogBuilder(context, theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder setTitle(String title) {
|
||||||
|
builder.setTitle(title);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder setTitle(int titleId) {
|
||||||
|
builder.setTitle(titleId);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder initialColor(int initialColor) {
|
||||||
|
this.initialColor[0] = initialColor;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder initialColors(int[] initialColor) {
|
||||||
|
for (int i = 0; i < initialColor.length && i < this.initialColor.length; i++) {
|
||||||
|
this.initialColor[i] = initialColor[i];
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder wheelType(ColorPickerView.WHEEL_TYPE wheelType) {
|
||||||
|
ColorWheelRenderer renderer = ColorWheelRendererBuilder.getRenderer(wheelType);
|
||||||
|
colorPickerView.setRenderer(renderer);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder density(int density) {
|
||||||
|
colorPickerView.setDensity(density);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder setOnColorChangedListener(OnColorChangedListener onColorChangedListener) {
|
||||||
|
colorPickerView.addOnColorChangedListener(onColorChangedListener);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder setOnColorSelectedListener(OnColorSelectedListener onColorSelectedListener) {
|
||||||
|
colorPickerView.addOnColorSelectedListener(onColorSelectedListener);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder setPositiveButton(CharSequence text, final ColorPickerClickListener onClickListener) {
|
||||||
|
builder.setPositiveButton(text, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
positiveButtonOnClick(dialog, onClickListener);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder setPositiveButton(int textId, final ColorPickerClickListener onClickListener) {
|
||||||
|
builder.setPositiveButton(textId, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
positiveButtonOnClick(dialog, onClickListener);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder setNegativeButton(CharSequence text, DialogInterface.OnClickListener onClickListener) {
|
||||||
|
builder.setNegativeButton(text, onClickListener);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder setNegativeButton(int textId, DialogInterface.OnClickListener onClickListener) {
|
||||||
|
builder.setNegativeButton(textId, onClickListener);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder noSliders() {
|
||||||
|
isLightnessSliderEnabled = false;
|
||||||
|
isAlphaSliderEnabled = false;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder alphaSliderOnly() {
|
||||||
|
isLightnessSliderEnabled = false;
|
||||||
|
isAlphaSliderEnabled = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder lightnessSliderOnly() {
|
||||||
|
isLightnessSliderEnabled = true;
|
||||||
|
isAlphaSliderEnabled = false;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder showAlphaSlider(boolean showAlpha) {
|
||||||
|
isAlphaSliderEnabled = showAlpha;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder showLightnessSlider(boolean showLightness) {
|
||||||
|
isLightnessSliderEnabled = showLightness;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder showBorder(boolean showBorder) {
|
||||||
|
isBorderEnabled = showBorder;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder showColorEdit(boolean showEdit) {
|
||||||
|
isColorEditEnabled = showEdit;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder setColorEditTextColor(int argb) {
|
||||||
|
colorPickerView.setColorEditTextColor(argb);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder showColorPreview(boolean showPreview) {
|
||||||
|
isPreviewEnabled = showPreview;
|
||||||
|
if (!showPreview)
|
||||||
|
pickerCount = 1;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorPickerDialogBuilder setPickerCount(int pickerCount) throws IndexOutOfBoundsException {
|
||||||
|
if (pickerCount < 1 || pickerCount > 5)
|
||||||
|
throw new IndexOutOfBoundsException("Picker Can Only Support 1-5 Colors");
|
||||||
|
this.pickerCount = pickerCount;
|
||||||
|
if (this.pickerCount > 1)
|
||||||
|
this.isPreviewEnabled = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AlertDialog build() {
|
||||||
|
Context context = builder.getContext();
|
||||||
|
colorPickerView.setInitialColors(initialColor, getStartOffset(initialColor));
|
||||||
|
colorPickerView.setShowBorder(isBorderEnabled);
|
||||||
|
|
||||||
|
if (isLightnessSliderEnabled) {
|
||||||
|
LinearLayout.LayoutParams layoutParamsForLightnessBar = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getDimensionAsPx(context, R.dimen.default_slider_height));
|
||||||
|
lightnessSlider = new LightnessSlider(context);
|
||||||
|
lightnessSlider.setLayoutParams(layoutParamsForLightnessBar);
|
||||||
|
pickerContainer.addView(lightnessSlider);
|
||||||
|
colorPickerView.setLightnessSlider(lightnessSlider);
|
||||||
|
lightnessSlider.setColor(getStartColor(initialColor));
|
||||||
|
lightnessSlider.setShowBorder(isBorderEnabled);
|
||||||
|
}
|
||||||
|
if (isAlphaSliderEnabled) {
|
||||||
|
LinearLayout.LayoutParams layoutParamsForAlphaBar = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getDimensionAsPx(context, R.dimen.default_slider_height));
|
||||||
|
alphaSlider = new AlphaSlider(context);
|
||||||
|
alphaSlider.setLayoutParams(layoutParamsForAlphaBar);
|
||||||
|
pickerContainer.addView(alphaSlider);
|
||||||
|
colorPickerView.setAlphaSlider(alphaSlider);
|
||||||
|
alphaSlider.setColor(getStartColor(initialColor));
|
||||||
|
alphaSlider.setShowBorder(isBorderEnabled);
|
||||||
|
}
|
||||||
|
if (isColorEditEnabled) {
|
||||||
|
LinearLayout.LayoutParams layoutParamsForColorEdit = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
colorEdit = (EditText) View.inflate(context, R.layout.color_edit, null);
|
||||||
|
colorEdit.setFilters(new InputFilter[]{new InputFilter.AllCaps()});
|
||||||
|
colorEdit.setSingleLine();
|
||||||
|
colorEdit.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
// limit number of characters to hexColors
|
||||||
|
int maxLength = isAlphaSliderEnabled ? 9 : 7;
|
||||||
|
colorEdit.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength)});
|
||||||
|
|
||||||
|
pickerContainer.addView(colorEdit, layoutParamsForColorEdit);
|
||||||
|
|
||||||
|
colorEdit.setText(Utils.getHexString(getStartColor(initialColor), isAlphaSliderEnabled));
|
||||||
|
colorPickerView.setColorEdit(colorEdit);
|
||||||
|
}
|
||||||
|
if (isPreviewEnabled) {
|
||||||
|
colorPreview = (LinearLayout) View.inflate(context, R.layout.color_preview, null);
|
||||||
|
colorPreview.setVisibility(View.GONE);
|
||||||
|
pickerContainer.addView(colorPreview);
|
||||||
|
|
||||||
|
if (initialColor.length == 0) {
|
||||||
|
ImageView colorImage = (ImageView) View.inflate(context, R.layout.color_selector, null);
|
||||||
|
colorImage.setImageDrawable(new ColorDrawable(Color.WHITE));
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < initialColor.length && i < this.pickerCount; i++) {
|
||||||
|
if (initialColor[i] == null)
|
||||||
|
break;
|
||||||
|
LinearLayout colorLayout = (LinearLayout) View.inflate(context, R.layout.color_selector, null);
|
||||||
|
ImageView colorImage = colorLayout.findViewById(R.id.image_preview);
|
||||||
|
colorImage.setImageDrawable(new ColorDrawable(initialColor[i]));
|
||||||
|
colorPreview.addView(colorLayout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
colorPreview.setVisibility(View.VISIBLE);
|
||||||
|
colorPickerView.setColorPreview(colorPreview, getStartOffset(initialColor));
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer getStartOffset(Integer[] colors) {
|
||||||
|
int start = 0;
|
||||||
|
for (int i = 0; i < colors.length; i++) {
|
||||||
|
if (colors[i] == null) {
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
start = (i + 1) / 2;
|
||||||
|
}
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getStartColor(Integer[] colors) {
|
||||||
|
Integer startColor = getStartOffset(colors);
|
||||||
|
return startColor == null ? Color.WHITE : colors[startColor];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getDimensionAsPx(Context context, int rid) {
|
||||||
|
return (int) (context.getResources().getDimension(rid) + .5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void positiveButtonOnClick(DialogInterface dialog, ColorPickerClickListener onClickListener) {
|
||||||
|
int selectedColor = colorPickerView.getSelectedColor();
|
||||||
|
Integer[] allColors = colorPickerView.getAllColors();
|
||||||
|
onClickListener.onClick(dialog, selectedColor, allColors);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.flask.colorpicker.builder;
|
||||||
|
|
||||||
|
import com.flask.colorpicker.ColorPickerView;
|
||||||
|
import com.flask.colorpicker.renderer.ColorWheelRenderer;
|
||||||
|
import com.flask.colorpicker.renderer.FlowerColorWheelRenderer;
|
||||||
|
import com.flask.colorpicker.renderer.SimpleColorWheelRenderer;
|
||||||
|
|
||||||
|
public class ColorWheelRendererBuilder {
|
||||||
|
public static ColorWheelRenderer getRenderer(ColorPickerView.WHEEL_TYPE wheelType) {
|
||||||
|
switch (wheelType) {
|
||||||
|
case CIRCLE:
|
||||||
|
return new SimpleColorWheelRenderer();
|
||||||
|
case FLOWER:
|
||||||
|
return new FlowerColorWheelRenderer();
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("wrong WHEEL_TYPE");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
package com.flask.colorpicker.builder;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapShader;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.graphics.PorterDuffXfermode;
|
||||||
|
import android.graphics.Shader;
|
||||||
|
|
||||||
|
public class PaintBuilder {
|
||||||
|
public static PaintHolder newPaint() {
|
||||||
|
return new PaintHolder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PaintHolder {
|
||||||
|
private Paint paint;
|
||||||
|
|
||||||
|
private PaintHolder() {
|
||||||
|
this.paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PaintHolder color(int color) {
|
||||||
|
this.paint.setColor(color);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PaintHolder antiAlias(boolean flag) {
|
||||||
|
this.paint.setAntiAlias(flag);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PaintHolder style(Paint.Style style) {
|
||||||
|
this.paint.setStyle(style);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PaintHolder mode(PorterDuff.Mode mode) {
|
||||||
|
this.paint.setXfermode(new PorterDuffXfermode(mode));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PaintHolder stroke(float width) {
|
||||||
|
this.paint.setStrokeWidth(width);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PaintHolder xPerMode(PorterDuff.Mode mode) {
|
||||||
|
this.paint.setXfermode(new PorterDuffXfermode(mode));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PaintHolder shader(Shader shader) {
|
||||||
|
this.paint.setShader(shader);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Paint build() {
|
||||||
|
return this.paint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Shader createAlphaPatternShader(int size) {
|
||||||
|
size /= 2;
|
||||||
|
size = Math.max(8, size * 2);
|
||||||
|
return new BitmapShader(createAlphaBackgroundPattern(size), Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Bitmap createAlphaBackgroundPattern(int size) {
|
||||||
|
Paint alphaPatternPaint = PaintBuilder.newPaint().build();
|
||||||
|
Bitmap bm = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
|
||||||
|
Canvas c = new Canvas(bm);
|
||||||
|
int s = Math.round(size / 2f);
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
for (int j = 0; j < 2; j++) {
|
||||||
|
if ((i + j) % 2 == 0) alphaPatternPaint.setColor(0xffffffff);
|
||||||
|
else alphaPatternPaint.setColor(0xffd0d0d0);
|
||||||
|
c.drawRect(i * s, j * s, (i + 1) * s, (j + 1) * s, alphaPatternPaint);
|
||||||
|
}
|
||||||
|
return bm;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.flask.colorpicker.renderer;
|
||||||
|
|
||||||
|
import com.flask.colorpicker.ColorCircle;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class AbsColorWheelRenderer implements ColorWheelRenderer {
|
||||||
|
protected ColorWheelRenderOption colorWheelRenderOption;
|
||||||
|
protected List<ColorCircle> colorCircleList = new ArrayList<>();
|
||||||
|
|
||||||
|
public void initWith(ColorWheelRenderOption colorWheelRenderOption) {
|
||||||
|
this.colorWheelRenderOption = colorWheelRenderOption;
|
||||||
|
this.colorCircleList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ColorWheelRenderOption getRenderOption() {
|
||||||
|
if (colorWheelRenderOption == null) colorWheelRenderOption = new ColorWheelRenderOption();
|
||||||
|
return colorWheelRenderOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ColorCircle> getColorCircleList() {
|
||||||
|
return colorCircleList;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getAlphaValueAsInt() {
|
||||||
|
return Math.round(colorWheelRenderOption.alpha * 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int calcTotalCount(float radius, float size) {
|
||||||
|
return Math.max(1, (int) ((1f - GAP_PERCENTAGE) * Math.PI / (Math.asin(size / radius)) + 0.5f));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.flask.colorpicker.renderer;
|
||||||
|
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
|
||||||
|
public class ColorWheelRenderOption {
|
||||||
|
public int density;
|
||||||
|
public float maxRadius;
|
||||||
|
public float cSize, strokeWidth, alpha, lightness;
|
||||||
|
public Canvas targetCanvas;
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.flask.colorpicker.renderer;
|
||||||
|
|
||||||
|
import com.flask.colorpicker.ColorCircle;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface ColorWheelRenderer {
|
||||||
|
float GAP_PERCENTAGE = 0.025f;
|
||||||
|
|
||||||
|
void draw();
|
||||||
|
|
||||||
|
ColorWheelRenderOption getRenderOption();
|
||||||
|
|
||||||
|
void initWith(ColorWheelRenderOption colorWheelRenderOption);
|
||||||
|
|
||||||
|
List<ColorCircle> getColorCircleList();
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package com.flask.colorpicker.renderer;
|
||||||
|
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
|
||||||
|
import com.flask.colorpicker.ColorCircle;
|
||||||
|
import com.flask.colorpicker.builder.PaintBuilder;
|
||||||
|
|
||||||
|
public class FlowerColorWheelRenderer extends AbsColorWheelRenderer {
|
||||||
|
private Paint selectorFill = PaintBuilder.newPaint().build();
|
||||||
|
private float[] hsv = new float[3];
|
||||||
|
private float sizeJitter = 1.2f;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw() {
|
||||||
|
final int setSize = colorCircleList.size();
|
||||||
|
int currentCount = 0;
|
||||||
|
float half = colorWheelRenderOption.targetCanvas.getWidth() / 2f;
|
||||||
|
int density = colorWheelRenderOption.density;
|
||||||
|
float strokeWidth = colorWheelRenderOption.strokeWidth;
|
||||||
|
float maxRadius = colorWheelRenderOption.maxRadius;
|
||||||
|
float cSize = colorWheelRenderOption.cSize;
|
||||||
|
|
||||||
|
for (int i = 0; i < density; i++) {
|
||||||
|
float p = (float) i / (density - 1); // 0~1
|
||||||
|
float jitter = (i - density / 2f) / density; // -0.5 ~ 0.5
|
||||||
|
float radius = maxRadius * p;
|
||||||
|
float size = Math.max(1.5f + strokeWidth, cSize + (i == 0 ? 0 : cSize * sizeJitter * jitter));
|
||||||
|
int total = Math.min(calcTotalCount(radius, size), density * 2);
|
||||||
|
|
||||||
|
for (int j = 0; j < total; j++) {
|
||||||
|
double angle = Math.PI * 2 * j / total + (Math.PI / total) * ((i + 1) % 2);
|
||||||
|
float x = half + (float) (radius * Math.cos(angle));
|
||||||
|
float y = half + (float) (radius * Math.sin(angle));
|
||||||
|
hsv[0] = (float) (angle * 180 / Math.PI);
|
||||||
|
hsv[1] = radius / maxRadius;
|
||||||
|
hsv[2] = colorWheelRenderOption.lightness;
|
||||||
|
selectorFill.setColor(Color.HSVToColor(hsv));
|
||||||
|
selectorFill.setAlpha(getAlphaValueAsInt());
|
||||||
|
|
||||||
|
colorWheelRenderOption.targetCanvas.drawCircle(x, y, size - strokeWidth, selectorFill);
|
||||||
|
|
||||||
|
if (currentCount >= setSize) {
|
||||||
|
colorCircleList.add(new ColorCircle(x, y, hsv));
|
||||||
|
} else colorCircleList.get(currentCount).set(x, y, hsv);
|
||||||
|
currentCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.flask.colorpicker.renderer;
|
||||||
|
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
|
||||||
|
import com.flask.colorpicker.ColorCircle;
|
||||||
|
import com.flask.colorpicker.builder.PaintBuilder;
|
||||||
|
|
||||||
|
public class SimpleColorWheelRenderer extends AbsColorWheelRenderer {
|
||||||
|
private Paint selectorFill = PaintBuilder.newPaint().build();
|
||||||
|
private float[] hsv = new float[3];
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw() {
|
||||||
|
final int setSize = colorCircleList.size();
|
||||||
|
int currentCount = 0;
|
||||||
|
float half = colorWheelRenderOption.targetCanvas.getWidth() / 2f;
|
||||||
|
int density = colorWheelRenderOption.density;
|
||||||
|
float maxRadius = colorWheelRenderOption.maxRadius;
|
||||||
|
|
||||||
|
for (int i = 0; i < density; i++) {
|
||||||
|
float p = (float) i / (density - 1); // 0~1
|
||||||
|
float radius = maxRadius * p;
|
||||||
|
float size = colorWheelRenderOption.cSize;
|
||||||
|
int total = calcTotalCount(radius, size);
|
||||||
|
|
||||||
|
for (int j = 0; j < total; j++) {
|
||||||
|
double angle = Math.PI * 2 * j / total + (Math.PI / total) * ((i + 1) % 2);
|
||||||
|
float x = half + (float) (radius * Math.cos(angle));
|
||||||
|
float y = half + (float) (radius * Math.sin(angle));
|
||||||
|
hsv[0] = (float) (angle * 180 / Math.PI);
|
||||||
|
hsv[1] = radius / maxRadius;
|
||||||
|
hsv[2] = colorWheelRenderOption.lightness;
|
||||||
|
selectorFill.setColor(Color.HSVToColor(hsv));
|
||||||
|
selectorFill.setAlpha(getAlphaValueAsInt());
|
||||||
|
|
||||||
|
colorWheelRenderOption.targetCanvas.drawCircle(x, y, size - colorWheelRenderOption.strokeWidth, selectorFill);
|
||||||
|
|
||||||
|
if (currentCount >= setSize)
|
||||||
|
colorCircleList.add(new ColorCircle(x, y, hsv));
|
||||||
|
else colorCircleList.get(currentCount).set(x, y, hsv);
|
||||||
|
currentCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,189 @@
|
||||||
|
package com.flask.colorpicker.slider;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import androidx.annotation.DimenRes;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import com.flask.colorpicker.R;
|
||||||
|
|
||||||
|
public abstract class AbsCustomSlider extends View {
|
||||||
|
protected Bitmap bitmap;
|
||||||
|
protected Canvas bitmapCanvas;
|
||||||
|
protected Bitmap bar;
|
||||||
|
protected Canvas barCanvas;
|
||||||
|
protected OnValueChangedListener onValueChangedListener;
|
||||||
|
protected int barOffsetX;
|
||||||
|
protected int handleRadius = 20;
|
||||||
|
protected int barHeight = 5;
|
||||||
|
protected float value = 1;
|
||||||
|
protected boolean showBorder = false;
|
||||||
|
|
||||||
|
private boolean inVerticalOrientation = false;
|
||||||
|
|
||||||
|
public AbsCustomSlider(Context context) {
|
||||||
|
super(context);
|
||||||
|
init(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbsCustomSlider(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
init(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbsCustomSlider(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
init(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(Context context, AttributeSet attrs) {
|
||||||
|
TypedArray styledAttrs = context.getTheme().obtainStyledAttributes(
|
||||||
|
attrs, R.styleable.AbsCustomSlider, 0, 0);
|
||||||
|
try {
|
||||||
|
inVerticalOrientation = styledAttrs.getBoolean(
|
||||||
|
R.styleable.AbsCustomSlider_inVerticalOrientation, inVerticalOrientation);
|
||||||
|
} finally {
|
||||||
|
styledAttrs.recycle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateBar() {
|
||||||
|
handleRadius = getDimension(R.dimen.default_slider_handler_radius);
|
||||||
|
barHeight = getDimension(R.dimen.default_slider_bar_height);
|
||||||
|
barOffsetX = handleRadius;
|
||||||
|
|
||||||
|
if (bar == null)
|
||||||
|
createBitmaps();
|
||||||
|
drawBar(barCanvas);
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void createBitmaps() {
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
if (inVerticalOrientation) {
|
||||||
|
width = getHeight();
|
||||||
|
height = getWidth();
|
||||||
|
} else {
|
||||||
|
width = getWidth();
|
||||||
|
height = getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
bar = Bitmap.createBitmap(Math.max(width - barOffsetX * 2, 1), barHeight, Bitmap.Config.ARGB_8888);
|
||||||
|
barCanvas = new Canvas(bar);
|
||||||
|
|
||||||
|
if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
|
||||||
|
if (bitmap != null) bitmap.recycle();
|
||||||
|
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||||
|
bitmapCanvas = new Canvas(bitmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDraw(Canvas canvas) {
|
||||||
|
super.onDraw(canvas);
|
||||||
|
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
if (inVerticalOrientation) {
|
||||||
|
width = getHeight();
|
||||||
|
height = getWidth();
|
||||||
|
|
||||||
|
canvas.rotate(-90);
|
||||||
|
canvas.translate(-width, 0);
|
||||||
|
} else {
|
||||||
|
width = getWidth();
|
||||||
|
height = getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bar != null && bitmapCanvas != null) {
|
||||||
|
bitmapCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
|
||||||
|
bitmapCanvas.drawBitmap(bar, barOffsetX, (height - bar.getHeight()) / 2, null);
|
||||||
|
|
||||||
|
float x = handleRadius + value * (width - handleRadius * 2);
|
||||||
|
float y = height / 2f;
|
||||||
|
drawHandle(bitmapCanvas, x, y);
|
||||||
|
canvas.drawBitmap(bitmap, 0, 0, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void drawBar(Canvas barCanvas);
|
||||||
|
|
||||||
|
protected abstract void onValueChanged(float value);
|
||||||
|
|
||||||
|
protected abstract void drawHandle(Canvas canvas, float x, float y);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||||
|
super.onSizeChanged(w, h, oldw, oldh);
|
||||||
|
updateBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||||
|
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||||
|
int width = 0;
|
||||||
|
if (widthMode == MeasureSpec.UNSPECIFIED)
|
||||||
|
width = widthMeasureSpec;
|
||||||
|
else if (widthMode == MeasureSpec.AT_MOST)
|
||||||
|
width = MeasureSpec.getSize(widthMeasureSpec);
|
||||||
|
else if (widthMode == MeasureSpec.EXACTLY)
|
||||||
|
width = MeasureSpec.getSize(widthMeasureSpec);
|
||||||
|
|
||||||
|
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||||
|
int height = 0;
|
||||||
|
if (heightMode == MeasureSpec.UNSPECIFIED)
|
||||||
|
height = heightMeasureSpec;
|
||||||
|
else if (heightMode == MeasureSpec.AT_MOST)
|
||||||
|
height = MeasureSpec.getSize(heightMeasureSpec);
|
||||||
|
else if (heightMode == MeasureSpec.EXACTLY)
|
||||||
|
height = MeasureSpec.getSize(heightMeasureSpec);
|
||||||
|
|
||||||
|
setMeasuredDimension(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
|
switch (event.getAction()) {
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
case MotionEvent.ACTION_MOVE: {
|
||||||
|
if (bar != null) {
|
||||||
|
if (inVerticalOrientation) {
|
||||||
|
value = 1 - (event.getY() - barOffsetX) / bar.getWidth();
|
||||||
|
} else {
|
||||||
|
value = (event.getX() - barOffsetX) / bar.getWidth();
|
||||||
|
}
|
||||||
|
value = Math.max(0, Math.min(value, 1));
|
||||||
|
onValueChanged(value);
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MotionEvent.ACTION_UP: {
|
||||||
|
onValueChanged(value);
|
||||||
|
if (onValueChangedListener != null)
|
||||||
|
onValueChangedListener.onValueChanged(value);
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getDimension(@DimenRes int id) {
|
||||||
|
return getResources().getDimensionPixelSize(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShowBorder(boolean showBorder) {
|
||||||
|
this.showBorder = showBorder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnValueChangedListener(OnValueChangedListener onValueChangedListener) {
|
||||||
|
this.onValueChangedListener = onValueChangedListener;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
package com.flask.colorpicker.slider;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
|
import com.flask.colorpicker.ColorPickerView;
|
||||||
|
import com.flask.colorpicker.Utils;
|
||||||
|
import com.flask.colorpicker.builder.PaintBuilder;
|
||||||
|
|
||||||
|
public class AlphaSlider extends AbsCustomSlider {
|
||||||
|
public int color;
|
||||||
|
private Paint alphaPatternPaint = PaintBuilder.newPaint().build();
|
||||||
|
private Paint barPaint = PaintBuilder.newPaint().build();
|
||||||
|
private Paint solid = PaintBuilder.newPaint().build();
|
||||||
|
private Paint clearingStroke = PaintBuilder.newPaint().color(0xffffffff).xPerMode(PorterDuff.Mode.CLEAR).build();
|
||||||
|
|
||||||
|
private Paint clearStroke = PaintBuilder.newPaint().build();
|
||||||
|
private Bitmap clearBitmap;
|
||||||
|
private Canvas clearBitmapCanvas;
|
||||||
|
|
||||||
|
private ColorPickerView colorPicker;
|
||||||
|
|
||||||
|
public AlphaSlider(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AlphaSlider(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AlphaSlider(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void createBitmaps() {
|
||||||
|
super.createBitmaps();
|
||||||
|
alphaPatternPaint.setShader(PaintBuilder.createAlphaPatternShader(barHeight * 2));
|
||||||
|
clearBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
|
||||||
|
clearBitmapCanvas = new Canvas(clearBitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void drawBar(Canvas barCanvas) {
|
||||||
|
int width = barCanvas.getWidth();
|
||||||
|
int height = barCanvas.getHeight();
|
||||||
|
|
||||||
|
barCanvas.drawRect(0, 0, width, height, alphaPatternPaint);
|
||||||
|
int l = Math.max(2, width / 256);
|
||||||
|
for (int x = 0; x <= width; x += l) {
|
||||||
|
float alpha = (float) x / (width - 1);
|
||||||
|
barPaint.setColor(color);
|
||||||
|
barPaint.setAlpha(Math.round(alpha * 255));
|
||||||
|
barCanvas.drawRect(x, 0, x + l, height, barPaint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onValueChanged(float value) {
|
||||||
|
if (colorPicker != null)
|
||||||
|
colorPicker.setAlphaValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void drawHandle(Canvas canvas, float x, float y) {
|
||||||
|
solid.setColor(color);
|
||||||
|
solid.setAlpha(Math.round(value * 255));
|
||||||
|
if (showBorder) canvas.drawCircle(x, y, handleRadius, clearingStroke);
|
||||||
|
if (value < 1) {
|
||||||
|
// this fixes the same artifact issue from ColorPickerView
|
||||||
|
// happens when alpha pattern is drawn underneath a circle with the same size
|
||||||
|
clearBitmapCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
|
||||||
|
clearBitmapCanvas.drawCircle(x, y, handleRadius * 0.75f + 4, alphaPatternPaint);
|
||||||
|
clearBitmapCanvas.drawCircle(x, y, handleRadius * 0.75f + 4, solid);
|
||||||
|
|
||||||
|
clearStroke = PaintBuilder.newPaint().color(0xffffffff).style(Paint.Style.STROKE).stroke(6).xPerMode(PorterDuff.Mode.CLEAR).build();
|
||||||
|
clearBitmapCanvas.drawCircle(x, y, handleRadius * 0.75f + (clearStroke.getStrokeWidth() / 2), clearStroke);
|
||||||
|
canvas.drawBitmap(clearBitmap, 0, 0, null);
|
||||||
|
} else {
|
||||||
|
canvas.drawCircle(x, y, handleRadius * 0.75f, solid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColorPicker(ColorPickerView colorPicker) {
|
||||||
|
this.colorPicker = colorPicker;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(int color) {
|
||||||
|
this.color = color;
|
||||||
|
this.value = Utils.getAlphaPercent(color);
|
||||||
|
if (bar != null) {
|
||||||
|
updateBar();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
package com.flask.colorpicker.slider;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
|
import com.flask.colorpicker.ColorPickerView;
|
||||||
|
import com.flask.colorpicker.Utils;
|
||||||
|
import com.flask.colorpicker.builder.PaintBuilder;
|
||||||
|
|
||||||
|
public class LightnessSlider extends AbsCustomSlider {
|
||||||
|
private int color;
|
||||||
|
private Paint barPaint = PaintBuilder.newPaint().build();
|
||||||
|
private Paint solid = PaintBuilder.newPaint().build();
|
||||||
|
private Paint clearingStroke = PaintBuilder.newPaint().color(0xffffffff).xPerMode(PorterDuff.Mode.CLEAR).build();
|
||||||
|
|
||||||
|
private ColorPickerView colorPicker;
|
||||||
|
|
||||||
|
public LightnessSlider(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LightnessSlider(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LightnessSlider(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void drawBar(Canvas barCanvas) {
|
||||||
|
int width = barCanvas.getWidth();
|
||||||
|
int height = barCanvas.getHeight();
|
||||||
|
|
||||||
|
float[] hsv = new float[3];
|
||||||
|
Color.colorToHSV(color, hsv);
|
||||||
|
int l = Math.max(2, width / 256);
|
||||||
|
for (int x = 0; x <= width; x += l) {
|
||||||
|
hsv[2] = (float) x / (width - 1);
|
||||||
|
barPaint.setColor(Color.HSVToColor(hsv));
|
||||||
|
barCanvas.drawRect(x, 0, x + l, height, barPaint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onValueChanged(float value) {
|
||||||
|
if (colorPicker != null)
|
||||||
|
colorPicker.setLightness(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void drawHandle(Canvas canvas, float x, float y) {
|
||||||
|
solid.setColor(Utils.colorAtLightness(color, value));
|
||||||
|
if (showBorder) canvas.drawCircle(x, y, handleRadius, clearingStroke);
|
||||||
|
canvas.drawCircle(x, y, handleRadius * 0.75f, solid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColorPicker(ColorPickerView colorPicker) {
|
||||||
|
this.colorPicker = colorPicker;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(int color) {
|
||||||
|
this.color = color;
|
||||||
|
this.value = Utils.lightnessOfColor(color);
|
||||||
|
if (bar != null) {
|
||||||
|
updateBar();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.flask.colorpicker.slider;
|
||||||
|
|
||||||
|
public interface OnValueChangedListener {
|
||||||
|
void onValueChanged(float value);
|
||||||
|
}
|
5
library/src/main/res/layout/color_edit.xml
Normal file
5
library/src/main/res/layout/color_edit.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
style="@style/PickerEditText"
|
||||||
|
android:hint="Color Value"
|
||||||
|
android:inputType="textNoSuggestions" />
|
7
library/src/main/res/layout/color_preview.xml
Normal file
7
library/src/main/res/layout/color_preview.xml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="@dimen/default_preview_height"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal" />
|
12
library/src/main/res/layout/color_selector.xml
Normal file
12
library/src/main/res/layout/color_selector.xml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="@dimen/default_preview_height"
|
||||||
|
android:layout_height="@dimen/default_preview_height"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:padding="2dp">
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="@dimen/default_preview_image_height"
|
||||||
|
android:layout_height="@dimen/default_preview_image_height"
|
||||||
|
android:src="@android:color/transparent"
|
||||||
|
android:id="@+id/image_preview"/>
|
||||||
|
</LinearLayout>
|
7
library/src/main/res/layout/color_widget.xml
Normal file
7
library/src/main/res/layout/color_widget.xml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/color_indicator"
|
||||||
|
android:layout_width="32dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
tools:ignore="ContentDescription" />
|
25
library/src/main/res/values/attrs.xml
Normal file
25
library/src/main/res/values/attrs.xml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<declare-styleable name="ColorPickerPreference">
|
||||||
|
<attr name="alphaSlider" format="boolean"/>
|
||||||
|
<attr name="lightnessSlider" format="boolean"/>
|
||||||
|
<attr name="border" format="boolean"/>
|
||||||
|
<attr name="density" format="integer"/>
|
||||||
|
<attr name="initialColor" format="integer"/>
|
||||||
|
<attr name="wheelType" format="enum">
|
||||||
|
<enum name="FLOWER" value="0"/>
|
||||||
|
<enum name="CIRCLE" value="1"/>
|
||||||
|
</attr>
|
||||||
|
<attr name="lightnessSliderView" format="reference"/>
|
||||||
|
<attr name="alphaSliderView" format="reference"/>
|
||||||
|
<attr name="pickerColorEdit" format="boolean"/>
|
||||||
|
<attr name="pickerColorEditTextColor" format="integer"/>
|
||||||
|
<attr name="pickerTitle" format="reference|string"/>
|
||||||
|
<attr name="pickerButtonOk" format="reference|string"/>
|
||||||
|
<attr name="pickerButtonCancel" format="reference|string"/>
|
||||||
|
</declare-styleable>
|
||||||
|
|
||||||
|
<declare-styleable name="AbsCustomSlider">
|
||||||
|
<attr name="inVerticalOrientation" format="boolean"/>
|
||||||
|
</declare-styleable>
|
||||||
|
</resources>
|
10
library/src/main/res/values/dimens.xml
Normal file
10
library/src/main/res/values/dimens.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<resources>
|
||||||
|
<dimen name="default_slider_height">36dp</dimen>
|
||||||
|
<dimen name="default_slider_margin">24dp</dimen>
|
||||||
|
<dimen name="default_slider_bar_height">4dp</dimen>
|
||||||
|
<dimen name="default_slider_handler_radius">10dp</dimen>
|
||||||
|
<dimen name="default_padding_side">24dp</dimen>
|
||||||
|
<dimen name="default_preview_height">40dp</dimen>
|
||||||
|
<dimen name="default_preview_image_height">36dp</dimen>
|
||||||
|
<dimen name="default_margin_top">20dp</dimen>
|
||||||
|
</resources>
|
11
library/src/main/res/values/styles.xml
Normal file
11
library/src/main/res/values/styles.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<style name="PickerEditText">
|
||||||
|
<item name="android:layout_width">match_parent</item>
|
||||||
|
<item name="android:layout_height">wrap_content</item>
|
||||||
|
<item name="android:layout_margin">4dp</item>
|
||||||
|
<item name="android:imeOptions">actionNext</item>
|
||||||
|
<item name="android:singleLine">true</item>
|
||||||
|
<item name="android:textSize">22sp</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
|
@ -2,3 +2,4 @@ include ':app'
|
||||||
rootProject.name = "RustedAssistant"
|
rootProject.name = "RustedAssistant"
|
||||||
include ':assistantCoreLibrary'
|
include ':assistantCoreLibrary'
|
||||||
include ':dialog'
|
include ':dialog'
|
||||||
|
include(':library')
|
||||||
|
|
Loading…
Reference in New Issue
Block a user