Skip to content

Instantly share code, notes, and snippets.

@thegarlynch
Created April 17, 2020 10:36
Show Gist options
  • Save thegarlynch/fc17f88ced12d00d75cc0bfe04392447 to your computer and use it in GitHub Desktop.
Save thegarlynch/fc17f88ced12d00d75cc0bfe04392447 to your computer and use it in GitHub Desktop.
package com.thegar.helper
import android.annotation.SuppressLint
import android.graphics.PixelFormat
import android.os.Build
import android.os.Bundle
import android.view.*
import android.widget.FrameLayout
import android.widget.ScrollView
import androidx.annotation.CallSuper
import androidx.annotation.LayoutRes
import androidx.core.view.doOnLayout
import androidx.fragment.app.Fragment
abstract class FullScreenFragment(@LayoutRes private val layoutId : Int) : Fragment(){
private val windowManager get() = requireActivity().windowManager
@SuppressLint("ClickableViewAccessibility")
@CallSuper
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val mChildrenView = inflater.inflate(layoutId, null)
val param = WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_APPLICATION_PANEL,
0,
PixelFormat.TRANSLUCENT
)
param.addFlag(WindowManager.LayoutParams.FLAG_FULLSCREEN)
param.addFlag(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
param.token = requireActivity().findViewById<View>(android.R.id.content).windowToken
param.windowAnimations = android.R.style.Animation_Dialog
updateLayoutParam(param)
val mTopView : ViewGroup
if(param.height == WindowManager.LayoutParams.MATCH_PARENT){
mTopView = object : FrameLayout(inflater.context){
override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
return dispatchKeyUtil(event) xor super.dispatchKeyEvent(event)
}
}
}else{
mTopView = object : ScrollView(inflater.context){
var childMeasurement = -1
var scrollable = false
init {
mChildrenView.doOnLayout {
childMeasurement = it.measuredHeight
}
viewTreeObserver.addOnGlobalLayoutListener {
scrollable = measuredHeight < childMeasurement
}
}
override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
return dispatchKeyUtil(event) xor super.dispatchKeyEvent(event)
}
override fun onTouchEvent(ev: MotionEvent): Boolean {
return when (ev.action) {
MotionEvent.ACTION_DOWN -> // if we can scroll pass the event to the superclass
scrollable && super.onTouchEvent(ev)
else -> super.onTouchEvent(ev)
}
}
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
// Don't do anything with intercepted touch events if
// we are not scrollable
return scrollable && super.onInterceptTouchEvent(ev)
}
}
}
mTopView.isFocusableInTouchMode = true
mTopView.isClickable = true
mTopView.setOnTouchListener { _, event ->
val isConsumed = event.action == MotionEvent.ACTION_OUTSIDE
if(isConsumed){
finish()
}
false
}
// HAHA. THIS IS A GREAT FIND.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
param.addFlag(WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR)
}
mTopView.addView(mChildrenView, ViewGroup.LayoutParams(-1, -2))
windowManager.addView(mTopView, param)
return mTopView
}
private fun dispatchKeyUtil(event : KeyEvent?) : Boolean{
if(event?.keyCode == KeyEvent.KEYCODE_BACK){
finish()
return true
}
return false
}
fun WindowManager.LayoutParams.addFlag(masks : Int){
flags = flags and masks.inv() or masks
}
fun WindowManager.LayoutParams.clearFlag(masks : Int){
flags = flags and masks.inv()
}
fun finish(){
if (parentFragment != null) {
requireParentFragment().childFragmentManager.popBackStack()
} else {
requireActivity().onBackPressed()
}
}
protected open fun updateLayoutParam(param : WindowManager.LayoutParams) : WindowManager.LayoutParams = param
@CallSuper
override fun onDestroyView() {
super.onDestroyView()
windowManager.removeView(view)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment