diff --git a/ads/build.gradle b/ads/build.gradle index 12eb5ec..1a212ef 100644 --- a/ads/build.gradle +++ b/ads/build.gradle @@ -27,25 +27,9 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(':app') - implementation "androidx.core:core-ktx:1.2.0" - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - // https://developer.android.com/kotlin/ktx#play-core - implementation 'com.google.android.play:core-ktx:1.7.0' // https://firebase.google.com/docs/admob/android/quick-start#import_the_mobile_ads_sdk implementation 'com.google.firebase:firebase-ads:19.1.0' - // https://developer.android.com/studio/build/multidex - implementation 'androidx.multidex:multidex:2.0.1' - // https://github.com/JakeWharton/timber - implementation 'com.jakewharton.timber:timber:4.7.1' - // https://firebase.google.com/docs/android/setup#add-sdks - implementation 'com.google.firebase:firebase-core:17.3.0' - implementation 'com.google.firebase:firebase-common-ktx:19.3.0' - implementation 'com.google.firebase:firebase-analytics:17.3.0' - implementation 'com.google.firebase:firebase-crashlytics:17.0.0-beta04' - implementation 'com.google.firebase:firebase-perf:19.0.6' - // https://developer.android.com/jetpack/androidx/releases/cardview - implementation 'androidx.cardview:cardview:1.0.0' } repositories { mavenCentral() diff --git a/app/build.gradle b/app/build.gradle index a9862cc..cf00ca9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -104,56 +104,58 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation 'androidx.appcompat:appcompat:1.1.0' - implementation 'androidx.core:core-ktx:1.2.0' - implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + api "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" + api 'androidx.appcompat:appcompat:1.1.0' + api 'androidx.core:core-ktx:1.2.0' + api 'androidx.legacy:legacy-support-v4:1.0.0' + api 'androidx.constraintlayout:constraintlayout:1.1.3' testImplementation 'junit:junit:4.13' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' // https://github.com/Javinator9889/LocaleManager - implementation 'com.github.javinator9889:localemanager:1.1X' + api 'com.github.javinator9889:localemanager:1.1X' // https://material.io/develop/android/docs/getting-started/ - implementation 'com.google.android.material:material:1.1.0' + api 'com.google.android.material:material:1.1.0' // https://developers.google.com/android/guides/setup implementation 'com.google.android.gms:play-services-location:17.0.0' // https://developer.android.com/jetpack/androidx/releases/annotation - implementation 'androidx.annotation:annotation:1.1.0' + api 'androidx.annotation:annotation:1.1.0' // https://developer.android.com/jetpack/androidx/releases/cardview - implementation 'androidx.cardview:cardview:1.0.0' + api 'androidx.cardview:cardview:1.0.0' // https://developer.android.com/jetpack/androidx/releases/recyclerview - implementation 'androidx.recyclerview:recyclerview:1.1.0' + api 'androidx.recyclerview:recyclerview:1.1.0' // https://developer.android.com/studio/build/multidex - implementation 'androidx.multidex:multidex:2.0.1' + api 'androidx.multidex:multidex:2.0.1' // https://github.com/mikepenz/Android-Iconics - implementation 'com.mikepenz:iconics-core:5.0.2' - implementation 'com.mikepenz:iconics-views:5.0.2' + api 'com.mikepenz:iconics-core:5.0.2' + api 'com.mikepenz:iconics-views:5.0.2' //noinspection GradleDependency - implementation 'com.mikepenz:google-material-typeface:3.0.1.4.original-kotlin@aar' - implementation 'com.mikepenz:ionicons-typeface:2.0.1.5-kotlin@aar' + api 'com.mikepenz:google-material-typeface:3.0.1.4.original-kotlin@aar' + api 'com.mikepenz:ionicons-typeface:2.0.1.5-kotlin@aar' // https://github.com/mikepenz/AboutLibraries implementation "com.mikepenz:aboutlibraries-core:${latestAboutLibsRelease}" implementation "com.mikepenz:aboutlibraries:${latestAboutLibsRelease}" // https://developer.android.com/kotlin/ktx#play-core - implementation 'com.google.android.play:core-ktx:1.7.0' + api 'com.google.android.play:core:1.7.2' + api 'com.google.android.play:core-ktx:1.7.0' // https://developer.android.com/kotlin/ktx#collection implementation 'androidx.collection:collection-ktx:1.1.0' // https://kotlinlang.org/docs/reference/reflection.html implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" // https://firebase.google.com/docs/android/setup#add-sdks - implementation 'com.google.firebase:firebase-common-ktx:19.3.0' - implementation 'com.google.firebase:firebase-analytics:17.3.0' - implementation 'com.google.firebase:firebase-crashlytics:17.0.0-beta04' - implementation 'com.google.firebase:firebase-perf:19.0.6' + api 'com.google.firebase:firebase-common-ktx:19.3.0' + api 'com.google.firebase:firebase-analytics:17.3.0' + api 'com.google.firebase:firebase-crashlytics:17.0.0-beta04' + api 'com.google.firebase:firebase-perf:19.0.6' // http://airbnb.io/lottie/#/android?id=getting-started - implementation "com.airbnb.android:lottie:3.4.0" + api "com.airbnb.android:lottie:3.4.0" // https://firebase.google.com/docs/remote-config/use-config-android implementation 'com.google.firebase:firebase-config:19.1.3' implementation 'com.google.firebase:firebase-config-ktx:19.1.3' // https://mvnrepository.com/artifact/androidx.emoji/emoji/1.0.0 - implementation 'androidx.emoji:emoji:1.0.0' - implementation 'androidx.emoji:emoji-appcompat:1.0.0' + api 'androidx.emoji:emoji:1.0.0' + api 'androidx.emoji:emoji-appcompat:1.0.0' // https://github.com/mikepenz/FastAdapter implementation "com.mikepenz:fastadapter:${latestFastAdapterRelease}" // https://developer.android.com/kotlin/ktx#lifecycle @@ -165,13 +167,13 @@ dependencies { // https://developer.android.com/kotlin/ktx#livedata implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0' // https://github.com/JakeWharton/timber - implementation 'com.jakewharton.timber:timber:4.7.1' + api 'com.jakewharton.timber:timber:4.7.1' // https://developer.android.com/jetpack/androidx/releases/lifecycle#declaring_dependencies implementation 'androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0' // https://developer.android.com/reference/kotlin/androidx/preference/package-summary implementation 'androidx.preference:preference:1.1.1' // https://github.com/bumptech/glide - implementation 'com.github.bumptech.glide:glide:4.11.0' + api 'com.github.bumptech.glide:glide:4.11.0' kapt 'com.github.bumptech.glide:compiler:4.11.0' // https://github.com/afollestad/material-dialogs/ implementation 'com.afollestad.material-dialogs:core:3.3.0' diff --git a/app/src/main/java/com/javinator9889/handwashingreminder/graphics/RecyclingImageView.java b/app/src/main/java/com/javinator9889/handwashingreminder/graphics/RecyclingImageView.java index c19ce18..194d5c9 100644 --- a/app/src/main/java/com/javinator9889/handwashingreminder/graphics/RecyclingImageView.java +++ b/app/src/main/java/com/javinator9889/handwashingreminder/graphics/RecyclingImageView.java @@ -20,6 +20,8 @@ import android.graphics.drawable.LayerDrawable; import android.util.AttributeSet; +import androidx.annotation.DrawableRes; +import androidx.annotation.Nullable; import androidx.appcompat.widget.AppCompatImageView; /** @@ -27,6 +29,8 @@ * being displayed. */ public class RecyclingImageView extends AppCompatImageView { + @DrawableRes + private Integer mSavedDrawableRes = null; public RecyclingImageView(Context context) { super(context); @@ -36,11 +40,39 @@ public RecyclingImageView(Context context, AttributeSet attrs) { super(context, attrs); } + public void setSavedDrawableRes(@Nullable @DrawableRes Integer mSavedDrawableRes) { + this.mSavedDrawableRes = mSavedDrawableRes; + } + + @Nullable + @DrawableRes + public Integer getSavedDrawableRes() { + return mSavedDrawableRes; + } + + @Override + protected void onWindowVisibilityChanged(int visibility) { + super.onWindowVisibilityChanged(visibility); + if (mSavedDrawableRes != null && + visibility == VISIBLE && + getDrawable() == null) { + try { + GlideApp.with(this) + .load(mSavedDrawableRes) + .centerInside() + .into(this); + } catch (Exception ignored) { + setImageResource(mSavedDrawableRes); + } + } else if (visibility == INVISIBLE || visibility == GONE) + onDetachedFromWindow(); + } + /** * @see android.widget.ImageView#onDetachedFromWindow() */ @Override - protected void onDetachedFromWindow() { + public void onDetachedFromWindow() { // This has been detached from Window, so clear the drawable setImageDrawable(null); diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index deb4cad..9029eef 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -7,7 +7,7 @@ tools:context=".activities.MainActivity"> + app:layout_constraintTop_toBottomOf="@+id/bar" /> - Intro de Handwashing reminder Política de privacidad Términos y condiciones Permite que la aplicación @@ -45,7 +44,6 @@ Permite que la aplicación monitorice el rendimiento de la misma y envíe datos anónimos para mejorar la experiencia de usuario - Anuncios Ad Construyendo tu aplicación… diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8741206..b68ff46 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -36,7 +36,7 @@ try to wash your hands as soon as you can for avoiding diseases 💦👏 - Handwashing reminder intro + Handwashing reminder intro Privacy policy Terms and conditions Allow the application to @@ -45,7 +45,7 @@ Allow the application to track its performance and send anonymous data for improving in-app experience - Ads + Ads Ad Building your app… We are adding new diff --git a/appintro/build.gradle b/appintro/build.gradle index 5dbb6a6..d26d497 100644 --- a/appintro/build.gradle +++ b/appintro/build.gradle @@ -40,41 +40,9 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(':app') - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation 'androidx.appcompat:appcompat:1.1.0' - implementation 'androidx.core:core-ktx:1.2.0' - implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - // https://developers.google.com/android/guides/setup - implementation 'com.google.android.gms:play-services-location:17.0.0' - // https://material.io/develop/android/docs/getting-started/ - implementation 'com.google.android.material:material:1.1.0' - // https://github.com/Javinator9889/LocaleManager - implementation 'com.github.javinator9889:localemanager:1.1X' + // https://github.com/AppIntro/AppIntro implementation 'com.github.AppIntro:AppIntro:5.1.0' - // https://developer.android.com/jetpack/androidx/releases/cardview - implementation 'androidx.cardview:cardview:1.0.0' - // https://developer.android.com/jetpack/androidx/releases/recyclerview - implementation 'androidx.recyclerview:recyclerview:1.1.0' - // https://github.com/mikepenz/Android-Iconics - implementation 'com.mikepenz:iconics-core:5.0.2' - implementation 'com.mikepenz:iconics-views:5.0.2' - //noinspection GradleDependency - implementation 'com.mikepenz:google-material-typeface:3.0.1.4.original-kotlin@aar' - implementation 'com.mikepenz:ionicons-typeface:2.0.1.5-kotlin@aar' - // https://developer.android.com/kotlin/ktx#play-core - implementation 'com.google.android.play:core-ktx:1.7.0' - // https://developer.android.com/studio/build/multidex - implementation 'androidx.multidex:multidex:2.0.1' - // http://airbnb.io/lottie/#/android?id=getting-started - implementation "com.airbnb.android:lottie:3.4.0" - // https://github.com/JakeWharton/timber - implementation 'com.jakewharton.timber:timber:4.7.1' - // https://firebase.google.com/docs/android/setup#add-sdks - implementation 'com.google.firebase:firebase-common-ktx:19.3.0' - implementation 'com.google.firebase:firebase-analytics:17.3.0' - implementation 'com.google.firebase:firebase-crashlytics:17.0.0-beta04' - implementation 'com.google.firebase:firebase-perf:19.0.6' - // https://github.com/bumptech/glide - implementation 'com.github.bumptech.glide:glide:4.11.0' + // https://github.com/mikepenz/FastAdapter + implementation "com.mikepenz:fastadapter:${latestFastAdapterRelease}" } diff --git a/appintro/src/main/AndroidManifest.xml b/appintro/src/main/AndroidManifest.xml index 78760b8..af282d9 100644 --- a/appintro/src/main/AndroidManifest.xml +++ b/appintro/src/main/AndroidManifest.xml @@ -14,12 +14,12 @@ - - + + + + + + diff --git a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/IntroActivity.kt b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/IntroActivity.kt index d611cb4..39b6830 100644 --- a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/IntroActivity.kt +++ b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/IntroActivity.kt @@ -27,14 +27,9 @@ import android.os.Bundle import android.view.View import android.widget.FrameLayout import androidx.annotation.Keep -import androidx.core.app.ActivityCompat -import androidx.core.app.ActivityOptionsCompat import androidx.core.content.edit -import androidx.core.util.Pair -import androidx.core.util.forEach +import androidx.core.util.set import androidx.fragment.app.Fragment -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView import com.github.paolorotolo.appintro.AppIntro2 import com.github.paolorotolo.appintro.AppIntroViewPager import com.google.android.gms.common.ConnectionResult.SUCCESS @@ -45,25 +40,25 @@ import com.google.android.play.core.splitinstall.SplitInstallManagerFactory import com.google.firebase.analytics.FirebaseAnalytics import com.google.firebase.perf.FirebasePerformance import com.javinator9889.handwashingreminder.activities.MainActivity -import com.javinator9889.handwashingreminder.appintro.config.TimeConfigActivity import com.javinator9889.handwashingreminder.appintro.custom.SliderPageBuilder import com.javinator9889.handwashingreminder.appintro.fragments.AnimatedAppIntro import com.javinator9889.handwashingreminder.appintro.fragments.SlidePolicyFragment import com.javinator9889.handwashingreminder.appintro.fragments.TimeConfigIntroFragment -import com.javinator9889.handwashingreminder.appintro.timeconfig.TimeConfigViewHolder +import com.javinator9889.handwashingreminder.appintro.fragments.TimeContainer +import com.javinator9889.handwashingreminder.appintro.timeconfig.TimeConfigItem import com.javinator9889.handwashingreminder.appintro.utils.AnimatedResources import com.javinator9889.handwashingreminder.application.HandwashingApplication import com.javinator9889.handwashingreminder.jobs.alarms.AlarmHandler -import com.javinator9889.handwashingreminder.listeners.ViewHolder import com.javinator9889.handwashingreminder.utils.* import kotlinx.android.synthetic.main.animated_intro.* import timber.log.Timber import com.javinator9889.handwashingreminder.appintro.R as RIntro +const val TIME_CONFIG_REQUEST_CODE = 16 + @Keep class IntroActivity : AppIntro2(), - ViewHolder.OnItemClickListener, AppIntroViewPager.OnNextPageRequestedListener, View.OnClickListener { private lateinit var activitySlide: Fragment @@ -100,10 +95,18 @@ class IntroActivity : AppIntro2(), .build() addSlide(secondSlide) - timeConfigSlide = TimeConfigIntroFragment() - timeConfigSlide.bgColor = Color.WHITE - timeConfigSlide.listener = this - timeConfigSlide.fromActivity = this + var timeFragment: TimeConfigIntroFragment? = null + if (savedInstanceState != null) { + timeFragment = + supportFragmentManager.getFragment( + savedInstanceState, + TimeConfigIntroFragment::class.simpleName!! + ) as TimeConfigIntroFragment? + } + if (timeFragment == null) { + timeConfigSlide = TimeConfigIntroFragment() + timeConfigSlide.bgColor = Color.WHITE + } else timeConfigSlide = timeFragment addSlide(timeConfigSlide) val gms = GoogleApiAvailability.getInstance() @@ -117,13 +120,22 @@ class IntroActivity : AppIntro2(), addSlide(activitySlide) } - policySlide = SlidePolicyFragment().apply { - title = this@IntroActivity - .getString(RIntro.string.privacy_policy_title) - animatedDrawable = AnimatedResources.PRIVACY - titleColor = Color.DKGRAY - bgColor = Color.WHITE + var policyConfig: SlidePolicyFragment? = null + if (savedInstanceState != null) { + policyConfig = supportFragmentManager.getFragment( + savedInstanceState, + SlidePolicyFragment::class.simpleName!! + ) as SlidePolicyFragment? } + if (policyConfig == null) { + policySlide = SlidePolicyFragment().apply { + title = this@IntroActivity + .getString(RIntro.string.privacy_policy_title) + animatedDrawable = AnimatedResources.PRIVACY + titleColor = Color.DKGRAY + bgColor = Color.WHITE + } + } else policySlide = policyConfig addSlide(policySlide) showSkipButton(false) @@ -133,12 +145,30 @@ class IntroActivity : AppIntro2(), nextButton.setOnClickListener(this) } + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + runCatching { + supportFragmentManager.putFragment( + outState, + TimeConfigIntroFragment::class.simpleName!!, + timeConfigSlide + ) + } + runCatching { + supportFragmentManager.putFragment( + outState, + SlidePolicyFragment::class.simpleName!!, + policySlide + ) + } + } + override fun onDonePressed(currentFragment: Fragment?) { super.onDonePressed(currentFragment) val app = HandwashingApplication.getInstance() val sharedPreferences = app.sharedPreferences sharedPreferences.edit(commit = true) { - timeConfigSlide.rvItems.forEach { item -> + timeConfigSlide.itemAdapter.adapterItems.forEach { item -> val time = "${item.hours}:${item.minutes}" when (item.id) { TimeConfig.BREAKFAST_ID -> @@ -216,78 +246,38 @@ class IntroActivity : AppIntro2(), this.finish() } - override fun onItemClick( - viewHolder: RecyclerView.ViewHolder?, - view: View?, - position: Int, - id: Long - ) { - if (viewHolder == null || viewHolder !is TimeConfigViewHolder) - return - val intent = Intent(this, TimeConfigActivity::class.java) - val options = if (isAtLeast(AndroidVersion.LOLLIPOP)) { - val pairs = mutableListOf>() - val items = HashMap(6).apply { - this[TimeConfigActivity.VIEW_TITLE_NAME] = viewHolder.title - this[TimeConfigActivity.INFO_IMAGE_NAME] = viewHolder.image - this[TimeConfigActivity.USER_TIME_ICON] = viewHolder.clockIcon - this[TimeConfigActivity.USER_TIME_HOURS] = viewHolder.hours - this[TimeConfigActivity.USER_DDOT] = viewHolder.ddot - this[TimeConfigActivity.USER_TIME_MINUTES] = viewHolder.minutes - } - val lm = - timeConfigSlide.recyclerView.layoutManager as LinearLayoutManager - if (position <= lm.findLastCompletelyVisibleItemPosition()) { - items.onEach { - pairs.add(Pair.create(it.value, it.key)) - } - } - ActivityOptionsCompat.makeSceneTransitionAnimation( - this, - *pairs.toTypedArray() - ) - } else { - null - } - intent.putExtra( - "title", viewHolder.title.text - ) - intent.putExtra( - "hours", viewHolder.hours.text - ) - intent.putExtra( - "minutes", viewHolder.minutes.text - ) - intent.putExtra("id", id) - ActivityCompat.startActivityForResult( - this, intent, id.toInt(), options?.toBundle() - ) - } - override fun onActivityResult( requestCode: Int, resultCode: Int, data: Intent? ) { super.onActivityResult(requestCode, resultCode, data) - if (data == null) + if (data == null || requestCode != TIME_CONFIG_REQUEST_CODE) return - val view: TimeConfigViewHolder = when (requestCode.toLong()) { - TimeConfig.BREAKFAST_ID -> { - timeConfigSlide.viewItems[TimeConfig.BREAKFAST_ID.toInt()] - } - TimeConfig.LUNCH_ID -> { - timeConfigSlide.viewItems[TimeConfig.LUNCH_ID.toInt()] + val id = data.getLongExtra("id", 0L) + if (timeConfigSlide.isInitialized) { + val position = data.getIntExtra("position", 0) + val hours = data.getStringExtra("hours") + val minutes = data.getStringExtra("minutes") + val titleText = when(id) { + TimeConfig.BREAKFAST_ID -> getString(RIntro.string.breakfast) + TimeConfig.LUNCH_ID -> getString(RIntro.string.lunch) + TimeConfig.DINNER_ID -> getString(RIntro.string.dinner) + else -> "" } - TimeConfig.DINNER_ID -> { - timeConfigSlide.viewItems[TimeConfig.DINNER_ID.toInt()] - } - else -> null - } as TimeConfigViewHolder - view.hours.text = data.getStringExtra("hours") - view.minutes.text = data.getStringExtra("minutes") - view.saveContentToTextViews() - setSwipeLock() + timeConfigSlide.itemAdapter[position] = TimeConfigItem( + getString(RIntro.string.time_config_title_tpl, titleText), + id, hours, minutes + ) + timeConfigSlide.fastAdapter.notifyAdapterItemChanged(position) + setSwipeLock() + } else { + timeConfigSlide.propertyContainer[id.toInt()] = + TimeContainer( + data.getStringExtra("hours"), + data.getStringExtra("minutes") + ) + } } override fun onSlideChanged( @@ -301,13 +291,15 @@ class IntroActivity : AppIntro2(), setSwipeLock(false) } if (oldFragment == activitySlide) - askForPermissions( - this, - Permission( - Manifest.permission.ACTIVITY_RECOGNITION, - PERMISSIONS_REQUEST_CODE + if (isAtLeast(AndroidVersion.Q)) { + askForPermissions( + this, + Permission( + Manifest.permission.ACTIVITY_RECOGNITION, + PERMISSIONS_REQUEST_CODE + ) ) - ) + } if (newFragment is AnimatedAppIntro || newFragment is SlidePolicyFragment ) @@ -317,8 +309,8 @@ class IntroActivity : AppIntro2(), private fun setSwipeLock() { var swipeLock = false - timeConfigSlide.viewItems.forEach { _, value -> - if (value.hours.text == "" && value.minutes.text == "") { + timeConfigSlide.itemAdapter.adapterItems.forEach { item -> + if (item.hours.isNullOrEmpty() && item.minutes.isNullOrEmpty()) { swipeLock = true return@forEach } @@ -332,9 +324,7 @@ class IntroActivity : AppIntro2(), return when (timeConfigIntroFragment) { timeConfigSlide -> { var isTimeSet = true - if (timeConfigSlide.rvItems.size != 3) - return false - timeConfigSlide.rvItems.forEach { item -> + timeConfigSlide.itemAdapter.adapterItems.forEach { item -> val hours = item.hours val minutes = item.minutes if (hours == "" || minutes == "") { diff --git a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/config/TimeConfigActivity.kt b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/config/TimeConfigActivity.kt index 2244612..13ca97d 100644 --- a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/config/TimeConfigActivity.kt +++ b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/config/TimeConfigActivity.kt @@ -40,6 +40,7 @@ import com.javinator9889.handwashingreminder.utils.formatTime import com.javinator9889.handwashingreminder.utils.isAtLeast import timber.log.Timber import java.util.* +import kotlin.properties.Delegates class TimeConfigActivity : ActionBarBase(), @@ -64,6 +65,8 @@ class TimeConfigActivity : private lateinit var hours: TextView private lateinit var minutes: TextView private lateinit var clockIcon: ImageView + private var id by Delegates.notNull() + private var position by Delegates.notNull() data class Time(val hour: Int, val minute: Int) @@ -104,7 +107,9 @@ class TimeConfigActivity : val sHours = data!!.getCharSequence("hours") val sMinutes = data.getCharSequence("minutes") title.text = data.getCharSequence("title") - val imageRes = when (data.getLong("id")) { + id = data.getLong("id", TimeConfig.BREAKFAST_ID) + position = data.getInt("position", 0) + val imageRes = when (id) { TimeConfig.BREAKFAST_ID -> R.drawable.ic_breakfast TimeConfig.LUNCH_ID -> R.drawable.ic_lunch TimeConfig.DINNER_ID -> R.drawable.ic_dinner @@ -153,6 +158,8 @@ class TimeConfigActivity : outState.putCharSequence("hours", hour) outState.putCharSequence("minutes", minute) outState.putCharSequence("title", title.text) + outState.putLong("id", id) + outState.putInt("position", position) } override fun onBackPressed() { @@ -160,6 +167,8 @@ class TimeConfigActivity : val tpTime = getHours() intent.putExtra("hours", formatTime(tpTime.hour)) intent.putExtra("minutes", formatTime(tpTime.minute)) + intent.putExtra("id", id) + intent.putExtra("position", position) setResult(Activity.RESULT_OK, intent) if (isAtLeast(AndroidVersion.LOLLIPOP)) finishAfterTransition() diff --git a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/TimeConfigIntroFragment.kt b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/TimeConfigIntroFragment.kt index bc3bd14..54d4bc9 100644 --- a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/TimeConfigIntroFragment.kt +++ b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/fragments/TimeConfigIntroFragment.kt @@ -18,107 +18,147 @@ */ package com.javinator9889.handwashingreminder.appintro.fragments -import android.content.Context +import android.content.Intent import android.graphics.Color import android.os.Bundle import android.util.SparseArray import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.appcompat.app.AppCompatActivity -import androidx.core.util.forEach +import androidx.core.app.ActivityCompat +import androidx.core.app.ActivityOptionsCompat +import androidx.core.util.Pair +import androidx.core.util.set +import androidx.core.view.isVisible import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.github.paolorotolo.appintro.AppIntroBaseFragment -import com.google.android.play.core.splitcompat.SplitCompat import com.javinator9889.handwashingreminder.appintro.R -import com.javinator9889.handwashingreminder.appintro.timeconfig.TimeConfigAdapter -import com.javinator9889.handwashingreminder.appintro.timeconfig.TimeConfigContent -import com.javinator9889.handwashingreminder.appintro.timeconfig.TimeConfigViewHolder -import com.javinator9889.handwashingreminder.listeners.ViewHolder +import com.javinator9889.handwashingreminder.appintro.TIME_CONFIG_REQUEST_CODE +import com.javinator9889.handwashingreminder.appintro.config.TimeConfigActivity +import com.javinator9889.handwashingreminder.appintro.timeconfig.TimeConfigItem +import com.javinator9889.handwashingreminder.utils.AndroidVersion import com.javinator9889.handwashingreminder.utils.TimeConfig -import com.javinator9889.handwashingreminder.utils.notNull +import com.javinator9889.handwashingreminder.utils.isAtLeast +import com.mikepenz.fastadapter.FastAdapter +import com.mikepenz.fastadapter.adapters.ItemAdapter +import com.mikepenz.fastadapter.listeners.ClickEventHook +import kotlinx.android.synthetic.main.time_card_view.view.* import kotlinx.android.synthetic.main.time_config.view.* -import com.javinator9889.handwashingreminder.R as RBase class TimeConfigIntroFragment : AppIntroBaseFragment() { - private lateinit var rvAdapter: TimeConfigAdapter - lateinit var rvItems: Array - lateinit var recyclerView: RecyclerView - lateinit var fromActivity: AppCompatActivity var bgColor: Int = Color.WHITE - var listener: ViewHolder.OnItemClickListener? = null - val viewItems = SparseArray(3) - + var isInitialized = false + val propertyContainer = SparseArray(3) + lateinit var recyclerView: RecyclerView + lateinit var fastAdapter: FastAdapter + lateinit var itemAdapter: ItemAdapter - override fun onAttach(context: Context) { - super.onAttach(context) - SplitCompat.installActivity(activity) + init { + propertyContainer[TimeConfig.BREAKFAST_ID.toInt()] = TimeContainer() + propertyContainer[TimeConfig.LUNCH_ID.toInt()] = TimeContainer() + propertyContainer[TimeConfig.DINNER_ID.toInt()] = TimeContainer() } + @Suppress("unchecked_cast") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val breakfast = getString(R.string.breakfast) val lunch = getString(R.string.lunch) val dinner = getString(R.string.dinner) - rvItems = arrayOf( - TimeConfigContent( - getString(R.string.time_config_title_tpl, breakfast), - TimeConfig.BREAKFAST_ID - ), - TimeConfigContent( - getString(R.string.time_config_title_tpl, lunch), - TimeConfig.LUNCH_ID - ), - TimeConfigContent( - getString(R.string.time_config_title_tpl, dinner), - TimeConfig.DINNER_ID + itemAdapter = ItemAdapter().apply { + val items = listOf( + TimeConfigItem( + getString(R.string.time_config_title_tpl, breakfast), + TimeConfig.BREAKFAST_ID, + propertyContainer[TimeConfig.BREAKFAST_ID.toInt()].hours, + propertyContainer[TimeConfig.BREAKFAST_ID.toInt()].minutes + ), + TimeConfigItem( + getString(R.string.time_config_title_tpl, lunch), + TimeConfig.LUNCH_ID, + propertyContainer[TimeConfig.LUNCH_ID.toInt()].hours, + propertyContainer[TimeConfig.LUNCH_ID.toInt()].minutes + ), + TimeConfigItem( + getString(R.string.time_config_title_tpl, dinner), + TimeConfig.DINNER_ID, + propertyContainer[TimeConfig.DINNER_ID.toInt()].hours, + propertyContainer[TimeConfig.DINNER_ID.toInt()].minutes + ) ) - ) - rvAdapter = - TimeConfigAdapter( - rvItems, - listener, - viewItems - ) - } - - @Suppress("unchecked_cast") - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) - savedInstanceState.notNull { - val restoredItems = it.getParcelableArray("rvItems") - as Array - restoredItems.forEachIndexed { i, timeConfigContent -> - rvItems[i].hours = timeConfigContent.hours - rvItems[i].minutes = timeConfigContent.minutes - } - viewItems.forEach { _, value -> value.loadContentToTextViews() } + setNewList(items) } } - override fun onSaveInstanceState(outState: Bundle) { - outState.putParcelableArray("rvItems", rvItems) - } - override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { - val view = inflater.inflate(layoutId, container, false) - val rvManager = LinearLayoutManager(context) - fromActivity.setSupportActionBar(view.findViewById(RBase.id.toolbar)) - recyclerView = - view.cardsView.apply { - setHasFixedSize(true) - layoutManager = rvManager - adapter = rvAdapter - } - recyclerView.setBackgroundColor(bgColor) + ): View = inflater.inflate(layoutId, container, false) - return view + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val manager = LinearLayoutManager(context) + fastAdapter = FastAdapter.with(itemAdapter) + recyclerView = view.cardsView.apply { + setHasFixedSize(true) + layoutManager = manager + adapter = fastAdapter + setBackgroundColor(bgColor) + } + isInitialized = true + fastAdapter.addEventHook(object : ClickEventHook() { + override fun onBind(viewHolder: RecyclerView.ViewHolder) = + if (viewHolder is TimeConfigItem.ViewHolder) viewHolder.cardView + else null + + override fun onClick( + v: View, + position: Int, + fastAdapter: FastAdapter, + item: TimeConfigItem + ) { + val intent = Intent(context, TimeConfigActivity::class.java) + val options = if (isAtLeast(AndroidVersion.LOLLIPOP)) { + val pairs = mutableListOf>() + val items = HashMap(6).apply { + this[TimeConfigActivity.VIEW_TITLE_NAME] = v.title + this[TimeConfigActivity.INFO_IMAGE_NAME] = v.infoImage + this[TimeConfigActivity.USER_TIME_ICON] = v.clockIcon + this[TimeConfigActivity.USER_TIME_HOURS] = v.hours + this[TimeConfigActivity.USER_DDOT] = v.ddot + this[TimeConfigActivity.USER_TIME_MINUTES] = v.minutes + } + items.onEach { + if (it.value.isVisible) + pairs.add(Pair.create(it.value, it.key)) + } + ActivityOptionsCompat.makeSceneTransitionAnimation( + requireActivity(), + *pairs.toTypedArray() + ) + } else { + null + } + intent.apply { + putExtra("title", v.title.text) + putExtra("hours", v.hours.text) + putExtra("minutes", v.minutes.text) + putExtra("id", item.id) + putExtra("position", position) + } + ActivityCompat.startActivityForResult( + requireActivity(), + intent, + TIME_CONFIG_REQUEST_CODE, + options?.toBundle() + ) + } + }) } override fun getLayoutId(): Int = R.layout.time_config -} \ No newline at end of file +} + +data class TimeContainer(val hours: String? = "", val minutes: String? = "") \ No newline at end of file diff --git a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/timeconfig/TimeConfigAdapter.kt b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/timeconfig/TimeConfigAdapter.kt index 372616c..9b36ad2 100644 --- a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/timeconfig/TimeConfigAdapter.kt +++ b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/timeconfig/TimeConfigAdapter.kt @@ -31,8 +31,7 @@ class TimeConfigAdapter( private val dataset: Array, private val listener: ViewHolder.OnItemClickListener?, private val viewItems: SparseArray -) : - RecyclerView.Adapter() { +) : RecyclerView.Adapter() { private var height = 0 private lateinit var context: Context diff --git a/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/timeconfig/TimeConfigItem.kt b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/timeconfig/TimeConfigItem.kt new file mode 100644 index 0000000..1720ca2 --- /dev/null +++ b/appintro/src/main/java/com/javinator9889/handwashingreminder/appintro/timeconfig/TimeConfigItem.kt @@ -0,0 +1,90 @@ +/* + * Copyright © 2020 - present | Handwashing reminder by Javinator9889 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + * + * Created by Javinator9889 on 26/04/20 - Handwashing reminder. + */ +package com.javinator9889.handwashingreminder.appintro.timeconfig + +import android.view.View +import android.widget.TextView +import androidx.annotation.LayoutRes +import androidx.cardview.widget.CardView +import com.javinator9889.handwashingreminder.appintro.R +import com.javinator9889.handwashingreminder.graphics.GlideApp +import com.javinator9889.handwashingreminder.graphics.RecyclingImageView +import com.javinator9889.handwashingreminder.utils.TimeConfig +import com.javinator9889.handwashingreminder.utils.notNull +import com.mikepenz.fastadapter.FastAdapter +import com.mikepenz.fastadapter.items.AbstractItem +import com.mikepenz.iconics.IconicsDrawable +import com.mikepenz.iconics.typeface.library.ionicons.Ionicons +import com.mikepenz.iconics.utils.sizeDp +import com.mikepenz.iconics.view.IconicsImageView + +class TimeConfigItem( + val title: CharSequence, + val id: Long, + var hours: String? = "", + var minutes: String? = "" +) : AbstractItem() { + @LayoutRes + override val layoutRes: Int = R.layout.time_card_view + override val type: Int = R.id.timeCard + + override fun getViewHolder(v: View) = ViewHolder(v) + + class ViewHolder(private val view: View) : + FastAdapter.ViewHolder(view) { + private val title: TextView = view.findViewById(R.id.title) + private val hours: TextView = view.findViewById(R.id.hours) + private val ddot: TextView = view.findViewById(R.id.ddot) + private val minutes: TextView = view.findViewById(R.id.minutes) + private val image: RecyclingImageView = view.findViewById(R.id.infoImage) + private val clockIcon: IconicsImageView = view.findViewById(R.id.clockIcon) + val cardView: CardView = view.findViewById(R.id.timeCard) + + override fun bindView(item: TimeConfigItem, payloads: List) { + title.text = item.title + hours.text = item.hours + minutes.text = item.minutes + ddot.text = view.context.getString(R.string.double_dot) + clockIcon.icon = + IconicsDrawable(view.context, Ionicons.Icon.ion_android_time) + .apply { sizeDp = 16 } + when (item.id) { + TimeConfig.BREAKFAST_ID -> R.drawable.ic_breakfast + TimeConfig.LUNCH_ID -> R.drawable.ic_lunch + TimeConfig.DINNER_ID -> R.drawable.ic_dinner + else -> null + }.notNull { + GlideApp.with(view) + .load(it) + .centerInside() + .into(image) + image.savedDrawableRes = it + } + } + + override fun unbindView(item: TimeConfigItem) { + title.text = null + hours.text = null + ddot.text = null + minutes.text = null + image.onDetachedFromWindow() + clockIcon.icon = null + } + } +} \ No newline at end of file diff --git a/appintro/src/main/res/layout-land/time_card_view_expanded.xml b/appintro/src/main/res/layout-land/time_card_view_expanded.xml new file mode 100644 index 0000000..e91e868 --- /dev/null +++ b/appintro/src/main/res/layout-land/time_card_view_expanded.xml @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +