修复已知BUG调色器MD3化
This commit is contained in:
parent
c6089ae67c
commit
c5fa00b988
|
@ -24,15 +24,15 @@ android {
|
|||
keyAlias 'coldmint'
|
||||
}
|
||||
}
|
||||
compileSdkVersion 33
|
||||
buildToolsVersion "30.0.3"
|
||||
compileSdk 33
|
||||
// buildToolsVersion "30.0.3"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.coldmint.rust.pro"
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 33
|
||||
versionCode 28
|
||||
versionName "2.1 Bata6(2023-7-20)"
|
||||
versionName "2.1.1 Bata6(2023-7-20)"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
@ -91,12 +91,15 @@ dependencies {
|
|||
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 'com.google.firebase:firebase-analytics-ktx'
|
||||
implementation 'com.google.firebase:firebase-crashlytics-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"
|
||||
|
||||
// implementation 'com.luolc:emoji-rain:0.1.1'
|
||||
|
@ -133,16 +136,10 @@ dependencies {
|
|||
implementation 'com.github.florent37:glidepalette:2.1.2'
|
||||
implementation 'cat.ereza:customactivityoncrash:2.3.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 'com.google.android.material:material:1.9.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
|
||||
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
|
||||
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:supportsRtl="true"
|
||||
android:theme="@style/Theme.rust.Concept"
|
||||
android:usesCleartextTraffic="true">
|
||||
android:usesCleartextTraffic="true"
|
||||
android:screenOrientation="portrait"
|
||||
tools:targetApi="tiramisu">
|
||||
<activity
|
||||
android:name=".FeedbackActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:screenOrientation="portrait"
|
||||
tools:ignore="LockedOrientationActivity" />
|
||||
<activity
|
||||
android:name=".ChangePasswordActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:screenOrientation="portrait"
|
||||
tools:ignore="LockedOrientationActivity" />
|
||||
<activity
|
||||
android:name=".NetworkTemplatePackageDetailsActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".CustomizeEditTextActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".SearchActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
|
@ -68,93 +69,71 @@
|
|||
android:value="portrait|landscape" /> <!-- Activity注册 -->
|
||||
<activity
|
||||
android:name=".CreationWizardActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".TurretDesignActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".BrowserActivity"
|
||||
android:exported="false"
|
||||
android:label="@string/built_in_browser"
|
||||
android:screenOrientation="portrait" /> <!-- 适配全面屏 -->
|
||||
android:label="@string/built_in_browser"/> <!-- 适配全面屏 -->
|
||||
<activity
|
||||
android:name=".OrderListActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".SearchResultActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".PayActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".ReviewModActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".ReportListActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".ErrorInfoActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".UserListActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".ActivateActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".ThanksActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".WorkManagementActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".FullScreenCoverActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".TagActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".ReportActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".EditUserInfoActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".UserHomePageActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".WebModInfoActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".ErrorActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name="com.yalantis.ucrop.UCropActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
android:name="com.yalantis.ucrop.UCropActivity"/>
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTask"
|
||||
android:screenOrientation="portrait">
|
||||
android:launchMode="singleTask">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
|
@ -167,8 +146,7 @@
|
|||
android:excludeFromRecents="true"
|
||||
android:exported="true"
|
||||
android:label="@string/file_importer"
|
||||
android:maxRecents="3"
|
||||
android:screenOrientation="portrait">
|
||||
android:maxRecents="3">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
|
@ -268,93 +246,69 @@
|
|||
</activity>
|
||||
<activity
|
||||
android:name=".AboutActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".ValueTypeActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
android:name=".ValueTypeActivity"/>
|
||||
<activity
|
||||
android:name=".GlobalOperationsActivity"
|
||||
android:label="@string/global_operations"
|
||||
android:screenOrientation="portrait" />
|
||||
android:label="@string/global_operations"/>
|
||||
<activity
|
||||
android:name=".EditActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/mod_action1"
|
||||
android:screenOrientation="portrait"
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
<activity
|
||||
android:name=".CreateModActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
android:name=".CreateModActivity"/>
|
||||
<activity
|
||||
android:name=".UnitsActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
android:name=".UnitsActivity"/>
|
||||
<activity
|
||||
android:name=".OptimizeActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
android:name=".OptimizeActivity"/>
|
||||
<activity
|
||||
android:name=".FileManagerActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
android:name=".FileManagerActivity"/>
|
||||
<activity
|
||||
android:name=".CreateUnitActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
android:name=".CreateUnitActivity"/>
|
||||
<activity
|
||||
android:name=".TemplateParserActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
android:name=".TemplateParserActivity"/>
|
||||
<activity
|
||||
android:name=".LibraryActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
android:name=".LibraryActivity"/>
|
||||
<activity
|
||||
android:name=".SettingsActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/setting"
|
||||
android:screenOrientation="portrait" />
|
||||
android:label="@string/setting"/>
|
||||
<activity
|
||||
android:name=".TemplateMakerActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
android:name=".TemplateMakerActivity"/>
|
||||
<activity
|
||||
android:name=".CreateTemplateActivity"
|
||||
android:screenOrientation="portrait" />
|
||||
android:name=".CreateTemplateActivity"/>
|
||||
<activity
|
||||
android:name=".CodeTableActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".LoginActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".RegisterActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".EditModInfoActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".ApplicationListActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".GameCheckActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".RecyclingStationActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".BookmarkManagerActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".ReleaseModActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
<activity
|
||||
android:name=".PackActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait" />
|
||||
android:exported="false"/>
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -8,7 +8,12 @@ import android.os.Bundle
|
|||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
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.Toast
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
|
@ -17,7 +22,6 @@ import androidx.core.view.GravityCompat
|
|||
import androidx.core.view.isVisible
|
||||
import androidx.drawerlayout.widget.DrawerLayout
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
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.DebugHelper
|
||||
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.base.BaseActivity
|
||||
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.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
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.component.EditorAutoCompletion
|
||||
import io.github.rosemoe.sora.widget.schemes.EditorColorScheme
|
||||
import jp.wasabeef.glide.transformations.BlurTransformation
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
|
||||
class EditActivity : BaseActivity<ActivityEditBinding>() {
|
||||
private val viewModel by lazy {
|
||||
ViewModelProvider(this).get(EditViewModel::class.java)
|
||||
ViewModelProvider(this)[EditViewModel::class.java]
|
||||
}
|
||||
|
||||
private lateinit var turretCoordinateResults: ActivityResultLauncher<Intent>
|
||||
|
|
|
@ -1,27 +1,21 @@
|
|||
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 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.os.*
|
||||
import android.view.*
|
||||
import android.widget.*
|
||||
import android.widget.Toast.makeText
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
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.contract.ActivityResultContracts
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.bumptech.glide.Glide
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.coldmint.dialog.CoreDialog
|
||||
import com.coldmint.dialog.InputDialog
|
||||
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.pro.adapters.FileAdapter
|
||||
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.databinding.ActivityFileBinding
|
||||
import com.coldmint.rust.pro.interfaces.BookmarkListener
|
||||
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.viewmodel.FileManagerViewModel
|
||||
import com.google.android.material.chip.Chip
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.snackbar.SnackbarContentLayout
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import me.zhanghai.android.fastscroll.FastScrollerBuilder
|
||||
import java.io.BufferedReader
|
||||
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>() {
|
||||
|
||||
|
|
|
@ -1,20 +1,17 @@
|
|||
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.pm.PackageInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Resources
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import android.os.*
|
||||
import android.util.Log
|
||||
import android.view.*
|
||||
import android.widget.Toast
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.KeyEvent
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import androidx.appcompat.app.ActionBarDrawerToggle
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.core.view.GravityCompat
|
||||
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.interfaces.ApiCallBack
|
||||
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.ServerConfiguration
|
||||
import com.coldmint.rust.pro.base.BaseActivity
|
||||
import com.coldmint.rust.pro.databinding.ActivityMainBinding
|
||||
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.GlobalMethod
|
||||
import com.coldmint.rust.pro.viewmodel.StartViewModel
|
||||
import com.google.android.material.color.DynamicColors
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.tabs.TabLayout
|
||||
import com.google.gson.Gson
|
||||
import com.gyf.immersionbar.ImmersionBar
|
||||
|
@ -331,7 +333,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||
intent.putExtra("type", "template")
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
|
@ -380,7 +381,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||
|
||||
menu.findItem(R.id.rust_api).setOnMenuItemClickListener {
|
||||
val thisIntent = Intent(this, BrowserActivity::class.java)
|
||||
thisIntent.putExtra("link", "https://rustedwarfareapicode.top/")
|
||||
thisIntent.putExtra("link", "https://git.coldmint.top/")
|
||||
thisIntent.putExtra("javaScriptEnabled", true)
|
||||
startActivity(thisIntent)
|
||||
false
|
||||
|
|
|
@ -1,23 +1,22 @@
|
|||
package com.coldmint.rust.pro
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.os.Environment
|
||||
import android.util.Log
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.os.Bundle
|
||||
import cat.ereza.customactivityoncrash.config.CaocConfig
|
||||
import com.coldmint.rust.core.debug.LogCat
|
||||
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.CompletionItemConverter
|
||||
import com.coldmint.rust.pro.tool.GlobalMethod
|
||||
import com.google.android.material.color.DynamicColors
|
||||
import com.google.android.material.color.DynamicColorsOptions
|
||||
import com.google.firebase.crashlytics.ktx.crashlytics
|
||||
import com.google.firebase.ktx.Firebase
|
||||
import com.hjq.language.MultiLanguages
|
||||
import com.youth.banner.BuildConfig
|
||||
import java.util.*
|
||||
|
||||
|
||||
class RustApplication : Application() {
|
||||
|
||||
|
@ -38,7 +37,7 @@ class RustApplication : Application() {
|
|||
AppSettings.initAppSettings(this)
|
||||
//动态颜色
|
||||
val options = DynamicColorsOptions.Builder()
|
||||
.setPrecondition { activity, theme ->
|
||||
.setPrecondition { _, _ ->
|
||||
AppSettings
|
||||
.getValue(
|
||||
AppSettings.Setting.DynamicColor,
|
||||
|
@ -66,8 +65,24 @@ class RustApplication : Application() {
|
|||
.errorActivity(ErrorActivity::class.java) //default: null (default error activity)
|
||||
.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
|
||||
|
||||
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.view.LayoutInflater
|
||||
import android.view.MenuItem
|
||||
|
@ -11,24 +8,15 @@ import android.view.View
|
|||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.EditText
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.coldmint.dialog.CoreDialog
|
||||
import com.coldmint.rust.pro.R
|
||||
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.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 java.util.*
|
||||
|
||||
/*主活动,所有活动都应该继承于此*/
|
||||
abstract class BaseActivity<ViewBingType : ViewBinding> :
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.coldmint.rust.pro.edit.autoComplete
|
||||
|
||||
import android.os.Bundle
|
||||
import com.coldmint.rust.core.SourceFile
|
||||
import com.coldmint.rust.core.database.code.CodeDao
|
||||
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.LineParser
|
||||
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.CompletionItemConverter
|
||||
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.CodeEditor
|
||||
|
||||
/**
|
||||
* 代码自动完成项目(来自数据库)
|
||||
|
|
|
@ -2,11 +2,10 @@ package com.coldmint.rust.pro.fragments
|
|||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.bumptech.glide.Glide
|
||||
import com.coldmint.dialog.CoreDialog
|
||||
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.GlobalMethod
|
||||
import com.coldmint.rust.pro.tool.TextStyleMaker
|
||||
import com.coldmint.rust.pro.ui.StableLinearLayoutManager
|
||||
import com.google.android.material.color.DynamicColors
|
||||
import com.coldmint.rust.pro.ui.ScrollLinearLayoutManager
|
||||
import com.youth.banner.adapter.BannerImageAdapter
|
||||
import com.youth.banner.holder.BannerImageHolder
|
||||
import com.youth.banner.indicator.CircleIndicator
|
||||
import com.youth.banner.transformer.AlphaPageTransformer
|
||||
import com.youth.banner.transformer.DepthPageTransformer
|
||||
|
||||
class RecommendedFragment : BaseFragment<FragmentRecommendedBinding>() {
|
||||
|
||||
|
@ -233,10 +229,10 @@ class RecommendedFragment : BaseFragment<FragmentRecommendedBinding>() {
|
|||
}
|
||||
|
||||
override fun whenViewCreated(inflater: LayoutInflater, savedInstanceState: Bundle?) {
|
||||
viewBinding.latestReleaseView.layoutManager = StableLinearLayoutManager(requireContext())
|
||||
viewBinding.latestReleaseView.layoutManager = ScrollLinearLayoutManager(requireContext())
|
||||
viewBinding.soleRecommendedRecyclerView.layoutManager =
|
||||
StableLinearLayoutManager(requireContext())
|
||||
viewBinding.randomRecommendedView.layoutManager = StableLinearLayoutManager(requireContext())
|
||||
ScrollLinearLayoutManager(requireContext())
|
||||
viewBinding.randomRecommendedView.layoutManager = ScrollLinearLayoutManager(requireContext())
|
||||
loadRandomRecommended()
|
||||
viewBinding.changeRandomRecommended.setOnClickListener {
|
||||
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_height="wrap_content"
|
||||
android:gravity="center">
|
||||
|
||||
<Button
|
||||
|
||||
style="@style/Widget.MaterialComponents.Button.TextButton.Dialog"
|
||||
android:id="@+id/codeTextItemView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="项目"/>
|
||||
|
||||
</LinearLayout>
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge>
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -13,8 +12,7 @@
|
|||
android:id="@+id/titleView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?android:attr/actionBarSize"
|
||||
android:layout_alignParentTop="true"
|
||||
app:cardBackgroundColor="?android:windowBackground">
|
||||
android:layout_alignParentTop="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
<?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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
android:layout_height="match_parent">
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
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
|
||||
android:id="@+id/textview"
|
||||
style="@style/TextAppearance.Material3.HeadlineMedium"
|
||||
|
@ -18,27 +18,23 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
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" />
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipeRefreshLayout"
|
||||
<LinearLayout
|
||||
android:id="@+id/linearLayout3"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<HorizontalScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:singleLine="true"
|
||||
app:singleSelection="true">
|
||||
|
@ -77,15 +73,16 @@
|
|||
|
||||
</com.google.android.material.chip.ChipGroup>
|
||||
</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
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -7,8 +7,6 @@
|
|||
android:animateLayoutChanges="true"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -30,7 +28,6 @@
|
|||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:visibility="visible">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
@ -75,7 +72,8 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:text="@string/change_random_recommended" />
|
||||
android:text="@string/change_random_recommended"
|
||||
card_view:ignore="RelativeOverlap" />
|
||||
</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
|
||||
android.enableJetifier=true
|
||||
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"
|
||||
include ':assistantCoreLibrary'
|
||||
include ':dialog'
|
||||
include(':library')
|
||||
|
|
Loading…
Reference in New Issue
Block a user