diff --git a/.idea/misc.xml b/.idea/misc.xml
index 1388f5f..67920b0 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -15,6 +15,7 @@
+
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index f7c9770..dc41d57 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -20,8 +20,7 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.QuestionForm">
-
-
+
diff --git a/app/src/main/java/com/example/questionform/MainActivity.kt b/app/src/main/java/com/example/questionform/MainActivity.kt
index 5fca0f4..7a7a1d1 100644
--- a/app/src/main/java/com/example/questionform/MainActivity.kt
+++ b/app/src/main/java/com/example/questionform/MainActivity.kt
@@ -10,6 +10,7 @@ import android.widget.ArrayAdapter
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider.getUriForFile
+import androidx.core.net.toFile
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.canhub.cropper.CropImage
@@ -133,7 +134,13 @@ class MainActivity : AppCompatActivity() {
ImageQuestion(
faker.hobbit().quote(), id = faker.crypto().md5(),
mandatory = faker.bool().bool(),
- done = faker.bool().bool()
+ done = faker.bool().bool(),
+ value = if (faker.bool().bool()) listOf(
+ faker.avatar().image(),
+ faker.avatar().image(),
+ "https://storage.googleapis.com/gweb-uniblog-publish-prod/images/Chrome__logo.max-500x500.png",
+ ""
+ ).toMutableList() else mutableListOf()
)
)
@@ -141,7 +148,8 @@ class MainActivity : AppCompatActivity() {
VideoQuestion(
faker.backToTheFuture().quote(), id = faker.crypto().md5(),
mandatory = faker.bool().bool(),
- done = faker.bool().bool()
+ done = faker.bool().bool(),
+ value = "https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/720/Big_Buck_Bunny_720_10s_1MB.mp4"
)
)
@@ -149,7 +157,8 @@ class MainActivity : AppCompatActivity() {
AudioQuestion(
title = faker.gameOfThrones().quote(), id = faker.crypto().md5(),
mandatory = faker.bool().bool(),
- done = faker.bool().bool()
+ done = faker.bool().bool(),
+ value = "https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_2MG.mp3"
)
)
@@ -247,7 +256,7 @@ class MainActivity : AppCompatActivity() {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 43) {
if (resultCode == RESULT_OK) {
- questionAdapter.updatePickedVideo(videoFile)
+ questionAdapter.updatePickedVideo(videoFile.path)
}
}
if (requestCode == 42) {
@@ -259,24 +268,11 @@ class MainActivity : AppCompatActivity() {
if (resultCode == RESULT_OK) {
val recordFile: Uri? = data?.getParcelableExtra("recordPath")
val position = data?.getIntExtra("position", -1) ?: -1
- recordFile.log()
- position.log()
- questionAdapter.addRecordFile(recordFile, position)
+ questionAdapter.addRecordFile(recordFile?.path, position)
}
}
- if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
- val result = CropImage.getActivityResult(data)
- if (resultCode == Activity.RESULT_OK) {
- result?.also {
- questionAdapter.updateImageAdapterAtPosition(
- it.originalUri.toString()
- )
- }
- } else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
- val error = result!!.error
- }
- }
+
}
override fun onRequestPermissionsResult(
diff --git a/form/build.gradle b/form/build.gradle
index 8bc6f01..f15aeaf 100644
--- a/form/build.gradle
+++ b/form/build.gradle
@@ -45,6 +45,5 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation 'com.squareup.picasso:picasso:2.71828'
- implementation ("com.github.CanHub:Android-Image-Cropper:3.1.1")
}
\ No newline at end of file
diff --git a/form/src/main/java/com/m7mdra/questionForm/ImageAdapter.kt b/form/src/main/java/com/m7mdra/questionForm/ImageAdapter.kt
index 9424890..ab9b96d 100644
--- a/form/src/main/java/com/m7mdra/questionForm/ImageAdapter.kt
+++ b/form/src/main/java/com/m7mdra/questionForm/ImageAdapter.kt
@@ -1,13 +1,22 @@
package com.m7mdra.questionForm
+import android.content.Context
+import android.graphics.Bitmap
import android.view.LayoutInflater
import android.view.ViewGroup
+import android.webkit.URLUtil
import androidx.recyclerview.widget.RecyclerView
import com.m7mdra.questionForm.viewholder.RowImageViewHolder
+import com.squareup.picasso.Cache
+import com.squareup.picasso.LruCache
+import com.squareup.picasso.OkHttp3Downloader
import com.squareup.picasso.Picasso
import java.io.File
-class ImageAdapter(private val clickListener: (Int, String) -> Unit = { _, _ -> }) :
+class ImageAdapter(
+ private val context: Context,
+ private val clickListener: (Int, String) -> Unit = { _, _ -> }
+) :
RecyclerView.Adapter() {
private val list = mutableListOf()
@@ -29,20 +38,43 @@ class ImageAdapter(private val clickListener: (Int, String) -> Unit = { _, _ ->
return RowImageViewHolder(view)
}
+ private val picasso: Picasso by lazy {
+ Picasso.Builder(context)
+ .memoryCache(LruCache(context))
+ .loggingEnabled(BuildConfig.DEBUG)
+ .downloader(OkHttp3Downloader(context))
+ .build()
+ }
+
+
override fun onBindViewHolder(holder: RowImageViewHolder, position: Int) {
val imageSource: String = list[position]
holder.view.setOnClickListener {
clickListener.invoke(position, imageSource)
}
- Picasso.get()
- .load(File(imageSource))
- .fit()
- .centerInside()
- .into(holder.selectedImageView)
+ if (URLUtil.isHttpUrl(imageSource) || URLUtil.isHttpsUrl(imageSource)) {
+ picasso.load(imageSource)
+ .fit()
+ .centerInside()
+ .error(R.drawable.placeholder_image)
+ .placeholder(R.drawable.placeholder_image)
+ .into(holder.selectedImageView)
+ } else if(URLUtil.isFileUrl(imageSource)) {
+ picasso
+ .load(File(imageSource))
+ .fit()
+ .error(R.drawable.placeholder_image)
+ .placeholder(R.drawable.placeholder_image)
+ .centerInside()
+ .into(holder.selectedImageView)
+ }else{
+ return
+ }
+
}
override fun getItemCount(): Int {
return list.size
}
-}
\ No newline at end of file
+}
diff --git a/form/src/main/java/com/m7mdra/questionForm/QuestionAdapter.kt b/form/src/main/java/com/m7mdra/questionForm/QuestionAdapter.kt
index ded18bb..b278a78 100644
--- a/form/src/main/java/com/m7mdra/questionForm/QuestionAdapter.kt
+++ b/form/src/main/java/com/m7mdra/questionForm/QuestionAdapter.kt
@@ -6,6 +6,7 @@ import android.content.pm.PackageManager
import android.graphics.Color
import android.graphics.Typeface
import android.media.MediaPlayer
+import android.net.Uri
import android.os.Handler
import android.os.Looper
import android.text.Editable
@@ -22,7 +23,6 @@ import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.core.content.ContextCompat
-import androidx.core.net.toUri
import androidx.core.util.forEach
import androidx.core.util.set
import androidx.recyclerview.widget.LinearLayoutManager
@@ -31,7 +31,6 @@ import androidx.recyclerview.widget.RecyclerView
import com.m7mdra.questionForm.question.*
import com.m7mdra.questionForm.question.QuestionType.*
import com.m7mdra.questionForm.viewholder.*
-import java.io.File
class QuestionAdapter(
@@ -155,14 +154,12 @@ class QuestionAdapter(
holder.textInputEditText.addTextChangedListener(textWatcher)
if (question.done) {
- holder.rootView.disable()
- holder.itemView.disable()
- holder.rootView.disableChildren()
+ holder.textInputEditText.disable()
holder.submittedTextView.show()
} else {
- holder.rootView.enable()
- holder.itemView.enable()
- holder.rootView.enableChildren()
+
+ holder.textInputEditText.enable()
+
holder.submittedTextView.gone()
}
@@ -199,14 +196,11 @@ class QuestionAdapter(
autoCompleteTextView.onItemClickListener = onItemClickListener
dropDownListener[position] = onItemClickListener
if (question.done) {
- holder.rootView.disable()
- holder.itemView.disable()
- holder.rootView.disableChildren()
+ holder.autoCompleteTextView.disable()
holder.submittedTextView.show()
} else {
- holder.rootView.enable()
- holder.itemView.enable()
- holder.rootView.enableChildren()
+ holder.autoCompleteTextView.enable()
+
holder.submittedTextView.gone()
}
}
@@ -259,7 +253,6 @@ class QuestionAdapter(
mediaViewHolderIndexes.append(position, position)
val holder = viewHolder as VideoViewHolder
val question = list[position] as VideoQuestion
- question.log()
val videoView = holder.videoView
@@ -276,10 +269,10 @@ class QuestionAdapter(
videoPickListener?.invoke(question, position)
}
- val file = question.value
- if (file != null) {
+ val video = question.value
+ if (video != null && video.isNotEmpty()) {
videoView.show()
- videoView.setVideoURI(file.toUri())
+ videoView.setVideoURI(Uri.parse(video))
videoView.setOnPreparedListener {
holder.playOrStopButton.show()
holder.playOrStopButton.setImageResource(R.drawable.ic_baseline_play_circle_filled_24)
@@ -304,14 +297,11 @@ class QuestionAdapter(
}
}
if (question.done) {
- holder.rootView.disable()
- holder.itemView.disable()
- holder.rootView.disableChildren()
+ holder.captureOrPickVideoButton.disable()
holder.submittedTextView.show()
} else {
- holder.rootView.enable()
- holder.itemView.enable()
- holder.rootView.enableChildren()
+ holder.captureOrPickVideoButton.enable()
+
holder.submittedTextView.gone()
}
@@ -339,7 +329,7 @@ class QuestionAdapter(
holder.titleTextView.text =
titleWithRedAsterisk(question.mandatory, question.title, position)
- val imageAdapter = ImageAdapter { childPosition, image ->
+ val imageAdapter = ImageAdapter(context) { childPosition, image ->
imageClickListener?.invoke(position, childPosition, image)
}
holder.imageButton.setOnClickListener {
@@ -351,14 +341,10 @@ class QuestionAdapter(
imageAdapter.addAll(question.value)
holder.imagesRecyclerView.adapter = imageAdapter
if (question.done) {
- holder.rootView.disable()
- holder.itemView.disable()
- holder.rootView.disableChildren()
+ holder.imageButton.disable()
holder.submittedTextView.show()
} else {
- holder.rootView.enable()
- holder.itemView.enable()
- holder.rootView.enableChildren()
+ holder.imageButton.disable()
holder.submittedTextView.gone()
}
@@ -379,7 +365,8 @@ class QuestionAdapter(
holder.titleTextView.text =
titleWithRedAsterisk(question.required, question.title, position)
- if (question.value != null) {
+ val audio = question.value
+ if (audio != null && audio.isNotEmpty()) {
val mediaPlayer = MediaPlayer()
val handler = Handler(Looper.getMainLooper())
@@ -404,22 +391,18 @@ class QuestionAdapter(
audioHandlers[position] = handler
audioHandlersCallback[position] = runnable
holder.playOrStopButton.setOnClickListener {
- val audio = question.value ?: return@setOnClickListener
- try {
- if (mediaPlayer.isPlaying) {
- mediaPlayer.stop()
- holder.recordDurationTextView.text =
- context.getString(R.string.zero_zero)
- holder.playOrStopButton.setImageResource(R.drawable.ic_baseline_play_arrow_24)
- holder.recordProgress.progress = 0
- } else {
- mediaPlayer.reset()
- mediaPlayer.setDataSource(audio.path)
- mediaPlayer.prepareAsync()
- }
- } catch (error: Exception) {
-
+ if (mediaPlayer.isPlaying) {
+ mediaPlayer.stop()
+ holder.recordDurationTextView.text =
+ context.getString(R.string.zero_zero)
+ holder.playOrStopButton.setImageResource(R.drawable.ic_baseline_play_arrow_24)
+ holder.recordProgress.progress = 0
+ } else {
+ mediaPlayer.reset()
+ mediaPlayer.setDataSource(audio)
+ mediaPlayer.prepareAsync()
}
+
}
mediaPlayer.setOnPreparedListener {
mediaPlayer.start()
@@ -435,7 +418,7 @@ class QuestionAdapter(
}
}
- holder.playOrStopButton.isEnabled = question.value != null
+ holder.playOrStopButton.isEnabled = audio != null
holder.recordAudioButton.text =
if (isAudioPermissionGranted(holder.context)
@@ -447,11 +430,11 @@ class QuestionAdapter(
}
if (question.done) {
- holder.rootView.disable()
- holder.itemView.disable()
- holder.rootView.disableChildren()
+ holder.recordAudioButton.disable()
holder.submittedTextView.show()
} else {
+ holder.recordAudioButton.disable()
+
holder.rootView.enable()
holder.itemView.enable()
holder.rootView.enableChildren()
@@ -498,7 +481,6 @@ class QuestionAdapter(
} else {
holder.rootView.enable()
holder.itemView.enable()
-
holder.rootView.enableChildren()
holder.submittedTextView.gone()
}
@@ -631,7 +613,7 @@ class QuestionAdapter(
mediaPlayers.remove(adapterPosition)
}
- fun addRecordFile(recordFile: File?, position: Int) {
+ fun addRecordFile(recordFile: String?, position: Int) {
if (recordFile == null)
return
if (position == -1)
@@ -641,7 +623,7 @@ class QuestionAdapter(
notifyItemChanged(position)
}
- fun updatePickedVideo(uri: File) {
+ fun updatePickedVideo(uri: String) {
val question = list[lastImageVideoIndex] as VideoQuestion
question.update(uri)
notifyItemChanged(lastImageVideoIndex)
diff --git a/form/src/main/java/com/m7mdra/questionForm/extensions.kt b/form/src/main/java/com/m7mdra/questionForm/extensions.kt
index 2396474..358ef4b 100644
--- a/form/src/main/java/com/m7mdra/questionForm/extensions.kt
+++ b/form/src/main/java/com/m7mdra/questionForm/extensions.kt
@@ -11,6 +11,7 @@ import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
+import android.webkit.URLUtil
import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.children
@@ -90,6 +91,14 @@ fun ViewGroup.disableChildren() {
}
+fun String.isUrl(): Boolean {
+ return this.isNotEmpty() && URLUtil.isHttpUrl(this) || URLUtil.isHttpsUrl(this)
+}
+
+fun String.isFile(): Boolean {
+ return this.isNotEmpty() && URLUtil.isFileUrl(this)
+}
+
fun ViewGroup.enableChildren() {
children.forEach {
if (it is ViewGroup) {
diff --git a/form/src/main/java/com/m7mdra/questionForm/question/AudioQuestion.kt b/form/src/main/java/com/m7mdra/questionForm/question/AudioQuestion.kt
index 20be093..9a91f13 100644
--- a/form/src/main/java/com/m7mdra/questionForm/question/AudioQuestion.kt
+++ b/form/src/main/java/com/m7mdra/questionForm/question/AudioQuestion.kt
@@ -1,9 +1,8 @@
package com.m7mdra.questionForm.question
-import java.io.File
class AudioQuestion(
- override var value: File? = null,
+ override var value: String? = null,
title: String,
id: String,
private val mandatory: Boolean = false,
@@ -11,7 +10,7 @@ class AudioQuestion(
done: Boolean = false
) :
- Question(
+ Question(
title,
questionType = QuestionType.Audio,
id = id,
@@ -38,7 +37,7 @@ class AudioQuestion(
}
- override fun update(value: File?) {
+ override fun update(value: String?) {
this.value = value
}
diff --git a/form/src/main/java/com/m7mdra/questionForm/question/VideoQuestion.kt b/form/src/main/java/com/m7mdra/questionForm/question/VideoQuestion.kt
index fa1c52c..9400b9f 100644
--- a/form/src/main/java/com/m7mdra/questionForm/question/VideoQuestion.kt
+++ b/form/src/main/java/com/m7mdra/questionForm/question/VideoQuestion.kt
@@ -6,10 +6,10 @@ class VideoQuestion(
title: String, id: String,
val mandatory: Boolean = false,
private val params: Map = mapOf(),
- done: Boolean = false, override var value: File? = null
+ done: Boolean = false, override var value: String? = null
-) : Question(
+) : Question(
title,
questionType = QuestionType.Video,
id = id,
@@ -35,7 +35,7 @@ class VideoQuestion(
}
- override fun update(value: File?) {
+ override fun update(value: String?) {
this.value = value
}
diff --git a/form/src/main/res/drawable/placeholder_image.xml b/form/src/main/res/drawable/placeholder_image.xml
new file mode 100644
index 0000000..1f87604
--- /dev/null
+++ b/form/src/main/res/drawable/placeholder_image.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file