Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom animations #75

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
buildscript {
ext.KOTLIN_VERSION = '1.3.21'
ext.ANDROID_GRADLE_PLUGIN_VERSION = '4.1.0'
ext.KOTLIN_VERSION = '1.4.31'
ext.ANDROID_GRADLE_PLUGIN_VERSION = '4.1.3'
ext.DOKKA_VERSION = '0.9.18'
ext.BINTRAY_VERSION = '1.8.4'
ext.KORDAMP_VERSION = '0.15.1'
Expand Down Expand Up @@ -43,7 +43,7 @@ configure(allprojects) {
ANDROIDX_RECYCLERVIEW_VERSION = '1.0.0'

ANDROIDX_CONSTRAINTLAYOUT_VERSION = '1.1.3'
ANDROIDX_CORE_KTX_VERSION = '1.1.0'
ANDROIDX_CORE_KTX_VERSION = '1.3.2'
MATERIAL_COMPONENTS_VERSION = '1.2.1'

JUNIT_VERSION = '4.13.1'
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip
13 changes: 12 additions & 1 deletion material-popup-menu/material-popup-menu.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,24 @@ android {
minifyEnabled false
}
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

kotlinOptions {
jvmTarget = '1.8'
}
}

dependencies {
api "androidx.appcompat:appcompat:$ANDROIDX_APPCOMPAT_VERSION"
api "androidx.recyclerview:recyclerview:$ANDROIDX_RECYCLERVIEW_VERSION"

api "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$KOTLIN_VERSION"
implementation "androidx.core:core-ktx:$ANDROIDX_CORE_KTX_VERSION"

api "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$KOTLIN_VERSION"

testImplementation "junit:junit:$JUNIT_VERSION"
testImplementation "org.hamcrest:hamcrest-core:$HAMCREST_VERSION"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package androidx.appcompat.widget

import android.content.Context
import android.widget.PopupWindow
import com.github.zawadz88.materialpopupmenu.PopupAnimation

internal fun createAppCompatPopupWindow(context: Context): PopupWindow = AppCompatPopupWindow(context, null, 0)
internal fun createAppCompatPopupWindow(context: Context, customAnimation: PopupAnimation?) = MaterialPopupWindow(context, customAnimation)
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package androidx.appcompat.widget

import android.content.Context
import android.os.Build
import android.util.Log
import android.view.View
import android.view.WindowManager
import android.widget.PopupWindow
import androidx.core.view.doOnLayout
import com.github.zawadz88.materialpopupmenu.PopupAnimation

internal class MaterialPopupWindow(
context: Context,
private val customAnimation: PopupAnimation?
) : AppCompatPopupWindow(context, null, 0) {

override fun showAsDropDown(anchor: View?) {
prepareAnimation()
super.showAsDropDown(anchor)
startAnimation()
}

override fun showAsDropDown(anchor: View?, xoff: Int, yoff: Int) {
prepareAnimation()
super.showAsDropDown(anchor, xoff, yoff)
startAnimation()
}

override fun showAsDropDown(anchor: View?, xoff: Int, yoff: Int, gravity: Int) {
prepareAnimation()
super.showAsDropDown(anchor, xoff, yoff, gravity)
startAnimation()
}

override fun dismiss() {
customAnimation?.let {
it.onHide(this) {
super.dismiss()
contentView = null
}
} ?: run {
super.dismiss()
contentView = null
}
}

private fun prepareAnimation() {
customAnimation?.onPrepare(this)
if (customAnimation != null) {
disableAnimations()
}
}

private fun startAnimation() {
customAnimation?.let { anim ->
disableAnimations()
anim.onPrepare(this)
contentView?.doOnLayout {
anim.onShow(this)
}
}
}

private fun disableAnimations() {
animationStyle = 0

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
enterTransition = null
exitTransition = null
} else {
try {
val field1 = PopupWindow::class.java.getDeclaredField("mPopupView")
field1.isAccessible = true
val popupView = field1.get(this) as View
val p = popupView.layoutParams as WindowManager.LayoutParams
p.windowAnimations = 0

val field2 = WindowManager.LayoutParams::class.java.getDeclaredField("privateFlags")
field2.isAccessible = true
var flag = field2.getInt(p)
flag = flag or 0x00000040
field2.set(p, flag)

} catch (e: NoSuchFieldException) {
Log.e("WINDOW_PARAMS", "Could not disable window animations.", e)
} catch (e: IllegalAccessException) {
Log.e("WINDOW_PARAMS", "Could not disable window animations.", e)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ internal constructor(
internal val sections: List<PopupMenuSection>,
internal val fixedContentWidthInPx: Int,
internal val dropDownVerticalOffset: Int?,
internal val dropDownHorizontalOffset: Int?
internal val dropDownHorizontalOffset: Int?,
internal val customAnimation: PopupAnimation?
) {

private var popupWindow: MaterialRecyclerViewPopupWindow? = null
Expand All @@ -52,7 +53,8 @@ internal constructor(
dropDownGravity = dropdownGravity,
fixedContentWidthInPx = fixedContentWidthInPx,
dropDownVerticalOffset = dropDownVerticalOffset,
dropDownHorizontalOffset = dropDownHorizontalOffset
dropDownHorizontalOffset = dropDownHorizontalOffset,
customAnimation = customAnimation
)
val adapter = PopupMenuAdapter(sections) { popupWindow.dismiss() }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ class MaterialPopupMenuBuilder {
*/
var dropDownHorizontalOffset: Int? = null

/**
* Set up a custom animation
*/
var customAnimation: PopupAnimation? = null

private val sectionHolderList = arrayListOf<SectionHolder>()

/**
Expand Down Expand Up @@ -88,7 +93,8 @@ class MaterialPopupMenuBuilder {
sections = sections,
fixedContentWidthInPx = fixedContentWidthInPx,
dropDownVerticalOffset = dropDownVerticalOffset,
dropDownHorizontalOffset = dropDownHorizontalOffset
dropDownHorizontalOffset = dropDownHorizontalOffset,
customAnimation = customAnimation
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.github.zawadz88.materialpopupmenu

import android.view.View
import android.widget.PopupWindow

interface PopupAnimation {

/* view is not yet layed out */
fun onPrepare(popup: PopupWindow) {
popup.contentView.visibility = View.INVISIBLE
}

/* view is layed out - animate it */
fun onShow(popup: PopupWindow)

/* animate the view dismissal */
fun onHide(popup: PopupWindow, onHidden: (() -> Unit))
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import android.view.ViewGroup
import android.view.WindowManager
import android.widget.FrameLayout
import android.widget.PopupWindow
import androidx.appcompat.widget.MaterialPopupWindow
import androidx.appcompat.widget.createAppCompatPopupWindow
import androidx.core.widget.PopupWindowCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.github.zawadz88.materialpopupmenu.PopupAnimation
import com.github.zawadz88.materialpopupmenu.R
import java.lang.reflect.Method

Expand All @@ -32,7 +34,8 @@ internal class MaterialRecyclerViewPopupWindow(
private var dropDownGravity: Int,
private val fixedContentWidthInPx: Int,
dropDownVerticalOffset: Int?,
dropDownHorizontalOffset: Int?
dropDownHorizontalOffset: Int?,
private val customAnimation: PopupAnimation?
) {

@SuppressLint("DiscouragedPrivateApi")
Expand Down Expand Up @@ -91,7 +94,7 @@ internal class MaterialRecyclerViewPopupWindow(

private val tempRect = Rect()

private val popup: PopupWindow
private val popup: MaterialPopupWindow

private val popupMaxWidth: Int

Expand All @@ -116,7 +119,7 @@ internal class MaterialRecyclerViewPopupWindow(
private val popupPaddingTop: Int

init {
popup = createAppCompatPopupWindow(context)
popup = createAppCompatPopupWindow(context, customAnimation)
popup.inputMethodMode = PopupWindow.INPUT_METHOD_NEEDED
popup.isFocusable = true

Expand Down Expand Up @@ -212,7 +215,6 @@ internal class MaterialRecyclerViewPopupWindow(
*/
internal fun dismiss() {
popup.dismiss()
popup.contentView = null
}

/**
Expand Down
4 changes: 4 additions & 0 deletions sample/sample.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ android {
targetCompatibility 1.8
}

kotlinOptions {
jvmTarget = '1.8'
}

buildTypes {
release {
minifyEnabled false
Expand Down
Loading