2
0
mirror of https://github.com/KDE/kdeconnect-android synced 2025-08-22 09:58:08 +00:00

Fix insets for android 15

Apps are edge-to-edge by default on devices running Android 15
https://developer.android.com/develop/ui/views/layout/edge-to-edge

Fix: https://bugs.kde.org/show_bug.cgi?id=495999
This commit is contained in:
Mash Kyrielight 2024-12-31 18:00:39 +00:00 committed by Albert Vaca Cintora
parent 16414401c0
commit ae24cd6ca8
31 changed files with 444 additions and 147 deletions

View File

@ -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_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:fillViewport="true" android:fillViewport="true"
android:clipToPadding="false"
android:id="@+id/scroll_view"
app:layout_behavior="@string/appbar_scrolling_view_behavior"> app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout <LinearLayout

View File

@ -26,6 +26,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:id="@+id/recyclerView" android:id="@+id/recyclerView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:clipToPadding="false"
tools:listitem="@layout/custom_device_item"/> tools:listitem="@layout/custom_device_item"/>
<TextView <TextView

View File

@ -30,7 +30,8 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:id="@+id/device_view" android:id="@+id/device_view"
android:descendantFocusability="afterDescendants" android:descendantFocusability="afterDescendants"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:clipToPadding="false">
<!-- Shown when the device is paired and reachable --> <!-- Shown when the device is paired and reachable -->
<androidx.compose.ui.platform.ComposeView <androidx.compose.ui.platform.ComposeView

View File

@ -20,5 +20,6 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:id="@+id/licenses_text" android:id="@+id/licenses_text"
app:layout_behavior="@string/appbar_scrolling_view_behavior" app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" /> android:layout_height="match_parent"
android:clipToPadding="false"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -17,7 +17,8 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
<!-- Keep in sync with toolbar.xml, copied here because it needs the nested TabLayout --> <!-- Keep in sync with toolbar.xml, copied here because it needs the nested TabLayout -->
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar <com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"

View File

@ -57,6 +57,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:dividerHeight="0dp" android:dividerHeight="0dp"
android:orientation="vertical" android:orientation="vertical"
android:paddingTop="8dp" android:paddingTop="8dp"
android:clipToPadding="false"
tools:context=".MainActivity" /> tools:context=".MainActivity" />
</LinearLayout> </LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -22,6 +22,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:descendantFocusability="afterDescendants" android:descendantFocusability="afterDescendants"
android:dividerHeight="12dp" android:dividerHeight="12dp"
android:orientation="vertical" android:orientation="vertical"
android:clipToPadding="false"
tools:listitem="@layout/list_card_entry" tools:listitem="@layout/list_card_entry"
tools:context=".MainActivity" /> tools:context=".MainActivity" />

View File

@ -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_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:fillViewport="true"> android:fillViewport="true"
android:clipToPadding="false"
android:id="@+id/scroll_view">
<LinearLayout <LinearLayout
android:id="@+id/about_layout" android:id="@+id/about_layout"

View File

@ -0,0 +1,25 @@
/*
* SPDX-FileCopyrightText: 2024 Mash Kyrielight <fiepi@live.com>
*
* 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()
}
}

View File

@ -15,37 +15,46 @@ import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer; import android.speech.SpeechRecognizer;
import android.view.View; import android.view.View;
import androidx.appcompat.app.AppCompatActivity; import androidx.annotation.NonNull;
import org.kde.kdeconnect.KdeConnect; import org.kde.kdeconnect.KdeConnect;
import org.kde.kdeconnect.UserInterface.MainActivity; import org.kde.kdeconnect.UserInterface.MainActivity;
import org.kde.kdeconnect.UserInterface.PermissionsAlertDialogFragment; import org.kde.kdeconnect.UserInterface.PermissionsAlertDialogFragment;
import org.kde.kdeconnect.base.BaseActivity;
import org.kde.kdeconnect_tp.R; import org.kde.kdeconnect_tp.R;
import org.kde.kdeconnect_tp.databinding.ActivityBigscreenBinding; import org.kde.kdeconnect_tp.databinding.ActivityBigscreenBinding;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Objects; import java.util.Objects;
public class BigscreenActivity extends AppCompatActivity { import kotlin.Lazy;
import kotlin.LazyKt;
public class BigscreenActivity extends BaseActivity<ActivityBigscreenBinding> {
private static final int REQUEST_SPEECH = 100; private static final int REQUEST_SPEECH = 100;
private final Lazy<ActivityBigscreenBinding> lazyBinding = LazyKt.lazy(() -> ActivityBigscreenBinding.inflate(getLayoutInflater()));
@NonNull
@Override
protected ActivityBigscreenBinding getBinding() {
return lazyBinding.getValue();
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
final ActivityBigscreenBinding binding = ActivityBigscreenBinding.inflate(getLayoutInflater()); setSupportActionBar(getBinding().toolbarLayout.toolbar);
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbarLayout.toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true); Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true); getSupportActionBar().setDisplayShowHomeEnabled(true);
final String deviceId = getIntent().getStringExtra("deviceId"); final String deviceId = getIntent().getStringExtra("deviceId");
if (!SpeechRecognizer.isRecognitionAvailable(this)) { if (!SpeechRecognizer.isRecognitionAvailable(this)) {
binding.micButton.setEnabled(false); getBinding().micButton.setEnabled(false);
binding.micButton.setVisibility(View.INVISIBLE); getBinding().micButton.setVisibility(View.INVISIBLE);
} }
BigscreenPlugin plugin = KdeConnect.getInstance().getDevicePlugin(deviceId, BigscreenPlugin.class); BigscreenPlugin plugin = KdeConnect.getInstance().getDevicePlugin(deviceId, BigscreenPlugin.class);
@ -54,13 +63,13 @@ public class BigscreenActivity extends AppCompatActivity {
return; return;
} }
binding.leftButton.setOnClickListener(v -> plugin.sendLeft()); getBinding().leftButton.setOnClickListener(v -> plugin.sendLeft());
binding.rightButton.setOnClickListener(v -> plugin.sendRight()); getBinding().rightButton.setOnClickListener(v -> plugin.sendRight());
binding.upButton.setOnClickListener(v -> plugin.sendUp()); getBinding().upButton.setOnClickListener(v -> plugin.sendUp());
binding.downButton.setOnClickListener(v -> plugin.sendDown()); getBinding().downButton.setOnClickListener(v -> plugin.sendDown());
binding.selectButton.setOnClickListener(v -> plugin.sendSelect()); getBinding().selectButton.setOnClickListener(v -> plugin.sendSelect());
binding.homeButton.setOnClickListener(v -> plugin.sendHome()); getBinding().homeButton.setOnClickListener(v -> plugin.sendHome());
binding.micButton.setOnClickListener(v -> { getBinding().micButton.setOnClickListener(v -> {
if (plugin.hasMicPermission()) { if (plugin.hasMicPermission()) {
activateSTT(); activateSTT();
} else { } else {

View File

@ -10,26 +10,35 @@ import android.util.Log;
import android.view.Window; import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import androidx.appcompat.app.AppCompatActivity; import androidx.annotation.NonNull;
import org.kde.kdeconnect.KdeConnect; import org.kde.kdeconnect.KdeConnect;
import org.kde.kdeconnect.base.BaseActivity;
import org.kde.kdeconnect_tp.databinding.ActivityFindMyPhoneBinding; import org.kde.kdeconnect_tp.databinding.ActivityFindMyPhoneBinding;
import java.util.Objects; import java.util.Objects;
public class FindMyPhoneActivity extends AppCompatActivity { import kotlin.Lazy;
import kotlin.LazyKt;
public class FindMyPhoneActivity extends BaseActivity<ActivityFindMyPhoneBinding> {
static final String EXTRA_DEVICE_ID = "deviceId"; static final String EXTRA_DEVICE_ID = "deviceId";
String deviceId; String deviceId;
private final Lazy<ActivityFindMyPhoneBinding> lazyBinding = LazyKt.lazy(() -> ActivityFindMyPhoneBinding.inflate(getLayoutInflater()));
@NonNull
@Override
protected ActivityFindMyPhoneBinding getBinding() {
return lazyBinding.getValue();
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
final ActivityFindMyPhoneBinding binding = ActivityFindMyPhoneBinding.inflate(getLayoutInflater()); setSupportActionBar(getBinding().toolbarLayout.toolbar);
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbarLayout.toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true); Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true); getSupportActionBar().setDisplayShowHomeEnabled(true);
@ -47,7 +56,7 @@ public class FindMyPhoneActivity extends AppCompatActivity {
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
); );
binding.bFindMyPhone.setOnClickListener(view -> finish()); getBinding().bFindMyPhone.setOnClickListener(view -> finish());
} }
@Override @Override

View File

@ -30,6 +30,7 @@ import org.kde.kdeconnect.UserInterface.compose.KdeTextButton
import org.kde.kdeconnect.UserInterface.compose.KdeTextField import org.kde.kdeconnect.UserInterface.compose.KdeTextField
import org.kde.kdeconnect.UserInterface.compose.KdeTheme import org.kde.kdeconnect.UserInterface.compose.KdeTheme
import org.kde.kdeconnect.UserInterface.compose.KdeTopAppBar import org.kde.kdeconnect.UserInterface.compose.KdeTopAppBar
import org.kde.kdeconnect.extensions.safeDrawPadding
import org.kde.kdeconnect_tp.R import org.kde.kdeconnect_tp.R
private const val INPUT_CACHE_KEY = "compose_send_input_cache" private const val INPUT_CACHE_KEY = "compose_send_input_cache"
@ -91,6 +92,7 @@ class ComposeSendActivity : AppCompatActivity() {
private fun ComposeSendScreen() { private fun ComposeSendScreen() {
KdeTheme(this) { KdeTheme(this) {
Scaffold( Scaffold(
modifier = Modifier.safeDrawPadding(),
topBar = { topBar = {
KdeTopAppBar( KdeTopAppBar(
title = stringResource(R.string.compose_send_title), title = stringResource(R.string.compose_send_title),

View File

@ -13,7 +13,6 @@ import android.hardware.SensorEvent;
import android.hardware.SensorEventListener; import android.hardware.SensorEventListener;
import android.hardware.SensorManager; import android.hardware.SensorManager;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector; import android.view.GestureDetector;
import android.view.HapticFeedbackConstants; import android.view.HapticFeedbackConstants;
import android.view.Menu; import android.view.Menu;
@ -24,18 +23,23 @@ import android.view.View;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.Toast; import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity; import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import org.kde.kdeconnect.KdeConnect; import org.kde.kdeconnect.KdeConnect;
import org.kde.kdeconnect.UserInterface.PluginSettingsActivity; import org.kde.kdeconnect.UserInterface.PluginSettingsActivity;
import org.kde.kdeconnect.base.BaseActivity;
import org.kde.kdeconnect_tp.R; import org.kde.kdeconnect_tp.R;
import org.kde.kdeconnect_tp.databinding.ActivityMousepadBinding;
import java.util.Objects; import java.util.Objects;
import kotlin.Lazy;
import kotlin.LazyKt;
public class MousePadActivity public class MousePadActivity
extends AppCompatActivity extends BaseActivity<ActivityMousepadBinding>
implements GestureDetector.OnGestureListener, implements GestureDetector.OnGestureListener,
GestureDetector.OnDoubleTapListener, GestureDetector.OnDoubleTapListener,
MousePadGestureDetector.OnGestureListener, MousePadGestureDetector.OnGestureListener,
@ -74,6 +78,14 @@ public class MousePadActivity
private boolean prefsApplied = false; private boolean prefsApplied = false;
private final Lazy<ActivityMousepadBinding> lazyBinding = LazyKt.lazy(() -> ActivityMousepadBinding.inflate(getLayoutInflater()));
@NonNull
@Override
protected ActivityMousepadBinding getBinding() {
return lazyBinding.getValue();
}
enum ClickType { enum ClickType {
LEFT, RIGHT, MIDDLE, NONE; LEFT, RIGHT, MIDDLE, NONE;
@ -131,15 +143,12 @@ public class MousePadActivity
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mousepad); setSupportActionBar(getBinding().toolbarLayout.toolbar);
setSupportActionBar(findViewById(R.id.toolbar));
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true); Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true); getSupportActionBar().setDisplayShowHomeEnabled(true);
getBinding().mouseClickLeft.setOnClickListener(v -> sendLeftClick());
findViewById(R.id.mouse_click_left).setOnClickListener(v -> sendLeftClick()); getBinding().mouseClickMiddle.setOnClickListener(v -> sendMiddleClick());
findViewById(R.id.mouse_click_middle).setOnClickListener(v -> sendMiddleClick()); getBinding().mouseClickRight.setOnClickListener(v -> sendRightClick());
findViewById(R.id.mouse_click_right).setOnClickListener(v -> sendRightClick());
deviceId = getIntent().getStringExtra("deviceId"); deviceId = getIntent().getStringExtra("deviceId");
@ -150,7 +159,7 @@ public class MousePadActivity
mDetector.setOnDoubleTapListener(this); mDetector.setOnDoubleTapListener(this);
mSensorManager = ContextCompat.getSystemService(this, SensorManager.class); mSensorManager = ContextCompat.getSystemService(this, SensorManager.class);
keyListenerView = findViewById(R.id.keyListener); keyListenerView = getBinding().keyListener;
keyListenerView.setDeviceId(deviceId); keyListenerView.setDeviceId(deviceId);
prefs = PreferenceManager.getDefaultSharedPreferences(this); prefs = PreferenceManager.getDefaultSharedPreferences(this);
@ -582,9 +591,9 @@ public class MousePadActivity
} }
if (prefs.getBoolean(getString(R.string.mousepad_mouse_buttons_enabled_pref), true)) { 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 { } 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); doubleTapDragEnabled = prefs.getBoolean(getString(R.string.mousepad_doubletap_drag_enabled_pref), true);

View File

@ -13,17 +13,18 @@ import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import org.kde.kdeconnect.BackgroundService; import org.kde.kdeconnect.BackgroundService;
import org.kde.kdeconnect.Device; import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.Helpers.SafeTextChecker; import org.kde.kdeconnect.Helpers.SafeTextChecker;
import org.kde.kdeconnect.Helpers.WindowHelper;
import org.kde.kdeconnect.KdeConnect; import org.kde.kdeconnect.KdeConnect;
import org.kde.kdeconnect.NetworkPacket; import org.kde.kdeconnect.NetworkPacket;
import org.kde.kdeconnect.UserInterface.List.EntryItemWithIcon; import org.kde.kdeconnect.UserInterface.List.EntryItemWithIcon;
import org.kde.kdeconnect.UserInterface.List.ListAdapter; import org.kde.kdeconnect.UserInterface.List.ListAdapter;
import org.kde.kdeconnect.UserInterface.List.SectionItem; import org.kde.kdeconnect.UserInterface.List.SectionItem;
import org.kde.kdeconnect.base.BaseActivity;
import org.kde.kdeconnect_tp.R; import org.kde.kdeconnect_tp.R;
import org.kde.kdeconnect_tp.databinding.ActivitySendkeystrokesBinding; import org.kde.kdeconnect_tp.databinding.ActivitySendkeystrokesBinding;
@ -33,7 +34,10 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class SendKeystrokesToHostActivity extends AppCompatActivity { import kotlin.Lazy;
import kotlin.LazyKt;
public class SendKeystrokesToHostActivity extends BaseActivity<ActivitySendkeystrokesBinding> {
// text with these length and content can be send without user confirmation. // 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) // 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"; public static final String SAFE_CHARS = "1234567890";
private ActivitySendkeystrokesBinding binding;
private boolean contentIsOkay; private boolean contentIsOkay;
private final Lazy<ActivitySendkeystrokesBinding> lazyBinding = LazyKt.lazy(() -> ActivitySendkeystrokesBinding.inflate(getLayoutInflater()));
@NonNull
@Override
public ActivitySendkeystrokesBinding getBinding() {
return lazyBinding.getValue();
}
@Override
public boolean isScrollable() {
return true;
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
binding = ActivitySendkeystrokesBinding.inflate(getLayoutInflater()); setSupportActionBar(getBinding().toolbarLayout.toolbar);
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbarLayout.toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true); Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true); getSupportActionBar().setDisplayShowHomeEnabled(true);
WindowHelper.setupBottomPadding(getBinding().devicesList);
} }
@ -73,7 +88,7 @@ public class SendKeystrokesToHostActivity extends AppCompatActivity {
if ("text/x-keystrokes".equals(type)) { if ("text/x-keystrokes".equals(type)) {
String toSend = intent.getStringExtra(Intent.EXTRA_TEXT); 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 // 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 // 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) { private void sendKeys(Device deviceId) {
String toSend; 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); final NetworkPacket np = new NetworkPacket(MousePadPlugin.PACKET_TYPE_MOUSEPAD_REQUEST);
np.set("key", toSend); np.set("key", toSend);
MousePadPlugin plugin = KdeConnect.getInstance().getDevicePlugin(deviceId.getDeviceId(), MousePadPlugin.class); 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)); getBinding().devicesList.setAdapter(new ListAdapter(SendKeystrokesToHostActivity.this, items));
binding.devicesList.setOnItemClickListener((adapterView, view, i, l) -> { getBinding().devicesList.setOnItemClickListener((adapterView, view, i, l) -> {
Device device = devicesList.get(i - 1); // NOTE: -1 because of the title! Device device = devicesList.get(i - 1); // NOTE: -1 because of the title!
sendKeys(device); sendKeys(device);
this.finish(); // close the activity this.finish(); // close the activity

View File

@ -8,22 +8,25 @@ package org.kde.kdeconnect.Plugins.MprisPlugin
import android.os.Bundle import android.os.Bundle
import android.view.KeyEvent import android.view.KeyEvent
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import com.google.android.material.tabs.TabLayoutMediator import com.google.android.material.tabs.TabLayoutMediator
import org.kde.kdeconnect.Plugins.SystemVolumePlugin.SystemVolumeFragment 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.R
import org.kde.kdeconnect_tp.databinding.ActivityMprisBinding import org.kde.kdeconnect_tp.databinding.ActivityMprisBinding
class MprisActivity : AppCompatActivity() { class MprisActivity : BaseActivity<ActivityMprisBinding>() {
private lateinit var activityMprisBinding: ActivityMprisBinding
override val binding: ActivityMprisBinding by viewBinding(ActivityMprisBinding::inflate)
private lateinit var mprisPagerAdapter: MprisPagerAdapter private lateinit var mprisPagerAdapter: MprisPagerAdapter
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
return when (keyCode) { return when (keyCode) {
KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_VOLUME_DOWN -> { KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_VOLUME_DOWN -> {
val pagePosition = activityMprisBinding.mprisTabs.selectedTabPosition val pagePosition = binding.mprisTabs.selectedTabPosition
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
mprisPagerAdapter.onVolumeUp(pagePosition) mprisPagerAdapter.onVolumeUp(pagePosition)
} else { } else {
@ -46,17 +49,13 @@ class MprisActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
activityMprisBinding = ActivityMprisBinding.inflate(layoutInflater)
setContentView(activityMprisBinding.root)
val deviceId = intent.getStringExtra(MprisPlugin.DEVICE_ID_KEY) val deviceId = intent.getStringExtra(MprisPlugin.DEVICE_ID_KEY)
mprisPagerAdapter = MprisPagerAdapter(this, deviceId) mprisPagerAdapter = MprisPagerAdapter(this, deviceId)
activityMprisBinding.mprisPager.adapter = mprisPagerAdapter binding.mprisPager.adapter = mprisPagerAdapter
val tabLayoutMediator = TabLayoutMediator( val tabLayoutMediator = TabLayoutMediator(
activityMprisBinding.mprisTabs, activityMprisBinding.mprisPager binding.mprisTabs, binding.mprisPager
) { tab, position -> ) { tab, position ->
tab.setText( tab.setText(
mprisPagerAdapter.getTitle(position) mprisPagerAdapter.getTitle(position)
@ -65,7 +64,7 @@ class MprisActivity : AppCompatActivity() {
tabLayoutMediator.attach() tabLayoutMediator.attach()
setSupportActionBar(activityMprisBinding.toolbar) setSupportActionBar(binding.toolbar)
supportActionBar!!.setDisplayHomeAsUpEnabled(true) supportActionBar!!.setDisplayHomeAsUpEnabled(true)
} }

View File

@ -27,14 +27,15 @@ import android.widget.CheckBox;
import android.widget.CheckedTextView; import android.widget.CheckedTextView;
import android.widget.ListView; import android.widget.ListView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView; import androidx.appcompat.widget.SearchView;
import androidx.core.widget.TextViewCompat; import androidx.core.widget.TextViewCompat;
import com.google.android.material.materialswitch.MaterialSwitch; import com.google.android.material.materialswitch.MaterialSwitch;
import org.kde.kdeconnect.Helpers.ThreadHelper; import org.kde.kdeconnect.Helpers.ThreadHelper;
import org.kde.kdeconnect.base.BaseActivity;
import org.kde.kdeconnect_tp.R; import org.kde.kdeconnect_tp.R;
import org.kde.kdeconnect_tp.databinding.ActivityNotificationFilterBinding; import org.kde.kdeconnect_tp.databinding.ActivityNotificationFilterBinding;
@ -43,9 +44,12 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import kotlin.Lazy;
import kotlin.LazyKt;
//TODO: Turn this into a PluginSettingsFragment //TODO: Turn this into a PluginSettingsFragment
public class NotificationFilterActivity extends AppCompatActivity { public class NotificationFilterActivity extends BaseActivity<ActivityNotificationFilterBinding> {
private ActivityNotificationFilterBinding binding;
private AppDatabase appDatabase; private AppDatabase appDatabase;
private String prefKey; 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. // This variable stores all app information and serves as a data source for filtering.
private List<AppListInfo> mAllApps; private List<AppListInfo> mAllApps;
private List<AppListInfo> apps; // Filtered data. private List<AppListInfo> apps; // Filtered data.
private final Lazy<ActivityNotificationFilterBinding> lazyBinding = LazyKt.lazy(() -> ActivityNotificationFilterBinding.inflate(getLayoutInflater()));
@NonNull
@Override
protected ActivityNotificationFilterBinding getBinding() {
return lazyBinding.getValue();
}
class AppListAdapter extends BaseAdapter { class AppListAdapter extends BaseAdapter {
@ -87,13 +99,13 @@ public class NotificationFilterActivity extends AppCompatActivity {
if (position == 0) { if (position == 0) {
checkedTextView.setText(R.string.all); checkedTextView.setText(R.string.all);
TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(checkedTextView, null, null, null, null); TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(checkedTextView, null, null, null, null);
binding.lvFilterApps.setItemChecked(position, appDatabase.getAllEnabled()); getBinding().lvFilterApps.setItemChecked(position, appDatabase.getAllEnabled());
} else { } else {
final AppListInfo info = apps.get(position - 1); final AppListInfo info = apps.get(position - 1);
checkedTextView.setText(info.name); checkedTextView.setText(info.name);
TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(checkedTextView, info.icon, null, null, null); TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(checkedTextView, info.icon, null, null, null);
checkedTextView.setCompoundDrawablePadding((int) (8 * getResources().getDisplayMetrics().density)); checkedTextView.setCompoundDrawablePadding((int) (8 * getResources().getDisplayMetrics().density));
binding.lvFilterApps.setItemChecked(position, info.isEnabled); getBinding().lvFilterApps.setItemChecked(position, info.isEnabled);
} }
return view; return view;
@ -105,14 +117,12 @@ public class NotificationFilterActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
binding = ActivityNotificationFilterBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
appDatabase = new AppDatabase(NotificationFilterActivity.this, false); appDatabase = new AppDatabase(NotificationFilterActivity.this, false);
if (getIntent()!= null){ if (getIntent()!= null){
prefKey = getIntent().getStringExtra(NotificationsPlugin.getPrefKey()); prefKey = getIntent().getStringExtra(NotificationsPlugin.getPrefKey());
} }
setSupportActionBar(binding.toolbarLayout.toolbar); setSupportActionBar(getBinding().toolbarLayout.toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true); Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true); getSupportActionBar().setDisplayShowHomeEnabled(true);
SharedPreferences preferences = this.getSharedPreferences(prefKey, Context.MODE_PRIVATE); SharedPreferences preferences = this.getSharedPreferences(prefKey, Context.MODE_PRIVATE);
@ -152,7 +162,7 @@ public class NotificationFilterActivity extends AppCompatActivity {
} }
private void displayAppList() { private void displayAppList() {
final ListView listView = binding.lvFilterApps; final ListView listView = getBinding().lvFilterApps;
AppListAdapter adapter = new AppListAdapter(); AppListAdapter adapter = new AppListAdapter();
listView.setAdapter(adapter); listView.setAdapter(adapter);
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
@ -233,7 +243,7 @@ public class NotificationFilterActivity extends AppCompatActivity {
} }
listView.setVisibility(View.VISIBLE); listView.setVisibility(View.VISIBLE);
binding.spinner.setVisibility(View.GONE); getBinding().spinner.setVisibility(View.GONE);
} }
private Drawable resizeIcon(Drawable icon, int maxSize) { 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; return true;
} }
}); });

View File

@ -37,6 +37,7 @@ import org.kde.kdeconnect.KdeConnect
import org.kde.kdeconnect.UserInterface.compose.KdeButton import org.kde.kdeconnect.UserInterface.compose.KdeButton
import org.kde.kdeconnect.UserInterface.compose.KdeTheme import org.kde.kdeconnect.UserInterface.compose.KdeTheme
import org.kde.kdeconnect.UserInterface.compose.KdeTopAppBar import org.kde.kdeconnect.UserInterface.compose.KdeTopAppBar
import org.kde.kdeconnect.extensions.safeDrawPadding
import org.kde.kdeconnect_tp.R import org.kde.kdeconnect_tp.R
private const val VOLUME_UP = 1 private const val VOLUME_UP = 1
@ -116,7 +117,10 @@ class PresenterActivity : AppCompatActivity(), SensorEventListener {
val sensorManager = LocalContext.current.getSystemService(SENSOR_SERVICE) as? SensorManager val sensorManager = LocalContext.current.getSystemService(SENSOR_SERVICE) as? SensorManager
KdeTheme(this) { KdeTheme(this) {
Scaffold(topBar = { PresenterAppBar() }) { Scaffold(
modifier = Modifier.safeDrawPadding(),
topBar = { PresenterAppBar() }
) {
Column( Column(
modifier = Modifier.fillMaxSize().padding(it).padding(16.dp), modifier = Modifier.fillMaxSize().padding(it).padding(16.dp),
verticalArrangement = Arrangement.spacedBy(20.dp), verticalArrangement = Arrangement.spacedBy(20.dp),

View File

@ -17,8 +17,8 @@ import android.view.View;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import org.json.JSONException; import org.json.JSONException;
@ -26,6 +26,7 @@ import org.json.JSONObject;
import org.kde.kdeconnect.Device; import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.KdeConnect; import org.kde.kdeconnect.KdeConnect;
import org.kde.kdeconnect.UserInterface.List.ListAdapter; import org.kde.kdeconnect.UserInterface.List.ListAdapter;
import org.kde.kdeconnect.base.BaseActivity;
import org.kde.kdeconnect_tp.R; import org.kde.kdeconnect_tp.R;
import org.kde.kdeconnect_tp.databinding.ActivityRunCommandBinding; import org.kde.kdeconnect_tp.databinding.ActivityRunCommandBinding;
@ -35,8 +36,19 @@ import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
public class RunCommandActivity extends AppCompatActivity { import kotlin.Lazy;
private ActivityRunCommandBinding binding; import kotlin.LazyKt;
public class RunCommandActivity extends BaseActivity<ActivityRunCommandBinding> {
private final Lazy<ActivityRunCommandBinding> lazyBinding = LazyKt.lazy(() -> ActivityRunCommandBinding.inflate(getLayoutInflater()));
@NonNull
@Override
protected ActivityRunCommandBinding getBinding() {
return lazyBinding.getValue();
}
private String deviceId; private String deviceId;
private final RunCommandPlugin.CommandsChangedCallback commandsChangedCallback = () -> runOnUiThread(this::updateView); private final RunCommandPlugin.CommandsChangedCallback commandsChangedCallback = () -> runOnUiThread(this::updateView);
private List<CommandEntry> commandItems; private List<CommandEntry> commandItems;
@ -48,7 +60,7 @@ public class RunCommandActivity extends AppCompatActivity {
return; return;
} }
registerForContextMenu(binding.runCommandsList); registerForContextMenu(getBinding().runCommandsList);
commandItems = new ArrayList<>(); commandItems = new ArrayList<>();
for (JSONObject obj : plugin.getCommandList()) { for (JSONObject obj : plugin.getCommandList()) {
@ -63,26 +75,23 @@ public class RunCommandActivity extends AppCompatActivity {
ListAdapter adapter = new ListAdapter(RunCommandActivity.this, commandItems); ListAdapter adapter = new ListAdapter(RunCommandActivity.this, commandItems);
binding.runCommandsList.setAdapter(adapter); getBinding().runCommandsList.setAdapter(adapter);
binding.runCommandsList.setOnItemClickListener((adapterView, view1, i, l) -> getBinding().runCommandsList.setOnItemClickListener((adapterView, view1, i, l) ->
plugin.runCommand(commandItems.get(i).getKey())); plugin.runCommand(commandItems.get(i).getKey()));
String text = getString(R.string.addcommand_explanation); String text = getString(R.string.addcommand_explanation);
if (!plugin.canAddCommand()) { if (!plugin.canAddCommand()) {
text += "\n" + getString(R.string.addcommand_explanation2); text += "\n" + getString(R.string.addcommand_explanation2);
} }
binding.addCommandExplanation.setText(text); getBinding().addCommandExplanation.setText(text);
binding.addCommandExplanation.setVisibility(commandItems.isEmpty() ? View.VISIBLE : View.GONE); getBinding().addCommandExplanation.setVisibility(commandItems.isEmpty() ? View.VISIBLE : View.GONE);
} }
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
binding = ActivityRunCommandBinding.inflate(getLayoutInflater()); setSupportActionBar(getBinding().toolbarLayout.toolbar);
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbarLayout.toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true); Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true); getSupportActionBar().setDisplayShowHomeEnabled(true);
@ -93,11 +102,11 @@ public class RunCommandActivity extends AppCompatActivity {
RunCommandPlugin plugin = device.getPlugin(RunCommandPlugin.class); RunCommandPlugin plugin = device.getPlugin(RunCommandPlugin.class);
if (plugin != null) { if (plugin != null) {
if (plugin.canAddCommand()) { if (plugin.canAddCommand()) {
binding.addCommandButton.show(); getBinding().addCommandButton.show();
} else { } else {
binding.addCommandButton.hide(); getBinding().addCommandButton.hide();
} }
binding.addCommandButton.setOnClickListener(v -> { getBinding().addCommandButton.setOnClickListener(v -> {
plugin.sendSetupPacket(); plugin.sendSetupPacket();
new AlertDialog.Builder(RunCommandActivity.this) new AlertDialog.Builder(RunCommandActivity.this)
.setTitle(R.string.add_command) .setTitle(R.string.add_command)

View File

@ -15,16 +15,19 @@ import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.webkit.URLUtil; import android.webkit.URLUtil;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import org.kde.kdeconnect.BackgroundService; import org.kde.kdeconnect.BackgroundService;
import org.kde.kdeconnect.Device; import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.Helpers.WindowHelper;
import org.kde.kdeconnect.KdeConnect; import org.kde.kdeconnect.KdeConnect;
import org.kde.kdeconnect.UserInterface.List.EntryItemWithIcon; import org.kde.kdeconnect.UserInterface.List.EntryItemWithIcon;
import org.kde.kdeconnect.UserInterface.List.ListAdapter; import org.kde.kdeconnect.UserInterface.List.ListAdapter;
import org.kde.kdeconnect.UserInterface.List.SectionItem; import org.kde.kdeconnect.UserInterface.List.SectionItem;
import org.kde.kdeconnect.base.BaseActivity;
import org.kde.kdeconnect_tp.R; import org.kde.kdeconnect_tp.R;
import org.kde.kdeconnect_tp.databinding.ActivityShareBinding; import org.kde.kdeconnect_tp.databinding.ActivityShareBinding;
@ -34,11 +37,27 @@ import java.util.HashSet;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
public class ShareActivity extends AppCompatActivity { import kotlin.Lazy;
import kotlin.LazyKt;
public class ShareActivity extends BaseActivity<ActivityShareBinding> {
private static final String KEY_UNREACHABLE_URL_LIST = "key_unreachable_url_list"; private static final String KEY_UNREACHABLE_URL_LIST = "key_unreachable_url_list";
private ActivityShareBinding binding;
private SharedPreferences mSharedPrefs; private SharedPreferences mSharedPrefs;
private final Lazy<ActivityShareBinding> lazyBinding = LazyKt.lazy(() -> ActivityShareBinding.inflate(getLayoutInflater()));
@NonNull
@Override
public ActivityShareBinding getBinding() {
return lazyBinding.getValue();
}
@Override
public boolean isScrollable() {
return true;
}
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater(); MenuInflater inflater = getMenuInflater();
@ -59,9 +78,9 @@ public class ShareActivity extends AppCompatActivity {
private void refreshDevicesAction() { private void refreshDevicesAction() {
BackgroundService.ForceRefreshConnections(this); BackgroundService.ForceRefreshConnections(this);
binding.devicesListLayout.refreshListLayout.setRefreshing(true); getBinding().devicesListLayout.refreshListLayout.setRefreshing(true);
binding.devicesListLayout.refreshListLayout.postDelayed(() -> { getBinding().devicesListLayout.refreshListLayout.postDelayed(() -> {
binding.devicesListLayout.refreshListLayout.setRefreshing(false); getBinding().devicesListLayout.refreshListLayout.setRefreshing(false);
}, 1500); }, 1500);
} }
@ -100,8 +119,8 @@ public class ShareActivity extends AppCompatActivity {
} }
} }
binding.devicesListLayout.devicesList.setAdapter(new ListAdapter(ShareActivity.this, items)); getBinding().devicesListLayout.devicesList.setAdapter(new ListAdapter(ShareActivity.this, items));
binding.devicesListLayout.devicesList.setOnItemClickListener((adapterView, view, i, l) -> { getBinding().devicesListLayout.devicesList.setOnItemClickListener((adapterView, view, i, l) -> {
Device device = devicesList.get(i - 1); //NOTE: -1 because of the title! Device device = devicesList.get(i - 1); //NOTE: -1 because of the title!
SharePlugin plugin = KdeConnect.getInstance().getDevicePlugin(device.getDeviceId(), SharePlugin.class); SharePlugin plugin = KdeConnect.getInstance().getDevicePlugin(device.getDeviceId(), SharePlugin.class);
if (intentHasUrl && !device.isReachable()) { if (intentHasUrl && !device.isReachable()) {
@ -140,20 +159,19 @@ public class ShareActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
binding = ActivityShareBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences (this); mSharedPrefs = PreferenceManager.getDefaultSharedPreferences (this);
setSupportActionBar(binding.toolbarLayout.toolbar); setSupportActionBar(getBinding().toolbarLayout.toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true); Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true); getSupportActionBar().setDisplayShowHomeEnabled(true);
ActionBar actionBar = getSupportActionBar(); ActionBar actionBar = getSupportActionBar();
binding.devicesListLayout.refreshListLayout.setOnRefreshListener(this::refreshDevicesAction); getBinding().devicesListLayout.refreshListLayout.setOnRefreshListener(this::refreshDevicesAction);
if (actionBar != null) { if (actionBar != null) {
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_CUSTOM); actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_CUSTOM);
} }
WindowHelper.setupBottomPadding(getBinding().devicesListLayout.devicesList);
} }
@Override @Override

View File

@ -18,11 +18,13 @@ import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import org.kde.kdeconnect.UserInterface.List.ListAdapter import org.kde.kdeconnect.UserInterface.List.ListAdapter
import org.kde.kdeconnect.UserInterface.MainActivity import org.kde.kdeconnect.UserInterface.MainActivity
import org.kde.kdeconnect.extensions.setupBottomPadding
import org.kde.kdeconnect_tp.R import org.kde.kdeconnect_tp.R
import org.kde.kdeconnect_tp.databinding.FragmentAboutBinding import org.kde.kdeconnect_tp.databinding.FragmentAboutBinding
class AboutFragment : Fragment() { class AboutFragment : Fragment() {
private var binding: FragmentAboutBinding? = null private var _binding: FragmentAboutBinding? = null
private val binding get() = _binding!!
private lateinit var aboutData: AboutData private lateinit var aboutData: AboutData
private var tapCount = 0 private var tapCount = 0
private var firstTapMillis: Long? = null private var firstTapMillis: Long? = null
@ -46,23 +48,28 @@ class AboutFragment : Fragment() {
} }
aboutData = requireArguments().getParcelable("ABOUT_DATA")!! aboutData = requireArguments().getParcelable("ABOUT_DATA")!!
binding = FragmentAboutBinding.inflate(inflater, container, false) _binding = FragmentAboutBinding.inflate(inflater, container, false)
updateData() updateData()
return binding!!.root return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.scrollView.setupBottomPadding()
} }
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
fun updateData() { fun updateData() {
// Update general info // Update general info
binding!!.appName.text = aboutData.name binding.appName.text = aboutData.name
binding!!.appIcon.setImageDrawable(this.context?.let { ContextCompat.getDrawable(it, aboutData.icon) }) binding.appIcon.setImageDrawable(this.context?.let { ContextCompat.getDrawable(it, aboutData.icon) })
binding!!.appVersion.text = this.context?.getString(R.string.version, aboutData.versionName) binding.appVersion.text = this.context?.getString(R.string.version, aboutData.versionName)
// Setup Easter Egg onClickListener // Setup Easter Egg onClickListener
binding!!.generalInfoCard.setOnClickListener { binding.generalInfoCard.setOnClickListener {
if (firstTapMillis == null) { if (firstTapMillis == null) {
firstTapMillis = System.currentTimeMillis() firstTapMillis = System.currentTimeMillis()
} }
@ -80,24 +87,24 @@ class AboutFragment : Fragment() {
// Update button onClickListeners // Update button onClickListeners
setupInfoButton(aboutData.bugURL, binding!!.reportBugButton) setupInfoButton(aboutData.bugURL, binding.reportBugButton)
setupInfoButton(aboutData.donateURL, binding!!.donateButton) setupInfoButton(aboutData.donateURL, binding.donateButton)
setupInfoButton(aboutData.sourceCodeURL, binding!!.sourceCodeButton) setupInfoButton(aboutData.sourceCodeURL, binding.sourceCodeButton)
binding!!.licensesButton.setOnClickListener { binding.licensesButton.setOnClickListener {
startActivity(Intent(context, LicensesActivity::class.java)) startActivity(Intent(context, LicensesActivity::class.java))
} }
binding!!.aboutKdeButton.setOnClickListener { binding.aboutKdeButton.setOnClickListener {
startActivity(Intent(context, AboutKDEActivity::class.java)) startActivity(Intent(context, AboutKDEActivity::class.java))
} }
setupInfoButton(aboutData.websiteURL, binding!!.websiteButton) setupInfoButton(aboutData.websiteURL, binding.websiteButton)
// Update authors // 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) { 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() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
binding = null _binding = null
} }
} }

View File

@ -10,17 +10,21 @@ import android.os.Bundle
import android.text.Html import android.text.Html
import android.text.Spanned import android.text.Spanned
import android.text.method.LinkMovementMethod 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.R
import org.kde.kdeconnect_tp.databinding.ActivityAboutKdeBinding import org.kde.kdeconnect_tp.databinding.ActivityAboutKdeBinding
class AboutKDEActivity : AppCompatActivity() { class AboutKDEActivity : BaseActivity<ActivityAboutKdeBinding>() {
override val binding: ActivityAboutKdeBinding by viewBinding(ActivityAboutKdeBinding::inflate)
override val isScrollable: Boolean = true
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val binding = ActivityAboutKdeBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(binding.toolbarLayout.toolbar) setSupportActionBar(binding.toolbarLayout.toolbar)
supportActionBar!!.setDisplayHomeAsUpEnabled(true) supportActionBar!!.setDisplayHomeAsUpEnabled(true)
supportActionBar!!.setDisplayShowHomeEnabled(true) supportActionBar!!.setDisplayShowHomeEnabled(true)
@ -34,6 +38,8 @@ class AboutKDEActivity : AppCompatActivity() {
binding.reportBugsOrWishesTextView.movementMethod = LinkMovementMethod.getInstance() binding.reportBugsOrWishesTextView.movementMethod = LinkMovementMethod.getInstance()
binding.joinKdeTextView.movementMethod = LinkMovementMethod.getInstance() binding.joinKdeTextView.movementMethod = LinkMovementMethod.getInstance()
binding.supportKdeTextView.movementMethod = LinkMovementMethod.getInstance() binding.supportKdeTextView.movementMethod = LinkMovementMethod.getInstance()
binding.scrollView.setupBottomPadding()
} }
private fun fromHtml(html: String): Spanned { private fun fromHtml(html: String): Spanned {

View File

@ -10,23 +10,26 @@ import android.os.Bundle
import android.util.DisplayMetrics import android.util.DisplayMetrics
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.LinearSmoothScroller import androidx.recyclerview.widget.LinearSmoothScroller
import org.apache.commons.io.IOUtils 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.R
import org.kde.kdeconnect_tp.databinding.ActivityLicensesBinding import org.kde.kdeconnect_tp.databinding.ActivityLicensesBinding
import java.nio.charset.Charset import java.nio.charset.Charset
class LicensesActivity : AppCompatActivity() { class LicensesActivity : BaseActivity<ActivityLicensesBinding>() {
private lateinit var binding: ActivityLicensesBinding
override val binding: ActivityLicensesBinding by viewBinding(ActivityLicensesBinding::inflate)
override val isScrollable: Boolean = true
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityLicensesBinding.inflate(layoutInflater) binding.licensesText.setupBottomPadding()
setContentView(binding.root)
setSupportActionBar(binding.toolbarLayout.toolbar) setSupportActionBar(binding.toolbarLayout.toolbar)
supportActionBar!!.setDisplayHomeAsUpEnabled(true) supportActionBar!!.setDisplayHomeAsUpEnabled(true)
supportActionBar!!.setDisplayShowHomeEnabled(true) supportActionBar!!.setDisplayShowHomeEnabled(true)

View File

@ -17,7 +17,6 @@ import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.TooltipCompat; import androidx.appcompat.widget.TooltipCompat;
import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
@ -28,6 +27,8 @@ import com.google.android.material.snackbar.BaseTransientBottomBar;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import org.kde.kdeconnect.DeviceHost; 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.R;
import org.kde.kdeconnect_tp.databinding.ActivityCustomDevicesBinding; import org.kde.kdeconnect_tp.databinding.ActivityCustomDevicesBinding;
@ -35,9 +36,11 @@ import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.Objects; import java.util.Objects;
import kotlin.Lazy;
import kotlin.LazyKt;
import kotlin.Unit; import kotlin.Unit;
public class CustomDevicesActivity extends AppCompatActivity implements CustomDevicesAdapter.Callback { public class CustomDevicesActivity extends BaseActivity<ActivityCustomDevicesBinding> implements CustomDevicesAdapter.Callback {
private static final String TAG_ADD_DEVICE_DIALOG = "AddDeviceDialog"; private static final String TAG_ADD_DEVICE_DIALOG = "AddDeviceDialog";
private static final String KEY_CUSTOM_DEVLIST_PREFERENCE = "device_list_preference"; 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 DeletedCustomDevice lastDeletedCustomDevice;
private int editingDeviceAtPosition; private int editingDeviceAtPosition;
private final Lazy<ActivityCustomDevicesBinding> lazyBinding = LazyKt.lazy(() -> ActivityCustomDevicesBinding.inflate(getLayoutInflater()));
@NonNull
@Override
protected ActivityCustomDevicesBinding getBinding() {
return lazyBinding.getValue();
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
final ActivityCustomDevicesBinding binding = ActivityCustomDevicesBinding.inflate(getLayoutInflater()); recyclerView = getBinding().recyclerView;
setContentView(binding.getRoot()); emptyListMessage = getBinding().emptyListMessage;
final FloatingActionButton fab = getBinding().floatingActionButton;
recyclerView = binding.recyclerView; setSupportActionBar(getBinding().toolbarLayout.toolbar);
emptyListMessage = binding.emptyListMessage;
final FloatingActionButton fab = binding.floatingActionButton;
setSupportActionBar(binding.toolbarLayout.toolbar);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true); Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true); getSupportActionBar().setDisplayShowHomeEnabled(true);
@ -86,6 +94,9 @@ public class CustomDevicesActivity extends AppCompatActivity implements CustomDe
recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL)); recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
recyclerView.setAdapter(customDevicesAdapter); recyclerView.setAdapter(customDevicesAdapter);
WindowHelper.setupBottomPadding(recyclerView);
WindowHelper.setupBottomMargin(getBinding().floatingActionButton);
addDeviceDialog = (EditTextAlertDialogFragment) getSupportFragmentManager().findFragmentByTag(TAG_ADD_DEVICE_DIALOG); addDeviceDialog = (EditTextAlertDialogFragment) getSupportFragmentManager().findFragmentByTag(TAG_ADD_DEVICE_DIALOG);
if (addDeviceDialog != null) { if (addDeviceDialog != null) {
addDeviceDialog.setCallback(new AddDeviceDialogCallback()); addDeviceDialog.setCallback(new AddDeviceDialogCallback());
@ -269,4 +280,9 @@ public class CustomDevicesActivity extends AppCompatActivity implements CustomDe
super.onBackPressed(); super.onBackPressed();
return true; return true;
} }
@Override
public boolean isScrollable() {
return true;
}
} }

View File

@ -44,6 +44,7 @@ import org.kde.kdeconnect.Plugins.Plugin
import org.kde.kdeconnect.Plugins.PresenterPlugin.PresenterPlugin import org.kde.kdeconnect.Plugins.PresenterPlugin.PresenterPlugin
import org.kde.kdeconnect.Plugins.RunCommandPlugin.RunCommandPlugin import org.kde.kdeconnect.Plugins.RunCommandPlugin.RunCommandPlugin
import org.kde.kdeconnect.UserInterface.compose.KdeTheme import org.kde.kdeconnect.UserInterface.compose.KdeTheme
import org.kde.kdeconnect.extensions.setupBottomPadding
import org.kde.kdeconnect_tp.R import org.kde.kdeconnect_tp.R
import org.kde.kdeconnect_tp.databinding.ActivityDeviceBinding import org.kde.kdeconnect_tp.databinding.ActivityDeviceBinding
import org.kde.kdeconnect_tp.databinding.ViewPairErrorBinding import org.kde.kdeconnect_tp.databinding.ViewPairErrorBinding
@ -156,6 +157,11 @@ class DeviceFragment : Fragment() {
return deviceBinding.root return deviceBinding.root
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
deviceBinding?.deviceView?.setupBottomPadding()
}
private fun refreshDevicesAction() { private fun refreshDevicesAction() {
BackgroundService.ForceRefreshConnections(requireContext()) BackgroundService.ForceRefreshConnections(requireContext())
requireErrorBinding().errorMessageContainer.isRefreshing = true requireErrorBinding().errorMessageContainer.isRefreshing = true

View File

@ -32,6 +32,7 @@ import androidx.fragment.app.Fragment;
import org.kde.kdeconnect.BackgroundService; import org.kde.kdeconnect.BackgroundService;
import org.kde.kdeconnect.Device; import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.Helpers.TrustedNetworkHelper; import org.kde.kdeconnect.Helpers.TrustedNetworkHelper;
import org.kde.kdeconnect.Helpers.WindowHelper;
import org.kde.kdeconnect.KdeConnect; import org.kde.kdeconnect.KdeConnect;
import org.kde.kdeconnect.UserInterface.List.ListAdapter; import org.kde.kdeconnect.UserInterface.List.ListAdapter;
import org.kde.kdeconnect.UserInterface.List.PairingDeviceItem; 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 // Configure focus order for Accessibility, for touchpads, and for TV remotes
// (allow focus of items in the device list) // (allow focus of items in the device list)
devicesListBinding.devicesList.setItemsCanFocus(true); devicesListBinding.devicesList.setItemsCanFocus(true);
WindowHelper.setupBottomPadding(devicesListBinding.devicesList);
} }
@Override @Override

View File

@ -13,8 +13,8 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
@ -24,12 +24,17 @@ import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.DeviceStats; import org.kde.kdeconnect.DeviceStats;
import org.kde.kdeconnect.KdeConnect; import org.kde.kdeconnect.KdeConnect;
import org.kde.kdeconnect.Plugins.Plugin; import org.kde.kdeconnect.Plugins.Plugin;
import org.kde.kdeconnect.base.BaseActivity;
import org.kde.kdeconnect_tp.R; import org.kde.kdeconnect_tp.R;
import org.kde.kdeconnect_tp.databinding.ActivityPluginSettingsBinding;
import java.util.Objects; import java.util.Objects;
import kotlin.Lazy;
import kotlin.LazyKt;
public class PluginSettingsActivity public class PluginSettingsActivity
extends AppCompatActivity extends BaseActivity<ActivityPluginSettingsBinding>
implements PluginPreference.PluginPreferenceCallback { implements PluginPreference.PluginPreferenceCallback {
public static final String EXTRA_DEVICE_ID = "deviceId"; public static final String EXTRA_DEVICE_ID = "deviceId";
@ -38,12 +43,18 @@ public class PluginSettingsActivity
//TODO: Save/restore state //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. 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<ActivityPluginSettingsBinding> lazyBinding = LazyKt.lazy(() -> ActivityPluginSettingsBinding.inflate(getLayoutInflater()));
@NonNull
@Override
protected ActivityPluginSettingsBinding getBinding() {
return lazyBinding.getValue();
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_plugin_settings);
setSupportActionBar(findViewById(R.id.toolbar)); setSupportActionBar(findViewById(R.id.toolbar));
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true); Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true); getSupportActionBar().setDisplayShowHomeEnabled(true);

View File

@ -34,6 +34,7 @@ import org.kde.kdeconnect.Helpers.DeviceHelper.filterName
import org.kde.kdeconnect.Helpers.DeviceHelper.getDeviceName import org.kde.kdeconnect.Helpers.DeviceHelper.getDeviceName
import org.kde.kdeconnect.Helpers.NotificationHelper import org.kde.kdeconnect.Helpers.NotificationHelper
import org.kde.kdeconnect.UserInterface.ThemeUtil.applyTheme import org.kde.kdeconnect.UserInterface.ThemeUtil.applyTheme
import org.kde.kdeconnect.extensions.setupBottomPadding
import org.kde.kdeconnect_tp.R import org.kde.kdeconnect_tp.R
class SettingsFragment : PreferenceFragmentCompat() { class SettingsFragment : PreferenceFragmentCompat() {
@ -62,6 +63,11 @@ class SettingsFragment : PreferenceFragmentCompat() {
preferenceScreen = screen preferenceScreen = screen
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
listView.setupBottomPadding()
}
private fun deviceNamePref(context: Context) = EditTextPreference(context).apply { private fun deviceNamePref(context: Context) = EditTextPreference(context).apply {
key = DeviceHelper.KEY_DEVICE_NAME_PREFERENCE key = DeviceHelper.KEY_DEVICE_NAME_PREFERENCE
isSelectable = true isSelectable = true

View File

@ -12,13 +12,14 @@ import android.view.View
import android.widget.* import android.widget.*
import android.widget.AdapterView.OnItemClickListener import android.widget.AdapterView.OnItemClickListener
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import org.kde.kdeconnect.Helpers.TrustedNetworkHelper 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.R
import org.kde.kdeconnect_tp.databinding.TrustedNetworkListBinding import org.kde.kdeconnect_tp.databinding.TrustedNetworkListBinding
class TrustedNetworksActivity : AppCompatActivity() { class TrustedNetworksActivity : BaseActivity<TrustedNetworkListBinding>() {
lateinit var binding: TrustedNetworkListBinding override val binding: TrustedNetworkListBinding by viewBinding(TrustedNetworkListBinding::inflate)
private val trustedNetworks: MutableList<String> = mutableListOf() private val trustedNetworks: MutableList<String> = mutableListOf()
private val trustedNetworksView: ListView private val trustedNetworksView: ListView
@ -39,9 +40,6 @@ class TrustedNetworksActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = TrustedNetworkListBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(binding.toolbarLayout.toolbar) setSupportActionBar(binding.toolbarLayout.toolbar)
supportActionBar!!.apply { supportActionBar!!.apply {
setDisplayHomeAsUpEnabled(true) setDisplayHomeAsUpEnabled(true)

View File

@ -0,0 +1,45 @@
/*
* SPDX-FileCopyrightText: 2024 Mash Kyrielight <fiepi@live.com>
*
* 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<VB: ViewBinding> : 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<MarginLayoutParams> {
bottomMargin = if (isScrollable) 0 else safeDrawInsets.bottom
leftMargin = safeDrawInsets.left
rightMargin = safeDrawInsets.right
}
}
}

View File

@ -0,0 +1,15 @@
/*
* SPDX-FileCopyrightText: 2024 Mash Kyrielight <fiepi@live.com>
*
* 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 <T : ViewBinding> AppCompatActivity.viewBinding(crossinline bindingInflater: (LayoutInflater) -> T) =
lazy(LazyThreadSafetyMode.NONE) {
bindingInflater.invoke(layoutInflater)
}

View File

@ -0,0 +1,63 @@
/*
* SPDX-FileCopyrightText: 2024 Mash Kyrielight <fiepi@live.com>
*
* 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<MarginLayoutParams> {
bottomMargin = originalBottomMargin + safeInsets.bottom
}
insets
}
}
fun Modifier.safeDrawPadding(): Modifier {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
safeDrawingPadding()
} else {
Modifier
}
}