From 5ff7aa29ac17b4e6d1dcb5a57ab39f2f1bc5ddeb Mon Sep 17 00:00:00 2001 From: Andrey <an.i.petrow@gmail.com> Date: Thu, 20 Feb 2025 12:59:36 +0300 Subject: [PATCH] version3.5(with qrscan and creating user) --- .../ui/createemployee/CreateUserFragment.java | 38 +++ .../createemployee/CreateUserViewModel.java | 7 + .../work/ui/scan/QrScanDestination.kt | 30 +++ .../myitschool/work/ui/scan/QrScanFragment.kt | 139 ++++++++++ .../work/ui/scan/QrScanViewModel.kt | 93 +++++++ app/src/main/res/drawable/scanqr.png | Bin 409 -> 564 bytes .../main/res/layout/fragment_create_user.xml | 246 ++++++++++++++++++ app/src/main/res/values/strings.xml | 8 +- app/src/main/res/values/styles.xml | 26 +- 9 files changed, 584 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/ru/myitschool/work/ui/createemployee/CreateUserFragment.java create mode 100644 app/src/main/java/ru/myitschool/work/ui/createemployee/CreateUserViewModel.java create mode 100644 app/src/main/java/ru/myitschool/work/ui/scan/QrScanDestination.kt create mode 100644 app/src/main/java/ru/myitschool/work/ui/scan/QrScanFragment.kt create mode 100644 app/src/main/java/ru/myitschool/work/ui/scan/QrScanViewModel.kt create mode 100644 app/src/main/res/layout/fragment_create_user.xml diff --git a/app/src/main/java/ru/myitschool/work/ui/createemployee/CreateUserFragment.java b/app/src/main/java/ru/myitschool/work/ui/createemployee/CreateUserFragment.java new file mode 100644 index 0000000..083057a --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/createemployee/CreateUserFragment.java @@ -0,0 +1,38 @@ +package ru.myitschool.work.ui.createemployee; + +import androidx.lifecycle.ViewModelProvider; + +import android.os.Bundle; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import ru.myitschool.work.R; + +public class CreateUserFragment extends Fragment { + + private CreateUserViewModel mViewModel; + + public static CreateUserFragment newInstance() { + return new CreateUserFragment(); + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_create_user, container, false); + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + mViewModel = new ViewModelProvider(this).get(CreateUserViewModel.class); + // TODO: Use the ViewModel + } + +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/createemployee/CreateUserViewModel.java b/app/src/main/java/ru/myitschool/work/ui/createemployee/CreateUserViewModel.java new file mode 100644 index 0000000..822f03d --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/createemployee/CreateUserViewModel.java @@ -0,0 +1,7 @@ +package ru.myitschool.work.ui.createemployee; + +import androidx.lifecycle.ViewModel; + +public class CreateUserViewModel extends ViewModel { + // TODO: Implement the ViewModel +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/scan/QrScanDestination.kt b/app/src/main/java/ru/myitschool/work/ui/scan/QrScanDestination.kt new file mode 100644 index 0000000..7e34b28 --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/scan/QrScanDestination.kt @@ -0,0 +1,30 @@ +package ru.myitschool.work.ui.qr.scan + +import android.os.Bundle +import androidx.core.os.bundleOf +import kotlinx.serialization.Serializable + +// НЕ ИЗМЕНЯЙТЕ ЭТОТ ФАЙЛ. В ТЕСТАХ ОН БУДЕМ ВОЗВРАЩЁН В ИСХОДНОЕ СОСТОЯНИЕ +@Serializable +data object QrScanDestination { + const val REQUEST_KEY = "qr_result" + private const val KEY_QR_DATA = "key_qr" + + fun newInstance(): QrScanFragment { + return QrScanFragment() + } + + fun getDataIfExist(bundle: Bundle): String? { + return if (bundle.containsKey(KEY_QR_DATA)) { + bundle.getString(KEY_QR_DATA) + } else { + null + } + } + + internal fun packToBundle(data: String): Bundle { + return bundleOf( + KEY_QR_DATA to data + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/scan/QrScanFragment.kt b/app/src/main/java/ru/myitschool/work/ui/scan/QrScanFragment.kt new file mode 100644 index 0000000..a9ddaab --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/scan/QrScanFragment.kt @@ -0,0 +1,139 @@ +package ru.myitschool.work.ui.qr.scan + +import android.os.Bundle +import android.view.View +import androidx.activity.result.contract.ActivityResultContracts +import androidx.camera.core.ImageAnalysis +import androidx.camera.mlkit.vision.MlKitAnalyzer +import androidx.camera.view.LifecycleCameraController +import androidx.camera.view.PreviewView +import androidx.core.content.ContextCompat +import androidx.core.os.bundleOf +import androidx.fragment.app.Fragment +import androidx.fragment.app.setFragmentResult +import androidx.fragment.app.viewModels +import androidx.navigation.NavController +import androidx.navigation.fragment.findNavController +import com.google.mlkit.vision.barcode.BarcodeScanner +import com.google.mlkit.vision.barcode.BarcodeScannerOptions +import com.google.mlkit.vision.barcode.BarcodeScanning +import com.google.mlkit.vision.barcode.common.Barcode +import ru.myitschool.work.R +import ru.myitschool.work.databinding.FragmentQrScanBinding +import ru.myitschool.work.utils.collectWhenStarted +import ru.myitschool.work.utils.visibleOrGone + +// НЕ ИЗМЕНЯЙТЕ ЭТОТ ФАЙЛ. В ТЕСТАХ ОН БУДЕМ ВОЗВРАЩЁН В ИСХОДНОЕ СОСТОЯНИЕ +class QrScanFragment : Fragment(R.layout.fragment_qr_scan) { + private var _binding: FragmentQrScanBinding? = null + private val binding: FragmentQrScanBinding get() = _binding!! + + private var barcodeScanner: BarcodeScanner? = null + private var isCameraInit: Boolean = false + private val permissionLauncher = registerForActivityResult( + ActivityResultContracts.RequestPermission() + ) { isGranted -> viewModel.onPermissionResult(isGranted) } + + private val viewModel: QrScanViewModel by viewModels() + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + _binding = FragmentQrScanBinding.bind(view) + sendResult(bundleOf()) + subscribe() + initCallback() + } + + private fun initCallback() { + binding.close.setOnClickListener { viewModel.close() } + } + + private fun subscribe() { + viewModel.state.collectWhenStarted(this) { state -> + binding.loading.visibleOrGone(state is QrScanViewModel.State.Loading) + binding.viewFinder.visibleOrGone(state is QrScanViewModel.State.Scan) + if (!isCameraInit && state is QrScanViewModel.State.Scan) { + startCamera() + isCameraInit = true + } + } + + viewModel.action.collectWhenStarted(this) { action -> + when (action) { + is QrScanViewModel.Action.RequestPermission -> requestPermission(action.permission) + is QrScanViewModel.Action.CloseWithCancel -> { + goBack() + } + is QrScanViewModel.Action.CloseWithResult -> { + sendResult(QrScanDestination.packToBundle(action.result)) + goBack() + } + } + } + } + + private fun requestPermission(permission: String) { + permissionLauncher.launch(permission) + } + + private fun startCamera() { + val context = requireContext() + val cameraController = LifecycleCameraController(context) + val previewView: PreviewView = binding.viewFinder + val executor = ContextCompat.getMainExecutor(context) + + val options = BarcodeScannerOptions.Builder() + .setBarcodeFormats(Barcode.FORMAT_QR_CODE) + .build() + val barcodeScanner = BarcodeScanning.getClient(options) + this.barcodeScanner = barcodeScanner + + cameraController.setImageAnalysisAnalyzer( + executor, + MlKitAnalyzer( + listOf(barcodeScanner), + ImageAnalysis.COORDINATE_SYSTEM_VIEW_REFERENCED, + executor + ) { result -> + result?.getValue(barcodeScanner)?.firstOrNull()?.let { value -> + viewModel.findBarcode(value) + + } + } + ) + + cameraController.bindToLifecycle(this) + previewView.controller = cameraController + } + + override fun onDestroyView() { + barcodeScanner?.close() + barcodeScanner = null + _binding = null + super.onDestroyView() + } + + private fun goBack() { + findNavControllerOrNull()?.popBackStack() + ?: requireActivity().onBackPressedDispatcher.onBackPressed() + } + + private fun sendResult(bundle: Bundle) { + setFragmentResult( + QrScanDestination.REQUEST_KEY, + bundle + ) + findNavControllerOrNull() + ?.previousBackStackEntry + ?.savedStateHandle + ?.set(QrScanDestination.REQUEST_KEY, bundle) + } + + private fun findNavControllerOrNull(): NavController? { + return try { + findNavController() + } catch (_: Throwable) { + null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/scan/QrScanViewModel.kt b/app/src/main/java/ru/myitschool/work/ui/scan/QrScanViewModel.kt new file mode 100644 index 0000000..14565ab --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/scan/QrScanViewModel.kt @@ -0,0 +1,93 @@ +package ru.myitschool.work.ui.qr.scan + +import android.Manifest +import android.app.Application +import android.content.pm.PackageManager +import androidx.core.content.ContextCompat +import androidx.lifecycle.AndroidViewModel +import androidx.lifecycle.viewModelScope +import com.google.mlkit.vision.barcode.common.Barcode +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import ru.myitschool.work.utils.MutablePublishFlow + +// НЕ ИЗМЕНЯЙТЕ ЭТОТ ФАЙЛ. В ТЕСТАХ ОН БУДЕМ ВОЗВРАЩЁН В ИСХОДНОЕ СОСТОЯНИЕ +class QrScanViewModel( + application: Application +) : AndroidViewModel(application) { + + private val _action = MutablePublishFlow<Action>() + val action = _action.asSharedFlow() + + private val _state = MutableStateFlow<State>(initialState) + val state = _state.asStateFlow() + + init { + checkPermission() + } + + fun onPermissionResult(isGranted: Boolean) { + viewModelScope.launch { + if (isGranted) { + _state.update { State.Scan } + } else { + _action.emit(Action.CloseWithCancel) + } + } + } + + private fun checkPermission() { + viewModelScope.launch { + val isPermissionGranted = ContextCompat.checkSelfPermission( + getApplication(), + CAMERA_PERMISSION + ) == PackageManager.PERMISSION_GRANTED + if (isPermissionGranted) { + _state.update { State.Scan } + } else { + delay(1000) + _action.emit(Action.RequestPermission(CAMERA_PERMISSION)) + } + } + } + + fun findBarcode(barcode: Barcode) { + viewModelScope.launch { + barcode.rawValue?.let { value -> + _action.emit(Action.CloseWithResult(value)) + } + } + } + + fun close() { + viewModelScope.launch { + _action.emit(Action.CloseWithCancel) + } + } + + sealed interface State { + data object Loading : State + + data object Scan : State + } + + sealed interface Action { + data class RequestPermission( + val permission: String + ) : Action + data object CloseWithCancel : Action + data class CloseWithResult( + val result: String + ) : Action + } + + private companion object { + val initialState = State.Loading + + const val CAMERA_PERMISSION = Manifest.permission.CAMERA + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/scanqr.png b/app/src/main/res/drawable/scanqr.png index 88b90251089968efaa50da47b495c8a7e8ead8ad..9f36ac69f9b4b8477c4c0a1a8dfa68588324bc4b 100644 GIT binary patch delta 488 zcmV<E0T=$61GEH?R)5J!L_t(|0mYQfE<;fe$LF@!SAtTKQV$@Ajo5etZ{a0~9f^g+ z-Xqvrkl1*DlBf_N*oZ`k&-kcTg0}wC`#-(Y=2n_mnB<q9Gw06NnKKpn2k{!LoBDVJ z%zzK>V_=cLW&SRJ5^dVS8aU>8jl*$p1kR0vPLSZQN&)1-BY%j4PcTMKol_?(jASLw zj|M@S>-w_KXj_q(InXj&xK_g~@VPI7Z?0RxzJ%GtXj>8AIMm4QZVo_38aE_k9F}Zi z)}bo<XgEb(+BkC=YWcHV>y>m#ME5<GQeb4uhWTzY;{2V-cv9!tXBL`OkviQ!NqDzk zU_iohHNzWYTYu9OCpNlobVUYJn+FM=js{49wz}l1k2wEJ$wNlhOWiB?tF}y+!4h}@ z-A1n&T}aR@`)G6K3S2@p4xQ5+OWOrIV2)>cSGOQ3K@+Yem>`|5I|(L6otCY`l8H1) zCsy?And>Bz(URY&tBk8{N{57Hsqq9OyA0KdUdcTe24VeRo0-o`I22VGr9+)({e#e9 z*KWG8N=ew11a(*3FN=xnM4!PrGd%<+63py0%h3#az#iC=;I8$3W|`@wMBGu7coFCB enKfhoH~9g>#e5(gALgb20000<MNUMnLSTX&RO{>j delta 332 zcmV-S0ki(J1epVnR(~!@L_t(|0nL;>PQySDg~yR;ffK|H2q_(bJ5ck}asW6`=n-^W zfJ=l9glI@^ke@DAoHy~?WSs0IajHD&lkMGkv)<VskwaHv-cyi+D{u!UTYMV-0ltj4 zl2G*u9>FjB5+`B71TFAJ&zi0on91(S=(!AoH%#X(_y#@DVSixYnAo-sV|6wUY@5$L zC^z3v;D!bb9I?H{?<V*J&-}ARy=}rms_Juek!3A^BC(Y^r{XKwFj(Q4yo6e>vH1D} zr?HNPWAL_%)wE8+0XP$17hqT?;kG_kwuU-QTkOoVht)pkvuWZAF(pc!<S$b0v!Iie z#34qNi?g_G*+u{8wPSzPmGYqfOL+u0?a@#gU7UA%=ZallI@&$oy$!6sBPp-1uJJ|# e>uMj*?wSF%Swb#RZEb`A0000<MNUMnLSTZ*HlNr4 diff --git a/app/src/main/res/layout/fragment_create_user.xml b/app/src/main/res/layout/fragment_create_user.xml new file mode 100644 index 0000000..fdd9355 --- /dev/null +++ b/app/src/main/res/layout/fragment_create_user.xml @@ -0,0 +1,246 @@ +<?xml version="1.0" encoding="utf-8"?> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + xmlns:app="http://schemas.android.com/apk/res-auto" + tools:context=".ui.createemployee.CreateUserFragment" + android:background="@drawable/background"> + + <RelativeLayout + android:layout_width="fill_parent" + android:layout_height="fill_parent"> + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="60dp" + android:layout_alignParentStart="true" + android:layout_alignParentEnd="true" + android:layout_marginStart="0dp" + android:layout_marginEnd="0dp" + android:orientation="horizontal"> + + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:layout_marginLeft="5dp" + android:background="@drawable/ic_user" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="30dp" + android:layout_gravity="center" + android:layout_marginLeft="10dp" + android:text="@string/addEmployee" + android:textSize="25dp" /> + + </LinearLayout> + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/name_create_lay" + android:layout_width="10dp" + android:layout_height="40dp" + android:layout_alignParentStart="true" + android:layout_alignParentTop="true" + android:layout_alignParentEnd="true" + android:layout_marginStart="70dp" + android:layout_marginTop="119dp" + android:layout_marginEnd="70dp" + app:shapeAppearance="@style/rounded"> + + <com.google.android.material.textfield.TextInputEditText + android:id="@+id/name_create" + android:layout_width="match_parent" + android:layout_height="40dp" + android:hint="Имя" + android:background="#FFFFFF" /> + + </com.google.android.material.textfield.TextInputLayout> + + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/surname_create_lay" + android:layout_width="10dp" + android:layout_height="40dp" + android:layout_below="@+id/name_create_lay" + android:layout_alignParentStart="true" + android:layout_alignParentEnd="true" + android:layout_marginStart="70dp" + android:layout_marginTop="20dp" + android:layout_marginEnd="70dp" + app:shapeAppearance="@style/rounded"> + + <com.google.android.material.textfield.TextInputEditText + android:id="@+id/surname_create" + android:layout_width="match_parent" + android:layout_height="40dp" + android:hint="Фамилия" + android:background="#FFFFFF"/> + + </com.google.android.material.textfield.TextInputLayout> + + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/patronomic_create_lay" + android:layout_width="10dp" + android:layout_height="40dp" + android:layout_below="@+id/surname_create_lay" + android:layout_alignParentStart="true" + android:layout_alignParentEnd="true" + android:layout_marginStart="70dp" + android:layout_marginTop="20dp" + android:layout_marginEnd="70dp" + app:shapeAppearance="@style/rounded"> + + <com.google.android.material.textfield.TextInputEditText + android:id="@+id/patronomic_create" + android:layout_width="match_parent" + android:layout_height="40dp" + android:hint="Отчество" + android:background="#FFFFFF"/> + + </com.google.android.material.textfield.TextInputLayout> + + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/telephone_create_lay" + android:layout_width="10dp" + android:layout_height="40dp" + android:layout_below="@+id/patronomic_create_lay" + android:layout_alignParentStart="true" + android:layout_alignParentEnd="true" + android:layout_marginStart="70dp" + android:layout_marginTop="20dp" + android:layout_marginEnd="70dp" + app:shapeAppearance="@style/rounded"> + + <com.google.android.material.textfield.TextInputEditText + android:id="@+id/telephone_create" + android:layout_width="match_parent" + android:layout_height="40dp" + android:hint="Телефон" + android:background="#FFFFFF"/> + + </com.google.android.material.textfield.TextInputLayout> + + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/email_create_lay" + android:layout_width="10dp" + android:layout_height="40dp" + android:layout_below="@+id/telephone_create_lay" + android:layout_alignParentStart="true" + android:layout_alignParentEnd="true" + android:layout_marginStart="70dp" + android:layout_marginTop="20dp" + android:layout_marginEnd="70dp" + app:shapeAppearance="@style/rounded"> + + <com.google.android.material.textfield.TextInputEditText + android:id="@+id/email_create" + android:layout_width="match_parent" + android:layout_height="40dp" + android:hint="Электронная почта" + android:background="#FFFFFF"/> + + </com.google.android.material.textfield.TextInputLayout> + + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/password_create_lay" + android:layout_width="10dp" + android:layout_height="40dp" + android:layout_below="@+id/email_create_lay" + android:layout_alignParentStart="true" + android:layout_alignParentEnd="true" + android:layout_marginStart="70dp" + android:layout_marginTop="20dp" + android:layout_marginEnd="70dp" + app:shapeAppearance="@style/rounded"> + + <com.google.android.material.textfield.TextInputEditText + android:id="@+id/password_create" + android:layout_width="match_parent" + android:layout_height="40dp" + android:hint="Пароль" + android:background="#FFFFFF"/> + + </com.google.android.material.textfield.TextInputLayout> + + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/officename_create_lay" + android:layout_width="10dp" + android:layout_height="40dp" + android:layout_below="@+id/password_create_lay" + android:layout_alignParentStart="true" + android:layout_alignParentEnd="true" + android:layout_marginStart="70dp" + android:layout_marginTop="20dp" + android:layout_marginEnd="70dp" + app:shapeAppearance="@style/rounded"> + + <com.google.android.material.textfield.TextInputEditText + android:id="@+id/officename_create" + android:layout_width="match_parent" + android:layout_height="40dp" + android:hint="Название офиса" + android:background="#FFFFFF"/> + + </com.google.android.material.textfield.TextInputLayout> + + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/possition_create_lay" + android:layout_width="10dp" + android:layout_height="40dp" + android:layout_below="@+id/officename_create_lay" + android:layout_alignParentStart="true" + android:layout_alignParentEnd="true" + android:layout_marginStart="70dp" + android:layout_marginTop="20dp" + android:layout_marginEnd="70dp" + app:shapeAppearance="@style/rounded"> + + <com.google.android.material.textfield.TextInputEditText + android:id="@+id/position_create" + android:layout_width="match_parent" + android:layout_height="40dp" + android:hint="Должность" + android:background="#FFFFFF"/> + + </com.google.android.material.textfield.TextInputLayout> + + + <Spinner + android:id="@+id/role_create_lay" + android:layout_width="10dp" + android:layout_height="40dp" + android:layout_below="@+id/possition_create_lay" + android:layout_alignParentStart="true" + android:layout_alignParentEnd="true" + android:layout_marginStart="70dp" + android:layout_marginTop="20dp" + android:layout_marginEnd="70dp" + android:background="@color/white" /> + + + <com.google.android.material.button.MaterialButton + android:id="@+id/button_create_lay" + android:layout_width="10dp" + android:layout_height="40dp" + android:layout_below="@+id/role_create_lay" + android:layout_alignParentStart="true" + android:layout_alignParentEnd="true" + android:layout_marginStart="70dp" + android:layout_marginTop="40dp" + android:layout_marginEnd="70dp" + android:text="Создать" + android:backgroundTint="#B1CFBB" + android:textColor="@color/black" + app:shapeAppearance="@style/rounded"/> + + </RelativeLayout> + +</FrameLayout> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 488b1b5..5c4f34a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -23,7 +23,7 @@ <string name="profile">Профиль</string> <string name="office">Офис</string> <string name="scaning">Сканировать</string> - <!-- TODO: Remove or change this placeholder text --> + <string name="hello_blank_fragment">Hello blank fragment</string> <string name="info">Информация о сотруднике</string> <string name="redact">Редактировать</string> @@ -40,4 +40,10 @@ <string name="contacts">Контакты</string> <string name="description">Описание</string> <string name="createEmployee">Создать сотрудника</string> + <string name="addEmployee">Добавить сотрудника</string> + + <string-array name="roles"> + <item>Админ</item> + <item>Пользователь</item> + </string-array> </resources> \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 1364cd4..cb94d3a 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,7 +1,29 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - <style name="Circle" - parent=""> + <style name="Widget.Theme.MyApplication.ButtonBar.Fullscreen" parent=""> + <item name="android:background">@color/black</item> + <item name="android:buttonBarStyle">?android:attr/buttonBarStyle</item> + </style> + + <style name="App.Custom.Indicator" parent="Widget.Material3.BottomNavigationView.ActiveIndicator"> + <item name="android:color">@color/white</item> + </style> + + <style name="rounded" parent="ShapeAppearance.MaterialComponents.SmallComponent"> + <item name="cornerFamily">rounded</item> + <item name="cornerSize">20dp</item> + </style> + + <style name="roundedImageView" parent=""> + <item name="cornerFamily">rounded</item> + <item name="cornerSize">16dp</item> + </style> + <style name="roundedImageViewSmall" parent=""> + <item name="cornerFamily">rounded</item> + <item name="cornerSize">6dp</item> + </style> + + <style name="circleImageView" parent=""> <item name="cornerFamily">rounded</item> <item name="cornerSize">50%</item> </style>