From 293ca5b31dafa2dd684557ca46886e5e271564c4 Mon Sep 17 00:00:00 2001 From: tom5079 Date: Sat, 20 Jun 2020 22:48:47 +0900 Subject: [PATCH] Added PIN Lock --- app/build.gradle | 3 +- app/libs/pinlockview-release.aar | Bin 0 -> 40695 bytes .../java/xyz/quaver/pupil/ui/LockActivity.kt | 203 ++++++++++++++---- .../quaver/pupil/ui/fragment/LockFragment.kt | 52 ++++- .../pupil/ui/fragment/PINLockFragment.kt | 53 +++++ .../pupil/ui/fragment/SettingsFragment.kt | 60 +++--- app/src/main/res/anim/shake.xml | 24 +++ app/src/main/res/anim/shake_cycle.xml | 21 ++ app/src/main/res/color/lock_fab.xml | 23 ++ .../main/res/drawable/backspace_outline.xml | 8 + app/src/main/res/drawable/fingerprint.xml | 2 +- app/src/main/res/drawable/lastpass.xml | 2 +- app/src/main/res/drawable/lock_pattern.xml | 2 +- app/src/main/res/drawable/pin_filled.xml | 23 ++ app/src/main/res/layout/activity_lock.xml | 13 +- app/src/main/res/layout/fragment_pin_lock.xml | 42 ++++ 16 files changed, 441 insertions(+), 90 deletions(-) create mode 100644 app/libs/pinlockview-release.aar create mode 100644 app/src/main/java/xyz/quaver/pupil/ui/fragment/PINLockFragment.kt create mode 100644 app/src/main/res/anim/shake.xml create mode 100644 app/src/main/res/anim/shake_cycle.xml create mode 100644 app/src/main/res/color/lock_fab.xml create mode 100644 app/src/main/res/drawable/backspace_outline.xml create mode 100644 app/src/main/res/drawable/pin_filled.xml create mode 100644 app/src/main/res/layout/fragment_pin_lock.xml diff --git a/app/build.gradle b/app/build.gradle index cccb7ec9..c7f6a513 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -52,7 +52,7 @@ android { dependencies { def markwonVersion = '3.1.0' - implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.7" @@ -80,6 +80,7 @@ dependencies { implementation 'net.rdrei.android.dirchooser:library:3.2@aar' implementation 'com.github.chrisbanes:PhotoView:2.3.0' implementation 'com.andrognito.patternlockview:patternlockview:1.0.0' + //implementation 'com.andrognito.pinlockview:pinlockview:2.1.0' implementation "ru.noties.markwon:core:${markwonVersion}" testImplementation 'junit:junit:4.13' androidTestImplementation 'androidx.test.ext:junit:1.1.1' diff --git a/app/libs/pinlockview-release.aar b/app/libs/pinlockview-release.aar new file mode 100644 index 0000000000000000000000000000000000000000..646f97a4b542c0f71566dc1fb62decb9c541937e GIT binary patch literal 40695 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 { + val result = lockManager.check(it) + + if (result == true) { + setResult(Activity.RESULT_OK) + finish() + } else + lock_pattern_view.setViewMode(PatternLockView.PatternViewMode.WRONG) + } + "add_lock" -> { + if (lastPass.isEmpty()) { + lastPass = it + + Snackbar.make(view!!, R.string.settings_lock_confirm, Snackbar.LENGTH_LONG).show() + } else { + if (lastPass == it) { + LockManager(context!!).add(Lock.generate(Lock.Type.PATTERN, it)) + finish() + } else { + lock_pattern_view.setViewMode(PatternLockView.PatternViewMode.WRONG) + lastPass = "" + + Snackbar.make(view!!, R.string.settings_lock_wrong_confirm, Snackbar.LENGTH_LONG).show() + } + } + } + } + } + } + + private val pinLockFragment = PINLockFragment().apply { + var lastPass = "" + onPINEntered = { + when(mode) { + null -> { + val result = lockManager.check(it) + + if (result == true) { + setResult(Activity.RESULT_OK) + finish() + } else { + indicator_dots.startAnimation(AnimationUtils.loadAnimation(context, R.anim.shake).apply { + setAnimationListener(object: Animation.AnimationListener { + override fun onAnimationEnd(animation: Animation?) { + pin_lock_view.resetPinLockView() + pin_lock_view.isEnabled = true + } + + override fun onAnimationStart(animation: Animation?) { + pin_lock_view.isEnabled = false + } + + override fun onAnimationRepeat(animation: Animation?) { + // Do Nothing + } + }) + }) + } + } + "add_lock" -> { + if (lastPass.isEmpty()) { + lastPass = it + + pin_lock_view.resetPinLockView() + Snackbar.make(view!!, R.string.settings_lock_confirm, Snackbar.LENGTH_LONG).show() + } else { + if (lastPass == it) { + LockManager(context!!).add(Lock.generate(Lock.Type.PIN, it)) + finish() + } else { + indicator_dots.startAnimation(AnimationUtils.loadAnimation(context, R.anim.shake).apply { + setAnimationListener(object: Animation.AnimationListener { + override fun onAnimationEnd(animation: Animation?) { + pin_lock_view.resetPinLockView() + pin_lock_view.isEnabled = true + } + + override fun onAnimationStart(animation: Animation?) { + pin_lock_view.isEnabled = false + } + + override fun onAnimationRepeat(animation: Animation?) { + // Do Nothing + } + }) + }) + lastPass = "" + + Snackbar.make(view!!, R.string.settings_lock_wrong_confirm, Snackbar.LENGTH_LONG).show() + } + } + } + } + } + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_lock) - val lockManager = try { + lockManager = try { LockManager(this) } catch (e: Exception) { AlertDialog.Builder(this).apply { @@ -50,12 +157,7 @@ class LockActivity : AppCompatActivity() { return } - val mode = intent.getStringExtra("mode") - - lock_pattern.isEnabled = false - lock_pin.isEnabled = false - lock_fingerprint.isEnabled = false - lock_password.isEnabled = false + mode = intent.getStringExtra("mode") when(mode) { null -> { @@ -64,52 +166,63 @@ class LockActivity : AppCompatActivity() { finish() return } + + lock_pattern.apply { + isEnabled = lockManager.contains(Lock.Type.PATTERN) + setOnClickListener { + supportFragmentManager.beginTransaction().replace( + R.id.lock_content, patternLockFragment + ).commit() + } + } + lock_pin.apply { + isEnabled = lockManager.contains(Lock.Type.PIN) + setOnClickListener { + supportFragmentManager.beginTransaction().replace( + R.id.lock_content, pinLockFragment + ).commit() + } + } + lock_fingerprint.isEnabled = false + lock_password.isEnabled = false + + when (lockManager.locks!!.first().type) { + Lock.Type.PIN -> { + + supportFragmentManager.beginTransaction().add( + R.id.lock_content, pinLockFragment + ).commit() + } + Lock.Type.PATTERN -> { + supportFragmentManager.beginTransaction().add( + R.id.lock_content, patternLockFragment + ).commit() + } + else -> return + } } "add_lock" -> { + lock_pattern.isEnabled = false + lock_pin.isEnabled = false + lock_fingerprint.isEnabled = false + lock_password.isEnabled = false + when(intent.getStringExtra("type")!!) { "pattern" -> { - + lock_pattern.isEnabled = true + supportFragmentManager.beginTransaction().add( + R.id.lock_content, patternLockFragment + ).commit() + } + "pin" -> { + lock_pin.isEnabled = true + supportFragmentManager.beginTransaction().add( + R.id.lock_content, pinLockFragment + ).commit() } } } } - - supportFragmentManager.beginTransaction().add( - R.id.lock_content, - PatternLockFragment().apply { - var lastPass = "" - onPatternDrawn = { - when(mode) { - null -> { - val result = lockManager.check(it) - - if (result == true) { - setResult(Activity.RESULT_OK) - finish() - } else - lock_pattern_view.setViewMode(PatternLockView.PatternViewMode.WRONG) - } - "add_lock" -> { - if (lastPass.isEmpty()) { - lastPass = it - - Snackbar.make(view!!, R.string.settings_lock_confirm, Snackbar.LENGTH_LONG).show() - } else { - if (lastPass == it) { - LockManager(context!!).add(Lock.generate(Lock.Type.PATTERN, it)) - finish() - } else { - lock_pattern_view.setViewMode(PatternLockView.PatternViewMode.WRONG) - lastPass = "" - - Snackbar.make(view!!, R.string.settings_lock_wrong_confirm, Snackbar.LENGTH_LONG).show() - } - } - } - } - } - } - ).commit() } } diff --git a/app/src/main/java/xyz/quaver/pupil/ui/fragment/LockFragment.kt b/app/src/main/java/xyz/quaver/pupil/ui/fragment/LockFragment.kt index b95900c1..022fe5ae 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/fragment/LockFragment.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/fragment/LockFragment.kt @@ -28,18 +28,25 @@ import xyz.quaver.pupil.ui.LockActivity import xyz.quaver.pupil.util.Lock import xyz.quaver.pupil.util.LockManager -class LockFragment : PreferenceFragmentCompat() { +class LockFragment : + PreferenceFragmentCompat() { override fun onResume() { super.onResume() - val lockManager = LockManager(context!!) + val lockManager = LockManager(requireContext()) findPreference("lock_pattern")?.summary = if (lockManager.contains(Lock.Type.PATTERN)) getString(R.string.settings_lock_enabled) else "" + + findPreference("lock_pin")?.summary = + if (lockManager.contains(Lock.Type.PIN)) + getString(R.string.settings_lock_enabled) + else + "" } override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { @@ -48,14 +55,14 @@ class LockFragment : PreferenceFragmentCompat() { with(findPreference("lock_pattern")) { this!! - if (LockManager(context!!).contains(Lock.Type.PATTERN)) + if (LockManager(requireContext()).contains(Lock.Type.PATTERN)) summary = getString(R.string.settings_lock_enabled) onPreferenceClickListener = Preference.OnPreferenceClickListener { - val lockManager = LockManager(context!!) + val lockManager = LockManager(requireContext()) if (lockManager.contains(Lock.Type.PATTERN)) { - AlertDialog.Builder(context).apply { + AlertDialog.Builder(requireContext()).apply { setTitle(R.string.warning) setMessage(R.string.settings_lock_remove_message) @@ -66,7 +73,7 @@ class LockFragment : PreferenceFragmentCompat() { setNegativeButton(android.R.string.no) { _, _ -> } }.show() } else { - val intent = Intent(context, LockActivity::class.java).apply { + val intent = Intent(requireContext(), LockActivity::class.java).apply { putExtra("mode", "add_lock") putExtra("type", "pattern") } @@ -77,5 +84,38 @@ class LockFragment : PreferenceFragmentCompat() { true } } + + with(findPreference("lock_pin")) { + this!! + + if (LockManager(requireContext()).contains(Lock.Type.PIN)) + summary = getString(R.string.settings_lock_enabled) + + onPreferenceClickListener = Preference.OnPreferenceClickListener { + val lockManager = LockManager(requireContext()) + + if (lockManager.contains(Lock.Type.PIN)) { + AlertDialog.Builder(requireContext()).apply { + setTitle(R.string.warning) + setMessage(R.string.settings_lock_remove_message) + + setPositiveButton(android.R.string.yes) { _, _ -> + lockManager.remove(Lock.Type.PIN) + onResume() + } + setNegativeButton(android.R.string.no) { _, _ -> } + }.show() + } else { + val intent = Intent(requireContext(), LockActivity::class.java).apply { + putExtra("mode", "add_lock") + putExtra("type", "pin") + } + + startActivity(intent) + } + + true + } + } } } \ No newline at end of file diff --git a/app/src/main/java/xyz/quaver/pupil/ui/fragment/PINLockFragment.kt b/app/src/main/java/xyz/quaver/pupil/ui/fragment/PINLockFragment.kt new file mode 100644 index 00000000..b058840d --- /dev/null +++ b/app/src/main/java/xyz/quaver/pupil/ui/fragment/PINLockFragment.kt @@ -0,0 +1,53 @@ +/* + * Pupil, Hitomi.la viewer for Android + * Copyright (C) 2020 tom5079 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package xyz.quaver.pupil.ui.fragment + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import com.andrognito.pinlockview.PinLockListener +import kotlinx.android.synthetic.main.fragment_pin_lock.view.* +import xyz.quaver.pupil.R + +class PINLockFragment : Fragment(), PinLockListener { + + var onPINEntered: ((String) -> Unit)? = null + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.fragment_pin_lock, container, false).apply { + pin_lock_view.attachIndicatorDots(indicator_dots) + pin_lock_view.setPinLockListener(this@PINLockFragment) + } + } + + override fun onComplete(pin: String?) { + onPINEntered?.invoke(pin!!) + } + + override fun onEmpty() { + + } + + override fun onPinChange(pinLength: Int, intermediatePin: String?) { + + } + +} \ No newline at end of file diff --git a/app/src/main/java/xyz/quaver/pupil/ui/fragment/SettingsFragment.kt b/app/src/main/java/xyz/quaver/pupil/ui/fragment/SettingsFragment.kt index 7f6b8004..a3dec70e 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/fragment/SettingsFragment.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/fragment/SettingsFragment.kt @@ -56,13 +56,13 @@ class SettingsFragment : override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - PreferenceManager.getDefaultSharedPreferences(context).registerOnSharedPreferenceChangeListener(this) + PreferenceManager.getDefaultSharedPreferences(requireContext()).registerOnSharedPreferenceChangeListener(this) } override fun onResume() { super.onResume() - val lockManager = LockManager(context!!) + val lockManager = LockManager(requireContext()) findPreference("app_lock")?.summary = if (lockManager.locks.isNullOrEmpty()) { getString(R.string.settings_lock_none) @@ -92,9 +92,9 @@ class SettingsFragment : checkUpdate(activity as SettingsActivity, true) } "delete_cache" -> { - val dir = File(context.cacheDir, "imageCache") + val dir = File(requireContext().cacheDir, "imageCache") - AlertDialog.Builder(context).apply { + AlertDialog.Builder(requireContext()).apply { setTitle(R.string.warning) setMessage(R.string.settings_clear_cache_alert_message) setPositiveButton(android.R.string.yes) { _, _ -> @@ -107,9 +107,9 @@ class SettingsFragment : }.show() } "delete_downloads" -> { - val dir = getDownloadDirectory(context) + val dir = getDownloadDirectory(requireContext()) - AlertDialog.Builder(context).apply { + AlertDialog.Builder(requireContext()).apply { setTitle(R.string.warning) setMessage(R.string.settings_clear_downloads_alert_message) setPositiveButton(android.R.string.yes) { _, _ -> @@ -122,9 +122,9 @@ class SettingsFragment : }.show() } "clear_history" -> { - val histories = (context.applicationContext as Pupil).histories + val histories = (requireContext().applicationContext as Pupil).histories - AlertDialog.Builder(context).apply { + AlertDialog.Builder(requireContext()).apply { setTitle(R.string.warning) setMessage(R.string.settings_clear_history_alert_message) setPositiveButton(android.R.string.yes) { _, _ -> @@ -135,10 +135,10 @@ class SettingsFragment : }.show() } "dl_location" -> { - DownloadLocationDialog(activity!!).show() + DownloadLocationDialog(requireActivity()).show() } "default_query" -> { - DefaultQueryDialog(context).apply { + DefaultQueryDialog(requireContext()).apply { onPositiveButtonClickListener = { newTags -> sharedPreferences.edit().putString("default_query", newTags.toString()).apply() summary = newTags.toString() @@ -146,20 +146,20 @@ class SettingsFragment : }.show() } "app_lock" -> { - val intent = Intent(context, LockActivity::class.java) + val intent = Intent(requireContext(), LockActivity::class.java) activity?.startActivityForResult(intent, REQUEST_LOCK) } "mirrors" -> { - MirrorDialog(context) + MirrorDialog(requireContext()) .show() } "proxy" -> { - ProxyDialog(context) + ProxyDialog(requireContext()) .show() } "backup" -> { - File(ContextCompat.getDataDir(context), "favorites.json").copyTo( - File(getDownloadDirectory(context), "favorites.json"), + File(ContextCompat.getDataDir(requireContext()), "favorites.json").copyTo( + File(getDownloadDirectory(requireContext()), "favorites.json"), true ) @@ -177,8 +177,8 @@ class SettingsFragment : "old_import_galleries" -> { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) - ActivityCompat.requestPermissions(activity!!, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), REQUEST_WRITE_PERMISSION_AND_SAF) + if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) + ActivityCompat.requestPermissions(requireActivity(), arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), REQUEST_WRITE_PERMISSION_AND_SAF) else { val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply { putExtra("android.content.extra.SHOW_ADVANCED", true) @@ -192,7 +192,7 @@ class SettingsFragment : .allowNewDirectoryNameModification(true) .build() - val intent = Intent(context, DirectoryChooserActivity::class.java).apply { + val intent = Intent(requireContext(), DirectoryChooserActivity::class.java).apply { putExtra(DirectoryChooserActivity.EXTRA_CONFIG, config) } @@ -232,10 +232,10 @@ class SettingsFragment : when (key) { "proxy" -> { - summary = getProxyInfo(context).type.name + summary = getProxyInfo(requireContext()).type.name } "dl_location" -> { - summary = getDownloadDirectory(context!!).canonicalPath + summary = getDownloadDirectory(requireContext()).canonicalPath } } } @@ -260,42 +260,42 @@ class SettingsFragment : when (key) { "app_version" -> { - val manager = context.packageManager - val info = manager.getPackageInfo(context.packageName, 0) - summary = context.getString(R.string.settings_app_version_description, info.versionName) + val manager = requireContext().packageManager + val info = manager.getPackageInfo(requireContext().packageName, 0) + summary = requireContext().getString(R.string.settings_app_version_description, info.versionName) onPreferenceClickListener = this@SettingsFragment } "delete_cache" -> { - val dir = File(context.cacheDir, "imageCache") + val dir = File(requireContext().cacheDir, "imageCache") summary = getDirSize(dir) onPreferenceClickListener = this@SettingsFragment } "delete_downloads" -> { - val dir = getDownloadDirectory(context) + val dir = getDownloadDirectory(requireContext()) summary = getDirSize(dir) onPreferenceClickListener = this@SettingsFragment } "clear_history" -> { - val histories = (activity!!.application as Pupil).histories + val histories = (requireActivity().application as Pupil).histories summary = getString(R.string.settings_clear_history_summary, histories.size) onPreferenceClickListener = this@SettingsFragment } "dl_location" -> { - summary = getDownloadDirectory(context).canonicalPath + summary = getDownloadDirectory(requireContext()).canonicalPath onPreferenceClickListener = this@SettingsFragment } "default_query" -> { - summary = PreferenceManager.getDefaultSharedPreferences(context).getString("default_query", "") ?: "" + summary = PreferenceManager.getDefaultSharedPreferences(requireContext()).getString("default_query", "") ?: "" onPreferenceClickListener = this@SettingsFragment } "app_lock" -> { - val lockManager = LockManager(context) + val lockManager = LockManager(requireContext()) summary = if (lockManager.locks.isNullOrEmpty()) { getString(R.string.settings_lock_none) @@ -315,7 +315,7 @@ class SettingsFragment : onPreferenceClickListener = this@SettingsFragment } "proxy" -> { - summary = getProxyInfo(context).type.name + summary = getProxyInfo(requireContext()).type.name onPreferenceClickListener = this@SettingsFragment } diff --git a/app/src/main/res/anim/shake.xml b/app/src/main/res/anim/shake.xml new file mode 100644 index 00000000..323768dd --- /dev/null +++ b/app/src/main/res/anim/shake.xml @@ -0,0 +1,24 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/shake_cycle.xml b/app/src/main/res/anim/shake_cycle.xml new file mode 100644 index 00000000..13dcab54 --- /dev/null +++ b/app/src/main/res/anim/shake_cycle.xml @@ -0,0 +1,21 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/color/lock_fab.xml b/app/src/main/res/color/lock_fab.xml new file mode 100644 index 00000000..197313e3 --- /dev/null +++ b/app/src/main/res/color/lock_fab.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/backspace_outline.xml b/app/src/main/res/drawable/backspace_outline.xml new file mode 100644 index 00000000..201e2e9b --- /dev/null +++ b/app/src/main/res/drawable/backspace_outline.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/fingerprint.xml b/app/src/main/res/drawable/fingerprint.xml index ffa8a34b..bfc10e9f 100644 --- a/app/src/main/res/drawable/fingerprint.xml +++ b/app/src/main/res/drawable/fingerprint.xml @@ -4,5 +4,5 @@ android:width="24dp" android:viewportWidth="24" android:viewportHeight="24"> - + \ No newline at end of file diff --git a/app/src/main/res/drawable/lastpass.xml b/app/src/main/res/drawable/lastpass.xml index 9dbf638b..40265510 100644 --- a/app/src/main/res/drawable/lastpass.xml +++ b/app/src/main/res/drawable/lastpass.xml @@ -4,5 +4,5 @@ android:width="24dp" android:viewportWidth="24" android:viewportHeight="24"> - + \ No newline at end of file diff --git a/app/src/main/res/drawable/lock_pattern.xml b/app/src/main/res/drawable/lock_pattern.xml index f1be51c2..f88355fb 100644 --- a/app/src/main/res/drawable/lock_pattern.xml +++ b/app/src/main/res/drawable/lock_pattern.xml @@ -4,5 +4,5 @@ android:width="24dp" android:viewportWidth="24" android:viewportHeight="24"> - + \ No newline at end of file diff --git a/app/src/main/res/drawable/pin_filled.xml b/app/src/main/res/drawable/pin_filled.xml new file mode 100644 index 00000000..98fe185c --- /dev/null +++ b/app/src/main/res/drawable/pin_filled.xml @@ -0,0 +1,23 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_lock.xml b/app/src/main/res/layout/activity_lock.xml index 00cd2898..db5b51be 100644 --- a/app/src/main/res/layout/activity_lock.xml +++ b/app/src/main/res/layout/activity_lock.xml @@ -36,7 +36,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" - android:layout_marginBottom="32dp" android:gravity="center" app:layout_constraintTop_toBottomOf="@id/lock_content" app:layout_constraintBottom_toTopOf="@id/lock_button_layout"> @@ -46,9 +45,10 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" app:srcCompat="@drawable/fingerprint" + app:backgroundTint="@color/lock_fab" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" - app:backgroundTint="@color/dark_gray" + app:tint="@null" app:fabSize="mini"/> @@ -67,26 +67,29 @@ android:id="@+id/lock_pattern" android:layout_width="wrap_content" android:layout_height="wrap_content" + app:tint="@null" app:srcCompat="@drawable/lock_pattern" - app:backgroundTint="@color/colorPrimary" + app:backgroundTint="@color/lock_fab" app:fabSize="mini"/> diff --git a/app/src/main/res/layout/fragment_pin_lock.xml b/app/src/main/res/layout/fragment_pin_lock.xml new file mode 100644 index 00000000..7099e499 --- /dev/null +++ b/app/src/main/res/layout/fragment_pin_lock.xml @@ -0,0 +1,42 @@ + + + + + + + + + + \ No newline at end of file