From 7c1adf5f16b379a9ee0872410896c78c9c2c6678 Mon Sep 17 00:00:00 2001 From: Karavaev Date: Tue, 4 Nov 2025 17:33:41 +0300 Subject: [PATCH 1/2] Homework_Activity_3 --- app/build.gradle | 9 +- app/src/main/AndroidManifest.xml | 13 +- .../activities/EditProfileActivity.kt | 167 +++++++++++++++++- .../homework/activities/FillFormActivity.kt | 42 +++++ .../gpb/homework/activities/UserProfile.kt | 10 ++ .../activities/UserProfileContract.kt | 37 ++++ .../main/res/layout/activity_edit_profile.xml | 4 +- .../main/res/layout/activity_fill_form.xml | 60 +++++++ app/src/main/res/values/strings.xml | 10 ++ build.gradle | 4 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 11 files changed, 347 insertions(+), 11 deletions(-) create mode 100644 app/src/main/java/otus/gpb/homework/activities/FillFormActivity.kt create mode 100644 app/src/main/java/otus/gpb/homework/activities/UserProfile.kt create mode 100644 app/src/main/java/otus/gpb/homework/activities/UserProfileContract.kt create mode 100644 app/src/main/res/layout/activity_fill_form.xml diff --git a/app/build.gradle b/app/build.gradle index 57688408..1d240543 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,15 +2,16 @@ plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' id("io.gitlab.arturbosch.detekt") + id("kotlin-parcelize") } android { - compileSdk 34 + compileSdk 36 defaultConfig { applicationId "otus.gpb.homework.activities" minSdk 23 - targetSdk 34 + targetSdk 36 versionCode 1 versionName "1.0" @@ -54,10 +55,12 @@ tasks.named("detekt").configure { dependencies { implementation 'androidx.core:core-ktx:1.13.1' - implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'androidx.appcompat:appcompat:1.7.1' implementation 'com.google.android.material:material:1.12.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.activity:activity-ktx:1.9.0' implementation 'androidx.fragment:fragment-ktx:1.7.1' implementation 'com.squareup.picasso:picasso:2.71828' + implementation 'com.google.android.material:material:1.14.0-alpha05' + implementation 'androidx.activity:activity:1.11.0' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e3d3319b..68bd5476 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,13 @@ + + + + + - + tools:targetApi="36"> + diff --git a/app/src/main/java/otus/gpb/homework/activities/EditProfileActivity.kt b/app/src/main/java/otus/gpb/homework/activities/EditProfileActivity.kt index d55ee922..91356c67 100644 --- a/app/src/main/java/otus/gpb/homework/activities/EditProfileActivity.kt +++ b/app/src/main/java/otus/gpb/homework/activities/EditProfileActivity.kt @@ -1,20 +1,56 @@ package otus.gpb.homework.activities +import android.Manifest +import android.content.Intent +import android.content.pm.PackageManager import android.graphics.BitmapFactory import android.net.Uri import android.os.Bundle +import android.provider.Settings import android.widget.ImageView +import android.widget.TextView +import android.widget.Toast +import androidx.activity.result.contract.ActivityResultContracts +import androidx.activity.result.launch import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar +import androidx.core.content.ContextCompat +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import android.content.DialogInterface +import android.widget.Button +import androidx.core.content.res.ResourcesCompat +import androidx.activity.result.PickVisualMediaRequest +import androidx.activity.result.registerForActivityResult -class EditProfileActivity : AppCompatActivity() { +class EditProfileActivity : AppCompatActivity() { private lateinit var imageView: ImageView + private lateinit var editProfileButton: Button + private var repeatCameraAccessAttempt: Boolean = false + + private val ImageMethods by lazy { + arrayOf( + resources.getString(R.string.alert_dialog_create_foto), + resources.getString(R.string.alert_dialog_choose_foto) + ) + } + + private var selectedImageMethod = -1 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_edit_profile) imageView = findViewById(R.id.imageview_photo) + imageView.setOnClickListener { + Toast.makeText(this, "ФОТО!!!", Toast.LENGTH_SHORT).show() + dialogActionWithFoto.show() + } + + editProfileButton = findViewById(R.id.editProfileButton) + editProfileButton.setOnClickListener { + launcherFillUserInfo.launch() + } + findViewById(R.id.toolbar).apply { inflateMenu(R.menu.menu) @@ -30,6 +66,118 @@ class EditProfileActivity : AppCompatActivity() { } } + private val launcherFillUserInfo = registerForActivityResult(UserProfileContract()){ userInfo -> + userInfo?.name?.let { findViewById(R.id.textview_name).text = it } + userInfo?.surName?.let { findViewById(R.id.textview_surname).text = it } + userInfo?.age?.let { findViewById(R.id.textview_age).text = it.toString() } + } + private val launcherPermissionCamera = registerForActivityResult( + ActivityResultContracts.RequestPermission() + ) { granted -> + when { + granted -> { + Toast.makeText(this, "Доступ к камере получен! Снимаем фото!", Toast.LENGTH_SHORT).show() + setImageToImageView() + } + !shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> { + if( !repeatCameraAccessAttempt ){ + Toast.makeText(this, "Очень нужен доступ к камере, чтобы сделать фото!", Toast.LENGTH_SHORT).show() + openSettingsDialog.show() + } + } + else -> { + Toast.makeText(this, "Потом попробуешь еще раз...", Toast.LENGTH_SHORT).show() + repeatCameraAccessAttempt = true + } + } + } + + private val launcherGetPicture = registerForActivityResult( + ActivityResultContracts.TakePicturePreview() + ) { result -> + findViewById(R.id.imageview_photo).setImageBitmap(result) + } + + private fun setImageToImageView(){ + imageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.cat, null)) + } + + private val dialogActionWithFoto + get()= MaterialAlertDialogBuilder(this) + .setTitle(R.string.alert_dialog_title) + .setSingleChoiceItems(ImageMethods, -1) { _, which -> selectedImageMethod = which} + .setPositiveButton(R.string.alert_dialog_ok, ::onPositiveButtonActionWithFotoClickListener) + .setNegativeButton(R.string.alert_dialog_canceled) { dialog, _ -> + dialog.dismiss() + selectedImageMethod = -1 + } + .create() + + fun onPositiveButtonActionWithFotoClickListener(dialog: DialogInterface?, which: Int) { + when(selectedImageMethod){ + 0 -> { + val isGrantedCamera = ContextCompat.checkSelfPermission( + this, + Manifest.permission.CAMERA + ) == PackageManager.PERMISSION_GRANTED + if(isGrantedCamera){ + Toast.makeText(this, "Доступ к камере есть! Снимаем фото!", Toast.LENGTH_SHORT).show() + launcherGetPicture.launch() + } + else{ + Toast.makeText(this, "Доступа к камере нет! Запрашиваем!", Toast.LENGTH_SHORT).show() + if( repeatCameraAccessAttempt ){ + repeatCameraPermissionDialog.show() + } + else{ + launcherPermissionCamera.launch(Manifest.permission.CAMERA) + } + } + } + 1 -> { + selectPictureLauncher.launch( + PickVisualMediaRequest( + ActivityResultContracts.PickVisualMedia.ImageOnly + )) + } + } + dialog?.dismiss() + } + + private val repeatCameraPermissionDialog + get() = MaterialAlertDialogBuilder(this) + .setTitle(R.string.repeat_alert_dialog_title) + .setMessage("Необходим доступ к камере для создания аватара!!!") + .setPositiveButton(R.string.repeat_alert_dialog_get_access, ::onPositiveButtonRepeatCameraPermissionDialog) + .setNegativeButton(R.string.repeat_alert_dialog_canceled) { dialog, _ -> + dialog.dismiss() + } + .create() + + fun onPositiveButtonRepeatCameraPermissionDialog(dialog: DialogInterface?, which: Int) { + launcherPermissionCamera.launch(Manifest.permission.CAMERA) + repeatCameraAccessAttempt = false + } + + private val openSettingsDialog + get() = MaterialAlertDialogBuilder(this) + .setTitle(R.string.open_settings_dialog_title) + .setPositiveButton(R.string.open_settings_dialog_button, ::onPositiveButtonOpenSettingsDialog) + .create() + + fun onPositiveButtonOpenSettingsDialog(dialog: DialogInterface?, which: Int) { + val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { + data = Uri.fromParts("package", packageName, null) + } + startActivity(intent) + } + + private val selectPictureLauncher = registerForActivityResult( + ActivityResultContracts.PickVisualMedia() + ) { result -> + result?.let { populateImage(it) } + } + /** * Используйте этот метод чтобы отобразить картинку полученную из медиатеки в ImageView */ @@ -39,6 +187,21 @@ class EditProfileActivity : AppCompatActivity() { } private fun openSenderApp() { - TODO("В качестве реализации метода отправьте неявный Intent чтобы поделиться профилем. В качестве extras передайте заполненные строки и картинку") + val intent = Intent().apply { + action = Intent.ACTION_SEND + type = "image/*" + setPackage("org.telegram.messenger") + + val imgUri = imageView.tag as? Uri + if (imgUri != null) putExtra(Intent.EXTRA_STREAM, imgUri) + putExtra(Intent.EXTRA_TEXT, + "Имя : ${ findViewById(R.id.textview_name).text}\nФамилия: ${ findViewById(R.id.textview_surname).text}\nВозраст: ${ findViewById(R.id.textview_age).text}") + } + + runCatching { + startActivity(intent) + }.getOrElse { + Toast.makeText(this, "Ну удалось запустить Telegram!!!", Toast.LENGTH_SHORT).show() + } } } \ No newline at end of file diff --git a/app/src/main/java/otus/gpb/homework/activities/FillFormActivity.kt b/app/src/main/java/otus/gpb/homework/activities/FillFormActivity.kt new file mode 100644 index 00000000..569e2b4f --- /dev/null +++ b/app/src/main/java/otus/gpb/homework/activities/FillFormActivity.kt @@ -0,0 +1,42 @@ +package otus.gpb.homework.activities + +import android.os.Bundle +import android.widget.EditText +import androidx.activity.enableEdgeToEdge +import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import android.widget.Button +import android.content.Intent + +class FillFormActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + enableEdgeToEdge() + setContentView(R.layout.activity_fill_form) + ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> + val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) + v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) + insets + } + + findViewById