Skip to content

RTL layout support #2021

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
android:backupAgent="com.kunzisoft.keepass.backup.SettingsBackupAgent"
android:largeHeap="true"
android:resizeableActivity="true"
android:supportsRtl="true"
android:theme="@style/KeepassDXStyle.Night"
tools:targetApi="s">
<meta-data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@
package com.kunzisoft.keepass.activities

import android.content.pm.PackageManager.NameNotFoundException
import android.os.Build
import android.os.Bundle
import android.text.method.LinkMovementMethod
import android.util.Log
import android.view.MenuItem
import android.view.View
import android.widget.TextView
import androidx.appcompat.widget.Toolbar
import androidx.core.text.HtmlCompat
Expand Down Expand Up @@ -76,6 +78,9 @@ class AboutActivity : StylishActivity() {
movementMethod = LinkMovementMethod.getInstance()
text = HtmlCompat.fromHtml(getString(R.string.html_about_licence, DateTime().year),
HtmlCompat.FROM_HTML_MODE_LEGACY)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
textDirection = View.TEXT_DIRECTION_ANY_RTL
}
}

findViewById<TextView>(R.id.activity_about_privacy_text).apply {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ import com.kunzisoft.keepass.view.asError
import com.kunzisoft.keepass.view.hideByFading
import com.kunzisoft.keepass.view.setTransparentNavigationBar
import com.kunzisoft.keepass.view.showActionErrorIfNeeded
import com.kunzisoft.keepass.view.updateLockPaddingLeft
import com.kunzisoft.keepass.view.updateLockPaddingStart
import com.kunzisoft.keepass.viewmodels.ColorPickerViewModel
import com.kunzisoft.keepass.viewmodels.EntryEditViewModel
import java.util.UUID
Expand Down Expand Up @@ -503,7 +503,7 @@ class EntryEditActivity : DatabaseLockActivity(),
}

// Padding if lock button visible
entryEditAddToolBar?.updateLockPaddingLeft()
entryEditAddToolBar?.updateLockPaddingStart()

mAttachmentFileBinderManager?.apply {
registerProgressTask()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ import com.kunzisoft.keepass.view.applyWindowInsets
import com.kunzisoft.keepass.view.hideByFading
import com.kunzisoft.keepass.view.setTransparentNavigationBar
import com.kunzisoft.keepass.view.showActionErrorIfNeeded
import com.kunzisoft.keepass.view.updateLockPaddingLeft
import com.kunzisoft.keepass.view.updateLockPaddingStart
import com.kunzisoft.keepass.viewmodels.GroupEditViewModel
import com.kunzisoft.keepass.viewmodels.GroupViewModel
import org.joda.time.Instant
Expand Down Expand Up @@ -1130,7 +1130,7 @@ class GroupActivity : DatabaseLockActivity(),
View.GONE
}
// Padding if lock button visible
toolbarAction?.updateLockPaddingLeft()
toolbarAction?.updateLockPaddingStart()

loadGroup()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import com.kunzisoft.keepass.utils.getParcelableExtraCompat
import com.kunzisoft.keepass.utils.UriUtil.getDocumentFile
import com.kunzisoft.keepass.utils.UriUtil.openUrl
import com.kunzisoft.keepass.view.asError
import com.kunzisoft.keepass.view.updateLockPaddingLeft
import com.kunzisoft.keepass.view.updateLockPaddingStart
import com.kunzisoft.keepass.viewmodels.IconPickerViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
Expand Down Expand Up @@ -212,7 +212,7 @@ class IconPickerActivity : DatabaseLockActivity() {
}

// Padding if lock button visible
toolbar.updateLockPaddingLeft()
toolbar.updateLockPaddingStart()
}

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.fragments.KeyGeneratorFragment
import com.kunzisoft.keepass.activities.legacy.DatabaseLockActivity
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.view.updateLockPaddingLeft
import com.kunzisoft.keepass.view.updateLockPaddingStart
import com.kunzisoft.keepass.viewmodels.KeyGeneratorViewModel

class KeyGeneratorActivity : DatabaseLockActivity() {
Expand Down Expand Up @@ -84,7 +84,7 @@ class KeyGeneratorActivity : DatabaseLockActivity() {
}

// Padding if lock button visible
toolbar.updateLockPaddingLeft()
toolbar.updateLockPaddingStart()
}

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package com.kunzisoft.keepass.adapters
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Color
import android.os.Build
import android.util.Log
import android.util.TypedValue
import android.view.LayoutInflater
Expand Down Expand Up @@ -529,6 +530,9 @@ class NodesAdapter (
holder?.otpToken?.apply {
text = otpElement?.tokenString
setTextSize(mTextSizeUnit, mOtpTokenTextDefaultDimension, mPrefSizeMultiplier)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
textDirection = View.TEXT_DIRECTION_LTR
}
}
holder?.otpContainer?.setOnClickListener {
otpElement?.token?.let { token ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,13 @@ class TemplateEditView @JvmOverloads constructor(context: Context,
setMaxChars(templateAttribute.options.getNumberChars())
setMaxLines(templateAttribute.options.getNumberLines())
setActionClick(templateAttribute, field, this)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_NO
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
if (field.protectedValue.isProtected) {
textDirection = TEXT_DIRECTION_LTR
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_NO
}
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/java/com/kunzisoft/keepass/view/TemplateView.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.kunzisoft.keepass.view

import android.content.Context
import android.os.Build
import android.util.AttributeSet
import android.view.View
import androidx.core.view.isVisible
Expand Down Expand Up @@ -62,6 +63,9 @@ class TemplateView @JvmOverloads constructor(context: Context,
// Here the value is often empty

if (field.protectedValue.isProtected) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
textDirection = TEXT_DIRECTION_LTR
}
if (mFirstTimeAskAllowCopyProtectedFields) {
setCopyButtonState(TextFieldView.ButtonState.DEACTIVATE)
setCopyButtonClickListener { _, _ ->
Expand Down Expand Up @@ -175,6 +179,9 @@ class TemplateView @JvmOverloads constructor(context: Context,
otpElement.type.name,
ProtectedString(false, otpElement.token)))
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
textDirection = TEXT_DIRECTION_LTR
}
mLastOtpTokenView = this
mOtpRunnable = Runnable {
if (otpElement.shouldRefreshToken()) {
Expand Down
23 changes: 15 additions & 8 deletions app/src/main/java/com/kunzisoft/keepass/view/ViewUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import androidx.core.view.forEach
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.core.view.updatePaddingRelative
import com.google.android.material.appbar.CollapsingToolbarLayout
import com.google.android.material.snackbar.Snackbar
import com.kunzisoft.keepass.R
Expand Down Expand Up @@ -225,14 +226,20 @@ fun View.showByFading() {
}
}

fun View.updateLockPaddingLeft() {
updatePadding(resources.getDimensionPixelSize(
if (PreferencesUtil.showLockDatabaseButton(context)) {
R.dimen.lock_button_size
} else {
R.dimen.hidden_lock_button_size
}
))
fun View.updateLockPaddingStart() {
resources.getDimensionPixelSize(
if (PreferencesUtil.showLockDatabaseButton(context)) {
R.dimen.lock_button_size
} else {
R.dimen.hidden_lock_button_size
}
).let { lockPadding ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
updatePaddingRelative(lockPadding)
} else {
updatePadding(lockPadding)
}
}
}

fun Context.showActionErrorIfNeeded(result: ActionRunnable.Result) {
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/res/drawable-ldrtl/ic_arrow_back_white_24dp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<group>
<path
android:fillColor="#ffffff"
android:strokeWidth="1.78885484"
android:pathData="M10,19Q7.5,19 5.5,17.5Q4,16 4,13.5Q4,11 5.5,9.5Q7.5,8 10,8L16,8L13.5,5.5L15,4L20,9L15,14L13.5,12.5L16,10L10,10Q8.5,10 7,11Q6,12 6,13.5Q6,15 7,16Q8.5,17 10,17L17,17L17,19L10,19Z" />
</group>
</vector>
9 changes: 9 additions & 0 deletions app/src/main/res/drawable-ldrtl/ic_arrow_left_white_24dp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFF"
android:pathData="M8.59,16.59L13.17,12 8.59,7.41 10,6l6,6 -6,6 -1.41,-1.41z"/>
</vector>
9 changes: 9 additions & 0 deletions app/src/main/res/drawable-ldrtl/ic_arrow_right_green_24dp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="@color/green"
android:pathData="M14,7l-5,5 5,5V7z"/>
</vector>
5 changes: 5 additions & 0 deletions app/src/main/res/drawable-ldrtl/ic_arrow_right_white_24dp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_arrow_left_white_24dp"
android:fromDegrees="180"
android:toDegrees="180"
android:visible="true" />
1 change: 1 addition & 0 deletions app/src/main/res/layout/activity_file_selection.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_collapseMode="parallax"
android:layoutDirection="ltr"
android:layout_gravity="center_horizontal|bottom"
android:gravity="center"
android:orientation="horizontal"
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/layout/fragment_set_main_credential.xml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
android:importantForAccessibility="no"
android:importantForAutofill="no"
android:inputType="textPassword|textMultiLine"
android:textDirection="ltr"
android:maxLines="3"
android:hint="@string/hint_conf_pass"/>
</com.google.android.material.textfield.TextInputLayout>
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/layout/pref_dialog_duration.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layoutDirection="ltr"
app:layout_constraintTop_toBottomOf="@+id/switch_element">

<LinearLayout
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/layout/view_main_credentials.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
android:minHeight="48dp"
android:hint="@string/password"
android:inputType="textPassword"
android:textDirection="ltr"
android:importantForAutofill="no"
android:focusable="true"
android:focusableInTouchMode="true"
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/layout/view_password_edit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
android:importantForAccessibility="no"
android:importantForAutofill="no"
android:inputType="textPassword|textMultiLine"
android:textDirection="ltr"
android:maxLines="3"
tools:ignore="TextFields" />
</com.google.android.material.textfield.TextInputLayout>
Expand Down
25 changes: 25 additions & 0 deletions app/src/main/res/values-v17/styles.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2025 Jeremy Jamet / Kunzisoft.

This file is part of KeePassDX.

KeePassDX 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.

KeePassDX 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 KeePassDX. If not, see <http://www.gnu.org/licenses/>.
-->
<resources>
<!-- Text Style -->
<style name="KeepassDXStyle.TextView.v17" parent="KeepassDXStyle.TextView.Base">
<item name="android:textAlignment">viewStart</item>
</style>
</resources>
6 changes: 6 additions & 0 deletions app/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
<item name="android:textColor">?attr/colorOnSurface</item>
<item name="android:textColorPrimary">@color/forest_theme_light_primary</item>
<item name="android:editTextColor">?attr/colorOnSurface</item>
<item name="android:textViewStyle">@style/KeepassDXStyle.TextView</item>

<!-- Dialog -->
<item name="android:alertDialogTheme">@style/KeepassDXStyle.Light.Dialog</item>
Expand Down Expand Up @@ -171,6 +172,7 @@
<item name="android:textColor">?attr/colorOnSurface</item>
<item name="android:textColorPrimary">@color/forest_theme_night_primary</item>
<item name="android:editTextColor">?attr/colorOnSurface</item>
<item name="android:textViewStyle">@style/KeepassDXStyle.TextView</item>

<!-- Dialog -->
<item name="android:alertDialogTheme">@style/KeepassDXStyle.Night.Dialog</item>
Expand Down Expand Up @@ -375,6 +377,10 @@
</style>

<!-- Text Style -->
<style name="KeepassDXStyle.TextView" parent="KeepassDXStyle.TextView.v17"/>
<style name="KeepassDXStyle.TextView.v17" parent="KeepassDXStyle.TextView.Base"/>
<style name="KeepassDXStyle.TextView.Base" parent="Widget.AppCompat.TextView"/>

<style name="KeepassDXStyle.Text" parent="android:style/TextAppearance">
<item name="android:textColor">?android:attr/textColor</item>
</style>
Expand Down