FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

[Jetsurvey] Added take a photo feature by florina-muntenescu · Pull Request #279 · android/compose-samples · GitHub

Merged
2 changes: 2 additions & 0 deletions Jetsurvey/app/build.gradle
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ dependencies {
implementation Libs.AndroidX.Compose.runtime
implementation Libs.AndroidX.Compose.runtimeLivedata

implementation Libs.Accompanist.coil

androidTestImplementation Libs.junit
androidTestImplementation Libs.AndroidX.Test.core
androidTestImplementation Libs.AndroidX.Test.espressoCore
Expand Down
3 changes: 3 additions & 0 deletions Jetsurvey/app/src/main/AndroidManifest.xml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.compose.jetsurvey">

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.example.compose.jetsurvey.survey

import android.content.ContentValues
import android.content.Context
import android.provider.MediaStore

/**
* Manages the creation of photo Uris. The Uri is used to store the photos taken with camera.
*/
class PhotoUriManager(private val appContext: Context) {

private val photoCollection by lazy {
MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
}

private val resolver by lazy { appContext.contentResolver }

fun buildNewUri() = resolver.insert(photoCollection, buildPhotoDetails())

private fun buildPhotoDetails() = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, generateFilename())
put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
}

/**
* Create a unique file name based on the time the photo is taken
*/
private fun generateFilename() = "selfie-${System.currentTimeMillis()}.jpg"
}
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package com.example.compose.jetsurvey.survey

import android.graphics.Bitmap
import android.net.Uri
import androidx.annotation.StringRes

data class SurveyResult(
Expand Down Expand Up @@ -44,7 +44,7 @@ enum class SurveyActionType { PICK_DATE, TAKE_PHOTO, SELECT_CONTACT }

sealed class SurveyActionResult {
data class Date(val date: String) : SurveyActionResult()
data class Photo(val bitmap: Bitmap) : SurveyActionResult()
data class Photo(val uri: Uri) : SurveyActionResult()
data class Contact(val contact: String) : SurveyActionResult()
}

Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.activity.result.contract.ActivityResultContracts.TakePicture
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.Fragment
Expand All @@ -30,7 +31,15 @@ import com.google.android.material.datepicker.MaterialDatePicker

class SurveyFragment : Fragment() {

private val viewModel: SurveyViewModel by viewModels { SurveyViewModelFactory() }
private val viewModel: SurveyViewModel by viewModels {
SurveyViewModelFactory(PhotoUriManager(requireContext().applicationContext))
}

private val takePicture = registerForActivityResult(TakePicture()) { photoSaved ->
if (photoSaved) {
viewModel.onImageSaved()
}
}

override fun onCreateView(
inflater: LayoutInflater,
Expand Down Expand Up @@ -71,7 +80,7 @@ class SurveyFragment : Fragment() {
private fun handleSurveyAction(questionId: Int, actionType: SurveyActionType) {
when (actionType) {
SurveyActionType.PICK_DATE -> showDatePicker(questionId)
SurveyActionType.TAKE_PHOTO -> takeAPhoto(questionId)
SurveyActionType.TAKE_PHOTO -> takeAPhoto()
SurveyActionType.SELECT_CONTACT -> selectContact(questionId)
}
}
Expand All @@ -86,9 +95,8 @@ class SurveyFragment : Fragment() {
}
}

@Suppress("UNUSED_PARAMETER")
private fun takeAPhoto(questionId: Int) {
// TODO: unsupported for now
private fun takeAPhoto() {
takePicture.launch(viewModel.getUriToSaveImage())
Comment thread
florina-muntenescu marked this conversation as resolved.
}

@Suppress("UNUSED_PARAMETER")
Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@

package com.example.compose.jetsurvey.survey

import androidx.annotation.StringRes
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.ScrollableColumn
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
Expand All @@ -25,21 +27,29 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.preferredHeight
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.selection.selectable
import androidx.compose.material.AmbientContentAlpha
import androidx.compose.material.Button
import androidx.compose.material.Checkbox
import androidx.compose.material.CheckboxConstants
import androidx.compose.material.ContentAlpha
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.OutlinedButton
import androidx.compose.material.RadioButton
import androidx.compose.material.RadioButtonConstants
import androidx.compose.material.Slider
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AddAPhoto
import androidx.compose.material.icons.filled.SwapHoriz
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Providers
import androidx.compose.runtime.getValue
Expand All @@ -49,10 +59,12 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.unit.dp
import androidx.ui.tooling.preview.Preview
import com.example.compose.jetsurvey.R
import com.example.compose.jetsurvey.theme.JetsurveyTheme
import dev.chrisbanes.accompanist.coil.CoilImage

@Composable
fun Question(
Expand Down Expand Up @@ -258,27 +270,118 @@ private fun ActionQuestion(
onAction: (Int, SurveyActionType) -> Unit,
modifier: Modifier = Modifier
) {
Button(
onClick = { onAction(questionId, possibleAnswer.actionType) },
modifier = modifier.padding(vertical = 20.dp)
) {
Text(text = stringResource(id = possibleAnswer.label))
when (possibleAnswer.actionType) {
SurveyActionType.PICK_DATE -> {
DateQuestion(
questionId = questionId,
answerLabel = possibleAnswer.label,
answer = answer,
onAction = onAction,
modifier = modifier
)
}
SurveyActionType.TAKE_PHOTO -> {
PhotoQuestion(
questionId = questionId,
answer = answer,
onAction = onAction,
modifier = modifier
)
}
SurveyActionType.SELECT_CONTACT -> TODO()
}
if (answer != null) {
when (answer.result) {
is SurveyActionResult.Date -> {
}

@Composable
private fun PhotoQuestion(
questionId: Int,
answer: Answer.Action?,
onAction: (Int, SurveyActionType) -> Unit,
modifier: Modifier = Modifier
) {
val resource = if (answer != null) {
Icons.Filled.SwapHoriz
} else {
Icons.Filled.AddAPhoto
}
OutlinedButton(
onClick = { onAction(questionId, SurveyActionType.TAKE_PHOTO) },
modifier = modifier,
contentPadding = PaddingValues()
) {
Column {
if (answer != null && answer.result is SurveyActionResult.Photo) {
CoilImage(
Comment thread
florina-muntenescu marked this conversation as resolved.
data = answer.result.uri,
modifier = Modifier.fillMaxSize(),
fadeIn = true
)
} else {
PhotoDefaultImage(modifier = Modifier.padding(horizontal = 86.dp, vertical = 74.dp))
}
Row(
modifier = Modifier
.fillMaxWidth()
.wrapContentSize(Alignment.BottomCenter)
.padding(vertical = 26.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(resource)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = stringResource(R.string.selected_date, answer.result.date),
style = MaterialTheme.typography.h4,
modifier = Modifier.padding(vertical = 20.dp)
text = stringResource(
id = if (answer != null) {
R.string.retake_photo
} else {
R.string.add_photo
}
)
)
}
is SurveyActionResult.Photo -> TODO()
is SurveyActionResult.Contact -> TODO()
}
}
}

@Composable
private fun DateQuestion(
questionId: Int,
@StringRes answerLabel: Int,
answer: Answer.Action?,
onAction: (Int, SurveyActionType) -> Unit,
modifier: Modifier = Modifier
) {
Button(
onClick = { onAction(questionId, SurveyActionType.PICK_DATE) },
modifier = modifier.padding(vertical = 20.dp)
) {
Text(text = stringResource(id = answerLabel))
}

if (answer != null && answer.result is SurveyActionResult.Date) {
Text(
text = stringResource(R.string.selected_date, answer.result.date),
style = MaterialTheme.typography.h4,
modifier = Modifier.padding(vertical = 20.dp)
)
}
}

@Composable
private fun PhotoDefaultImage(
lightTheme: Boolean = MaterialTheme.colors.isLight,
modifier: Modifier = Modifier
) {
val assetId = if (lightTheme) {
R.drawable.ic_selfie_light
} else {
R.drawable.ic_selfie_dark
}
Image(
asset = vectorResource(id = assetId),
modifier = modifier
)
}

@Composable
private fun SliderQuestion(
possibleAnswer: PossibleAnswer.Slider,
Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@

package com.example.compose.jetsurvey.survey

import android.os.Build
import com.example.compose.jetsurvey.R
import com.example.compose.jetsurvey.survey.PossibleAnswer.Action
import com.example.compose.jetsurvey.survey.PossibleAnswer.MultipleChoice
import com.example.compose.jetsurvey.survey.PossibleAnswer.SingleChoice
import com.example.compose.jetsurvey.survey.SurveyActionType.PICK_DATE
import com.example.compose.jetsurvey.survey.SurveyActionType.TAKE_PHOTO

// Static data of questions
private val jetpackQuestions = listOf(
private val jetpackQuestions = mutableListOf(
Question(
id = 1,
questionText = R.string.in_my_free_time,
Expand Down Expand Up @@ -81,7 +83,19 @@ private val jetpackQuestions = listOf(
endText = R.string.selfie_max
)
)
)
).apply {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
// Add the camera feature only for devices 29+
add(
Question(
id = 975,
questionText = R.string.selfie_skills,
answer = Action(label = R.string.add_photo, actionType = TAKE_PHOTO)
)
)
}
}.toList()

private val jetpackSurvey = Survey(
title = R.string.which_jetpack_library,
questions = jetpackQuestions
Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Providers
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.savedinstancestate.savedInstanceState
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.annotatedString
Expand All @@ -61,9 +58,9 @@ fun SurveyQuestionsScreen(
onDonePressed: () -> Unit,
onBackPressed: () -> Unit
) {
var currentQuestionIndex by savedInstanceState { 0 }
val questionState =
remember(currentQuestionIndex) { questions.questionsState[currentQuestionIndex] }
val questionState = remember(questions.currentQuestionIndex) {
questions.questionsState[questions.currentQuestionIndex]
}

Surface(modifier = Modifier.fillMaxSize()) {
Scaffold(
Expand Down Expand Up @@ -91,8 +88,8 @@ fun SurveyQuestionsScreen(
bottomBar = {
SurveyBottomBar(
questionState = questionState,
onPreviousPressed = { currentQuestionIndex-- },
onNextPressed = { currentQuestionIndex++ },
onPreviousPressed = { questions.currentQuestionIndex-- },
onNextPressed = { questions.currentQuestionIndex++ },
onDonePressed = onDonePressed
)
}
Expand Down Expand Up @@ -157,9 +154,7 @@ private fun TopAppBarTitle(
val indexStyle = MaterialTheme.typography.caption.toSpanStyle().copy(
fontWeight = FontWeight.Bold
)
val totalStyle = MaterialTheme.typography.caption.toSpanStyle().copy(
fontWeight = FontWeight.SemiBold
)
val totalStyle = MaterialTheme.typography.caption.toSpanStyle()
val text = annotatedString {
withStyle(style = indexStyle) {
append("${questionIndex + 1}")
Expand Down
Loading

Back | FazBrowse Home | New Git URL