diff --git a/res/layout/activity_about_kde.xml b/res/layout/activity_about_kde.xml
index 2426d32b..e0fa2107 100644
--- a/res/layout/activity_about_kde.xml
+++ b/res/layout/activity_about_kde.xml
@@ -21,6 +21,8 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
+ android:clipToPadding="false"
+ android:id="@+id/scroll_view"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
+ android:layout_height="match_parent"
+ android:clipToPadding="false">
+ android:layout_height="match_parent"
+ android:clipToPadding="false"/>
diff --git a/res/layout/activity_mpris.xml b/res/layout/activity_mpris.xml
index 45fed849..69723542 100644
--- a/res/layout/activity_mpris.xml
+++ b/res/layout/activity_mpris.xml
@@ -17,7 +17,8 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
+ android:layout_height="wrap_content"
+ android:fitsSystemWindows="true">
diff --git a/res/layout/devices_list.xml b/res/layout/devices_list.xml
index 4d983db3..b590ccb6 100644
--- a/res/layout/devices_list.xml
+++ b/res/layout/devices_list.xml
@@ -22,6 +22,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:descendantFocusability="afterDescendants"
android:dividerHeight="12dp"
android:orientation="vertical"
+ android:clipToPadding="false"
tools:listitem="@layout/list_card_entry"
tools:context=".MainActivity" />
diff --git a/res/layout/fragment_about.xml b/res/layout/fragment_about.xml
index 152b038e..4c8cb694 100644
--- a/res/layout/fragment_about.xml
+++ b/res/layout/fragment_about.xml
@@ -11,7 +11,9 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
- android:fillViewport="true">
+ android:fillViewport="true"
+ android:clipToPadding="false"
+ android:id="@+id/scroll_view">
+ *
+ * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
+ */
+package org.kde.kdeconnect.Helpers
+
+import android.view.View
+import org.kde.kdeconnect.extensions.setupBottomMargin
+import org.kde.kdeconnect.extensions.setupBottomPadding
+
+object WindowHelper {
+
+ // for java only
+ @JvmStatic
+ fun setupBottomPadding(view: View) {
+ view.setupBottomPadding()
+ }
+
+ // for java only
+ @JvmStatic
+ fun setupBottomMargin(view: View) {
+ view.setupBottomMargin()
+ }
+}
\ No newline at end of file
diff --git a/src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenActivity.java b/src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenActivity.java
index 5b324f6f..3ce20443 100644
--- a/src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenActivity.java
+++ b/src/org/kde/kdeconnect/Plugins/BigscreenPlugin/BigscreenActivity.java
@@ -15,37 +15,46 @@ import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.view.View;
-import androidx.appcompat.app.AppCompatActivity;
+import androidx.annotation.NonNull;
import org.kde.kdeconnect.KdeConnect;
import org.kde.kdeconnect.UserInterface.MainActivity;
import org.kde.kdeconnect.UserInterface.PermissionsAlertDialogFragment;
+import org.kde.kdeconnect.base.BaseActivity;
import org.kde.kdeconnect_tp.R;
import org.kde.kdeconnect_tp.databinding.ActivityBigscreenBinding;
import java.util.ArrayList;
import java.util.Objects;
-public class BigscreenActivity extends AppCompatActivity {
+import kotlin.Lazy;
+import kotlin.LazyKt;
+
+public class BigscreenActivity extends BaseActivity {
private static final int REQUEST_SPEECH = 100;
+
+ private final Lazy lazyBinding = LazyKt.lazy(() -> ActivityBigscreenBinding.inflate(getLayoutInflater()));
+
+ @NonNull
+ @Override
+ protected ActivityBigscreenBinding getBinding() {
+ return lazyBinding.getValue();
+ }
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- final ActivityBigscreenBinding binding = ActivityBigscreenBinding.inflate(getLayoutInflater());
- setContentView(binding.getRoot());
-
- setSupportActionBar(binding.toolbarLayout.toolbar);
+ setSupportActionBar(getBinding().toolbarLayout.toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
final String deviceId = getIntent().getStringExtra("deviceId");
if (!SpeechRecognizer.isRecognitionAvailable(this)) {
- binding.micButton.setEnabled(false);
- binding.micButton.setVisibility(View.INVISIBLE);
+ getBinding().micButton.setEnabled(false);
+ getBinding().micButton.setVisibility(View.INVISIBLE);
}
BigscreenPlugin plugin = KdeConnect.getInstance().getDevicePlugin(deviceId, BigscreenPlugin.class);
@@ -54,13 +63,13 @@ public class BigscreenActivity extends AppCompatActivity {
return;
}
- binding.leftButton.setOnClickListener(v -> plugin.sendLeft());
- binding.rightButton.setOnClickListener(v -> plugin.sendRight());
- binding.upButton.setOnClickListener(v -> plugin.sendUp());
- binding.downButton.setOnClickListener(v -> plugin.sendDown());
- binding.selectButton.setOnClickListener(v -> plugin.sendSelect());
- binding.homeButton.setOnClickListener(v -> plugin.sendHome());
- binding.micButton.setOnClickListener(v -> {
+ getBinding().leftButton.setOnClickListener(v -> plugin.sendLeft());
+ getBinding().rightButton.setOnClickListener(v -> plugin.sendRight());
+ getBinding().upButton.setOnClickListener(v -> plugin.sendUp());
+ getBinding().downButton.setOnClickListener(v -> plugin.sendDown());
+ getBinding().selectButton.setOnClickListener(v -> plugin.sendSelect());
+ getBinding().homeButton.setOnClickListener(v -> plugin.sendHome());
+ getBinding().micButton.setOnClickListener(v -> {
if (plugin.hasMicPermission()) {
activateSTT();
} else {
diff --git a/src/org/kde/kdeconnect/Plugins/FindMyPhonePlugin/FindMyPhoneActivity.java b/src/org/kde/kdeconnect/Plugins/FindMyPhonePlugin/FindMyPhoneActivity.java
index a344f99d..6c6a1087 100644
--- a/src/org/kde/kdeconnect/Plugins/FindMyPhonePlugin/FindMyPhoneActivity.java
+++ b/src/org/kde/kdeconnect/Plugins/FindMyPhonePlugin/FindMyPhoneActivity.java
@@ -10,26 +10,35 @@ import android.util.Log;
import android.view.Window;
import android.view.WindowManager;
-import androidx.appcompat.app.AppCompatActivity;
+import androidx.annotation.NonNull;
import org.kde.kdeconnect.KdeConnect;
+import org.kde.kdeconnect.base.BaseActivity;
import org.kde.kdeconnect_tp.databinding.ActivityFindMyPhoneBinding;
import java.util.Objects;
-public class FindMyPhoneActivity extends AppCompatActivity {
+import kotlin.Lazy;
+import kotlin.LazyKt;
+
+public class FindMyPhoneActivity extends BaseActivity {
static final String EXTRA_DEVICE_ID = "deviceId";
String deviceId;
+ private final Lazy lazyBinding = LazyKt.lazy(() -> ActivityFindMyPhoneBinding.inflate(getLayoutInflater()));
+
+ @NonNull
+ @Override
+ protected ActivityFindMyPhoneBinding getBinding() {
+ return lazyBinding.getValue();
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- final ActivityFindMyPhoneBinding binding = ActivityFindMyPhoneBinding.inflate(getLayoutInflater());
- setContentView(binding.getRoot());
-
- setSupportActionBar(binding.toolbarLayout.toolbar);
+ setSupportActionBar(getBinding().toolbarLayout.toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
@@ -47,7 +56,7 @@ public class FindMyPhoneActivity extends AppCompatActivity {
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
);
- binding.bFindMyPhone.setOnClickListener(view -> finish());
+ getBinding().bFindMyPhone.setOnClickListener(view -> finish());
}
@Override
diff --git a/src/org/kde/kdeconnect/Plugins/MousePadPlugin/ComposeSendActivity.kt b/src/org/kde/kdeconnect/Plugins/MousePadPlugin/ComposeSendActivity.kt
index 60480811..961d4aa5 100644
--- a/src/org/kde/kdeconnect/Plugins/MousePadPlugin/ComposeSendActivity.kt
+++ b/src/org/kde/kdeconnect/Plugins/MousePadPlugin/ComposeSendActivity.kt
@@ -30,6 +30,7 @@ import org.kde.kdeconnect.UserInterface.compose.KdeTextButton
import org.kde.kdeconnect.UserInterface.compose.KdeTextField
import org.kde.kdeconnect.UserInterface.compose.KdeTheme
import org.kde.kdeconnect.UserInterface.compose.KdeTopAppBar
+import org.kde.kdeconnect.extensions.safeDrawPadding
import org.kde.kdeconnect_tp.R
private const val INPUT_CACHE_KEY = "compose_send_input_cache"
@@ -91,6 +92,7 @@ class ComposeSendActivity : AppCompatActivity() {
private fun ComposeSendScreen() {
KdeTheme(this) {
Scaffold(
+ modifier = Modifier.safeDrawPadding(),
topBar = {
KdeTopAppBar(
title = stringResource(R.string.compose_send_title),
diff --git a/src/org/kde/kdeconnect/Plugins/MousePadPlugin/MousePadActivity.java b/src/org/kde/kdeconnect/Plugins/MousePadPlugin/MousePadActivity.java
index 5102afc4..41b2043b 100644
--- a/src/org/kde/kdeconnect/Plugins/MousePadPlugin/MousePadActivity.java
+++ b/src/org/kde/kdeconnect/Plugins/MousePadPlugin/MousePadActivity.java
@@ -13,7 +13,6 @@ import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
-import android.util.Log;
import android.view.GestureDetector;
import android.view.HapticFeedbackConstants;
import android.view.Menu;
@@ -24,18 +23,23 @@ import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;
-import androidx.appcompat.app.AppCompatActivity;
+import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.preference.PreferenceManager;
import org.kde.kdeconnect.KdeConnect;
import org.kde.kdeconnect.UserInterface.PluginSettingsActivity;
+import org.kde.kdeconnect.base.BaseActivity;
import org.kde.kdeconnect_tp.R;
+import org.kde.kdeconnect_tp.databinding.ActivityMousepadBinding;
import java.util.Objects;
+import kotlin.Lazy;
+import kotlin.LazyKt;
+
public class MousePadActivity
- extends AppCompatActivity
+ extends BaseActivity
implements GestureDetector.OnGestureListener,
GestureDetector.OnDoubleTapListener,
MousePadGestureDetector.OnGestureListener,
@@ -74,6 +78,14 @@ public class MousePadActivity
private boolean prefsApplied = false;
+ private final Lazy lazyBinding = LazyKt.lazy(() -> ActivityMousepadBinding.inflate(getLayoutInflater()));
+
+ @NonNull
+ @Override
+ protected ActivityMousepadBinding getBinding() {
+ return lazyBinding.getValue();
+ }
+
enum ClickType {
LEFT, RIGHT, MIDDLE, NONE;
@@ -131,15 +143,12 @@ public class MousePadActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_mousepad);
-
- setSupportActionBar(findViewById(R.id.toolbar));
+ setSupportActionBar(getBinding().toolbarLayout.toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
-
- findViewById(R.id.mouse_click_left).setOnClickListener(v -> sendLeftClick());
- findViewById(R.id.mouse_click_middle).setOnClickListener(v -> sendMiddleClick());
- findViewById(R.id.mouse_click_right).setOnClickListener(v -> sendRightClick());
+ getBinding().mouseClickLeft.setOnClickListener(v -> sendLeftClick());
+ getBinding().mouseClickMiddle.setOnClickListener(v -> sendMiddleClick());
+ getBinding().mouseClickRight.setOnClickListener(v -> sendRightClick());
deviceId = getIntent().getStringExtra("deviceId");
@@ -150,7 +159,7 @@ public class MousePadActivity
mDetector.setOnDoubleTapListener(this);
mSensorManager = ContextCompat.getSystemService(this, SensorManager.class);
- keyListenerView = findViewById(R.id.keyListener);
+ keyListenerView = getBinding().keyListener;
keyListenerView.setDeviceId(deviceId);
prefs = PreferenceManager.getDefaultSharedPreferences(this);
@@ -582,9 +591,9 @@ public class MousePadActivity
}
if (prefs.getBoolean(getString(R.string.mousepad_mouse_buttons_enabled_pref), true)) {
- findViewById(R.id.mouse_buttons).setVisibility(View.VISIBLE);
+ getBinding().mouseButtons.setVisibility(View.VISIBLE);
} else {
- findViewById(R.id.mouse_buttons).setVisibility(View.GONE);
+ getBinding().mouseButtons.setVisibility(View.GONE);
}
doubleTapDragEnabled = prefs.getBoolean(getString(R.string.mousepad_doubletap_drag_enabled_pref), true);
diff --git a/src/org/kde/kdeconnect/Plugins/MousePadPlugin/SendKeystrokesToHostActivity.java b/src/org/kde/kdeconnect/Plugins/MousePadPlugin/SendKeystrokesToHostActivity.java
index 7fee2c83..7e10c031 100644
--- a/src/org/kde/kdeconnect/Plugins/MousePadPlugin/SendKeystrokesToHostActivity.java
+++ b/src/org/kde/kdeconnect/Plugins/MousePadPlugin/SendKeystrokesToHostActivity.java
@@ -13,17 +13,18 @@ import android.os.Bundle;
import android.preference.PreferenceManager;
import android.widget.Toast;
+import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
-import androidx.appcompat.app.AppCompatActivity;
-
import org.kde.kdeconnect.BackgroundService;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.Helpers.SafeTextChecker;
+import org.kde.kdeconnect.Helpers.WindowHelper;
import org.kde.kdeconnect.KdeConnect;
import org.kde.kdeconnect.NetworkPacket;
import org.kde.kdeconnect.UserInterface.List.EntryItemWithIcon;
import org.kde.kdeconnect.UserInterface.List.ListAdapter;
import org.kde.kdeconnect.UserInterface.List.SectionItem;
+import org.kde.kdeconnect.base.BaseActivity;
import org.kde.kdeconnect_tp.R;
import org.kde.kdeconnect_tp.databinding.ActivitySendkeystrokesBinding;
@@ -33,7 +34,10 @@ import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
-public class SendKeystrokesToHostActivity extends AppCompatActivity {
+import kotlin.Lazy;
+import kotlin.LazyKt;
+
+public class SendKeystrokesToHostActivity extends BaseActivity {
// text with these length and content can be send without user confirmation.
// more or less chosen arbitrarily, so that we allow short PINS and TANS without interruption (if only one device is connected)
@@ -42,19 +46,30 @@ public class SendKeystrokesToHostActivity extends AppCompatActivity {
public static final String SAFE_CHARS = "1234567890";
- private ActivitySendkeystrokesBinding binding;
private boolean contentIsOkay;
+ private final Lazy lazyBinding = LazyKt.lazy(() -> ActivitySendkeystrokesBinding.inflate(getLayoutInflater()));
+
+ @NonNull
+ @Override
+ public ActivitySendkeystrokesBinding getBinding() {
+ return lazyBinding.getValue();
+ }
+
+ @Override
+ public boolean isScrollable() {
+ return true;
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- binding = ActivitySendkeystrokesBinding.inflate(getLayoutInflater());
- setContentView(binding.getRoot());
-
- setSupportActionBar(binding.toolbarLayout.toolbar);
+ setSupportActionBar(getBinding().toolbarLayout.toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
+
+ WindowHelper.setupBottomPadding(getBinding().devicesList);
}
@@ -73,7 +88,7 @@ public class SendKeystrokesToHostActivity extends AppCompatActivity {
if ("text/x-keystrokes".equals(type)) {
String toSend = intent.getStringExtra(Intent.EXTRA_TEXT);
- binding.textToSend.setText(toSend);
+ getBinding().textToSend.setText(toSend);
// if the preference send_safe_text_immediately is true, we will check if exactly one
// device is connected and send the text to it without user confirmation, to make sending of
@@ -121,7 +136,7 @@ public class SendKeystrokesToHostActivity extends AppCompatActivity {
private void sendKeys(Device deviceId) {
String toSend;
- if (binding.textToSend.getText() != null && (toSend = binding.textToSend.getText().toString().trim()).length() > 0) {
+ if (getBinding().textToSend.getText() != null && (toSend = getBinding().textToSend.getText().toString().trim()).length() > 0) {
final NetworkPacket np = new NetworkPacket(MousePadPlugin.PACKET_TYPE_MOUSEPAD_REQUEST);
np.set("key", toSend);
MousePadPlugin plugin = KdeConnect.getInstance().getDevicePlugin(deviceId.getDeviceId(), MousePadPlugin.class);
@@ -156,8 +171,8 @@ public class SendKeystrokesToHostActivity extends AppCompatActivity {
}
}
- binding.devicesList.setAdapter(new ListAdapter(SendKeystrokesToHostActivity.this, items));
- binding.devicesList.setOnItemClickListener((adapterView, view, i, l) -> {
+ getBinding().devicesList.setAdapter(new ListAdapter(SendKeystrokesToHostActivity.this, items));
+ getBinding().devicesList.setOnItemClickListener((adapterView, view, i, l) -> {
Device device = devicesList.get(i - 1); // NOTE: -1 because of the title!
sendKeys(device);
this.finish(); // close the activity
diff --git a/src/org/kde/kdeconnect/Plugins/MprisPlugin/MprisActivity.kt b/src/org/kde/kdeconnect/Plugins/MprisPlugin/MprisActivity.kt
index 81afd169..167ba28d 100644
--- a/src/org/kde/kdeconnect/Plugins/MprisPlugin/MprisActivity.kt
+++ b/src/org/kde/kdeconnect/Plugins/MprisPlugin/MprisActivity.kt
@@ -8,22 +8,25 @@ package org.kde.kdeconnect.Plugins.MprisPlugin
import android.os.Bundle
import android.view.KeyEvent
import androidx.annotation.StringRes
-import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.google.android.material.tabs.TabLayoutMediator
import org.kde.kdeconnect.Plugins.SystemVolumePlugin.SystemVolumeFragment
+import org.kde.kdeconnect.base.BaseActivity
+import org.kde.kdeconnect.extensions.viewBinding
import org.kde.kdeconnect_tp.R
import org.kde.kdeconnect_tp.databinding.ActivityMprisBinding
-class MprisActivity : AppCompatActivity() {
- private lateinit var activityMprisBinding: ActivityMprisBinding
+class MprisActivity : BaseActivity() {
+
+ override val binding: ActivityMprisBinding by viewBinding(ActivityMprisBinding::inflate)
+
private lateinit var mprisPagerAdapter: MprisPagerAdapter
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
return when (keyCode) {
KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_VOLUME_DOWN -> {
- val pagePosition = activityMprisBinding.mprisTabs.selectedTabPosition
+ val pagePosition = binding.mprisTabs.selectedTabPosition
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
mprisPagerAdapter.onVolumeUp(pagePosition)
} else {
@@ -46,17 +49,13 @@ class MprisActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- activityMprisBinding = ActivityMprisBinding.inflate(layoutInflater)
-
- setContentView(activityMprisBinding.root)
-
val deviceId = intent.getStringExtra(MprisPlugin.DEVICE_ID_KEY)
mprisPagerAdapter = MprisPagerAdapter(this, deviceId)
- activityMprisBinding.mprisPager.adapter = mprisPagerAdapter
+ binding.mprisPager.adapter = mprisPagerAdapter
val tabLayoutMediator = TabLayoutMediator(
- activityMprisBinding.mprisTabs, activityMprisBinding.mprisPager
+ binding.mprisTabs, binding.mprisPager
) { tab, position ->
tab.setText(
mprisPagerAdapter.getTitle(position)
@@ -65,7 +64,7 @@ class MprisActivity : AppCompatActivity() {
tabLayoutMediator.attach()
- setSupportActionBar(activityMprisBinding.toolbar)
+ setSupportActionBar(binding.toolbar)
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
}
diff --git a/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationFilterActivity.java b/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationFilterActivity.java
index fa0034c6..858ceaaf 100644
--- a/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationFilterActivity.java
+++ b/src/org/kde/kdeconnect/Plugins/NotificationsPlugin/NotificationFilterActivity.java
@@ -27,14 +27,15 @@ import android.widget.CheckBox;
import android.widget.CheckedTextView;
import android.widget.ListView;
+import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
-import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.core.widget.TextViewCompat;
import com.google.android.material.materialswitch.MaterialSwitch;
import org.kde.kdeconnect.Helpers.ThreadHelper;
+import org.kde.kdeconnect.base.BaseActivity;
import org.kde.kdeconnect_tp.R;
import org.kde.kdeconnect_tp.databinding.ActivityNotificationFilterBinding;
@@ -43,9 +44,12 @@ import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import kotlin.Lazy;
+import kotlin.LazyKt;
+
//TODO: Turn this into a PluginSettingsFragment
-public class NotificationFilterActivity extends AppCompatActivity {
- private ActivityNotificationFilterBinding binding;
+public class NotificationFilterActivity extends BaseActivity {
+
private AppDatabase appDatabase;
private String prefKey;
@@ -60,6 +64,14 @@ public class NotificationFilterActivity extends AppCompatActivity {
// This variable stores all app information and serves as a data source for filtering.
private List mAllApps;
private List apps; // Filtered data.
+
+ private final Lazy lazyBinding = LazyKt.lazy(() -> ActivityNotificationFilterBinding.inflate(getLayoutInflater()));
+
+ @NonNull
+ @Override
+ protected ActivityNotificationFilterBinding getBinding() {
+ return lazyBinding.getValue();
+ }
class AppListAdapter extends BaseAdapter {
@@ -87,13 +99,13 @@ public class NotificationFilterActivity extends AppCompatActivity {
if (position == 0) {
checkedTextView.setText(R.string.all);
TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(checkedTextView, null, null, null, null);
- binding.lvFilterApps.setItemChecked(position, appDatabase.getAllEnabled());
+ getBinding().lvFilterApps.setItemChecked(position, appDatabase.getAllEnabled());
} else {
final AppListInfo info = apps.get(position - 1);
checkedTextView.setText(info.name);
TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(checkedTextView, info.icon, null, null, null);
checkedTextView.setCompoundDrawablePadding((int) (8 * getResources().getDisplayMetrics().density));
- binding.lvFilterApps.setItemChecked(position, info.isEnabled);
+ getBinding().lvFilterApps.setItemChecked(position, info.isEnabled);
}
return view;
@@ -105,14 +117,12 @@ public class NotificationFilterActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- binding = ActivityNotificationFilterBinding.inflate(getLayoutInflater());
- setContentView(binding.getRoot());
appDatabase = new AppDatabase(NotificationFilterActivity.this, false);
if (getIntent()!= null){
prefKey = getIntent().getStringExtra(NotificationsPlugin.getPrefKey());
}
- setSupportActionBar(binding.toolbarLayout.toolbar);
+ setSupportActionBar(getBinding().toolbarLayout.toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
SharedPreferences preferences = this.getSharedPreferences(prefKey, Context.MODE_PRIVATE);
@@ -152,7 +162,7 @@ public class NotificationFilterActivity extends AppCompatActivity {
}
private void displayAppList() {
- final ListView listView = binding.lvFilterApps;
+ final ListView listView = getBinding().lvFilterApps;
AppListAdapter adapter = new AppListAdapter();
listView.setAdapter(adapter);
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
@@ -233,7 +243,7 @@ public class NotificationFilterActivity extends AppCompatActivity {
}
listView.setVisibility(View.VISIBLE);
- binding.spinner.setVisibility(View.GONE);
+ getBinding().spinner.setVisibility(View.GONE);
}
private Drawable resizeIcon(Drawable icon, int maxSize) {
@@ -284,7 +294,7 @@ public class NotificationFilterActivity extends AppCompatActivity {
}
}
- ((AppListAdapter) binding.lvFilterApps.getAdapter()).notifyDataSetChanged();
+ ((AppListAdapter) getBinding().lvFilterApps.getAdapter()).notifyDataSetChanged();
return true;
}
});
diff --git a/src/org/kde/kdeconnect/Plugins/PresenterPlugin/PresenterActivity.kt b/src/org/kde/kdeconnect/Plugins/PresenterPlugin/PresenterActivity.kt
index 98ed4bf0..66166229 100644
--- a/src/org/kde/kdeconnect/Plugins/PresenterPlugin/PresenterActivity.kt
+++ b/src/org/kde/kdeconnect/Plugins/PresenterPlugin/PresenterActivity.kt
@@ -37,6 +37,7 @@ import org.kde.kdeconnect.KdeConnect
import org.kde.kdeconnect.UserInterface.compose.KdeButton
import org.kde.kdeconnect.UserInterface.compose.KdeTheme
import org.kde.kdeconnect.UserInterface.compose.KdeTopAppBar
+import org.kde.kdeconnect.extensions.safeDrawPadding
import org.kde.kdeconnect_tp.R
private const val VOLUME_UP = 1
@@ -116,7 +117,10 @@ class PresenterActivity : AppCompatActivity(), SensorEventListener {
val sensorManager = LocalContext.current.getSystemService(SENSOR_SERVICE) as? SensorManager
KdeTheme(this) {
- Scaffold(topBar = { PresenterAppBar() }) {
+ Scaffold(
+ modifier = Modifier.safeDrawPadding(),
+ topBar = { PresenterAppBar() }
+ ) {
Column(
modifier = Modifier.fillMaxSize().padding(it).padding(16.dp),
verticalArrangement = Arrangement.spacedBy(20.dp),
diff --git a/src/org/kde/kdeconnect/Plugins/RunCommandPlugin/RunCommandActivity.java b/src/org/kde/kdeconnect/Plugins/RunCommandPlugin/RunCommandActivity.java
index 4ff50eff..25a89137 100644
--- a/src/org/kde/kdeconnect/Plugins/RunCommandPlugin/RunCommandActivity.java
+++ b/src/org/kde/kdeconnect/Plugins/RunCommandPlugin/RunCommandActivity.java
@@ -17,8 +17,8 @@ import android.view.View;
import android.widget.AdapterView;
import android.widget.Toast;
+import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
-import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import org.json.JSONException;
@@ -26,6 +26,7 @@ import org.json.JSONObject;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.KdeConnect;
import org.kde.kdeconnect.UserInterface.List.ListAdapter;
+import org.kde.kdeconnect.base.BaseActivity;
import org.kde.kdeconnect_tp.R;
import org.kde.kdeconnect_tp.databinding.ActivityRunCommandBinding;
@@ -35,8 +36,19 @@ import java.util.Comparator;
import java.util.List;
import java.util.Objects;
-public class RunCommandActivity extends AppCompatActivity {
- private ActivityRunCommandBinding binding;
+import kotlin.Lazy;
+import kotlin.LazyKt;
+
+public class RunCommandActivity extends BaseActivity {
+
+ private final Lazy lazyBinding = LazyKt.lazy(() -> ActivityRunCommandBinding.inflate(getLayoutInflater()));
+
+ @NonNull
+ @Override
+ protected ActivityRunCommandBinding getBinding() {
+ return lazyBinding.getValue();
+ }
+
private String deviceId;
private final RunCommandPlugin.CommandsChangedCallback commandsChangedCallback = () -> runOnUiThread(this::updateView);
private List commandItems;
@@ -48,7 +60,7 @@ public class RunCommandActivity extends AppCompatActivity {
return;
}
- registerForContextMenu(binding.runCommandsList);
+ registerForContextMenu(getBinding().runCommandsList);
commandItems = new ArrayList<>();
for (JSONObject obj : plugin.getCommandList()) {
@@ -63,26 +75,23 @@ public class RunCommandActivity extends AppCompatActivity {
ListAdapter adapter = new ListAdapter(RunCommandActivity.this, commandItems);
- binding.runCommandsList.setAdapter(adapter);
- binding.runCommandsList.setOnItemClickListener((adapterView, view1, i, l) ->
+ getBinding().runCommandsList.setAdapter(adapter);
+ getBinding().runCommandsList.setOnItemClickListener((adapterView, view1, i, l) ->
plugin.runCommand(commandItems.get(i).getKey()));
String text = getString(R.string.addcommand_explanation);
if (!plugin.canAddCommand()) {
text += "\n" + getString(R.string.addcommand_explanation2);
}
- binding.addCommandExplanation.setText(text);
- binding.addCommandExplanation.setVisibility(commandItems.isEmpty() ? View.VISIBLE : View.GONE);
+ getBinding().addCommandExplanation.setText(text);
+ getBinding().addCommandExplanation.setVisibility(commandItems.isEmpty() ? View.VISIBLE : View.GONE);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- binding = ActivityRunCommandBinding.inflate(getLayoutInflater());
- setContentView(binding.getRoot());
-
- setSupportActionBar(binding.toolbarLayout.toolbar);
+ setSupportActionBar(getBinding().toolbarLayout.toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
@@ -93,11 +102,11 @@ public class RunCommandActivity extends AppCompatActivity {
RunCommandPlugin plugin = device.getPlugin(RunCommandPlugin.class);
if (plugin != null) {
if (plugin.canAddCommand()) {
- binding.addCommandButton.show();
+ getBinding().addCommandButton.show();
} else {
- binding.addCommandButton.hide();
+ getBinding().addCommandButton.hide();
}
- binding.addCommandButton.setOnClickListener(v -> {
+ getBinding().addCommandButton.setOnClickListener(v -> {
plugin.sendSetupPacket();
new AlertDialog.Builder(RunCommandActivity.this)
.setTitle(R.string.add_command)
diff --git a/src/org/kde/kdeconnect/Plugins/SharePlugin/ShareActivity.java b/src/org/kde/kdeconnect/Plugins/SharePlugin/ShareActivity.java
index 188fa354..7bfa1ecb 100644
--- a/src/org/kde/kdeconnect/Plugins/SharePlugin/ShareActivity.java
+++ b/src/org/kde/kdeconnect/Plugins/SharePlugin/ShareActivity.java
@@ -15,16 +15,19 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.webkit.URLUtil;
+import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.preference.PreferenceManager;
import org.kde.kdeconnect.BackgroundService;
import org.kde.kdeconnect.Device;
+import org.kde.kdeconnect.Helpers.WindowHelper;
import org.kde.kdeconnect.KdeConnect;
import org.kde.kdeconnect.UserInterface.List.EntryItemWithIcon;
import org.kde.kdeconnect.UserInterface.List.ListAdapter;
import org.kde.kdeconnect.UserInterface.List.SectionItem;
+import org.kde.kdeconnect.base.BaseActivity;
import org.kde.kdeconnect_tp.R;
import org.kde.kdeconnect_tp.databinding.ActivityShareBinding;
@@ -34,11 +37,27 @@ import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
-public class ShareActivity extends AppCompatActivity {
+import kotlin.Lazy;
+import kotlin.LazyKt;
+
+public class ShareActivity extends BaseActivity {
private static final String KEY_UNREACHABLE_URL_LIST = "key_unreachable_url_list";
- private ActivityShareBinding binding;
+
private SharedPreferences mSharedPrefs;
+ private final Lazy lazyBinding = LazyKt.lazy(() -> ActivityShareBinding.inflate(getLayoutInflater()));
+
+ @NonNull
+ @Override
+ public ActivityShareBinding getBinding() {
+ return lazyBinding.getValue();
+ }
+
+ @Override
+ public boolean isScrollable() {
+ return true;
+ }
+
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
@@ -59,9 +78,9 @@ public class ShareActivity extends AppCompatActivity {
private void refreshDevicesAction() {
BackgroundService.ForceRefreshConnections(this);
- binding.devicesListLayout.refreshListLayout.setRefreshing(true);
- binding.devicesListLayout.refreshListLayout.postDelayed(() -> {
- binding.devicesListLayout.refreshListLayout.setRefreshing(false);
+ getBinding().devicesListLayout.refreshListLayout.setRefreshing(true);
+ getBinding().devicesListLayout.refreshListLayout.postDelayed(() -> {
+ getBinding().devicesListLayout.refreshListLayout.setRefreshing(false);
}, 1500);
}
@@ -100,8 +119,8 @@ public class ShareActivity extends AppCompatActivity {
}
}
- binding.devicesListLayout.devicesList.setAdapter(new ListAdapter(ShareActivity.this, items));
- binding.devicesListLayout.devicesList.setOnItemClickListener((adapterView, view, i, l) -> {
+ getBinding().devicesListLayout.devicesList.setAdapter(new ListAdapter(ShareActivity.this, items));
+ getBinding().devicesListLayout.devicesList.setOnItemClickListener((adapterView, view, i, l) -> {
Device device = devicesList.get(i - 1); //NOTE: -1 because of the title!
SharePlugin plugin = KdeConnect.getInstance().getDevicePlugin(device.getDeviceId(), SharePlugin.class);
if (intentHasUrl && !device.isReachable()) {
@@ -140,20 +159,19 @@ public class ShareActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- binding = ActivityShareBinding.inflate(getLayoutInflater());
- setContentView(binding.getRoot());
-
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences (this);
- setSupportActionBar(binding.toolbarLayout.toolbar);
+ setSupportActionBar(getBinding().toolbarLayout.toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
ActionBar actionBar = getSupportActionBar();
- binding.devicesListLayout.refreshListLayout.setOnRefreshListener(this::refreshDevicesAction);
+ getBinding().devicesListLayout.refreshListLayout.setOnRefreshListener(this::refreshDevicesAction);
if (actionBar != null) {
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_CUSTOM);
}
+
+ WindowHelper.setupBottomPadding(getBinding().devicesListLayout.devicesList);
}
@Override
diff --git a/src/org/kde/kdeconnect/UserInterface/About/AboutFragment.kt b/src/org/kde/kdeconnect/UserInterface/About/AboutFragment.kt
index 3e5da530..24aaa4dc 100644
--- a/src/org/kde/kdeconnect/UserInterface/About/AboutFragment.kt
+++ b/src/org/kde/kdeconnect/UserInterface/About/AboutFragment.kt
@@ -18,11 +18,13 @@ import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import org.kde.kdeconnect.UserInterface.List.ListAdapter
import org.kde.kdeconnect.UserInterface.MainActivity
+import org.kde.kdeconnect.extensions.setupBottomPadding
import org.kde.kdeconnect_tp.R
import org.kde.kdeconnect_tp.databinding.FragmentAboutBinding
class AboutFragment : Fragment() {
- private var binding: FragmentAboutBinding? = null
+ private var _binding: FragmentAboutBinding? = null
+ private val binding get() = _binding!!
private lateinit var aboutData: AboutData
private var tapCount = 0
private var firstTapMillis: Long? = null
@@ -46,23 +48,28 @@ class AboutFragment : Fragment() {
}
aboutData = requireArguments().getParcelable("ABOUT_DATA")!!
- binding = FragmentAboutBinding.inflate(inflater, container, false)
+ _binding = FragmentAboutBinding.inflate(inflater, container, false)
updateData()
- return binding!!.root
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ binding.scrollView.setupBottomPadding()
}
@SuppressLint("SetTextI18n")
fun updateData() {
// Update general info
- binding!!.appName.text = aboutData.name
- binding!!.appIcon.setImageDrawable(this.context?.let { ContextCompat.getDrawable(it, aboutData.icon) })
- binding!!.appVersion.text = this.context?.getString(R.string.version, aboutData.versionName)
+ binding.appName.text = aboutData.name
+ binding.appIcon.setImageDrawable(this.context?.let { ContextCompat.getDrawable(it, aboutData.icon) })
+ binding.appVersion.text = this.context?.getString(R.string.version, aboutData.versionName)
// Setup Easter Egg onClickListener
- binding!!.generalInfoCard.setOnClickListener {
+ binding.generalInfoCard.setOnClickListener {
if (firstTapMillis == null) {
firstTapMillis = System.currentTimeMillis()
}
@@ -80,24 +87,24 @@ class AboutFragment : Fragment() {
// Update button onClickListeners
- setupInfoButton(aboutData.bugURL, binding!!.reportBugButton)
- setupInfoButton(aboutData.donateURL, binding!!.donateButton)
- setupInfoButton(aboutData.sourceCodeURL, binding!!.sourceCodeButton)
+ setupInfoButton(aboutData.bugURL, binding.reportBugButton)
+ setupInfoButton(aboutData.donateURL, binding.donateButton)
+ setupInfoButton(aboutData.sourceCodeURL, binding.sourceCodeButton)
- binding!!.licensesButton.setOnClickListener {
+ binding.licensesButton.setOnClickListener {
startActivity(Intent(context, LicensesActivity::class.java))
}
- binding!!.aboutKdeButton.setOnClickListener {
+ binding.aboutKdeButton.setOnClickListener {
startActivity(Intent(context, AboutKDEActivity::class.java))
}
- setupInfoButton(aboutData.websiteURL, binding!!.websiteButton)
+ setupInfoButton(aboutData.websiteURL, binding.websiteButton)
// Update authors
- binding!!.authorsList.adapter = ListAdapter(this.requireContext(), aboutData.authors.map { AboutPersonEntryItem(it) }, false)
+ binding.authorsList.adapter = ListAdapter(this.requireContext(), aboutData.authors.map { AboutPersonEntryItem(it) }, false)
if (aboutData.authorsFooterText != null) {
- binding!!.authorsFooterText.text = context?.getString(aboutData.authorsFooterText!!)
+ binding.authorsFooterText.text = context?.getString(aboutData.authorsFooterText!!)
}
}
@@ -113,6 +120,6 @@ class AboutFragment : Fragment() {
override fun onDestroyView() {
super.onDestroyView()
- binding = null
+ _binding = null
}
}
\ No newline at end of file
diff --git a/src/org/kde/kdeconnect/UserInterface/About/AboutKDEActivity.kt b/src/org/kde/kdeconnect/UserInterface/About/AboutKDEActivity.kt
index 63e87982..68c29d12 100644
--- a/src/org/kde/kdeconnect/UserInterface/About/AboutKDEActivity.kt
+++ b/src/org/kde/kdeconnect/UserInterface/About/AboutKDEActivity.kt
@@ -10,17 +10,21 @@ import android.os.Bundle
import android.text.Html
import android.text.Spanned
import android.text.method.LinkMovementMethod
-import androidx.appcompat.app.AppCompatActivity
+import org.kde.kdeconnect.base.BaseActivity
+import org.kde.kdeconnect.extensions.setupBottomPadding
+import org.kde.kdeconnect.extensions.viewBinding
import org.kde.kdeconnect_tp.R
import org.kde.kdeconnect_tp.databinding.ActivityAboutKdeBinding
-class AboutKDEActivity : AppCompatActivity() {
+class AboutKDEActivity : BaseActivity() {
+
+ override val binding: ActivityAboutKdeBinding by viewBinding(ActivityAboutKdeBinding::inflate)
+
+ override val isScrollable: Boolean = true
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- val binding = ActivityAboutKdeBinding.inflate(layoutInflater)
- setContentView(binding.root)
-
setSupportActionBar(binding.toolbarLayout.toolbar)
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
supportActionBar!!.setDisplayShowHomeEnabled(true)
@@ -34,6 +38,8 @@ class AboutKDEActivity : AppCompatActivity() {
binding.reportBugsOrWishesTextView.movementMethod = LinkMovementMethod.getInstance()
binding.joinKdeTextView.movementMethod = LinkMovementMethod.getInstance()
binding.supportKdeTextView.movementMethod = LinkMovementMethod.getInstance()
+
+ binding.scrollView.setupBottomPadding()
}
private fun fromHtml(html: String): Spanned {
diff --git a/src/org/kde/kdeconnect/UserInterface/About/LicensesActivity.kt b/src/org/kde/kdeconnect/UserInterface/About/LicensesActivity.kt
index 407f99ab..c086808b 100644
--- a/src/org/kde/kdeconnect/UserInterface/About/LicensesActivity.kt
+++ b/src/org/kde/kdeconnect/UserInterface/About/LicensesActivity.kt
@@ -10,23 +10,26 @@ import android.os.Bundle
import android.util.DisplayMetrics
import android.view.Menu
import android.view.MenuItem
-import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.LinearSmoothScroller
import org.apache.commons.io.IOUtils
+import org.kde.kdeconnect.base.BaseActivity
+import org.kde.kdeconnect.extensions.setupBottomPadding
+import org.kde.kdeconnect.extensions.viewBinding
import org.kde.kdeconnect_tp.R
import org.kde.kdeconnect_tp.databinding.ActivityLicensesBinding
import java.nio.charset.Charset
-class LicensesActivity : AppCompatActivity() {
- private lateinit var binding: ActivityLicensesBinding
+class LicensesActivity : BaseActivity() {
+
+ override val binding: ActivityLicensesBinding by viewBinding(ActivityLicensesBinding::inflate)
+
+ override val isScrollable: Boolean = true
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- binding = ActivityLicensesBinding.inflate(layoutInflater)
- setContentView(binding.root)
-
+ binding.licensesText.setupBottomPadding()
setSupportActionBar(binding.toolbarLayout.toolbar)
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
supportActionBar!!.setDisplayShowHomeEnabled(true)
diff --git a/src/org/kde/kdeconnect/UserInterface/CustomDevicesActivity.java b/src/org/kde/kdeconnect/UserInterface/CustomDevicesActivity.java
index 8e416b44..f26cd729 100644
--- a/src/org/kde/kdeconnect/UserInterface/CustomDevicesActivity.java
+++ b/src/org/kde/kdeconnect/UserInterface/CustomDevicesActivity.java
@@ -17,7 +17,6 @@ import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
-import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.TooltipCompat;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
@@ -28,6 +27,8 @@ import com.google.android.material.snackbar.BaseTransientBottomBar;
import com.google.android.material.snackbar.Snackbar;
import org.kde.kdeconnect.DeviceHost;
+import org.kde.kdeconnect.Helpers.WindowHelper;
+import org.kde.kdeconnect.base.BaseActivity;
import org.kde.kdeconnect_tp.R;
import org.kde.kdeconnect_tp.databinding.ActivityCustomDevicesBinding;
@@ -35,9 +36,11 @@ import java.util.ArrayList;
import java.util.Comparator;
import java.util.Objects;
+import kotlin.Lazy;
+import kotlin.LazyKt;
import kotlin.Unit;
-public class CustomDevicesActivity extends AppCompatActivity implements CustomDevicesAdapter.Callback {
+public class CustomDevicesActivity extends BaseActivity implements CustomDevicesAdapter.Callback {
private static final String TAG_ADD_DEVICE_DIALOG = "AddDeviceDialog";
private static final String KEY_CUSTOM_DEVLIST_PREFERENCE = "device_list_preference";
@@ -53,18 +56,23 @@ public class CustomDevicesActivity extends AppCompatActivity implements CustomDe
private DeletedCustomDevice lastDeletedCustomDevice;
private int editingDeviceAtPosition;
+ private final Lazy lazyBinding = LazyKt.lazy(() -> ActivityCustomDevicesBinding.inflate(getLayoutInflater()));
+
+ @NonNull
+ @Override
+ protected ActivityCustomDevicesBinding getBinding() {
+ return lazyBinding.getValue();
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- final ActivityCustomDevicesBinding binding = ActivityCustomDevicesBinding.inflate(getLayoutInflater());
- setContentView(binding.getRoot());
+ recyclerView = getBinding().recyclerView;
+ emptyListMessage = getBinding().emptyListMessage;
+ final FloatingActionButton fab = getBinding().floatingActionButton;
- recyclerView = binding.recyclerView;
- emptyListMessage = binding.emptyListMessage;
- final FloatingActionButton fab = binding.floatingActionButton;
-
- setSupportActionBar(binding.toolbarLayout.toolbar);
+ setSupportActionBar(getBinding().toolbarLayout.toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
@@ -86,6 +94,9 @@ public class CustomDevicesActivity extends AppCompatActivity implements CustomDe
recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
recyclerView.setAdapter(customDevicesAdapter);
+ WindowHelper.setupBottomPadding(recyclerView);
+ WindowHelper.setupBottomMargin(getBinding().floatingActionButton);
+
addDeviceDialog = (EditTextAlertDialogFragment) getSupportFragmentManager().findFragmentByTag(TAG_ADD_DEVICE_DIALOG);
if (addDeviceDialog != null) {
addDeviceDialog.setCallback(new AddDeviceDialogCallback());
@@ -269,4 +280,9 @@ public class CustomDevicesActivity extends AppCompatActivity implements CustomDe
super.onBackPressed();
return true;
}
+
+ @Override
+ public boolean isScrollable() {
+ return true;
+ }
}
diff --git a/src/org/kde/kdeconnect/UserInterface/DeviceFragment.kt b/src/org/kde/kdeconnect/UserInterface/DeviceFragment.kt
index 688df5d4..4dd0124e 100644
--- a/src/org/kde/kdeconnect/UserInterface/DeviceFragment.kt
+++ b/src/org/kde/kdeconnect/UserInterface/DeviceFragment.kt
@@ -44,6 +44,7 @@ import org.kde.kdeconnect.Plugins.Plugin
import org.kde.kdeconnect.Plugins.PresenterPlugin.PresenterPlugin
import org.kde.kdeconnect.Plugins.RunCommandPlugin.RunCommandPlugin
import org.kde.kdeconnect.UserInterface.compose.KdeTheme
+import org.kde.kdeconnect.extensions.setupBottomPadding
import org.kde.kdeconnect_tp.R
import org.kde.kdeconnect_tp.databinding.ActivityDeviceBinding
import org.kde.kdeconnect_tp.databinding.ViewPairErrorBinding
@@ -156,6 +157,11 @@ class DeviceFragment : Fragment() {
return deviceBinding.root
}
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ deviceBinding?.deviceView?.setupBottomPadding()
+ }
+
private fun refreshDevicesAction() {
BackgroundService.ForceRefreshConnections(requireContext())
requireErrorBinding().errorMessageContainer.isRefreshing = true
diff --git a/src/org/kde/kdeconnect/UserInterface/PairingFragment.java b/src/org/kde/kdeconnect/UserInterface/PairingFragment.java
index 6881cc1b..484b289f 100644
--- a/src/org/kde/kdeconnect/UserInterface/PairingFragment.java
+++ b/src/org/kde/kdeconnect/UserInterface/PairingFragment.java
@@ -32,6 +32,7 @@ import androidx.fragment.app.Fragment;
import org.kde.kdeconnect.BackgroundService;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.Helpers.TrustedNetworkHelper;
+import org.kde.kdeconnect.Helpers.WindowHelper;
import org.kde.kdeconnect.KdeConnect;
import org.kde.kdeconnect.UserInterface.List.ListAdapter;
import org.kde.kdeconnect.UserInterface.List.PairingDeviceItem;
@@ -118,6 +119,7 @@ public class PairingFragment extends Fragment implements PairingDeviceItem.Callb
// Configure focus order for Accessibility, for touchpads, and for TV remotes
// (allow focus of items in the device list)
devicesListBinding.devicesList.setItemsCanFocus(true);
+ WindowHelper.setupBottomPadding(devicesListBinding.devicesList);
}
@Override
diff --git a/src/org/kde/kdeconnect/UserInterface/PluginSettingsActivity.java b/src/org/kde/kdeconnect/UserInterface/PluginSettingsActivity.java
index 901350e7..6c94c3db 100644
--- a/src/org/kde/kdeconnect/UserInterface/PluginSettingsActivity.java
+++ b/src/org/kde/kdeconnect/UserInterface/PluginSettingsActivity.java
@@ -13,8 +13,8 @@ import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
+import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
-import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
@@ -24,12 +24,17 @@ import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.DeviceStats;
import org.kde.kdeconnect.KdeConnect;
import org.kde.kdeconnect.Plugins.Plugin;
+import org.kde.kdeconnect.base.BaseActivity;
import org.kde.kdeconnect_tp.R;
+import org.kde.kdeconnect_tp.databinding.ActivityPluginSettingsBinding;
import java.util.Objects;
+import kotlin.Lazy;
+import kotlin.LazyKt;
+
public class PluginSettingsActivity
- extends AppCompatActivity
+ extends BaseActivity
implements PluginPreference.PluginPreferenceCallback {
public static final String EXTRA_DEVICE_ID = "deviceId";
@@ -38,12 +43,18 @@ public class PluginSettingsActivity
//TODO: Save/restore state
static private String deviceId; //Static because if we get here by using the back button in the action bar, the extra deviceId will not be set.
+ private final Lazy lazyBinding = LazyKt.lazy(() -> ActivityPluginSettingsBinding.inflate(getLayoutInflater()));
+
+ @NonNull
+ @Override
+ protected ActivityPluginSettingsBinding getBinding() {
+ return lazyBinding.getValue();
+ }
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_plugin_settings);
-
setSupportActionBar(findViewById(R.id.toolbar));
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
diff --git a/src/org/kde/kdeconnect/UserInterface/SettingsFragment.kt b/src/org/kde/kdeconnect/UserInterface/SettingsFragment.kt
index e2b1d2fe..8d11d8aa 100644
--- a/src/org/kde/kdeconnect/UserInterface/SettingsFragment.kt
+++ b/src/org/kde/kdeconnect/UserInterface/SettingsFragment.kt
@@ -34,6 +34,7 @@ import org.kde.kdeconnect.Helpers.DeviceHelper.filterName
import org.kde.kdeconnect.Helpers.DeviceHelper.getDeviceName
import org.kde.kdeconnect.Helpers.NotificationHelper
import org.kde.kdeconnect.UserInterface.ThemeUtil.applyTheme
+import org.kde.kdeconnect.extensions.setupBottomPadding
import org.kde.kdeconnect_tp.R
class SettingsFragment : PreferenceFragmentCompat() {
@@ -62,6 +63,11 @@ class SettingsFragment : PreferenceFragmentCompat() {
preferenceScreen = screen
}
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ listView.setupBottomPadding()
+ }
+
private fun deviceNamePref(context: Context) = EditTextPreference(context).apply {
key = DeviceHelper.KEY_DEVICE_NAME_PREFERENCE
isSelectable = true
diff --git a/src/org/kde/kdeconnect/UserInterface/TrustedNetworksActivity.kt b/src/org/kde/kdeconnect/UserInterface/TrustedNetworksActivity.kt
index e4dd0fea..fa013197 100644
--- a/src/org/kde/kdeconnect/UserInterface/TrustedNetworksActivity.kt
+++ b/src/org/kde/kdeconnect/UserInterface/TrustedNetworksActivity.kt
@@ -12,13 +12,14 @@ import android.view.View
import android.widget.*
import android.widget.AdapterView.OnItemClickListener
import androidx.appcompat.app.AlertDialog
-import androidx.appcompat.app.AppCompatActivity
import org.kde.kdeconnect.Helpers.TrustedNetworkHelper
+import org.kde.kdeconnect.base.BaseActivity
+import org.kde.kdeconnect.extensions.viewBinding
import org.kde.kdeconnect_tp.R
import org.kde.kdeconnect_tp.databinding.TrustedNetworkListBinding
-class TrustedNetworksActivity : AppCompatActivity() {
- lateinit var binding: TrustedNetworkListBinding
+class TrustedNetworksActivity : BaseActivity() {
+ override val binding: TrustedNetworkListBinding by viewBinding(TrustedNetworkListBinding::inflate)
private val trustedNetworks: MutableList = mutableListOf()
private val trustedNetworksView: ListView
@@ -39,9 +40,6 @@ class TrustedNetworksActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- binding = TrustedNetworkListBinding.inflate(layoutInflater)
- setContentView(binding.root)
-
setSupportActionBar(binding.toolbarLayout.toolbar)
supportActionBar!!.apply {
setDisplayHomeAsUpEnabled(true)
diff --git a/src/org/kde/kdeconnect/base/BaseActivity.kt b/src/org/kde/kdeconnect/base/BaseActivity.kt
new file mode 100644
index 00000000..76b6f294
--- /dev/null
+++ b/src/org/kde/kdeconnect/base/BaseActivity.kt
@@ -0,0 +1,45 @@
+/*
+ * SPDX-FileCopyrightText: 2024 Mash Kyrielight
+ *
+ * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
+ */
+package org.kde.kdeconnect.base
+
+import android.os.Build
+import android.os.Bundle
+import android.view.View
+import android.view.ViewGroup.MarginLayoutParams
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.updateLayoutParams
+import androidx.viewbinding.ViewBinding
+import org.kde.kdeconnect.extensions.getSafeDrawInsets
+import org.kde.kdeconnect.extensions.setOnApplyWindowInsetsListenerCompat
+
+abstract class BaseActivity : AppCompatActivity() {
+
+ protected abstract val binding: VB
+
+ open val isScrollable = false
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(binding.root)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
+ binding.root.setOnApplyWindowInsetsListenerCompat { view, insets ->
+ onWindowInsetsChanged(view, insets)
+ insets
+ }
+ }
+ }
+
+ open fun onWindowInsetsChanged(view: View, insets: WindowInsetsCompat) {
+ val safeDrawInsets = insets.getSafeDrawInsets()
+ view.updateLayoutParams {
+ bottomMargin = if (isScrollable) 0 else safeDrawInsets.bottom
+ leftMargin = safeDrawInsets.left
+ rightMargin = safeDrawInsets.right
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/org/kde/kdeconnect/extensions/ViewBinding.kt b/src/org/kde/kdeconnect/extensions/ViewBinding.kt
new file mode 100644
index 00000000..d971050d
--- /dev/null
+++ b/src/org/kde/kdeconnect/extensions/ViewBinding.kt
@@ -0,0 +1,15 @@
+/*
+ * SPDX-FileCopyrightText: 2024 Mash Kyrielight
+ *
+ * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
+ */
+package org.kde.kdeconnect.extensions
+
+import android.view.LayoutInflater
+import androidx.appcompat.app.AppCompatActivity
+import androidx.viewbinding.ViewBinding
+
+inline fun AppCompatActivity.viewBinding(crossinline bindingInflater: (LayoutInflater) -> T) =
+ lazy(LazyThreadSafetyMode.NONE) {
+ bindingInflater.invoke(layoutInflater)
+ }
\ No newline at end of file
diff --git a/src/org/kde/kdeconnect/extensions/Window.kt b/src/org/kde/kdeconnect/extensions/Window.kt
new file mode 100644
index 00000000..bb6f98fb
--- /dev/null
+++ b/src/org/kde/kdeconnect/extensions/Window.kt
@@ -0,0 +1,63 @@
+/*
+ * SPDX-FileCopyrightText: 2024 Mash Kyrielight
+ *
+ * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
+ */
+package org.kde.kdeconnect.extensions
+
+import android.os.Build
+import android.view.View
+import android.view.ViewGroup.MarginLayoutParams
+import androidx.compose.foundation.layout.safeDrawingPadding
+import androidx.compose.ui.Modifier
+import androidx.core.graphics.Insets
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.updateLayoutParams
+import androidx.core.view.updatePadding
+
+fun View.setOnApplyWindowInsetsListenerCompat(listener: (v: View, insets: WindowInsetsCompat) -> WindowInsetsCompat) {
+ ViewCompat.setOnApplyWindowInsetsListener(this, listener)
+}
+
+fun WindowInsetsCompat.getSafeDrawInsets(): Insets {
+ return getInsets(
+ WindowInsetsCompat.Type.systemBars()
+ or WindowInsetsCompat.Type.displayCutout()
+ or WindowInsetsCompat.Type.ime()
+ )
+}
+
+fun View.setupBottomPadding() {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
+ return
+ }
+ val originalBottomPadding = paddingBottom
+ setOnApplyWindowInsetsListenerCompat { _, insets ->
+ val safeInsets = insets.getSafeDrawInsets()
+ updatePadding(bottom = originalBottomPadding + safeInsets.bottom)
+ insets
+ }
+}
+
+fun View.setupBottomMargin() {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
+ return
+ }
+ val originalBottomMargin = (layoutParams as MarginLayoutParams).bottomMargin
+ setOnApplyWindowInsetsListenerCompat { _, insets ->
+ val safeInsets = insets.getSafeDrawInsets()
+ updateLayoutParams {
+ bottomMargin = originalBottomMargin + safeInsets.bottom
+ }
+ insets
+ }
+}
+
+fun Modifier.safeDrawPadding(): Modifier {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
+ safeDrawingPadding()
+ } else {
+ Modifier
+ }
+}
\ No newline at end of file