From feae3be2ec0aa42b3f942f3638a06cc04bef9856 Mon Sep 17 00:00:00 2001 From: Billy Brawner Date: Sun, 4 Aug 2019 18:47:23 -0700 Subject: [PATCH] Show and hide the keyboard when navigating to and from the EditFragment --- app/build.gradle | 17 ++++--- .../simplemarkdown/utility/Extensions.kt | 13 +++++ .../simplemarkdown/view/ViewPagerPage.kt | 6 +++ .../view/activity/MainActivity.kt | 4 +- .../view/adapter/EditPagerAdapter.kt | 28 +++++++++-- .../view/fragment/EditFragment.kt | 48 ++++++++++++------- .../view/fragment/PreviewFragment.kt | 17 +++---- 7 files changed, 93 insertions(+), 40 deletions(-) create mode 100644 app/src/main/java/com/wbrawner/simplemarkdown/utility/Extensions.kt create mode 100644 app/src/main/java/com/wbrawner/simplemarkdown/view/ViewPagerPage.kt diff --git a/app/build.gradle b/app/build.gradle index 4f46a15..4a685ba 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -29,7 +29,7 @@ android { exclude 'META-INF/LICENSE' exclude 'META-INF/DEPENDENCIES' } - compileSdkVersion 28 + compileSdkVersion 29 buildToolsVersion '28.0.3' compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 @@ -38,7 +38,7 @@ android { defaultConfig { applicationId "com.wbrawner.simplemarkdown" minSdkVersion 21 - targetSdkVersion 28 + targetSdkVersion 29 multiDexEnabled true versionCode 20 versionName "0.7.0" @@ -64,7 +64,6 @@ android { buildConfigField "boolean", "ENABLE_CUSTOM_CSS", "false" } } - flavorDimensions "platform" dexOptions { jumboMode true } @@ -83,11 +82,11 @@ dependencies { androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0', { exclude group: 'com.android.support', module: 'support-annotations' }) - androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' - androidTestImplementation 'androidx.test:runner:1.1.1' - androidTestImplementation 'androidx.test:rules:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + androidTestImplementation 'androidx.test:runner:1.2.0' + androidTestImplementation 'androidx.test:rules:1.2.0' androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0' - implementation 'androidx.appcompat:appcompat:1.1.0-alpha05' + implementation 'androidx.appcompat:appcompat:1.1.0-rc01' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'com.google.android.material:material:1.0.0' implementation 'androidx.legacy:legacy-support-v13:1.0.0' @@ -100,9 +99,9 @@ dependencies { implementation 'com.jakewharton.rxbinding2:rxbinding-design:2.0.0' implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' implementation 'io.reactivex.rxjava2:rxjava:2.2.7' - implementation 'com.google.firebase:firebase-core:16.0.9' + implementation 'com.google.firebase:firebase-core:17.0.1' implementation 'com.android.billingclient:billing:1.2' - implementation 'com.crashlytics.sdk.android:crashlytics:2.10.0' + implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1' implementation 'androidx.multidex:multidex:2.0.1' implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/utility/Extensions.kt b/app/src/main/java/com/wbrawner/simplemarkdown/utility/Extensions.kt new file mode 100644 index 0000000..0762ee4 --- /dev/null +++ b/app/src/main/java/com/wbrawner/simplemarkdown/utility/Extensions.kt @@ -0,0 +1,13 @@ +package com.wbrawner.simplemarkdown.utility + +import android.content.Context +import android.view.View +import android.view.inputmethod.InputMethodManager + +fun View.showKeyboard() = + (context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager) + .toggleSoftInput(InputMethodManager.SHOW_FORCED, 0) + +fun View.hideKeyboard() = + (context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager) + .hideSoftInputFromWindow(windowToken, 0) \ No newline at end of file diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/view/ViewPagerPage.kt b/app/src/main/java/com/wbrawner/simplemarkdown/view/ViewPagerPage.kt new file mode 100644 index 0000000..d978d44 --- /dev/null +++ b/app/src/main/java/com/wbrawner/simplemarkdown/view/ViewPagerPage.kt @@ -0,0 +1,6 @@ +package com.wbrawner.simplemarkdown.view + +interface ViewPagerPage { + fun onSelected() + fun onDeselected() +} \ No newline at end of file diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/MainActivity.kt b/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/MainActivity.kt index 3556e40..25c7209 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/MainActivity.kt +++ b/app/src/main/java/com/wbrawner/simplemarkdown/view/activity/MainActivity.kt @@ -50,7 +50,9 @@ class MainActivity : AppCompatActivity(), ActivityCompat.OnRequestPermissionsRes ) } (application as MarkdownApplication).component.inject(this) - pager.adapter = EditPagerAdapter(supportFragmentManager, this@MainActivity) + val adapter = EditPagerAdapter(supportFragmentManager, this@MainActivity) + pager.adapter = adapter + pager.addOnPageChangeListener(adapter) pager.pageMargin = 1 pager.setPageMarginDrawable(R.color.colorAccent) tabLayout.setupWithViewPager(pager) diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/view/adapter/EditPagerAdapter.kt b/app/src/main/java/com/wbrawner/simplemarkdown/view/adapter/EditPagerAdapter.kt index 6e1dc60..d2003a3 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/view/adapter/EditPagerAdapter.kt +++ b/app/src/main/java/com/wbrawner/simplemarkdown/view/adapter/EditPagerAdapter.kt @@ -5,16 +5,21 @@ import android.content.res.Configuration import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter +import androidx.viewpager.widget.ViewPager import com.wbrawner.simplemarkdown.R import com.wbrawner.simplemarkdown.view.fragment.EditFragment import com.wbrawner.simplemarkdown.view.fragment.PreviewFragment -class EditPagerAdapter(fm: FragmentManager, private val context: Context) : FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { +class EditPagerAdapter(fm: FragmentManager, private val context: Context) + : FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT), ViewPager.OnPageChangeListener { + + private val editFragment = EditFragment() + private val previewFragment = PreviewFragment() override fun getItem(position: Int): Fragment { return when (position) { - FRAGMENT_EDIT -> EditFragment() - FRAGMENT_PREVIEW -> PreviewFragment() + FRAGMENT_EDIT -> editFragment + FRAGMENT_PREVIEW -> previewFragment else -> throw IllegalStateException("Attempting to get fragment for invalid page number") } } @@ -40,6 +45,23 @@ class EditPagerAdapter(fm: FragmentManager, private val context: Context) : Frag } } + override fun onPageScrollStateChanged(state: Int) { + } + + override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { + } + + override fun onPageSelected(position: Int) { + when (position) { + FRAGMENT_EDIT -> { + editFragment.onSelected() + } + FRAGMENT_PREVIEW -> { + editFragment.onDeselected() + } + } + } + companion object { const val FRAGMENT_EDIT = 0 const val FRAGMENT_PREVIEW = 1 diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/view/fragment/EditFragment.kt b/app/src/main/java/com/wbrawner/simplemarkdown/view/fragment/EditFragment.kt index c583d4b..925d423 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/view/fragment/EditFragment.kt +++ b/app/src/main/java/com/wbrawner/simplemarkdown/view/fragment/EditFragment.kt @@ -1,14 +1,12 @@ package com.wbrawner.simplemarkdown.view.fragment import android.annotation.SuppressLint -import android.content.Context import android.os.Bundle import android.preference.PreferenceManager import android.view.LayoutInflater import android.view.MotionEvent import android.view.View import android.view.ViewGroup -import android.view.inputmethod.InputMethodManager import android.widget.EditText import android.widget.ScrollView import android.widget.Toast @@ -19,20 +17,22 @@ import com.wbrawner.simplemarkdown.R import com.wbrawner.simplemarkdown.presentation.MarkdownPresenter import com.wbrawner.simplemarkdown.utility.MarkdownObserver import com.wbrawner.simplemarkdown.utility.ReadabilityObserver +import com.wbrawner.simplemarkdown.utility.hideKeyboard +import com.wbrawner.simplemarkdown.utility.showKeyboard import com.wbrawner.simplemarkdown.view.MarkdownEditView +import com.wbrawner.simplemarkdown.view.ViewPagerPage import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers import java.util.concurrent.TimeUnit import javax.inject.Inject +import kotlin.math.abs -class EditFragment : Fragment(), MarkdownEditView { +class EditFragment : Fragment(), MarkdownEditView, ViewPagerPage { @Inject lateinit var presenter: MarkdownPresenter private var markdownEditor: EditText? = null private var markdownEditorScroller: ScrollView? = null - private var lastScrollEvent = -1 - @SuppressLint("ClickableViewAccessibility") override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { @@ -68,19 +68,26 @@ class EditFragment : Fragment(), MarkdownEditView { super.onViewCreated(view, savedInstanceState) presenter.setEditView(this@EditFragment) - markdownEditorScroller!!.setOnTouchListener { v, event -> - // The focus should only be set if this was a click, and not a scroll - if (lastScrollEvent == MotionEvent.ACTION_DOWN && event.action == MotionEvent.ACTION_UP) { - if (activity == null) { - return@setOnTouchListener false + var touchDown = 0L + var oldX = 0f + var oldY = 0f + markdownEditorScroller!!.setOnTouchListener { _, event -> + // The ScrollView's onClickListener doesn't seem to be called, so I've had to + // implement a sort of custom click listener that checks that the tap was both quick + // and didn't drag. + when (event?.action) { + MotionEvent.ACTION_DOWN -> { + touchDown = System.currentTimeMillis() + oldX = event.rawX + oldY = event.rawY + } + MotionEvent.ACTION_UP -> { + if (System.currentTimeMillis() - touchDown < 150 + && abs(event.rawX - oldX) < 25 + && abs(event.rawY - oldY) < 25) + markdownEditor?.showKeyboard() } - val imm = activity - ?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager - ?: return@setOnTouchListener false - imm.showSoftInput(markdownEditor, InputMethodManager.SHOW_IMPLICIT) - markdownEditor!!.requestFocus() } - lastScrollEvent = event.action false } } @@ -94,6 +101,15 @@ class EditFragment : Fragment(), MarkdownEditView { override fun onPause() { super.onPause() presenter.setEditView(null) + markdownEditor?.hideKeyboard() + } + + override fun onSelected() { + markdownEditor?.showKeyboard() + } + + override fun onDeselected() { + markdownEditor?.hideKeyboard() } override fun getMarkdown(): String { diff --git a/app/src/main/java/com/wbrawner/simplemarkdown/view/fragment/PreviewFragment.kt b/app/src/main/java/com/wbrawner/simplemarkdown/view/fragment/PreviewFragment.kt index e5bffe4..ed369ac 100644 --- a/app/src/main/java/com/wbrawner/simplemarkdown/view/fragment/PreviewFragment.kt +++ b/app/src/main/java/com/wbrawner/simplemarkdown/view/fragment/PreviewFragment.kt @@ -29,18 +29,13 @@ class PreviewFragment : Fragment(), MarkdownPreviewView { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { - sharedPreferences = PreferenceManager.getDefaultSharedPreferences(container!!.context) - // Inflate the layout for this fragment - val view = inflater.inflate(R.layout.fragment_preview, container, false) + ): View? = inflater.inflate(R.layout.fragment_preview, container, false) + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + sharedPreferences = PreferenceManager.getDefaultSharedPreferences(view.context) markdownPreview = view.findViewById(R.id.markdown_view) - val activity = activity - if (activity != null) { - (activity.application as MarkdownApplication).component.inject(this) - } - if (BuildConfig.DEBUG) - WebView.setWebContentsDebuggingEnabled(true) - return view + (activity?.application as? MarkdownApplication)?.component?.inject(this) + WebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG) } override fun updatePreview(html: String) {