0
0
mirror of https://github.com/Ishan09811/pine.git synced 2025-04-28 09:35:08 +00:00

Merge branch 'master' into android-15-support

This commit is contained in:
Ishan09811 2024-12-26 19:28:08 +05:30 committed by GitHub
commit 6e3d14c00c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 327 additions and 37 deletions

View File

@ -1,6 +1,7 @@
name: CI
on:
workflow_dispatch:
push:
pull_request:
types: [opened, synchronize, reopened, labeled]

@ -1 +1 @@
Subproject commit 80dada6a7b455cf18c39788d70aa7711323ea977
Subproject commit 1055cb5e780c12fb2aab98949cc5a0d45f6ed0a1

View File

@ -165,6 +165,14 @@ extern "C" JNIEXPORT jboolean Java_emu_skyline_EmulationActivity_setSurface(JNIE
return true;
}
extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_pauseEmulation(JNIEnv *, jobject, jboolean pause) {
auto gpu = GpuWeak.lock();
if (!gpu) return;
if (pause) {
gpu->presentation.Pause();
} else gpu->presentation.Resume();
}
extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_changeAudioStatus(JNIEnv *, jobject, jboolean play) {
auto audio{AudioWeak.lock()};
if (audio)

View File

@ -209,7 +209,7 @@ namespace skyline::gpu {
static vk::raii::DebugReportCallbackEXT CreateDebugReportCallback(GPU *gpu, const vk::raii::Instance &instance) {
return vk::raii::DebugReportCallbackEXT(instance, vk::DebugReportCallbackCreateInfoEXT{
.flags = vk::DebugReportFlagBitsEXT::eError | vk::DebugReportFlagBitsEXT::eWarning | vk::DebugReportFlagBitsEXT::ePerformanceWarning | vk::DebugReportFlagBitsEXT::eInformation | vk::DebugReportFlagBitsEXT::eDebug,
.pfnCallback = reinterpret_cast<PFN_vkDebugReportCallbackEXT>(&DebugCallback),
.pfnCallback = reinterpret_cast<vk::PFN_DebugReportCallbackEXT>(&DebugCallback),
.pUserData = gpu,
});
}

View File

@ -74,7 +74,7 @@ namespace skyline::gpu {
auto result{(*gpu.vkDevice).allocateCommandBuffers(&commandBufferAllocateInfo, &commandBuffer, *gpu.vkDevice.getDispatcher())};
if (result != vk::Result::eSuccess)
vk::throwResultException(result, __builtin_FUNCTION());
vk::detail::throwResultException(result, __builtin_FUNCTION());
return {pool->buffers.emplace_back(gpu.vkDevice, commandBuffer, pool->vkCommandPool)};
}

View File

@ -70,11 +70,11 @@ namespace skyline::gpu {
if (pool->freeSetCount > 0)
pool->freeSetCount--;
return vk::createResultValue(result, descriptorSet, __builtin_FUNCTION(), {
vk::Result::eSuccess,
vk::Result::eErrorOutOfPoolMemory,
vk::Result::eErrorFragmentedPool
});
if (result == vk::Result::eSuccess) {
return vk::ResultValue<vk::DescriptorSet>(vk::Result::eSuccess, descriptorSet);
} else {
return vk::ResultValue<vk::DescriptorSet>(result, vk::DescriptorSet{});
}
}
DescriptorAllocator::ActiveDescriptorSet::ActiveDescriptorSet(std::shared_ptr<DescriptorPool> pPool, DescriptorSetSlot *slot) : pool{std::move(pPool)}, slot{slot} {}

View File

@ -5,6 +5,7 @@
#include <vulkan/vulkan_raii.hpp>
#include <common/spin_lock.h>
#include "vk_descriptor_set_layout_hash.hpp"
#include <common.h>
namespace skyline::gpu {

View File

@ -10,7 +10,7 @@ namespace skyline::gpu::memory {
*/
void ThrowOnFail(VkResult result, const char *function = __builtin_FUNCTION()) {
if (result != VK_SUCCESS)
vk::throwResultException(vk::Result(result), function);
vk::detail::throwResultException(vk::Result(result), function);
}
Buffer::~Buffer() {

View File

@ -24,7 +24,7 @@ namespace skyline::gpu::memory {
Buffer(const Buffer &) = delete;
constexpr Buffer(Buffer &&other)
Buffer(Buffer &&other)
: vmaAllocator(std::exchange(other.vmaAllocator, nullptr)),
vmaAllocation(std::exchange(other.vmaAllocation, nullptr)),
vkBuffer(std::exchange(other.vkBuffer, {})),
@ -94,7 +94,7 @@ namespace skyline::gpu::memory {
Image(const Image &) = delete;
constexpr Image(Image &&other)
Image(Image &&other)
: pointer(std::exchange(other.pointer, nullptr)),
vmaAllocator(std::exchange(other.vmaAllocator, nullptr)),
vmaAllocation(std::exchange(other.vmaAllocation, nullptr)),

View File

@ -21,6 +21,8 @@ extern jfloat AverageFrametimeDeviationMs;
namespace skyline::gpu {
using namespace service::hosbinder;
std::atomic<bool> paused{false};
PresentationEngine::PresentationEngine(const DeviceState &state, GPU &gpu)
: state{state},
gpu{gpu},
@ -76,7 +78,14 @@ namespace skyline::gpu {
try {
choreographerLooper = ALooper_prepare(0);
AChoreographer_postFrameCallback64(AChoreographer_getInstance(), reinterpret_cast<AChoreographer_frameCallback64>(&ChoreographerCallback), this);
while (ALooper_pollOnce(-1, nullptr, nullptr, nullptr) == ALOOPER_POLL_WAKE && !choreographerStop); // Will block and process callbacks till ALooper_wake() is called with choreographerStop set
while (ALooper_pollOnce(-1, nullptr, nullptr, nullptr) == ALOOPER_POLL_WAKE && !choreographerStop) {
while (paused.load(std::memory_order_acquire)) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
} catch (const signal::SignalException &e) {
LOGE("{}\nStack Trace:{}", e.what(), state.loader->GetStackTrace(e.frames));
if (state.process)
@ -235,6 +244,9 @@ namespace skyline::gpu {
try {
presentQueue.Process([this](const PresentableFrame &frame) {
while (paused.load(std::memory_order_acquire)) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
PresentFrame(frame);
frame.presentCallback(); // We're calling the callback here as it's outside of all the locks in PresentFrame
skipSignal = true;
@ -412,6 +424,16 @@ namespace skyline::gpu {
return nextFrameId++;
}
void PresentationEngine::Pause() {
paused.store(true, std::memory_order_release);
LOGI("PresentationEngine paused.");
}
void PresentationEngine::Resume() {
paused.store(false, std::memory_order_release);
LOGI("PresentationEngine resumed.");
}
NativeWindowTransform PresentationEngine::GetTransformHint() {
if (!vkSurface.has_value()) {
std::unique_lock lock{mutex};

View File

@ -115,6 +115,9 @@ namespace skyline::gpu {
*/
void UpdateSurface(jobject newSurface);
void Pause();
void Resume();
/**
* @brief Queue the supplied texture to be presented to the screen
* @param timestamp The earliest timestamp (relative to skyline::util::GetTickNs) at which the frame must be presented, it should be 0 when it doesn't matter

View File

@ -10,6 +10,7 @@
#include "common/trap_manager.h"
#include <gpu/tag_allocator.h>
#include <gpu/memory_manager.h>
#include <vulkan/vulkan_format_traits.hpp>
#include <gpu/usage_tracker.h>
namespace skyline::gpu {

View File

@ -0,0 +1,18 @@
#ifndef VK_DESCRIPTOR_SET_LAYOUT_HASH_HPP
#define VK_DESCRIPTOR_SET_LAYOUT_HASH_HPP
#include <vulkan/vulkan.hpp>
#include <unordered_map>
// Specialization of std::hash for vk::DescriptorSetLayout
namespace std {
template <>
struct hash<vk::DescriptorSetLayout> {
std::size_t operator()(const vk::DescriptorSetLayout &layout) const noexcept {
// Use the raw Vulkan handle for hashing
return std::hash<VkDescriptorSetLayout>()(static_cast<VkDescriptorSetLayout>(layout));
}
};
}
#endif // VK_DESCRIPTOR_SET_LAYOUT_HASH_HPP

View File

@ -33,6 +33,7 @@ import android.util.TypedValue
import android.view.*
import android.widget.Toast
import android.widget.PopupMenu
import android.widget.TextView
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
@ -41,6 +42,9 @@ import androidx.core.view.isGone
import androidx.core.view.isInvisible
import androidx.core.view.updateMargins
import androidx.core.view.updatePadding
import androidx.core.graphics.Insets
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.FragmentTransaction
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
@ -172,6 +176,8 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
*/
private external fun stopEmulation(join : Boolean) : Boolean
private external fun pauseEmulation(pause: Boolean)
/**
* This sets the surface object in libskyline to the provided value, emulation is halted if set to null
*
@ -308,7 +314,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
requestedOrientation = emulationSettings.orientation
window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
inputHandler = InputHandler(inputManager, emulationSettings)
setContentView(binding.root)
@ -445,11 +451,12 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
// No op
}
})
binding.inGameMenu.getHeaderView(0).findViewById<TextView>(R.id.game_title).text = item.title
binding.inGameMenu.setNavigationItemSelectedListener {
when (it.itemId) {
R.id.menu_emulation_resume -> {
if (isEmulatorPaused) {
pauseEmulator()
resumeEmulator()
it.title = resources.getString(R.string.pause_emulation)
it.icon = ResourcesCompat.getDrawable(
resources,
@ -457,7 +464,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
this.theme
)
} else {
resumeEmulator()
pauseEmulator()
it.title = resources.getString(R.string.resume_emulation)
it.icon = ResourcesCompat.getDrawable(
resources,
@ -493,21 +500,39 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
else -> true
}
}
setInsets()
executeApplication(intent!!)
}
private fun setInsets() {
ViewCompat.setOnApplyWindowInsetsListener(
binding.inGameMenu
) { v: View, windowInsets: WindowInsetsCompat ->
val cutInsets: Insets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
var left = 0
var right = 0
if (ViewCompat.getLayoutDirection(v) == ViewCompat.LAYOUT_DIRECTION_LTR) {
left = cutInsets.left
} else {
right = cutInsets.right
}
v.setPadding(left, cutInsets.top, right, 0)
windowInsets
}
}
@SuppressWarnings("WeakerAccess")
fun pauseEmulator() {
if (isEmulatorPaused) return
setSurface(null)
pauseEmulation(true)
changeAudioStatus(false)
isEmulatorPaused = true
}
@SuppressWarnings("WeakerAccess")
fun resumeEmulator() {
gameSurface?.let { setSurface(it) }
pauseEmulation(false)
changeAudioStatus(true)
isEmulatorPaused = false
}

View File

@ -12,13 +12,16 @@ import android.os.Bundle
import android.provider.DocumentsContract
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.view.ViewGroup.MarginLayoutParams
import androidx.activity.OnBackPressedCallback
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.res.use
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.documentfile.provider.DocumentFile
@ -27,6 +30,7 @@ import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.R as MaterialR
import com.google.android.material.color.MaterialColors
import dagger.hilt.android.AndroidEntryPoint
import emu.skyline.adapter.*
import emu.skyline.data.AppItem
@ -41,6 +45,7 @@ import emu.skyline.settings.SettingsActivity
import emu.skyline.utils.GpuDriverHelper
import emu.skyline.utils.SearchLocationHelper
import emu.skyline.utils.WindowInsetsHelper
import emu.skyline.SkylineApplication
import javax.inject.Inject
import kotlin.math.ceil
@ -147,6 +152,29 @@ class MainActivity : AppCompatActivity() {
window.decorView.findViewById<View>(android.R.id.content).viewTreeObserver.addOnTouchModeChangeListener { isInTouchMode ->
refreshIconVisible = !isInTouchMode
}
binding.statusBarShade.setBackgroundColor(
SkylineApplication.applyAlphaToColor(
MaterialColors.getColor(
binding.root,
MaterialR.attr.colorSurface
),
0.9f
)
)
if (SkylineApplication.detectNavigationType(this) != SkylineApplication.NAV_TYPE_GESTURE) {
binding.navigationBarShade.setBackgroundColor(
SkylineApplication.applyAlphaToColor(
MaterialColors.getColor(
binding.root,
MaterialR.attr.colorSurface
),
0.9f
)
)
}
setInsets()
}
private fun setAppListDecoration() {
@ -331,4 +359,20 @@ class MainActivity : AppCompatActivity() {
viewModel.checkRomHash(SearchLocationHelper.getSearchLocations(this), EmulationSettings.global.systemLanguage)
}
private fun setInsets() =
ViewCompat.setOnApplyWindowInsetsListener(
binding.root
) { _: View, windowInsets: WindowInsetsCompat ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
val mlpStatusShade = binding.statusBarShade.layoutParams as MarginLayoutParams
mlpStatusShade.height = insets.top
binding.statusBarShade.layoutParams = mlpStatusShade
val mlpNavShade = binding.navigationBarShade.layoutParams as MarginLayoutParams
mlpNavShade.height = insets.bottom
binding.navigationBarShade.layoutParams = mlpNavShade
windowInsets
}
}

View File

@ -7,11 +7,14 @@ package emu.skyline
import android.app.Application
import android.content.Context
import android.graphics.Color
import androidx.annotation.ColorInt
import com.google.android.material.color.DynamicColors
import com.google.android.material.color.DynamicColorsOptions
import dagger.hilt.android.HiltAndroidApp
import emu.skyline.di.getSettings
import java.io.File
import kotlin.math.roundToInt
/**
* @return The optimal directory for putting public files inside, this may return a private directory if a public directory cannot be retrieved
@ -29,6 +32,61 @@ class SkylineApplication : Application() {
private set
val context : Context get() = instance.applicationContext
const val NAV_TYPE_THREE_BUTTON = 0
const val NAV_TYPE_TWO_BUTTON = 1
const val NAV_TYPE_GESTURE = 2
/**
* Adjusts the opacity of a color by applying an alpha factor.
*
* @param color The original color (including alpha).
* @param alphaFactor A value between 0.0 (fully transparent) and 1.0 (no change in opacity).
* @return A new color with the adjusted opacity.
*/
@ColorInt
fun applyAlphaToColor(@ColorInt color: Int, alphaFactor: Float): Int {
val newAlpha = (Color.alpha(color) * alphaFactor).coerceIn(0f, 255f).roundToInt()
return Color.argb(
newAlpha,
Color.red(color),
Color.green(color),
Color.blue(color)
)
}
/**
* Determines the system navigation type.
*
* @param context The context used to access resources.
* @return An integer representing the navigation type:
* - 0: Three-button navigation
* - 1: Two-button navigation
* - 2: Gesture navigation
*/
fun detectNavigationType(context: Context): Int {
val navBarModeResource = context.resources.getIdentifier(
"config_navBarInteractionMode",
"integer",
"android"
)
return if (navBarModeResource != 0) {
try {
context.resources.getInteger(navBarModeResource)
} catch (e: Exception) {
NAV_TYPE_THREE_BUTTON // Fallback to default
}
} else {
NAV_TYPE_THREE_BUTTON // Fallback to default
}
}
fun setTheme(newValue: Boolean) {
val dynamicColorsOptions = DynamicColorsOptions.Builder().setPrecondition { _, _ -> newValue }.build()
DynamicColors.applyToActivitiesIfAvailable(instance, dynamicColorsOptions)
if (newValue == false) { instance.setTheme(R.style.AppTheme) }
}
}
override fun onCreate() {

View File

@ -20,6 +20,7 @@ import emu.skyline.MainActivity
import emu.skyline.R
import emu.skyline.utils.GpuDriverHelper
import emu.skyline.utils.WindowInsetsHelper
import emu.skyline.SkylineApplication
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -45,9 +46,10 @@ class GlobalSettingsFragment : PreferenceFragmentCompat() {
addPreferencesFromResource(R.xml.credits_preferences)
// Re-launch the app if Material You is toggled
findPreference<Preference>("use_material_you")?.setOnPreferenceChangeListener { _, _ ->
requireActivity().finishAffinity()
startActivity(Intent(requireContext(), MainActivity::class.java))
findPreference<Preference>("use_material_you")?.setOnPreferenceChangeListener { _, newValue ->
val isMaterialYouEnabled = newValue as Boolean
SkylineApplication.setTheme(isMaterialYouEnabled)
requireActivity().recreate()
true
}

View File

@ -8,14 +8,18 @@ package emu.skyline.settings
import android.annotation.SuppressLint
import android.os.Bundle
import android.text.TextUtils
import android.view.View
import android.view.KeyEvent
import android.view.Menu
import android.view.ViewTreeObserver
import android.view.ViewGroup.MarginLayoutParams
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SearchView
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.WindowCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.preference.EditTextPreference
import androidx.preference.ListPreference
import androidx.preference.Preference
@ -24,6 +28,8 @@ import androidx.preference.PreferenceFragmentCompat
import androidx.preference.forEach
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.internal.ToolbarUtils
import com.google.android.material.R as MaterialR
import com.google.android.material.color.MaterialColors
import emu.skyline.BuildConfig
import emu.skyline.R
import emu.skyline.data.AppItemTag
@ -33,6 +39,7 @@ import emu.skyline.preference.dialog.EditTextPreferenceMaterialDialogFragmentCom
import emu.skyline.preference.dialog.IntegerListPreferenceMaterialDialogFragmentCompat
import emu.skyline.preference.dialog.ListPreferenceMaterialDialogFragmentCompat
import emu.skyline.utils.WindowInsetsHelper
import emu.skyline.SkylineApplication
private const val PREFERENCE_DIALOG_FRAGMENT_TAG = "androidx.preference.PreferenceFragment.DIALOG"
@ -123,6 +130,29 @@ class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPrefere
.replace(R.id.settings, preferenceFragment)
.commit()
}
binding.statusBarShade.setBackgroundColor(
SkylineApplication.applyAlphaToColor(
MaterialColors.getColor(
binding.root,
MaterialR.attr.colorSurface
),
0.9f
)
)
if (SkylineApplication.detectNavigationType(this) != SkylineApplication.NAV_TYPE_GESTURE) {
binding.navigationBarShade.setBackgroundColor(
SkylineApplication.applyAlphaToColor(
MaterialColors.getColor(
binding.root,
MaterialR.attr.colorSurface
),
0.9f
)
)
}
setInsets()
}
override fun onCreateOptionsMenu(menu : Menu?) : Boolean {
@ -131,13 +161,13 @@ class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPrefere
val searchView = menuItem.actionView as SearchView
searchView.queryHint = getString(R.string.search)
searchView.setOnQueryTextFocusChangeListener { _, focus ->
/* searchView.setOnQueryTextFocusChangeListener { _, focus ->
(binding.titlebar.toolbar.layoutParams as AppBarLayout.LayoutParams).scrollFlags =
if (focus)
AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL
else
AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
}
}*/
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query : String) : Boolean {
@ -233,4 +263,20 @@ class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPrefere
else -> return false
}
}
private fun setInsets() =
ViewCompat.setOnApplyWindowInsetsListener(
binding.root
) { _: View, windowInsets: WindowInsetsCompat ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
val statusShade = binding.statusBarShade.layoutParams as MarginLayoutParams
statusShade.height = insets.top
binding.statusBarShade.layoutParams = statusShade
val navShade = binding.navigationBarShade.layoutParams as MarginLayoutParams
navShade.height = insets.bottom
binding.navigationBarShade.layoutParams = navShade
windowInsets
}
}

View File

@ -5,7 +5,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/drawer_layout"
android:background="@android:color/black"
android:keepScreenOn="true"
tools:context=".EmulationActivity"
tools:openDrawer="start"
@ -94,6 +93,7 @@
android:layout_height="match_parent"
android:layout_gravity="start"
android:focusedByDefault="true"
app:headerLayout="@layout/game_menu_header"
app:menu="@menu/menu_in_game"
tools:visibility="gone" />

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.textview.MaterialTextView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/game_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:textAppearance="?attr/textAppearanceHeadlineMedium"
android:textColor="?attr/colorOnSurface"
android:textAlignment="viewStart"
tools:text="Game Title" />

View File

@ -6,6 +6,15 @@
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".MainActivity">
<View
android:id="@+id/status_bar_shade"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@android:color/transparent"
android:clickable="false"
android:focusable="false"
android:layout_gravity="top" />
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar_layout"
@ -142,4 +151,12 @@
android:overScrollMode="ifContentScrolls"
android:paddingBottom="20dp" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<View
android:id="@+id/navigation_bar_shade"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@android:color/transparent"
android:clickable="false"
android:focusable="false"
android:layout_gravity="bottom" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -6,6 +6,15 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<View
android:id="@+id/status_bar_shade"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@android:color/transparent"
android:clickable="false"
android:focusable="false"
android:layout_gravity="top" />
<include
android:id="@+id/titlebar"
layout="@layout/titlebar" />
@ -15,4 +24,13 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<View
android:id="@+id/navigation_bar_shade"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@android:color/transparent"
android:clickable="false"
android:focusable="false"
android:layout_gravity="bottom" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,16 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.appbar.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:fitsSystemWindows="true"
app:elevation="0dp">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll" />
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:elevation="0dp">
<com.google.android.material.appbar.CollapsingToolbarLayout
style="?attr/collapsingToolbarLayoutMediumStyle"
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="?attr/collapsingToolbarLayoutMediumSize"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>

View File

@ -33,6 +33,8 @@
<style name="BaseAppTheme" parent="ColorAppTheme">
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:enforceStatusBarContrast">false</item>
<item name="android:enforceNavigationBarContrast">false</item>
<item name="chipChoiceStyle">@style/ChipChoice</item>
<!-- Workaround for AndroidX PreferenceScreen since it doesn't use MaterialAlertDialogs -->