Skip to content

Commit

Permalink
Tweaking PanelsChildGestureRegionObserver (#29)
Browse files Browse the repository at this point in the history
* Fixing listener

* Fixing more issues

* Panel fixes

* Adding instructions

* Fixing gradle
  • Loading branch information
charlesx2013 authored Aug 18, 2021
1 parent 7959038 commit 2396dc0
Show file tree
Hide file tree
Showing 8 changed files with 344 additions and 81 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ buildscript {
ext.robolectricVersion = '4.3.1'
ext.rxJavaVersion = '3.0.3'
ext.truthVersion = '0.40'
ext.coordinatorLayoutVersion = '1.1.0'
ext.materialDesignVersion = '1.4.0'

repositories {
google()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package com.discord.panels

import android.graphics.Rect
import android.view.View
import android.view.ViewTreeObserver
import androidx.annotation.UiThread
import com.discord.panels.PanelsChildGestureRegionObserver.GestureRegionsListener
import java.lang.ref.WeakReference

/**
Expand All @@ -28,11 +30,12 @@ class PanelsChildGestureRegionObserver : View.OnLayoutChangeListener {
fun onGestureRegionsUpdate(gestureRegions: List<Rect>)
}

private var viewIdToGestureRegionMap = mutableMapOf<Int, Rect>()
private var gestureRegionsListeners = mutableSetOf<GestureRegionsListener>()
private val viewIdToGestureRegionMap = mutableMapOf<Int, Rect>()
private val viewIdToListenerMap = mutableMapOf<Int, ViewTreeObserver.OnScrollChangedListener>()
private val gestureRegionsListeners = mutableSetOf<GestureRegionsListener>()

override fun onLayoutChange(
view: View?,
view: View,
left: Int,
top: Int,
right: Int,
Expand All @@ -42,39 +45,76 @@ class PanelsChildGestureRegionObserver : View.OnLayoutChangeListener {
oldRight: Int,
oldBottom: Int
) {
if (view != null) {
val coordinates = intArrayOf(0, 0)
view.getLocationOnScreen(coordinates)

val x = coordinates[0]
val y = coordinates[1]

val absoluteLeft = x + left
val absoluteTop = y + top
val absoluteRight = x + right
val absoluteBottom = y + bottom

viewIdToGestureRegionMap[view.id] = Rect(
absoluteLeft,
absoluteTop,
absoluteRight,
absoluteBottom
)
val coordinates = intArrayOf(0, 0)
view.getLocationInWindow(coordinates)

val x = coordinates[0]
val y = coordinates[1]

val absoluteRight = x + right
val absoluteBottom = y + bottom

viewIdToGestureRegionMap[view.id] = Rect(
x,
y,
absoluteRight,
absoluteBottom
)

publishGestureRegionsUpdate()
}

publishGestureRegionsUpdate()
@UiThread
fun register(view: View) {
view.addOnLayoutChangeListener(this)

val listener = ViewTreeObserver.OnScrollChangedListener {
onLayoutChange(
view = view,
left = view.left,
top = view.top,
right = view.right,
bottom = view.bottom,
oldLeft = 0,
oldTop = 0,
oldRight = 0,
oldBottom = 0
)
}

view.viewTreeObserver.addOnScrollChangedListener(listener)
viewIdToListenerMap[view.id] = listener
}

/**
* Stop publishing gesture region updates based on layout changes to android.view.View
* corresponding to [viewId].
*/
@Deprecated(
message = "Use unregister instead",
replaceWith = ReplaceWith("unregister(view)")
)
@UiThread
fun remove(viewId: Int) {
viewIdToGestureRegionMap.remove(viewId)
publishGestureRegionsUpdate()
}

/**
* Stop publishing gesture region updates based on layout and scroll changes to android.view.View
*/
@UiThread
fun unregister(view: View) {
viewIdToListenerMap.remove(view.id)?.let {
view.viewTreeObserver.removeOnScrollChangedListener(it)
}

view.removeOnLayoutChangeListener(this)

viewIdToGestureRegionMap.remove(view.id)
publishGestureRegionsUpdate()
}

/**
* Add [gestureRegionsListener] to this [PanelsChildGestureRegionObserver]. This method notifies
* that listener as soon as it adds the listener. That listener will continue to get future
Expand Down
10 changes: 8 additions & 2 deletions sample_app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ android {
buildToolsVersion "29.0.2"

compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
sourceCompatibility JavaVersion.VERSION_1_8.toString()
targetCompatibility JavaVersion.VERSION_1_8.toString()
}

kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
}

defaultConfig {
Expand Down Expand Up @@ -57,6 +61,8 @@ dependencies {
implementation "androidx.core:core-ktx:$androidxCoreVersion"
implementation "io.reactivex.rxjava3:rxjava:$rxJavaVersion"
implementation project(':overlapping_panels')
implementation "androidx.coordinatorlayout:coordinatorlayout:$coordinatorLayoutVersion"
implementation "com.google.android.material:material:$materialDesignVersion"

testImplementation "junit:junit:$junitVersion"
testImplementation "com.google.truth:truth:$truthVersion"
Expand Down
95 changes: 95 additions & 0 deletions sample_app/src/main/java/com/discord/sampleapp/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,25 @@ package com.discord.sampleapp

import android.graphics.Rect
import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.ViewModelProvider
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import com.discord.panels.OverlappingPanelsLayout
import com.discord.panels.PanelState
import com.discord.panels.PanelsChildGestureRegionObserver
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import io.reactivex.rxjava3.disposables.Disposable

class MainActivity : AppCompatActivity(),
Expand All @@ -22,9 +34,18 @@ class MainActivity : AppCompatActivity(),
private lateinit var horizontalScrollItemsContainer: View
private lateinit var showToastButton: View

private lateinit var tabLayout: TabLayout
private lateinit var viewPager: ViewPager2

private lateinit var centerPanelMainLayout: ViewGroup
private lateinit var viewPagerLayout: ViewGroup

private val adapter = ViewPagerAdapter(this)

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main_activity)
setSupportActionBar(findViewById(R.id.toolbar))
overlappingPanels = findViewById(R.id.overlapping_panels)

openStartPanelButton = findViewById(R.id.open_start_panel_button)
Expand Down Expand Up @@ -68,6 +89,41 @@ class MainActivity : AppCompatActivity(),
this,
MainViewModel.Factory()
).get(MainViewModel::class.java)

centerPanelMainLayout = findViewById(R.id.center_panel_main_layout)
viewPagerLayout = findViewById(R.id.view_pager_layout)
viewPager = findViewById(R.id.view_pager)
tabLayout = findViewById(R.id.tabs)

viewPager.apply {
adapter = this@MainActivity.adapter
addOnLayoutChangeListener(PanelsChildGestureRegionObserver.Provider.get())
PanelsChildGestureRegionObserver.Provider.get().register(this)
}

TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.text = "Text $position"
}.attach()

tabLayout.apply {
addOnLayoutChangeListener(PanelsChildGestureRegionObserver.Provider.get())
PanelsChildGestureRegionObserver.Provider.get().register(this)
}
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_activity, menu)
return true
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.view_pager_menu_item -> {
viewPagerLayout.isVisible = !viewPagerLayout.isVisible
centerPanelMainLayout.isVisible = !centerPanelMainLayout.isVisible
}
}
return super.onOptionsItemSelected(item)
}

override fun onResume() {
Expand Down Expand Up @@ -111,7 +167,10 @@ class MainActivity : AppCompatActivity(),
override fun onDestroy() {
super.onDestroy()

@Suppress("DEPRECATION")
PanelsChildGestureRegionObserver.Provider.get().remove(horizontalScrollItemsContainer.id)
PanelsChildGestureRegionObserver.Provider.get().unregister(viewPager)
PanelsChildGestureRegionObserver.Provider.get().unregister(tabLayout)
}

override fun onGestureRegionsUpdate(gestureRegions: List<Rect>) {
Expand All @@ -123,3 +182,39 @@ class MainActivity : AppCompatActivity(),
overlappingPanels.handleEndPanelState(viewState.endPanelState)
}
}

class ViewPagerAdapter(
activity: FragmentActivity
) : FragmentStateAdapter(activity) {

override fun getItemCount() = 7

override fun createFragment(position: Int) = MainFragment().apply {
this.position = position
}
}

class MainFragment : Fragment() {
private val colors = listOf(
R.color.one,
R.color.two,
R.color.three,
R.color.four,
R.color.five,
R.color.six,
R.color.seven
)

var position: Int = 0

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_main, container, true)
val colorView = view.findViewById<View>(R.id.color)
colorView.setBackgroundColor(ContextCompat.getColor(requireContext(), colors[position]))
return view
}
}
26 changes: 26 additions & 0 deletions sample_app/src/main/res/layout/fragment_main.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

<View
android:id="@+id/color"
android:layout_width="match_parent"
android:layout_height="5000dp"
android:background="@color/one"/>

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="24dp"
android:text="@string/child_gesture_region_instructions" />

</FrameLayout>

</androidx.core.widget.NestedScrollView>
Loading

0 comments on commit 2396dc0

Please sign in to comment.