Skip to content

Commit b958310

Browse files
CDRussellsubsymbolic
authored andcommitted
UI and keyboard interaction improvements
* Update libraries and add android-ktx * Replace `match_parent` with `0dp` which *might* because of toolbar bug The toolbar occasionally stops filling the entire width, and it might be because of this. View immediately under a ConstraintLayout should not use `match_parent`, as per official docs (https://developer.android.com/reference/android/support/constraint/ConstraintLayout.html#RelativePositioning) * Remove excessive margin from logo guideline * Make DDG logo animate with the keyboard * Clean up keyboard interactions including hiding keyboard when popup menu accessed
1 parent 2717167 commit b958310

File tree

10 files changed

+62
-59
lines changed

10 files changed

+62
-59
lines changed

app/build.gradle

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,9 @@ android {
7777
}
7878

7979
ext {
80-
supportLibrary = "27.0.2"
80+
supportLibrary = "27.1.0"
8181
architectureComponents = "1.0.0"
82+
architectureComponentsExtensions = "1.1.0"
8283
dagger = "2.14.1"
8384
retrofit = "2.3.0"
8485
ankoVersion = "0.10.4"
@@ -113,8 +114,11 @@ dependencies {
113114
implementation "org.jetbrains.anko:anko-commons:$ankoVersion"
114115
implementation "org.jetbrains.anko:anko-design:$ankoVersion"
115116

117+
// Android KTX
118+
implementation 'androidx.core:core-ktx:0.2'
119+
116120
// ViewModel and LiveData
117-
implementation "android.arch.lifecycle:extensions:$architectureComponents"
121+
implementation "android.arch.lifecycle:extensions:$architectureComponentsExtensions"
118122
kapt "android.arch.lifecycle:compiler:$architectureComponents"
119123
testImplementation "android.arch.core:core-testing:$architectureComponents"
120124
androidTestImplementation "android.arch.core:core-testing:$architectureComponents"

app/src/androidTest/java/com/duckduckgo/app/browser/BrowserTabViewModelTest.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,11 +171,11 @@ class BrowserTabViewModelTest {
171171
}
172172

173173
@Test
174-
fun whenViewBecomesVisibleWithoutActiveSiteThenKeyboardNotHidden() {
174+
fun whenViewBecomesVisibleWithoutActiveSiteThenKeyboardShown() {
175175
testee.url.value = null
176176
testee.onViewVisible()
177177
verify(mockCommandObserver, atLeastOnce()).onChanged(commandCaptor.capture())
178-
assertTrue(commandCaptor.allValues.none { it is Command.HideKeyboard })
178+
assertTrue(commandCaptor.lastValue is Command.ShowKeyboard)
179179
}
180180

181181
@Test
@@ -557,8 +557,7 @@ class BrowserTabViewModelTest {
557557
@Test
558558
fun whenUserSelectsToShareLinkWithNullUrlThenShareLinkCommandNotSent() {
559559
testee.userSharingLink(null)
560-
val allCommands = captureCommands().allValues
561-
assertEquals(0, allCommands.count{ it is Command.ShareLink })
560+
verify(mockCommandObserver, never()).onChanged(any())
562561
}
563562

564563
private fun captureCommands() : ArgumentCaptor<Command> {

app/src/main/java/com/duckduckgo/app/bookmarks/ui/BookmarksActivity.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,14 +157,14 @@ class BookmarksActivity : DuckDuckGoActivity() {
157157
notifyDataSetChanged()
158158
}
159159

160-
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): BookmarksViewHolder {
160+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BookmarksViewHolder {
161161
val inflater = LayoutInflater.from(context)
162162
val view = inflater.inflate(R.layout.view_bookmark_entry, parent, false)
163163
return BookmarksViewHolder(view, viewModel)
164164
}
165165

166-
override fun onBindViewHolder(holder: BookmarksViewHolder?, position: Int) {
167-
holder?.update(bookmarks[position])
166+
override fun onBindViewHolder(holder: BookmarksViewHolder, position: Int) {
167+
holder.update(bookmarks[position])
168168
}
169169

170170
override fun getItemCount(): Int {

app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.duckduckgo.app.browser
1818

19+
import android.animation.LayoutTransition.CHANGING
1920
import android.annotation.SuppressLint
2021
import android.arch.lifecycle.Observer
2122
import android.arch.lifecycle.ViewModelProviders
@@ -36,6 +37,8 @@ import android.webkit.WebView
3637
import android.webkit.WebView.FindListener
3738
import android.widget.EditText
3839
import android.widget.TextView
40+
import androidx.view.postDelayed
41+
import androidx.view.updatePaddingRelative
3942
import com.duckduckgo.app.bookmarks.ui.SaveBookmarkDialogFragment
4043
import com.duckduckgo.app.browser.BrowserTabViewModel.*
4144
import com.duckduckgo.app.browser.autoComplete.BrowserAutoCompleteSuggestionsAdapter
@@ -125,7 +128,7 @@ class BrowserTabFragment : Fragment(), FindListener {
125128
configureOmnibarTextInput()
126129
configureFindInPage()
127130
configureAutoComplete()
128-
addTextChangedListeners()
131+
configureKeyboardAwareLogoAnimation()
129132
consumeSharedText()
130133
}
131134

@@ -134,6 +137,12 @@ class BrowserTabFragment : Fragment(), FindListener {
134137
viewModel.onUserSubmittedQuery(text)
135138
}
136139

140+
override fun onResume() {
141+
super.onResume()
142+
addTextChangedListeners()
143+
viewModel.onViewVisible()
144+
}
145+
137146
private fun createPopupMenu() {
138147
popupMenu = BrowserPopupMenu(layoutInflater)
139148
val view = popupMenu.contentView
@@ -210,7 +219,7 @@ class BrowserTabFragment : Fragment(), FindListener {
210219
startActivity(intent)
211220
}
212221
Command.ShowKeyboard -> {
213-
omnibarTextInput.postDelayed({ omnibarTextInput?.showKeyboard() }, 100)
222+
showKeyboard()
214223
}
215224
Command.HideKeyboard -> {
216225
hideKeyboard()
@@ -337,7 +346,7 @@ class BrowserTabFragment : Fragment(), FindListener {
337346
private fun showFindInPageView(viewState: FindInPage) {
338347
if (findInPageContainer.visibility != View.VISIBLE) {
339348
findInPageContainer.show()
340-
findInPageInput.postDelayed({ findInPageInput?.showKeyboard() }, 300)
349+
findInPageInput.postDelayed(KEYBOARD_DELAY) { findInPageInput?.showKeyboard() }
341350
}
342351

343352
when (viewState.showNumberMatches) {
@@ -369,14 +378,14 @@ class BrowserTabFragment : Fragment(), FindListener {
369378
private fun showClearButton() {
370379
omnibarTextInput.post {
371380
clearOmnibarInputButton?.show()
372-
omnibarTextInput?.updatePadding(paddingEnd = 40.toPx())
381+
omnibarTextInput?.updatePaddingRelative(end = 40.toPx())
373382
}
374383
}
375384

376385
private fun hideClearButton() {
377386
omnibarTextInput.post {
378387
clearOmnibarInputButton?.hide()
379-
omnibarTextInput?.updatePadding(paddingEnd = 10.toPx())
388+
omnibarTextInput?.updatePaddingRelative(end = 10.toPx())
380389
}
381390
}
382391

@@ -397,6 +406,7 @@ class BrowserTabFragment : Fragment(), FindListener {
397406
return@setOnMenuItemClickListener true
398407
}
399408
R.id.browserPopup -> {
409+
hideKeyboard()
400410
launchPopupMenu()
401411
return@setOnMenuItemClickListener true
402412
}
@@ -454,6 +464,10 @@ class BrowserTabFragment : Fragment(), FindListener {
454464
clearOmnibarInputButton.setOnClickListener { omnibarTextInput.setText("") }
455465
}
456466

467+
private fun configureKeyboardAwareLogoAnimation() {
468+
logoParent.layoutTransition.enableTransitionType(CHANGING)
469+
}
470+
457471
private fun userEnteredQuery(query: String) {
458472
viewModel.onUserSubmittedQuery(query)
459473
}
@@ -551,8 +565,18 @@ class BrowserTabFragment : Fragment(), FindListener {
551565
}
552566

553567
private fun hideKeyboard() {
554-
omnibarTextInput.hideKeyboard()
555-
focusDummy.requestFocus()
568+
if (!isHidden) {
569+
Timber.v("Keyboard now hiding")
570+
omnibarTextInput.postDelayed(KEYBOARD_DELAY) { omnibarTextInput?.hideKeyboard() }
571+
focusDummy.requestFocus()
572+
}
573+
}
574+
575+
private fun showKeyboard() {
576+
if (!isHidden) {
577+
Timber.v("Keyboard now showing")
578+
omnibarTextInput.postDelayed(KEYBOARD_DELAY) { omnibarTextInput?.showKeyboard() }
579+
}
556580
}
557581

558582
override fun onSaveInstanceState(bundle: Bundle) {
@@ -577,7 +601,7 @@ class BrowserTabFragment : Fragment(), FindListener {
577601
viewModel.resetView()
578602
destroyWebView()
579603
configureWebView()
580-
omnibarTextInput.postDelayed({ omnibarTextInput?.showKeyboard() }, 300)
604+
showKeyboard()
581605
}
582606

583607
fun onBackPressed(): Boolean {
@@ -611,6 +635,7 @@ class BrowserTabFragment : Fragment(), FindListener {
611635
private const val TAB_ID_ARG = "TAB_ID_ARG"
612636
private const val ADD_BOOKMARK_FRAGMENT_TAG = "ADD_BOOKMARK"
613637
private const val QUERY_EXTRA_ARG = "QUERY_EXTRA_ARG"
638+
private const val KEYBOARD_DELAY = 200L
614639

615640
fun newInstance(tabId: String, query: String? = null): BrowserTabFragment {
616641
val fragment = BrowserTabFragment()

app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ class BrowserTabViewModel(
130130
viewState.value = ViewState()
131131
appConfigurationObservable.observeForever(appConfigurationObserver)
132132
configureAutoComplete()
133-
command.value = ShowKeyboard
134133
}
135134

136135
fun load(tabId: String) {
@@ -170,9 +169,7 @@ class BrowserTabViewModel(
170169
}
171170

172171
fun onViewVisible() {
173-
if (url.value != null) {
174-
command.value = HideKeyboard
175-
}
172+
command.value = if (url.value == null) ShowKeyboard else Command.HideKeyboard
176173
}
177174

178175
fun onUserSubmittedQuery(input: String) {

app/src/main/java/com/duckduckgo/app/global/view/ViewExtension.kt

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -79,17 +79,5 @@ fun View.hideKeyboard(): Boolean {
7979
return false
8080
}
8181

82-
/**
83-
* Update the padding. Only specify the padding you want updated; all others will take current value
84-
*
85-
* Values are to be specified in pixels.
86-
*/
87-
fun View.updatePadding(paddingStart: Int = getPaddingStart(),
88-
paddingTop: Int = getPaddingTop(),
89-
paddingEnd: Int = getPaddingEnd(),
90-
paddingBottom: Int = getPaddingBottom()) {
91-
setPaddingRelative(paddingStart, paddingTop, paddingEnd, paddingBottom)
92-
}
93-
9482
fun Int.toDp(): Int = (this / Resources.getSystem().displayMetrics.density).toInt()
9583
fun Int.toPx(): Int = (this * Resources.getSystem().displayMetrics.density).toInt()

app/src/main/java/com/duckduckgo/app/privacy/ui/PrivacyPracticesAdapter.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ class PrivacyPracticesAdapter : RecyclerView.Adapter<PrivacyPracticesAdapter.Pra
3535

3636
private var terms: List<Pair<Int, String>> = ArrayList()
3737

38-
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): PracticeViewHolder {
39-
val root = LayoutInflater.from(parent!!.context).inflate(R.layout.item_privacy_practice, parent, false)
38+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PracticeViewHolder {
39+
val root = LayoutInflater.from(parent.context).inflate(R.layout.item_privacy_practice, parent, false)
4040
return PracticeViewHolder(root, root.icon, root.description)
4141
}
4242

app/src/main/java/com/duckduckgo/app/privacy/ui/TrackerNetworksAdapter.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,14 @@ class TrackerNetworksAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
5555
private var viewData: List<ViewData> = ArrayList()
5656
private var networkRenderer: TrackersRenderer = TrackersRenderer()
5757

58-
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): RecyclerView.ViewHolder {
58+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
5959
return when (viewType) {
6060
HEADER -> {
61-
val root = LayoutInflater.from(parent!!.context).inflate(R.layout.item_tracker_network_header, parent, false)
61+
val root = LayoutInflater.from(parent.context).inflate(R.layout.item_tracker_network_header, parent, false)
6262
HeaderViewHolder(root, root.network, root.icon)
6363
}
6464
else -> {
65-
val root = LayoutInflater.from(parent!!.context).inflate(R.layout.item_tracker_network_element, parent, false)
65+
val root = LayoutInflater.from(parent.context).inflate(R.layout.item_tracker_network_element, parent, false)
6666
RowViewHolder(root, root.host, root.category)
6767
}
6868
}

app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherAdapter.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ class TabSwitcherAdapter(private val context: Context, private val itemClickList
3434

3535
private var data: List<TabEntity> = ArrayList()
3636

37-
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): TabViewHolder {
38-
val inflater = LayoutInflater.from(parent!!.context)
37+
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TabViewHolder {
38+
val inflater = LayoutInflater.from(parent.context)
3939
val root = inflater.inflate(R.layout.item_tab, parent, false)
4040
return TabViewHolder(root, root.favicon, root.title, root.url, root.close)
4141
}

app/src/main/res/layout/fragment_browser_tab.xml

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,50 +21,40 @@
2121
android:layout_width="match_parent"
2222
android:layout_height="match_parent"
2323
app:layout_scrollFlags="scroll|enterAlways"
24+
android:fitsSystemWindows="true"
2425
tools:context="com.duckduckgo.app.browser.BrowserActivity"
2526
tools:menu="menu_browser_activity">
2627

2728
<android.support.design.widget.CoordinatorLayout
2829
android:id="@+id/rootView"
29-
android:layout_width="match_parent"
30+
android:layout_width="0dp"
3031
android:layout_height="match_parent">
3132

3233
<android.support.constraint.ConstraintLayout
34+
android:id="@+id/logoParent"
3335
android:layout_width="match_parent"
3436
android:layout_height="match_parent"
35-
android:layout_marginTop="?attr/actionBarSize">
37+
android:animateLayoutChanges="true">
3638

3739
<android.support.constraint.Guideline
3840
android:id="@+id/guidelineTop"
3941
android:layout_width="wrap_content"
4042
android:layout_height="wrap_content"
4143
android:orientation="horizontal"
42-
app:layout_constraintGuide_percent="0.15"
43-
/>
44+
app:layout_constraintGuide_percent="0.5" />
4445

4546
<ImageView
4647
android:id="@+id/ddgLogo"
47-
android:layout_width="0dp"
48-
android:layout_height="0dp"
49-
android:layout_marginStart="20dp"
50-
android:layout_marginEnd="20dp"
48+
android:layout_width="180dp"
49+
android:layout_height="180dp"
5150
android:contentDescription="@string/duckDuckGoLogoDescription"
5251
android:src="@drawable/full_logo"
53-
app:layout_constraintBottom_toBottomOf="@id/guidelineBottom"
52+
app:layout_constraintBottom_toBottomOf="@id/guidelineTop"
5453
app:layout_constraintEnd_toEndOf="parent"
55-
app:layout_constraintHorizontal_bias="0.5"
5654
app:layout_constraintStart_toStartOf="parent"
57-
app:layout_constraintTop_toTopOf="@id/guidelineTop" />
58-
59-
<android.support.constraint.Guideline
60-
android:id="@+id/guidelineBottom"
61-
android:layout_width="wrap_content"
62-
android:layout_height="wrap_content"
63-
android:orientation="horizontal"
64-
app:layout_constraintGuide_percent="0.75"
55+
app:layout_constraintTop_toTopOf="@id/guidelineTop"
6556
/>
6657

67-
6858
</android.support.constraint.ConstraintLayout>
6959

7060
<android.support.design.widget.AppBarLayout

0 commit comments

Comments
 (0)