From ccf95088380e5e237f48e9f579c9a6baad2f8565 Mon Sep 17 00:00:00 2001 From: Haley Date: Mon, 3 Dec 2018 18:15:06 +0900 Subject: [PATCH 001/105] Fix NPE resulting from HoverViewState's callback after it already lost control (#3) --- .../io/mattcarroll/hover/HoverViewStateClosed.java | 14 +++++++++++++- .../mattcarroll/hover/HoverViewStateCollapsed.java | 8 +++++++- .../mattcarroll/hover/HoverViewStateExpanded.java | 5 ++++- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java index 53cb899..8328570 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java @@ -28,14 +28,19 @@ */ class HoverViewStateClosed extends BaseHoverViewState { - private static final String TAG = "HoverMenuViewStateClosed"; + private static final String TAG = "HoverViewStateClosed"; private HoverView mHoverView; + private boolean mHasControl = false; @Override public void takeControl(@NonNull HoverView hoverView) { Log.d(TAG, "Taking control."); super.takeControl(hoverView); + if (mHasControl) { + throw new RuntimeException("Cannot take control of a FloatingTab when we already control one."); + } + mHasControl = true; mHoverView = hoverView; mHoverView.notifyListenersClosing(); mHoverView.mState = this; @@ -47,6 +52,9 @@ public void takeControl(@NonNull HoverView hoverView) { selectedTab.disappear(new Runnable() { @Override public void run() { + if (!mHasControl) { + return; + } mHoverView.mScreen.destroyChainedTab(selectedTab); mHoverView.notifyListenersClosed(); } @@ -59,6 +67,10 @@ public void run() { } private void changeState(@NonNull HoverViewState nextState) { + if (!mHasControl) { + throw new RuntimeException("Cannot give control to another HoverMenuController when we don't have the HoverTab."); + } + mHasControl = false; mHoverView.setState(nextState); mHoverView = null; } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 8092f21..7918360 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -37,7 +37,7 @@ */ class HoverViewStateCollapsed extends BaseHoverViewState { - private static final String TAG = "HoverMenuViewStateCollapsed"; + private static final String TAG = "HoverViewStateCollapsed"; private HoverView mHoverView; private FloatingTab mFloatingTab; @@ -108,6 +108,9 @@ public void takeControl(@NonNull HoverView hoverView) { mHoverView.post(new Runnable() { @Override public void run() { + if (!mHasControl) { + return; + } if (wasFloatingTabVisible) { sendToDock(); } else { @@ -303,6 +306,9 @@ private void sendToDock() { mFloatingTab.dock(new Runnable() { @Override public void run() { + if (!mHasControl) { + return; + } onDocked(); } }); diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java index 577c043..2ddc51d 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java @@ -38,7 +38,7 @@ */ class HoverViewStateExpanded extends BaseHoverViewState { - private static final String TAG = "HoverMenuViewStateExpanded"; + private static final String TAG = "HoverViewStateExpanded"; private static final int ANCHOR_TAB_X_OFFSET_IN_PX = 100; private static final int ANCHOR_TAB_Y_OFFSET_IN_PX = 100; private static final int TAB_SPACING_IN_PX = 200; @@ -57,6 +57,9 @@ class HoverViewStateExpanded extends BaseHoverViewState { private final Runnable mShowTabsRunnable = new Runnable() { @Override public void run() { + if (!mHasControl) { + return; + } mHoverView.mScreen.getShadeView().show(); mHoverView.mScreen.getContentDisplay().selectedTabIs(mSelectedTab); From eeeab6bc313aa6794a061fb0af38f48236d2e745 Mon Sep 17 00:00:00 2001 From: Haley Date: Mon, 3 Dec 2018 18:15:24 +0900 Subject: [PATCH 002/105] Update gradle version, build properties (#1) --- build.gradle | 4 +++- gradle.properties | 5 ++--- gradle/wrapper/gradle-wrapper.properties | 4 ++-- hover/build.gradle | 9 ++++----- hoverdemo-helloworld/build.gradle | 5 ++--- ...ngleSectionNotificationHoverMenuService.java | 2 +- hoverdemo-kitchensink/build.gradle | 17 ++++++++--------- hoverdemo-nonfullscreen/build.gradle | 11 +++++------ 8 files changed, 27 insertions(+), 30 deletions(-) diff --git a/build.gradle b/build.gradle index a8a3253..e209835 100644 --- a/build.gradle +++ b/build.gradle @@ -2,10 +2,11 @@ buildscript { repositories { + google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.0.0-alpha4' + classpath 'com.android.tools.build:gradle:3.2.1' // For Bintray publishing classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.2' @@ -15,6 +16,7 @@ buildscript { allprojects { repositories { + google() jcenter() } } diff --git a/gradle.properties b/gradle.properties index aaf2362..4bced23 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,6 +17,5 @@ # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true compileSdkVersion = 26 -targetSdkVersion = 25 -buildToolsVersion = 25.0.3 -supportLibVersion = 24.2.0 \ No newline at end of file +targetSdkVersion = 26 +supportLibVersion = 26.1.0 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 5027f0d..f09db74 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sat Jun 24 21:38:23 PDT 2017 +#Tue Nov 13 00:07:04 KST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-rc-1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip diff --git a/hover/build.gradle b/hover/build.gradle index 988f291..64c497f 100644 --- a/hover/build.gradle +++ b/hover/build.gradle @@ -5,7 +5,6 @@ version = '0.9.8' android { compileSdkVersion project.compileSdkVersion.toInteger() - buildToolsVersion project.buildToolsVersion defaultConfig { minSdkVersion 15 @@ -21,11 +20,11 @@ android { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - compile "com.android.support:appcompat-v7:${supportLibVersion}" - compile "com.android.support:recyclerview-v7:${supportLibVersion}" // Used to get DiffUtil + implementation fileTree(dir: 'libs', include: ['*.jar']) + api "com.android.support:appcompat-v7:${supportLibVersion}" + api "com.android.support:recyclerview-v7:${supportLibVersion}" // Used to get DiffUtil - testCompile 'junit:junit:4.12' + testImplementation 'junit:junit:4.12' } // For Bintray publishing diff --git a/hoverdemo-helloworld/build.gradle b/hoverdemo-helloworld/build.gradle index 6ced383..255c599 100644 --- a/hoverdemo-helloworld/build.gradle +++ b/hoverdemo-helloworld/build.gradle @@ -2,7 +2,6 @@ apply plugin: 'com.android.application' android { compileSdkVersion project.compileSdkVersion.toInteger() - buildToolsVersion project.buildToolsVersion defaultConfig { applicationId "org.codecanon.hover.hoverdemo.helloworld" @@ -23,6 +22,6 @@ android { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - compile project(':hover') + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation project(':hover') } diff --git a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/SingleSectionNotificationHoverMenuService.java b/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/SingleSectionNotificationHoverMenuService.java index 4be998d..9542a78 100644 --- a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/SingleSectionNotificationHoverMenuService.java +++ b/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/SingleSectionNotificationHoverMenuService.java @@ -20,7 +20,7 @@ import android.content.Intent; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.support.v7.app.NotificationCompat; +import android.support.v4.app.NotificationCompat; import android.view.View; import android.widget.ImageView; diff --git a/hoverdemo-kitchensink/build.gradle b/hoverdemo-kitchensink/build.gradle index b7208da..1592225 100644 --- a/hoverdemo-kitchensink/build.gradle +++ b/hoverdemo-kitchensink/build.gradle @@ -2,7 +2,6 @@ apply plugin: 'com.android.application' android { compileSdkVersion project.compileSdkVersion.toInteger() - buildToolsVersion project.buildToolsVersion defaultConfig { applicationId "io.mattcarroll.hover.hoverdemo" @@ -20,12 +19,12 @@ android { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - testCompile 'junit:junit:4.12' - compile "com.android.support:appcompat-v7:${supportLibVersion}" - compile "com.android.support:design:${supportLibVersion}" - compile "com.android.support:recyclerview-v7:${supportLibVersion}" - compile 'de.greenrobot:eventbus:2.4.0' - compile 'com.larswerkman:HoloColorPicker:1.5' - compile project(':hover') + implementation fileTree(dir: 'libs', include: ['*.jar']) + testImplementation 'junit:junit:4.12' + implementation "com.android.support:appcompat-v7:${supportLibVersion}" + implementation "com.android.support:design:${supportLibVersion}" + implementation "com.android.support:recyclerview-v7:${supportLibVersion}" + implementation 'de.greenrobot:eventbus:2.4.0' + implementation 'com.larswerkman:HoloColorPicker:1.5' + implementation project(':hover') } diff --git a/hoverdemo-nonfullscreen/build.gradle b/hoverdemo-nonfullscreen/build.gradle index d5e797b..c81abc7 100644 --- a/hoverdemo-nonfullscreen/build.gradle +++ b/hoverdemo-nonfullscreen/build.gradle @@ -2,7 +2,6 @@ apply plugin: 'com.android.application' android { compileSdkVersion project.compileSdkVersion.toInteger() - buildToolsVersion project.buildToolsVersion defaultConfig { applicationId "io.mattcarroll.hoverdemonon_fullscreen" @@ -23,13 +22,13 @@ android { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - compile "com.android.support:appcompat-v7:${supportLibVersion}" - compile project(':hover') + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "com.android.support:appcompat-v7:${supportLibVersion}" + implementation project(':hover') - testCompile 'junit:junit:4.12' + testImplementation 'junit:junit:4.12' - androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { + androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) } From 44b8fa942906aa9026c0bcd247b5088d825df21f Mon Sep 17 00:00:00 2001 From: Haley Date: Mon, 14 Jan 2019 19:51:20 +0900 Subject: [PATCH 003/105] [BZZRWRDD-100] Add Preview State for customization (#4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * TabMessageView 생성, Screen 에 붙이기 * onDockChange 에서 MessageView 방향 전환 * Animation detail * MIN, MAX vertical position 을 정해서 tab 이 화면 밖을 벗어나지 못하게 함 * Design Review - Preview 상태에서 다음 State 로 변할 때 상황에 따라 Animation 보여주지 않기 * add 'Preview' in StateChangeListener --- .../io/mattcarroll/hover/ContentDisplay.java | 2 +- .../io/mattcarroll/hover/FloatingTab.java | 13 ++- .../java/io/mattcarroll/hover/HoverMenu.java | 11 ++ .../java/io/mattcarroll/hover/HoverView.java | 107 +++++++++++++++--- .../io/mattcarroll/hover/HoverViewState.java | 2 + .../hover/HoverViewStateClosed.java | 13 +++ .../hover/HoverViewStateCollapsed.java | 53 ++++----- .../hover/HoverViewStateExpanded.java | 29 ++--- .../hover/HoverViewStatePreviewed.java | 62 ++++++++++ .../java/io/mattcarroll/hover/Screen.java | 27 ++++- .../java/io/mattcarroll/hover/TabChain.java | 4 +- .../io/mattcarroll/hover/TabMessageView.java | 98 ++++++++++++++++ hover/src/main/res/values/dimens.xml | 2 + 13 files changed, 345 insertions(+), 78 deletions(-) create mode 100644 hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java create mode 100644 hover/src/main/java/io/mattcarroll/hover/TabMessageView.java diff --git a/hover/src/main/java/io/mattcarroll/hover/ContentDisplay.java b/hover/src/main/java/io/mattcarroll/hover/ContentDisplay.java index 222396b..553d38d 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ContentDisplay.java +++ b/hover/src/main/java/io/mattcarroll/hover/ContentDisplay.java @@ -73,7 +73,7 @@ public void onPositionChange(@NonNull Point position) { } @Override - public void onDockChange(@NonNull Point dock) { + public void onDockChange(@NonNull Dock dock) { // No-op. } }; diff --git a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java index 53a8502..5684abc 100644 --- a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java +++ b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java @@ -48,6 +48,7 @@ class FloatingTab extends FrameLayout { private static final String TAG = "FloatingTab"; + private static final int APPEARING_ANIMATION_DURATION = 300; private final String mId; private int mTabSize; @@ -101,9 +102,9 @@ public void enableDebugMode(boolean debugMode) { public void appear(@Nullable final Runnable onAppeared) { AnimatorSet animatorSet = new AnimatorSet(); ObjectAnimator scaleX = ObjectAnimator.ofFloat(this, "scaleX", 0.0f, 1.0f); - scaleX.setDuration(250); ObjectAnimator scaleY = ObjectAnimator.ofFloat(this, "scaleY", 0.0f, 1.0f); - scaleY.setDuration(250); + animatorSet.setDuration(APPEARING_ANIMATION_DURATION); + animatorSet.setInterpolator(new OvershootInterpolator()); animatorSet.playTogether(scaleX, scaleY); animatorSet.start(); @@ -138,9 +139,8 @@ public void appearImmediate() { public void disappear(@Nullable final Runnable onDisappeared) { AnimatorSet animatorSet = new AnimatorSet(); ObjectAnimator scaleX = ObjectAnimator.ofFloat(this, "scaleX", 0.0f); - scaleX.setDuration(250); ObjectAnimator scaleY = ObjectAnimator.ofFloat(this, "scaleY", 0.0f); - scaleY.setDuration(250); + animatorSet.setDuration(APPEARING_ANIMATION_DURATION); animatorSet.playTogether(scaleX, scaleY); animatorSet.start(); @@ -268,6 +268,7 @@ public void moveTo(@NonNull Point floatPosition) { Point cornerPosition = convertCenterToCorner(floatPosition); setX(cornerPosition.x); setY(cornerPosition.y); + notifyListenersOfPositionChange(); } private Point convertCenterToCorner(@NonNull Point centerPosition) { @@ -294,7 +295,7 @@ private void notifyListenersOfPositionChange() { private void notifyListenersOfDockChange() { for (OnPositionChangeListener listener : mOnPositionChangeListeners) { - listener.onDockChange(mDock.position()); + listener.onDockChange(mDock); } } @@ -307,6 +308,6 @@ public void setOnClickListener(@Nullable View.OnClickListener onClickListener) { public interface OnPositionChangeListener { void onPositionChange(@NonNull Point tabPosition); - void onDockChange(@NonNull Point dockPosition); + void onDockChange(@NonNull Dock dock); } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverMenu.java b/hover/src/main/java/io/mattcarroll/hover/HoverMenu.java index aa51f38..6ebe213 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverMenu.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverMenu.java @@ -112,11 +112,17 @@ public static class Section { private final SectionId mId; private final View mTabView; private final Content mContent; + private final View mTabMessageView; public Section(@NonNull SectionId id, @NonNull View tabView, @NonNull Content content) { + this(id, tabView, content, null); + } + + public Section(@NonNull SectionId id, @NonNull View tabView, @NonNull Content content, @Nullable View tabMessageView) { mId = id; mTabView = tabView; mContent = content; + mTabMessageView = tabMessageView; } @NonNull @@ -129,6 +135,11 @@ public View getTabView() { return mTabView; } + @Nullable + public View getTabMessageView() { + return mTabMessageView; + } + @NonNull public Content getContent() { return mContent; diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverView.java b/hover/src/main/java/io/mattcarroll/hover/HoverView.java index b5d837d..3dd4d96 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverView.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverView.java @@ -87,6 +87,7 @@ public static HoverView createForView(@NonNull Context context) { final HoverViewState mClosed = new HoverViewStateClosed(); final HoverViewState mCollapsed = new HoverViewStateCollapsed(); + final HoverViewState mPreviewed = new HoverViewStatePreviewed(); final HoverViewState mExpanded = new HoverViewStateExpanded(); final WindowViewController mWindowViewController; final Dragger mDragger; @@ -98,9 +99,10 @@ public static HoverView createForView(@NonNull Context context) { boolean mIsAddedToWindow; boolean mIsTouchableInWindow; boolean mIsDebugMode = false; + boolean mUseShadeView = true; int mTabSize; OnExitListener mOnExitListener; - final Set mListeners = new CopyOnWriteArraySet<>(); + final Set mOnStateChangeListeners = new CopyOnWriteArraySet<>(); // Public for use with XML inflation. Clients should use static methods for construction. public HoverView(@NonNull Context context, @Nullable AttributeSet attrs) { @@ -259,6 +261,10 @@ public void setMenu(@Nullable HoverMenu menu) { mState.setMenu(menu); } + public void preview() { + mState.preview(); + } + public void expand() { mState.expand(); } @@ -271,57 +277,77 @@ public void close() { mState.close(); } + public void setUseShadeView(final boolean useShadeView) { + mUseShadeView = useShadeView; + } + + public boolean useShadeView() { + return mUseShadeView; + } + public void setOnExitListener(@Nullable OnExitListener listener) { mOnExitListener = listener; } - public void addOnExpandAndCollapseListener(@NonNull Listener listener) { - mListeners.add(listener); + public void addOnStateChangeListener(@NonNull OnStateChangeListener onStateChangeListener) { + mOnStateChangeListeners.add(onStateChangeListener); } - public void removeOnExpandAndCollapseListener(@NonNull Listener listener) { - mListeners.remove(listener); + public void removeOnStateChangeListener(@NonNull OnStateChangeListener onStateChangeListener) { + mOnStateChangeListeners.remove(onStateChangeListener); } void notifyListenersExpanding() { Log.d(TAG, "Notifying listeners that Hover is expanding."); - for (Listener listener : mListeners) { - listener.onExpanding(); + for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { + onStateChangeListener.onExpanding(); } } void notifyListenersExpanded() { Log.d(TAG, "Notifying listeners that Hover is now expanded."); - for (Listener listener : mListeners) { - listener.onExpanded(); + for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { + onStateChangeListener.onExpanded(); } } void notifyListenersCollapsing() { Log.d(TAG, "Notifying listeners that Hover is collapsing."); - for (Listener listener : mListeners) { - listener.onCollapsing(); + for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { + onStateChangeListener.onCollapsing(); } } void notifyListenersCollapsed() { Log.d(TAG, "Notifying listeners that Hover is now collapsed."); - for (Listener listener : mListeners) { - listener.onCollapsed(); + for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { + onStateChangeListener.onCollapsed(); + } + } + + void notifyListenersPreviewing() { + for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { + onStateChangeListener.onPreviewing(); + } + } + + void notifyListenersPreviewed() { + for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { + onStateChangeListener.onPreviewed(); } } void notifyListenersClosing() { Log.d(TAG, "Notifying listeners that Hover is closing."); - for (Listener listener : mListeners) { - listener.onClosing(); + for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { + onStateChangeListener.onClosing(); } } void notifyListenersClosed() { Log.d(TAG, "Notifying listeners that Hover is closed."); - for (Listener listener : mListeners) { - listener.onClosed(); + for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { + onStateChangeListener.onClosed(); } } @@ -503,7 +529,7 @@ public void save(@NonNull HoverMenu menu, /** * Listener invoked when the corresponding transitions occur within a given {@link HoverView}. */ - public interface Listener { + public interface OnStateChangeListener { void onExpanding(); @@ -513,9 +539,54 @@ public interface Listener { void onCollapsed(); + void onPreviewing(); + + void onPreviewed(); + void onClosing(); void onClosed(); + } + + public static class DefaultOnStateChangeListener implements OnStateChangeListener { + @Override + public void onExpanding() { + + } + + @Override + public void onExpanded() { + + } + @Override + public void onCollapsing() { + + } + + @Override + public void onCollapsed() { + + } + + @Override + public void onPreviewing() { + + } + + @Override + public void onPreviewed() { + + } + + @Override + public void onClosing() { + + } + + @Override + public void onClosed() { + + } } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewState.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewState.java index e46ec7a..5cbc207 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewState.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewState.java @@ -29,6 +29,8 @@ interface HoverViewState { */ void takeControl(@NonNull HoverView hoverView); + void preview(); + /** * Expands the HoverView. */ diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java index 8328570..9275f19 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java @@ -56,6 +56,9 @@ public void run() { return; } mHoverView.mScreen.destroyChainedTab(selectedTab); + if (null != mHoverView.mOnExitListener) { + mHoverView.mOnExitListener.onExit(); + } mHoverView.notifyListenersClosed(); } }); @@ -75,6 +78,16 @@ private void changeState(@NonNull HoverViewState nextState) { mHoverView = null; } + @Override + public void preview() { + if (null != mHoverView.mMenu) { + Log.d(TAG, "Preview."); + changeState(mHoverView.mPreviewed); + } else { + Log.d(TAG, "Asked to preview, but there is no menu set. Can't preview until a menu is available."); + } + } + @Override public void expand() { if (null != mHoverView.mMenu) { diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 7918360..987488f 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -38,8 +38,10 @@ class HoverViewStateCollapsed extends BaseHoverViewState { private static final String TAG = "HoverViewStateCollapsed"; + private static final float MIN_TAB_VERTICAL_POSITION = 0.0f; + private static final float MAX_TAB_VERTICAL_POSITION = 1.0f; - private HoverView mHoverView; + protected HoverView mHoverView; private FloatingTab mFloatingTab; private HoverMenu.Section mSelectedSection; private int mSelectedSectionIndex = -1; @@ -89,7 +91,7 @@ public void takeControl(@NonNull HoverView hoverView) { final boolean wasFloatingTabVisible; if (null == mFloatingTab) { wasFloatingTabVisible = false; - mFloatingTab = mHoverView.mScreen.createChainedTab(mHoverView.mSelectedSectionId, mSelectedSection.getTabView()); + mFloatingTab = mHoverView.mScreen.createChainedTab(mSelectedSection); } else { wasFloatingTabVisible = true; } @@ -114,7 +116,7 @@ public void run() { if (wasFloatingTabVisible) { sendToDock(); } else { - mFloatingTab.setVisibility(VISIBLE); + mFloatingTab.appear(null); moveToDock(); onDocked(); } @@ -128,6 +130,11 @@ public void run() { } } + @Override + public void preview() { + changeState(mHoverView.mPreviewed); + } + @Override public void expand() { changeState(mHoverView.mExpanded); @@ -143,7 +150,7 @@ public void close() { changeState(mHoverView.mClosed); } - private void changeState(@NonNull HoverViewState nextState) { + protected void changeState(@NonNull HoverViewState nextState) { Log.d(TAG, "Giving up control."); if (!mHasControl) { throw new RuntimeException("Cannot give control to another HoverMenuController when we don't have the HoverTab."); @@ -203,10 +210,7 @@ public void onRemoved(int position, int count) { mSelectedSectionIndex = mSelectedSectionIndex > 0 ? mSelectedSectionIndex - 1 : 0; mSelectedSection = mHoverView.mMenu.getSection(mSelectedSectionIndex); mHoverView.mSelectedSectionId = mSelectedSection.getId(); - mFloatingTab = mHoverView.mScreen.createChainedTab( - mSelectedSection.getId(), - mSelectedSection.getTabView() - ); + mFloatingTab = mHoverView.mScreen.createChainedTab(mSelectedSection); mFloatingTab.addOnLayoutChangeListener(mOnLayoutChangeListener); } @@ -261,19 +265,17 @@ private void onDroppedByUser() { boolean droppedOnExit = mHoverView.mScreen.getExitView().isInExitZone(mFloatingTab.getPosition()); if (droppedOnExit) { Log.d(TAG, "User dropped floating tab on exit."); - closeMenu(new Runnable() { - @Override - public void run() { - if (null != mHoverView.mOnExitListener) { - mHoverView.mOnExitListener.onExit(); - } - } - }); + close(); } else { int tabSize = mHoverView.getResources().getDimensionPixelSize(R.dimen.hover_tab_size); Point screenSize = new Point(mHoverView.mScreen.getWidth(), mHoverView.mScreen.getHeight()); float tabHorizontalPositionPercent = (float) mFloatingTab.getPosition().x / screenSize.x; float tabVerticalPosition = (float) mFloatingTab.getPosition().y / screenSize.y; + if (tabVerticalPosition < MIN_TAB_VERTICAL_POSITION) { + tabVerticalPosition = MIN_TAB_VERTICAL_POSITION; + } else if (tabVerticalPosition > MAX_TAB_VERTICAL_POSITION) { + tabVerticalPosition = MAX_TAB_VERTICAL_POSITION; + } Log.d(TAG, "Dropped at horizontal " + tabHorizontalPositionPercent + ", vertical " + tabVerticalPosition); SideDock.SidePosition sidePosition = new SideDock.SidePosition( tabHorizontalPositionPercent <= 0.5 ? SideDock.SidePosition.LEFT : SideDock.SidePosition.RIGHT, @@ -356,21 +358,6 @@ private void moveTabTo(@NonNull Point position) { mFloatingTab.moveTo(position); } - private void closeMenu(final @Nullable Runnable onClosed) { - mFloatingTab.disappear(new Runnable() { - @Override - public void run() { - mHoverView.mScreen.destroyChainedTab(mFloatingTab); - - if (null != onClosed) { - onClosed.run(); - } - - close(); - } - }); - } - private void activateDragger() { mHoverView.mDragger.activate(mDragListener, mFloatingTab.getPosition()); } @@ -396,11 +383,11 @@ public interface Listener { void onExited(); } - private static final class FloatingTabDragListener implements Dragger.DragListener { + protected static final class FloatingTabDragListener implements Dragger.DragListener { private final HoverViewStateCollapsed mOwner; - private FloatingTabDragListener(@NonNull HoverViewStateCollapsed owner) { + protected FloatingTabDragListener(@NonNull HoverViewStateCollapsed owner) { mOwner = owner; } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java index 2ddc51d..90050fb 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java @@ -60,7 +60,9 @@ public void run() { if (!mHasControl) { return; } - mHoverView.mScreen.getShadeView().show(); + if (mHoverView.useShadeView()) { + mHoverView.mScreen.getShadeView().show(); + } mHoverView.mScreen.getContentDisplay().selectedTabIs(mSelectedTab); HoverMenu.Section selectedSection = null != mHoverView.mSelectedSectionId @@ -131,10 +133,7 @@ private void createChainedTabs() { for (int i = 0; i < mHoverView.mMenu.getSectionCount(); ++i) { HoverMenu.Section section = mHoverView.mMenu.getSection(i); Log.d(TAG, "Creating tab view for: " + section.getId()); - final FloatingTab chainedTab = mHoverView.mScreen.createChainedTab( - section.getId(), - section.getTabView() - ); + final FloatingTab chainedTab = mHoverView.mScreen.createChainedTab(section); Log.d(TAG, "Created FloatingTab for ID " + section.getId()); if (!mHoverView.mSelectedSectionId.equals(section.getId())) { @@ -198,6 +197,11 @@ public void run() { } } + @Override + public void preview() { + changeState(mHoverView.mPreviewed); + } + @Override public void expand() { Log.d(TAG, "Instructed to expand, but already expanded."); @@ -230,7 +234,9 @@ private void changeState(@NonNull final HoverViewState nextState) { mHoverView.mScreen.getContentDisplay().selectedTabIs(null); mHoverView.mScreen.getContentDisplay().displayContent(null); mHoverView.mScreen.getContentDisplay().setVisibility(View.GONE); - mHoverView.mScreen.getShadeView().hide(); + if (mHoverView.useShadeView()) { + mHoverView.mScreen.getShadeView().hide(); + } mHoverView.setState(nextState); unchainTabs(new Runnable() { @Override @@ -392,20 +398,15 @@ private void createTabsForIndices(int ... sectionIndices) { Log.d(TAG, "Creating tab for section at index " + sectionIndex); HoverMenu.Section section = mHoverView.mMenu.getSection(sectionIndex); Log.d(TAG, "Adding new tab. Section: " + sectionIndex + ", ID: " + section.getId()); - FloatingTab newTab = addTab(section.getId(), section.getTabView(), sectionIndex); + FloatingTab newTab = addTab(sectionIndex, section); mSections.put(newTab, section); } updateChainedPositions(); } - private FloatingTab addTab(@NonNull HoverMenu.SectionId sectionId, - @NonNull View tabView, - int position) { - final FloatingTab newTab = mHoverView.mScreen.createChainedTab( - sectionId, - tabView - ); + private FloatingTab addTab(int position, HoverMenu.Section section) { + final FloatingTab newTab = mHoverView.mScreen.createChainedTab(section); newTab.disappearImmediate(); if (mChainedTabs.size() <= position) { // This section was appended to the end. diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java new file mode 100644 index 0000000..be01505 --- /dev/null +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -0,0 +1,62 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *    http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.mattcarroll.hover; + +import android.support.annotation.NonNull; +import android.util.Log; + +/** + * {@link HoverViewState} that operates the {@link HoverView} when it is closed. Closed means that + * nothing is visible - no tabs, no content. From the user's perspective, there is no + * {@code HoverView}. + */ +class HoverViewStatePreviewed extends HoverViewStateCollapsed { + + private static final String TAG = "HoverViewStatePreviewed"; + + @Override + public void takeControl(@NonNull HoverView hoverView) { + super.takeControl(hoverView); + mHoverView.mState = this; + mHoverView.notifyListenersPreviewing(); + mHoverView.mScreen.showTabContentView(mHoverView.mSelectedSectionId, mHoverView.mCollapsedDock, new Runnable() { + @Override + public void run() { + mHoverView.notifyListenersPreviewed(); + } + }); + } + + @Override + protected void changeState(@NonNull final HoverViewState nextState) { + if (nextState instanceof HoverViewStateCollapsed) { + mHoverView.mScreen.hideTabContentView(mHoverView.mSelectedSectionId, true); + } else { + mHoverView.mScreen.hideTabContentView(mHoverView.mSelectedSectionId, false); + } + super.changeState(nextState); + } + + @Override + public void preview() { + Log.d(TAG, "Instructed to preview, but already previewed."); + } + + @Override + public void collapse() { + changeState(mHoverView.mCollapsed); + } +} diff --git a/hover/src/main/java/io/mattcarroll/hover/Screen.java b/hover/src/main/java/io/mattcarroll/hover/Screen.java index 441f976..02e3e1d 100644 --- a/hover/src/main/java/io/mattcarroll/hover/Screen.java +++ b/hover/src/main/java/io/mattcarroll/hover/Screen.java @@ -40,6 +40,7 @@ class Screen { private ExitView mExitView; private ShadeView mShadeView; private Map mTabs = new HashMap<>(); + private Map mTabMessageViews = new HashMap<>(); private boolean mIsDebugMode = false; Screen(@NonNull ViewGroup hoverMenuContainer) { @@ -82,13 +83,13 @@ public int getHeight() { } @NonNull - public FloatingTab createChainedTab(@NonNull HoverMenu.SectionId sectionId, @NonNull View tabView) { - String tabId = sectionId.toString(); - return createChainedTab(tabId, tabView); + public FloatingTab createChainedTab(@NonNull HoverMenu.Section section) { + String tabId = section.getId().toString(); + return createChainedTab(tabId, section.getTabView(), section.getTabMessageView()); } @NonNull - public FloatingTab createChainedTab(@NonNull String tabId, @NonNull View tabView) { + public FloatingTab createChainedTab(@NonNull String tabId, @NonNull View tabView, @Nullable View tabMessageView) { Log.d(TAG, "Existing tabs..."); for (String existingTabId : mTabs.keySet()) { Log.d(TAG, existingTabId); @@ -102,6 +103,11 @@ public FloatingTab createChainedTab(@NonNull String tabId, @NonNull View tabView chainedTab.enableDebugMode(mIsDebugMode); mContainer.addView(chainedTab); mTabs.put(tabId, chainedTab); + if (tabMessageView != null) { + final TabMessageView messageView = new TabMessageView(tabView.getContext(), tabMessageView, chainedTab); + mContainer.addView(messageView); + mTabMessageViews.put(tabId, messageView); + } return chainedTab; } } @@ -134,4 +140,17 @@ public ExitView getExitView() { public ShadeView getShadeView() { return mShadeView; } + + public void showTabContentView(final HoverMenu.SectionId sectionId, final SideDock dock, final Runnable onAppeared) { + if (getChainedTab(sectionId) != null && mTabMessageViews.get(sectionId.toString()) != null) { + mTabMessageViews.get(sectionId.toString()).appear(dock, onAppeared); + } + } + + public void hideTabContentView(final HoverMenu.SectionId sectionId, final boolean withAnimation) { + final TabMessageView tabMessageView = mTabMessageViews.get(sectionId.toString()); + if (tabMessageView != null) { + tabMessageView.disappear(withAnimation); + } + } } diff --git a/hover/src/main/java/io/mattcarroll/hover/TabChain.java b/hover/src/main/java/io/mattcarroll/hover/TabChain.java index 16147c8..7c53a45 100644 --- a/hover/src/main/java/io/mattcarroll/hover/TabChain.java +++ b/hover/src/main/java/io/mattcarroll/hover/TabChain.java @@ -45,7 +45,7 @@ public void onPositionChange(@NonNull Point position) { } @Override - public void onDockChange(@NonNull Point dock) { + public void onDockChange(@NonNull Dock dock) { Log.d(TAG, hashCode() + "'s predecessor dock moved to: " + dock); moveToChainedPosition(false); } @@ -113,7 +113,7 @@ private void moveToChainedPosition(boolean immediate) { mTab.dock(); } } else { - mTab.moveTo(mTab.getDockPosition()); + mTab.dockImmediately(); mTab.appear(null); } } diff --git a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java new file mode 100644 index 0000000..fb9db06 --- /dev/null +++ b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java @@ -0,0 +1,98 @@ +package io.mattcarroll.hover; + +import android.content.Context; +import android.graphics.Point; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.view.animation.LinearOutSlowInInterpolator; +import android.util.Log; +import android.view.View; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.view.animation.AnimationSet; +import android.view.animation.TranslateAnimation; +import android.widget.FrameLayout; + +public class TabMessageView extends FrameLayout { + private static final String TAG = "TabMessageView"; + + private final FloatingTab mFloatingTab; + private SideDock mSideDock; + + private final FloatingTab.OnPositionChangeListener mOnTabPositionChangeListener = new FloatingTab.OnPositionChangeListener() { + @Override + public void onPositionChange(@NonNull Point position) { + Log.d(TAG, mFloatingTab + " tab moved to " + position); + if (mSideDock != null && mSideDock.sidePosition().getSide() == SideDock.SidePosition.RIGHT) { + setX(position.x - (mFloatingTab.getTabSize() / 2) - getWidth()); + setY(position.y - (mFloatingTab.getTabSize() / 2)); + } else { + setX(position.x + (mFloatingTab.getTabSize() / 2)); + setY(position.y - (mFloatingTab.getTabSize() / 2)); + } + } + + @Override + public void onDockChange(@NonNull Dock dock) { + if (dock instanceof SideDock) { + final SideDock sideDock = (SideDock) dock; + if (sideDock.sidePosition() != mSideDock.sidePosition()) { + appear(sideDock, null); + } + } + } + }; + + public TabMessageView(@NonNull Context context, @NonNull View messageView, @NonNull FloatingTab floatingTab) { + super(context); + mFloatingTab = floatingTab; + addView(messageView); + setVisibility(GONE); + } + + public void appear(final SideDock dock, @Nullable final Runnable onAppeared) { + mSideDock = dock; + mFloatingTab.addOnPositionChangeListener(mOnTabPositionChangeListener); + final AnimationSet animation = new AnimationSet(true); + final AlphaAnimation alpha = new AlphaAnimation(0, 1); + final float fromXDelta = getResources().getDimensionPixelSize(R.dimen.hover_message_animate_translation_x) + * (dock.sidePosition().getSide() == SideDock.SidePosition.LEFT ? -1 : 1); + final float fromYDelta = getResources().getDimensionPixelSize(R.dimen.hover_message_animate_translation_y); + TranslateAnimation translate = new TranslateAnimation(fromXDelta, 0, fromYDelta, 0); + animation.setDuration(300); + animation.setInterpolator(new LinearOutSlowInInterpolator()); + animation.addAnimation(alpha); + animation.addAnimation(translate); + animation.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + } + + @Override + public void onAnimationEnd(Animation animation) { + if (onAppeared != null) { + onAppeared.run(); + } + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + }); + startAnimation(animation); + setVisibility(VISIBLE); + } + + public void disappear(final boolean withAnimation) { + mFloatingTab.removeOnPositionChangeListener(mOnTabPositionChangeListener); + mSideDock = null; + if (withAnimation) { + final AnimationSet animation = new AnimationSet(true); + final AlphaAnimation alpha = new AlphaAnimation(1, 0); + alpha.setDuration(300); + animation.addAnimation(alpha); + startAnimation(animation); + } + setVisibility(GONE); + } +} diff --git a/hover/src/main/res/values/dimens.xml b/hover/src/main/res/values/dimens.xml index f8897a8..0023349 100755 --- a/hover/src/main/res/values/dimens.xml +++ b/hover/src/main/res/values/dimens.xml @@ -4,4 +4,6 @@ 7dp 40dp 75dp + 32dp + 24dp From 78ae4e376c4eb43c8ffdd4b9e6726ae304ddbe26 Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Wed, 13 Feb 2019 18:24:19 +0900 Subject: [PATCH 004/105] =?UTF-8?q?Collapsed=20State=EC=9D=BC=EB=95=8C=205?= =?UTF-8?q?=EC=B4=88=EA=B0=80=20=EC=A7=80=EB=82=98=EB=A9=B4=20hover=20view?= =?UTF-8?q?=EA=B0=80=20=EB=B0=98=ED=88=AC=EB=AA=85=ED=95=B4=EC=A7=80?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hover/HoverViewStateCollapsed.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 987488f..5b919ce 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -16,6 +16,7 @@ package io.mattcarroll.hover; import android.graphics.Point; +import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.util.ListUpdateCallback; @@ -40,6 +41,7 @@ class HoverViewStateCollapsed extends BaseHoverViewState { private static final String TAG = "HoverViewStateCollapsed"; private static final float MIN_TAB_VERTICAL_POSITION = 0.0f; private static final float MAX_TAB_VERTICAL_POSITION = 1.0f; + private static final long ALPHA_IDLE_MILLIS = 5000; protected HoverView mHoverView; private FloatingTab mFloatingTab; @@ -50,6 +52,15 @@ class HoverViewStateCollapsed extends BaseHoverViewState { private boolean mIsDocked = false; private Dragger.DragListener mDragListener; private Listener mListener; + private Handler mHandler = new Handler(); + private Runnable mAlphaChanger = new Runnable() { + @Override + public void run() { + if (!(mHoverView.mState instanceof HoverViewStatePreviewed) && mHoverView.mState instanceof HoverViewStateCollapsed) { + mHoverView.setAlpha(0.5f); + } + } + }; private final View.OnLayoutChangeListener mOnLayoutChangeListener = new View.OnLayoutChangeListener() { @Override @@ -128,6 +139,8 @@ public void run() { if (null != mHoverView.mMenu) { listenForMenuChanges(); } + + scheduleHoverViewAlphaChange(); } @Override @@ -156,6 +169,8 @@ protected void changeState(@NonNull HoverViewState nextState) { throw new RuntimeException("Cannot give control to another HoverMenuController when we don't have the HoverTab."); } + restoreHoverViewAlphaValue(); + mFloatingTab.removeOnLayoutChangeListener(mOnLayoutChangeListener); if (null != mHoverView.mMenu) { @@ -254,6 +269,7 @@ private void onPickedUpByUser() { if (null != mListener) { mListener.onDragStart(); } + restoreHoverViewAlphaValue(); } private void onDroppedByUser() { @@ -340,6 +356,7 @@ private void onDocked() { Log.d(TAG, "Docked. Activating dragger."); mIsDocked = true; activateDragger(); + scheduleHoverViewAlphaChange(); // We consider ourselves having gone from "collapsing" to "collapsed" upon the very first dock. boolean didJustCollapse = !mIsCollapsed; @@ -366,6 +383,15 @@ private void deactivateDragger() { mHoverView.mDragger.deactivate(); } + private void scheduleHoverViewAlphaChange() { + mHandler.postDelayed(mAlphaChanger, ALPHA_IDLE_MILLIS); + } + + protected void restoreHoverViewAlphaValue() { + mHandler.removeCallbacksAndMessages(null); + mHoverView.setAlpha(1f); + } + public interface Listener { void onCollapsing(); From 5fedc98df581d9ddeebddd9043efea1f3a12ca81 Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Thu, 14 Feb 2019 11:54:31 +0900 Subject: [PATCH 005/105] =?UTF-8?q?handler=EC=97=90=EC=84=9C=20=ED=8A=B9?= =?UTF-8?q?=EC=A0=95=20runnable=EB=A7=8C=20=EC=A0=9C=EA=B1=B0=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 5b919ce..1bf2e1f 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -388,7 +388,7 @@ private void scheduleHoverViewAlphaChange() { } protected void restoreHoverViewAlphaValue() { - mHandler.removeCallbacksAndMessages(null); + mHandler.removeCallbacks(mAlphaChanger); mHoverView.setAlpha(1f); } From e4d21595c5e218bba4fdcf94b3b3893fe1cc0a6c Mon Sep 17 00:00:00 2001 From: Haley Date: Thu, 14 Feb 2019 12:01:04 +0900 Subject: [PATCH 006/105] =?UTF-8?q?[BZZRWRDD-165]=20MessageView=20?= =?UTF-8?q?=EC=98=81=EC=97=AD=EB=8F=84=20drag,=20tab=20=EA=B0=80=EB=8A=A5?= =?UTF-8?q?=ED=95=98=EA=B2=8C=20=EB=A7=8C=EB=93=A4=EA=B8=B0=20(#6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * View 를 넘기는 방식 대신 Rect 넘기기, FloatingTab 과 MessageView 는 어떤 뷰에 같이 속해 있지 않음 --- .../java/io/mattcarroll/hover/Dragger.java | 6 ++-- .../java/io/mattcarroll/hover/HoverView.java | 4 --- .../hover/HoverViewStateCollapsed.java | 15 +++++---- .../hover/HoverViewStatePreviewed.java | 31 +++++++++++++++++-- .../java/io/mattcarroll/hover/Screen.java | 13 ++------ .../mattcarroll/hover/view/InViewDragger.java | 26 ++++++++-------- .../hover/window/InWindowDragger.java | 19 ++++++------ 7 files changed, 65 insertions(+), 49 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/Dragger.java b/hover/src/main/java/io/mattcarroll/hover/Dragger.java index cf36ae3..0e2572d 100644 --- a/hover/src/main/java/io/mattcarroll/hover/Dragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/Dragger.java @@ -15,7 +15,7 @@ */ package io.mattcarroll.hover; -import android.graphics.Point; +import android.graphics.Rect; import android.support.annotation.NonNull; /** @@ -26,9 +26,9 @@ public interface Dragger { /** * Starts reporting user drag behavior given a drag area represented by {@code controlBounds}. * @param dragListener listener that receives information about drag behavior - * @param dragStartCenterPosition initial touch point to start dragging + * @param rect Rect area to be draggable */ - void activate(@NonNull DragListener dragListener, @NonNull Point dragStartCenterPosition); + void activate(@NonNull DragListener dragListener, @NonNull Rect rect); /** * Stops monitoring and reporting user drag behavior. diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverView.java b/hover/src/main/java/io/mattcarroll/hover/HoverView.java index 3dd4d96..61c9709 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverView.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverView.java @@ -70,12 +70,10 @@ public static HoverView createForWindow(@NonNull Context context, @NonNull private static Dragger createWindowDragger(@NonNull Context context, @NonNull WindowViewController windowViewController) { - int touchDiameter = context.getResources().getDimensionPixelSize(R.dimen.hover_exit_radius); int slop = ViewConfiguration.get(context).getScaledTouchSlop(); return new InWindowDragger( context, windowViewController, - touchDiameter, slop ); } @@ -120,11 +118,9 @@ public HoverView(@NonNull Context context, @Nullable AttributeSet attrs) { @NonNull private Dragger createInViewDragger(@NonNull Context context) { - int touchDiameter = context.getResources().getDimensionPixelSize(R.dimen.hover_exit_radius); int slop = ViewConfiguration.get(context).getScaledTouchSlop(); return new InViewDragger( this, - touchDiameter, slop ); } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 1bf2e1f..c0f46dc 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -16,6 +16,7 @@ package io.mattcarroll.hover; import android.graphics.Point; +import android.graphics.Rect; import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -44,13 +45,13 @@ class HoverViewStateCollapsed extends BaseHoverViewState { private static final long ALPHA_IDLE_MILLIS = 5000; protected HoverView mHoverView; - private FloatingTab mFloatingTab; + protected FloatingTab mFloatingTab; private HoverMenu.Section mSelectedSection; private int mSelectedSectionIndex = -1; private boolean mHasControl = false; private boolean mIsCollapsed = false; private boolean mIsDocked = false; - private Dragger.DragListener mDragListener; + protected Dragger.DragListener mDragListener; private Listener mListener; private Handler mHandler = new Handler(); private Runnable mAlphaChanger = new Runnable() { @@ -371,15 +372,17 @@ private void onDocked() { } } - private void moveTabTo(@NonNull Point position) { + protected void moveTabTo(@NonNull Point position) { mFloatingTab.moveTo(position); } - private void activateDragger() { - mHoverView.mDragger.activate(mDragListener, mFloatingTab.getPosition()); + protected void activateDragger() { + final Rect visibleRect = new Rect(); + mFloatingTab.getGlobalVisibleRect(visibleRect); + mHoverView.mDragger.activate(mDragListener, visibleRect); } - private void deactivateDragger() { + protected void deactivateDragger() { mHoverView.mDragger.deactivate(); } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index be01505..32523a4 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -15,6 +15,8 @@ */ package io.mattcarroll.hover; +import android.graphics.Point; +import android.graphics.Rect; import android.support.annotation.NonNull; import android.util.Log; @@ -26,13 +28,15 @@ class HoverViewStatePreviewed extends HoverViewStateCollapsed { private static final String TAG = "HoverViewStatePreviewed"; + private TabMessageView mMessageView; @Override public void takeControl(@NonNull HoverView hoverView) { super.takeControl(hoverView); mHoverView.mState = this; mHoverView.notifyListenersPreviewing(); - mHoverView.mScreen.showTabContentView(mHoverView.mSelectedSectionId, mHoverView.mCollapsedDock, new Runnable() { + mMessageView = mHoverView.mScreen.getTabMessageView(mHoverView.mSelectedSectionId); + mMessageView.appear(mHoverView.mCollapsedDock, new Runnable() { @Override public void run() { mHoverView.notifyListenersPreviewed(); @@ -43,9 +47,9 @@ public void run() { @Override protected void changeState(@NonNull final HoverViewState nextState) { if (nextState instanceof HoverViewStateCollapsed) { - mHoverView.mScreen.hideTabContentView(mHoverView.mSelectedSectionId, true); + mMessageView.disappear(true); } else { - mHoverView.mScreen.hideTabContentView(mHoverView.mSelectedSectionId, false); + mMessageView.disappear(false); } super.changeState(nextState); } @@ -59,4 +63,25 @@ public void preview() { public void collapse() { changeState(mHoverView.mCollapsed); } + + @Override + protected void moveTabTo(@NonNull Point position) { + final int floatingTabOffset = mMessageView.getWidth() / 2; + if (mHoverView.mCollapsedDock.sidePosition().getSide() == SideDock.SidePosition.RIGHT) { + mFloatingTab.moveTo(new Point(position.x + floatingTabOffset, position.y)); + } else { + mFloatingTab.moveTo(new Point(position.x - floatingTabOffset, position.y)); + } + } + + @Override + protected void activateDragger() { + final Rect tabRect = new Rect(); + final Rect messageRect = new Rect(); + mFloatingTab.getGlobalVisibleRect(tabRect); + mMessageView.getGlobalVisibleRect(messageRect); + tabRect.union(messageRect); + + mHoverView.mDragger.activate(mDragListener, tabRect); + } } diff --git a/hover/src/main/java/io/mattcarroll/hover/Screen.java b/hover/src/main/java/io/mattcarroll/hover/Screen.java index 02e3e1d..1c4212a 100644 --- a/hover/src/main/java/io/mattcarroll/hover/Screen.java +++ b/hover/src/main/java/io/mattcarroll/hover/Screen.java @@ -141,16 +141,7 @@ public ShadeView getShadeView() { return mShadeView; } - public void showTabContentView(final HoverMenu.SectionId sectionId, final SideDock dock, final Runnable onAppeared) { - if (getChainedTab(sectionId) != null && mTabMessageViews.get(sectionId.toString()) != null) { - mTabMessageViews.get(sectionId.toString()).appear(dock, onAppeared); - } - } - - public void hideTabContentView(final HoverMenu.SectionId sectionId, final boolean withAnimation) { - final TabMessageView tabMessageView = mTabMessageViews.get(sectionId.toString()); - if (tabMessageView != null) { - tabMessageView.disappear(withAnimation); - } + public TabMessageView getTabMessageView(final HoverMenu.SectionId sectionId) { + return mTabMessageViews.get(sectionId.toString()); } } diff --git a/hover/src/main/java/io/mattcarroll/hover/view/InViewDragger.java b/hover/src/main/java/io/mattcarroll/hover/view/InViewDragger.java index 8a8667f..1811bc2 100644 --- a/hover/src/main/java/io/mattcarroll/hover/view/InViewDragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/view/InViewDragger.java @@ -15,8 +15,8 @@ */ package io.mattcarroll.hover.view; -import android.graphics.Point; import android.graphics.PointF; +import android.graphics.Rect; import android.support.annotation.NonNull; import android.util.Log; import android.view.MotionEvent; @@ -34,7 +34,6 @@ public class InViewDragger implements Dragger { private static final String TAG = "InViewDragger"; private final ViewGroup mContainer; - private final int mTouchAreaDiameter; private final int mTapTouchSlop; private boolean mIsActivated; private boolean mIsDragging; @@ -98,9 +97,8 @@ public boolean onTouch(View view, MotionEvent motionEvent) { } }; - public InViewDragger(@NonNull ViewGroup container, int touchAreaDiameter, int touchSlop) { + public InViewDragger(@NonNull ViewGroup container, int touchSlop) { mContainer = container; - mTouchAreaDiameter = touchAreaDiameter; mTapTouchSlop = touchSlop; } @@ -111,12 +109,12 @@ public void enableDebugMode(boolean isDebugMode) { } @Override - public void activate(@NonNull DragListener dragListener, @NonNull Point dragStartCenterPosition) { + public void activate(@NonNull DragListener dragListener, @NonNull Rect rect) { if (!mIsActivated) { Log.d(TAG, "Activating."); mIsActivated = true; mDragListener = dragListener; - createTouchControlView(dragStartCenterPosition); + createTouchControlView(rect); } } @@ -129,14 +127,16 @@ public void deactivate() { } } - private void createTouchControlView(@NonNull Point dragStartCenterPosition) { + private void createTouchControlView(@NonNull Rect rect) { mDragView = new View(mContainer.getContext()); mDragView.setId(R.id.hover_drag_view); - mDragView.setLayoutParams(new ViewGroup.LayoutParams(mTouchAreaDiameter, mTouchAreaDiameter)); + final int width = rect.right - rect.left; + final int height = rect.bottom - rect.top; + mDragView.setLayoutParams(new ViewGroup.LayoutParams(width, height)); mDragView.setOnTouchListener(mDragTouchListener); mContainer.addView(mDragView); - moveDragViewTo(new PointF(dragStartCenterPosition.x, dragStartCenterPosition.y)); + moveDragViewTo(new PointF((rect.right + rect.left) / 2, (rect.bottom + rect.top) / 2)); updateTouchControlViewAppearance(); } @@ -179,15 +179,15 @@ private void moveDragViewTo(PointF centerPosition) { private PointF convertCornerToCenter(@NonNull PointF cornerPosition) { return new PointF( - cornerPosition.x + (mTouchAreaDiameter / 2), - cornerPosition.y + (mTouchAreaDiameter / 2) + cornerPosition.x + (mDragView.getWidth() / 2), + cornerPosition.y + (mDragView.getHeight() / 2) ); } private PointF convertCenterToCorner(@NonNull PointF centerPosition) { return new PointF( - centerPosition.x - (mTouchAreaDiameter / 2), - centerPosition.y - (mTouchAreaDiameter / 2) + centerPosition.x - (mDragView.getWidth() / 2), + centerPosition.y - (mDragView.getHeight() / 2) ); } } diff --git a/hover/src/main/java/io/mattcarroll/hover/window/InWindowDragger.java b/hover/src/main/java/io/mattcarroll/hover/window/InWindowDragger.java index 24a6aad..aac914a 100755 --- a/hover/src/main/java/io/mattcarroll/hover/window/InWindowDragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/window/InWindowDragger.java @@ -18,6 +18,7 @@ import android.content.Context; import android.graphics.Point; import android.graphics.PointF; +import android.graphics.Rect; import android.support.annotation.NonNull; import android.util.Log; import android.view.MotionEvent; @@ -34,7 +35,6 @@ public class InWindowDragger implements Dragger { private final Context mContext; private final WindowViewController mWindowViewController; - private final int mTouchAreaDiameter; private final float mTapTouchSlop; private View mDragView; private Dragger.DragListener mDragListener; @@ -108,24 +108,24 @@ public boolean onTouch(View view, MotionEvent motionEvent) { */ public InWindowDragger(@NonNull Context context, @NonNull WindowViewController windowViewController, - int touchAreaDiameter, float tapTouchSlop) { mContext = context; mWindowViewController = windowViewController; - mTouchAreaDiameter = touchAreaDiameter; mTapTouchSlop = tapTouchSlop; } - public void activate(@NonNull DragListener dragListener, @NonNull Point dragStartCenterPosition) { + @Override + public void activate(@NonNull DragListener dragListener, @NonNull Rect rect) { if (!mIsActivated) { Log.d(TAG, "Activating."); - createTouchControlView(dragStartCenterPosition); + createTouchControlView(rect); mDragListener = dragListener; mDragView.setOnTouchListener(mDragTouchListener); mIsActivated = true; } } + @Override public void deactivate() { if (mIsActivated) { Log.d(TAG, "Deactivating."); @@ -141,11 +141,12 @@ public void enableDebugMode(boolean isDebugMode) { updateTouchControlViewAppearance(); } - private void createTouchControlView(@NonNull final Point dragStartCenterPosition) { - // TODO: define dimen size + private void createTouchControlView(@NonNull Rect rect) { mDragView = new View(mContext); - mWindowViewController.addView(mTouchAreaDiameter, mTouchAreaDiameter, true, mDragView); - mWindowViewController.moveViewTo(mDragView, dragStartCenterPosition.x - (mTouchAreaDiameter / 2), dragStartCenterPosition.y - (mTouchAreaDiameter / 2)); + final int width = rect.right - rect.left; + final int height = rect.bottom - rect.top; + mWindowViewController.addView(width, height, true, mDragView); + mWindowViewController.moveViewTo(mDragView, rect.left, rect.top); mDragView.setOnTouchListener(mDragTouchListener); updateTouchControlViewAppearance(); From e83facd3bfb9a07e12f9cb39b245c0c5f66a15e5 Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Thu, 14 Feb 2019 15:14:08 +0900 Subject: [PATCH 007/105] =?UTF-8?q?Preview=EA=B0=80=20=EC=8B=9C=EA=B0=84?= =?UTF-8?q?=EC=9D=B4=20=EB=8B=A4=20=EB=90=98=EC=96=B4=20=EB=8B=AB=ED=9E=90?= =?UTF-8?q?=EB=95=8C=20=EC=82=AC=EC=9A=A9=EC=9E=90=EA=B0=80=20Drag?= =?UTF-8?q?=EB=A5=BC=20=ED=95=98=EA=B3=A0=EC=9E=88=EC=9D=84=20=EA=B2=BD?= =?UTF-8?q?=EC=9A=B0=20exit=20view=EA=B0=80=20=EA=B3=84=EC=86=8D=20?= =?UTF-8?q?=ED=91=9C=EC=8B=9C=EB=90=98=EB=8A=94=20=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index c0f46dc..bce4e61 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -178,6 +178,8 @@ protected void changeState(@NonNull HoverViewState nextState) { mHoverView.mMenu.setUpdatedCallback(null); } + mHoverView.mScreen.getExitView().setVisibility(GONE); + mHasControl = false; mIsDocked = false; deactivateDragger(); From e6e30a8517f8725d4fee7088f758ebbc8a8c0f8b Mon Sep 17 00:00:00 2001 From: Haley Date: Fri, 15 Feb 2019 13:47:42 +0900 Subject: [PATCH 008/105] [BZZRWRDD-252] Added 'Anchored' State for not using ContentDisplay, refactor callbacks (#8) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * HoverViewState control 방법 변경 - hover view 에서 state 변경을 관리하고, 각 state는 본인의 로직만 구현 --- .../mattcarroll/hover/BaseHoverViewState.java | 59 ++--- .../java/io/mattcarroll/hover/HoverView.java | 220 ++++++++++-------- .../io/mattcarroll/hover/HoverViewState.java | 42 +--- .../hover/HoverViewStateAnchored.java | 55 +++++ .../hover/HoverViewStateClosed.java | 93 +------- .../hover/HoverViewStateCollapsed.java | 130 ++--------- .../hover/HoverViewStateExpanded.java | 121 ++-------- .../hover/HoverViewStatePreviewed.java | 24 +- 8 files changed, 256 insertions(+), 488 deletions(-) create mode 100644 hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java diff --git a/hover/src/main/java/io/mattcarroll/hover/BaseHoverViewState.java b/hover/src/main/java/io/mattcarroll/hover/BaseHoverViewState.java index 770d4d1..ee8deda 100644 --- a/hover/src/main/java/io/mattcarroll/hover/BaseHoverViewState.java +++ b/hover/src/main/java/io/mattcarroll/hover/BaseHoverViewState.java @@ -15,64 +15,43 @@ */ package io.mattcarroll.hover; +import android.support.annotation.CallSuper; import android.support.annotation.NonNull; -import android.view.WindowManager; +import android.support.annotation.Nullable; /** * {@link HoverViewState} that includes behavior common to all implementations. */ abstract class BaseHoverViewState implements HoverViewState { - private HoverView mHoverView; + private boolean mHasControl = false; + protected HoverView mHoverView; + @CallSuper @Override - public void takeControl(@NonNull HoverView hoverView) { - mHoverView = hoverView; - } - - // Only call this if using HoverMenuView directly in a window. - @Override - public void addToWindow() { - if (!mHoverView.mIsAddedToWindow) { - mHoverView.mWindowViewController.addView( - WindowManager.LayoutParams.MATCH_PARENT, - WindowManager.LayoutParams.MATCH_PARENT, - false, - mHoverView - ); - - mHoverView.mIsAddedToWindow = true; - - if (mHoverView.mIsTouchableInWindow) { - mHoverView.makeTouchableInWindow(); - } else { - mHoverView.makeUntouchableInWindow(); - } + public void takeControl(@NonNull HoverView hoverView, Runnable onStateChanged) { + if (mHasControl) { + throw new RuntimeException("Cannot take control of a FloatingTab when we already control one."); } + mHasControl = true; + mHoverView = hoverView; } - // Only call this if using HoverMenuView directly in a window. + @CallSuper @Override - public void removeFromWindow() { - if (mHoverView.mIsAddedToWindow) { - mHoverView.mWindowViewController.removeView(mHoverView); - mHoverView.mIsAddedToWindow = false; + public void giveUpControl(@NonNull HoverViewState nextState) { + if (!mHasControl) { + throw new RuntimeException("Cannot give up control of a FloatingTab when we don't have the control"); } + mHasControl = false; + mHoverView = null; } - @Override - public void makeTouchableInWindow() { - mHoverView.mIsTouchableInWindow = true; - if (mHoverView.mIsAddedToWindow) { - mHoverView.mWindowViewController.makeTouchable(mHoverView); - } + protected final boolean hasControl() { + return mHasControl; } @Override - public void makeUntouchableInWindow() { - mHoverView.mIsTouchableInWindow = false; - if (mHoverView.mIsAddedToWindow) { - mHoverView.mWindowViewController.makeUntouchable(mHoverView); - } + public void setMenu(@Nullable HoverMenu menu) { } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverView.java b/hover/src/main/java/io/mattcarroll/hover/HoverView.java index 61c9709..923122d 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverView.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverView.java @@ -26,6 +26,7 @@ import android.util.Log; import android.view.KeyEvent; import android.view.ViewConfiguration; +import android.view.WindowManager; import android.widget.RelativeLayout; import java.util.Set; @@ -83,24 +84,25 @@ public static HoverView createForView(@NonNull Context context) { return new HoverView(context, null); } - final HoverViewState mClosed = new HoverViewStateClosed(); - final HoverViewState mCollapsed = new HoverViewStateCollapsed(); - final HoverViewState mPreviewed = new HoverViewStatePreviewed(); - final HoverViewState mExpanded = new HoverViewStateExpanded(); + private final HoverViewState mClosed = new HoverViewStateClosed(); + private final HoverViewState mCollapsed = new HoverViewStateCollapsed(); + private final HoverViewState mPreviewed = new HoverViewStatePreviewed(); + private final HoverViewState mExpanded = new HoverViewStateExpanded(); + private final HoverViewState mAnchored = new HoverViewStateAnchored(); final WindowViewController mWindowViewController; final Dragger mDragger; final Screen mScreen; - HoverViewState mState; + private HoverViewState mState; HoverMenu mMenu; HoverMenu.SectionId mSelectedSectionId; SideDock mCollapsedDock; boolean mIsAddedToWindow; boolean mIsTouchableInWindow; boolean mIsDebugMode = false; - boolean mUseShadeView = true; int mTabSize; OnExitListener mOnExitListener; - final Set mOnStateChangeListeners = new CopyOnWriteArraySet<>(); + private final Set mOnStateChangeListeners = new CopyOnWriteArraySet<>(); + private final Set mOnInteractionListeners = new CopyOnWriteArraySet<>(); // Public for use with XML inflation. Clients should use static methods for construction. public HoverView(@NonNull Context context, @Nullable AttributeSet attrs) { @@ -171,7 +173,7 @@ private void init() { mTabSize = getResources().getDimensionPixelSize(R.dimen.hover_tab_size); restoreVisualState(); setFocusableInTouchMode(true); // For handling hardware back button presses. - setState(new HoverViewStateClosed()); + close(); } @Override @@ -244,9 +246,18 @@ public void enableDebugMode(boolean debugMode) { mScreen.enableDrugMode(debugMode); } - void setState(@NonNull HoverViewState state) { - mState = state; - mState.takeControl(this); + void setState(@NonNull HoverViewState newState, Runnable onStateChanged) { + if (mState != newState) { + if (mState != null) { + mState.giveUpControl(newState); + } + mState = newState; + mState.takeControl(this, onStateChanged); + } + } + + public HoverViewState getState() { + return mState; } private void onBackPressed() { @@ -254,31 +265,73 @@ private void onBackPressed() { } public void setMenu(@Nullable HoverMenu menu) { + mMenu = menu; + // If the menu is null or empty then close the menu. + if (null == menu || menu.getSectionCount() == 0) { + close(); + return; + } + restoreVisualState(); + + if (null == mSelectedSectionId || null == mMenu.getSection(mSelectedSectionId)) { + mSelectedSectionId = mMenu.getSection(0).getId(); + } mState.setMenu(menu); } public void preview() { - mState.preview(); + setState(mPreviewed, new Runnable() { + @Override + public void run() { + for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { + onStateChangeListener.onPreviewed(); + } + } + }); } public void expand() { - mState.expand(); + setState(mExpanded, new Runnable() { + @Override + public void run() { + for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { + onStateChangeListener.onExpanded(); + } + } + }); } public void collapse() { - mState.collapse(); + setState(mCollapsed, new Runnable() { + @Override + public void run() { + for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { + onStateChangeListener.onCollapsed(); + } + } + }); } public void close() { - mState.close(); - } - - public void setUseShadeView(final boolean useShadeView) { - mUseShadeView = useShadeView; + setState(mClosed, new Runnable() { + @Override + public void run() { + for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { + onStateChangeListener.onClosed(); + } + } + }); } - public boolean useShadeView() { - return mUseShadeView; + public void anchor() { + setState(mAnchored, new Runnable() { + @Override + public void run() { + for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { + onStateChangeListener.onAnchored(); + } + } + }); } public void setOnExitListener(@Nullable OnExitListener listener) { @@ -293,76 +346,72 @@ public void removeOnStateChangeListener(@NonNull OnStateChangeListener onStateCh mOnStateChangeListeners.remove(onStateChangeListener); } - void notifyListenersExpanding() { - Log.d(TAG, "Notifying listeners that Hover is expanding."); - for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { - onStateChangeListener.onExpanding(); - } + public void addOnInteractionListener(@NonNull OnInteractionListener onInteractionListener) { + mOnInteractionListeners.add(onInteractionListener); } - void notifyListenersExpanded() { - Log.d(TAG, "Notifying listeners that Hover is now expanded."); - for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { - onStateChangeListener.onExpanded(); - } + public void removeOnInteractionListener(@NonNull OnInteractionListener onInteractionListener) { + mOnInteractionListeners.remove(onInteractionListener); } - void notifyListenersCollapsing() { - Log.d(TAG, "Notifying listeners that Hover is collapsing."); - for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { - onStateChangeListener.onCollapsing(); + void notifyOnTap() { + for (OnInteractionListener onInteractionListener : mOnInteractionListeners) { + onInteractionListener.onTap(); } } - void notifyListenersCollapsed() { - Log.d(TAG, "Notifying listeners that Hover is now collapsed."); - for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { - onStateChangeListener.onCollapsed(); + void notifyOnDragStart() { + for (OnInteractionListener onInteractionListener : mOnInteractionListeners) { + onInteractionListener.onDragStart(); } } - void notifyListenersPreviewing() { - for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { - onStateChangeListener.onPreviewing(); + void notifyOnDocked() { + for (OnInteractionListener onInteractionListener : mOnInteractionListeners) { + onInteractionListener.onDocked(); } } - void notifyListenersPreviewed() { - for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { - onStateChangeListener.onPreviewed(); - } - } + // Only call this if using HoverMenuView directly in a window. + public void addToWindow() { + if (!mIsAddedToWindow) { + mWindowViewController.addView( + WindowManager.LayoutParams.MATCH_PARENT, + WindowManager.LayoutParams.MATCH_PARENT, + false, + this + ); - void notifyListenersClosing() { - Log.d(TAG, "Notifying listeners that Hover is closing."); - for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { - onStateChangeListener.onClosing(); - } - } + mIsAddedToWindow = true; - void notifyListenersClosed() { - Log.d(TAG, "Notifying listeners that Hover is closed."); - for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { - onStateChangeListener.onClosed(); + if (mIsTouchableInWindow) { + makeTouchableInWindow(); + } else { + makeUntouchableInWindow(); + } } } - // Only call this if using HoverMenuView directly in a window. - public void addToWindow() { - mState.addToWindow(); - } - // Only call this if using HoverMenuView directly in a window. public void removeFromWindow() { - mState.removeFromWindow(); + if (mIsAddedToWindow) { + mWindowViewController.removeView(this); + mIsAddedToWindow = false; + } } void makeTouchableInWindow() { - mState.makeTouchableInWindow(); + mIsTouchableInWindow = true; + if (mIsAddedToWindow) { + mWindowViewController.makeTouchable(this); + } } void makeUntouchableInWindow() { - mState.makeUntouchableInWindow(); + mIsTouchableInWindow = false; + if (mIsAddedToWindow) { + mWindowViewController.makeUntouchable(this); + } } // State of the HoverMenuView that is persisted across configuration change and other brief OS @@ -526,63 +575,44 @@ public void save(@NonNull HoverMenu menu, * Listener invoked when the corresponding transitions occur within a given {@link HoverView}. */ public interface OnStateChangeListener { - - void onExpanding(); - void onExpanded(); - void onCollapsing(); - void onCollapsed(); - void onPreviewing(); - void onPreviewed(); - void onClosing(); - void onClosed(); + + void onAnchored(); } public static class DefaultOnStateChangeListener implements OnStateChangeListener { - @Override - public void onExpanding() { - - } - @Override public void onExpanded() { - - } - - @Override - public void onCollapsing() { - } @Override public void onCollapsed() { - } @Override - public void onPreviewing() { - + public void onPreviewed() { } @Override - public void onPreviewed() { - + public void onClosed() { } @Override - public void onClosing() { - + public void onAnchored() { } + } - @Override - public void onClosed() { + public interface OnInteractionListener { + void onTap(); - } + void onDragStart(); + + void onDocked(); } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewState.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewState.java index 5cbc207..c080668 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewState.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewState.java @@ -26,25 +26,11 @@ interface HoverViewState { /** * Activates this state. * @param hoverView hoverView + * @param onStateChanged Runnable to be run after state has changed */ - void takeControl(@NonNull HoverView hoverView); + void takeControl(@NonNull HoverView hoverView, Runnable onStateChanged); - void preview(); - - /** - * Expands the HoverView. - */ - void expand(); - - /** - * Collapses the HoverView. - */ - void collapse(); - - /** - * Closes the HoverView (no menu or tabs are visible). - */ - void close(); + void giveUpControl(@NonNull HoverViewState nextState); /** * Displays the given {@code menu} within the HoverView. @@ -63,26 +49,4 @@ interface HoverViewState { * {@link #respondsToBackButton()} returns true. */ void onBackPressed(); - - /** - * Adds the HoverView to the Android device's Window. - */ - void addToWindow(); - - /** - * Removes the HoverView from the Android device's Window. - */ - void removeFromWindow(); - - /** - * Assuming that the HoverView is added to the Android device's Window, makes the HoverView - * touchable. - */ - void makeTouchableInWindow(); - - /** - * Assuming that the HoverView is added to the Android device's Window, makes the HoverView - * untouchable (touch events pass through the overlay to whatever is beneath). - */ - void makeUntouchableInWindow(); } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java new file mode 100644 index 0000000..992ed73 --- /dev/null +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java @@ -0,0 +1,55 @@ +package io.mattcarroll.hover; + +import android.graphics.Point; +import android.support.annotation.NonNull; +import android.util.Log; + +public class HoverViewStateAnchored extends BaseHoverViewState { + + private static final String TAG = "HoverViewStateAnchored"; + private static final int ANCHOR_TAB_X_OFFSET_IN_PX = 100; + private static final int ANCHOR_TAB_Y_OFFSET_IN_PX = 100; + + private FloatingTab mSelectedTab; + private Point mDock; + + @Override + public void takeControl(@NonNull HoverView hoverView, final Runnable onStateChanged) { + super.takeControl(hoverView, onStateChanged); + Log.d(TAG, "Taking control."); + mHoverView.makeUntouchableInWindow(); + mHoverView.clearFocus(); + mDock = new Point( + mHoverView.mScreen.getWidth() - ANCHOR_TAB_X_OFFSET_IN_PX, + ANCHOR_TAB_Y_OFFSET_IN_PX + ); + + HoverMenu.Section section = mHoverView.mMenu.getSection(0); + mSelectedTab = mHoverView.mScreen.createChainedTab(section); + mSelectedTab.setDock(new PositionDock(mDock)); + mSelectedTab.dock(new Runnable() { + @Override + public void run() { + if (!hasControl()) { + return; + } + onStateChanged.run(); + } + }); + } + + @Override + public void giveUpControl(@NonNull HoverViewState nextState) { + Log.d(TAG, "Giving up control."); + super.giveUpControl(nextState); + } + + @Override + public boolean respondsToBackButton() { + return false; + } + + @Override + public void onBackPressed() { + } +} diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java index 9275f19..acddf2a 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java @@ -16,11 +16,8 @@ package io.mattcarroll.hover; import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.Log; -import static android.view.View.GONE; - /** * {@link HoverViewState} that operates the {@link HoverView} when it is closed. Closed means that * nothing is visible - no tabs, no content. From the user's perspective, there is no @@ -30,102 +27,30 @@ class HoverViewStateClosed extends BaseHoverViewState { private static final String TAG = "HoverViewStateClosed"; - private HoverView mHoverView; - private boolean mHasControl = false; - @Override - public void takeControl(@NonNull HoverView hoverView) { + public void takeControl(@NonNull HoverView hoverView, final Runnable onStateChanged) { + super.takeControl(hoverView, onStateChanged); Log.d(TAG, "Taking control."); - super.takeControl(hoverView); - if (mHasControl) { - throw new RuntimeException("Cannot take control of a FloatingTab when we already control one."); - } - mHasControl = true; - mHoverView = hoverView; - mHoverView.notifyListenersClosing(); - mHoverView.mState = this; + mHoverView.makeUntouchableInWindow(); mHoverView.clearFocus(); - mHoverView.mScreen.getContentDisplay().setVisibility(GONE); final FloatingTab selectedTab = mHoverView.mScreen.getChainedTab(mHoverView.mSelectedSectionId); if (null != selectedTab) { selectedTab.disappear(new Runnable() { @Override public void run() { - if (!mHasControl) { + if (!hasControl()) { return; } mHoverView.mScreen.destroyChainedTab(selectedTab); if (null != mHoverView.mOnExitListener) { mHoverView.mOnExitListener.onExit(); } - mHoverView.notifyListenersClosed(); + onStateChanged.run(); } }); } else { - mHoverView.notifyListenersClosed(); - } - - mHoverView.makeUntouchableInWindow(); - } - - private void changeState(@NonNull HoverViewState nextState) { - if (!mHasControl) { - throw new RuntimeException("Cannot give control to another HoverMenuController when we don't have the HoverTab."); - } - mHasControl = false; - mHoverView.setState(nextState); - mHoverView = null; - } - - @Override - public void preview() { - if (null != mHoverView.mMenu) { - Log.d(TAG, "Preview."); - changeState(mHoverView.mPreviewed); - } else { - Log.d(TAG, "Asked to preview, but there is no menu set. Can't preview until a menu is available."); - } - } - - @Override - public void expand() { - if (null != mHoverView.mMenu) { - Log.d(TAG, "Expanding."); - changeState(mHoverView.mExpanded); - } else { - Log.d(TAG, "Asked to expand, but there is no menu set. Can't expand until a menu is available."); - } - } - - @Override - public void collapse() { - if (null != mHoverView.mMenu) { - Log.d(TAG, "Collapsing."); - changeState(mHoverView.mCollapsed); - } else { - Log.d(TAG, "Asked to collapse, but there is no menu set. Can't collapse until a menu is available."); - } - } - - @Override - public void close() { - Log.d(TAG, "Instructed to close, but Hover is already closed."); - } - - @Override - public void setMenu(@Nullable final HoverMenu menu) { - mHoverView.mMenu = menu; - - // If the menu is null then there is nothing to restore. - if (null == menu) { - return; - } - - mHoverView.restoreVisualState(); - - if (null == mHoverView.mSelectedSectionId || null == mHoverView.mMenu.getSection(mHoverView.mSelectedSectionId)) { - mHoverView.mSelectedSectionId = mHoverView.mMenu.getSection(0).getId(); + onStateChanged.run(); } } @@ -138,4 +63,10 @@ public boolean respondsToBackButton() { public void onBackPressed() { // No-op } + + @Override + public void giveUpControl(@NonNull HoverViewState nextState) { + Log.d(TAG, "Giving up control."); + super.giveUpControl(nextState); + } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index bce4e61..dd1b887 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -44,29 +44,28 @@ class HoverViewStateCollapsed extends BaseHoverViewState { private static final float MAX_TAB_VERTICAL_POSITION = 1.0f; private static final long ALPHA_IDLE_MILLIS = 5000; - protected HoverView mHoverView; protected FloatingTab mFloatingTab; + protected final Dragger.DragListener mDragListener = new FloatingTabDragListener(this); private HoverMenu.Section mSelectedSection; private int mSelectedSectionIndex = -1; - private boolean mHasControl = false; private boolean mIsCollapsed = false; private boolean mIsDocked = false; - protected Dragger.DragListener mDragListener; - private Listener mListener; private Handler mHandler = new Handler(); private Runnable mAlphaChanger = new Runnable() { @Override public void run() { - if (!(mHoverView.mState instanceof HoverViewStatePreviewed) && mHoverView.mState instanceof HoverViewStateCollapsed) { + final HoverViewState state = mHoverView.getState(); + if (!(state instanceof HoverViewStatePreviewed) && state instanceof HoverViewStateCollapsed) { mHoverView.setAlpha(0.5f); } } }; + private Runnable mOnStateChanged; private final View.OnLayoutChangeListener mOnLayoutChangeListener = new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { - if (mHasControl && mIsDocked) { + if (hasControl() && mIsDocked) { // We're docked. Adjust the tab position in case the screen was rotated. This should // only be a concern when displaying as a window overlay, but not when displaying // within a view hierarchy. @@ -75,25 +74,13 @@ public void onLayoutChange(View v, int left, int top, int right, int bottom, int } }; - HoverViewStateCollapsed() { } - @Override - public void takeControl(@NonNull HoverView hoverView) { + public void takeControl(@NonNull HoverView hoverView, final Runnable onStateChanged) { + super.takeControl(hoverView, onStateChanged); Log.d(TAG, "Taking control."); - super.takeControl(hoverView); - - if (mHasControl) { - Log.w(TAG, "Already has control."); - return; - } - - Log.d(TAG, "Instructing tab to dock itself."); - mHasControl = true; - mHoverView = hoverView; - mHoverView.mState = this; - mHoverView.clearFocus(); // For handling hardware back button presses. - mHoverView.mScreen.getContentDisplay().setVisibility(GONE); + mOnStateChanged = onStateChanged; mHoverView.makeUntouchableInWindow(); + mHoverView.clearFocus(); // For handling hardware back button presses. Log.d(TAG, "Taking control with selected section: " + mHoverView.mSelectedSectionId); mSelectedSection = mHoverView.mMenu.getSection(mHoverView.mSelectedSectionId); @@ -107,12 +94,7 @@ public void takeControl(@NonNull HoverView hoverView) { } else { wasFloatingTabVisible = true; } - mDragListener = new FloatingTabDragListener(this); mIsCollapsed = false; // We're collapsing, not yet collapsed. - if (null != mListener) { - mHoverView.notifyListenersCollapsing(); - mListener.onCollapsing(); - } initDockPosition(); // post() animation to dock in case the container hasn't measured itself yet. @@ -122,7 +104,7 @@ public void takeControl(@NonNull HoverView hoverView) { mHoverView.post(new Runnable() { @Override public void run() { - if (!mHasControl) { + if (!hasControl()) { return; } if (wasFloatingTabVisible) { @@ -145,31 +127,8 @@ public void run() { } @Override - public void preview() { - changeState(mHoverView.mPreviewed); - } - - @Override - public void expand() { - changeState(mHoverView.mExpanded); - } - - @Override - public void collapse() { - Log.d(TAG, "Instructed to collapse, but already collapsed."); - } - - @Override - public void close() { - changeState(mHoverView.mClosed); - } - - protected void changeState(@NonNull HoverViewState nextState) { + public void giveUpControl(@NonNull HoverViewState nextState) { Log.d(TAG, "Giving up control."); - if (!mHasControl) { - throw new RuntimeException("Cannot give control to another HoverMenuController when we don't have the HoverTab."); - } - restoreHoverViewAlphaValue(); mFloatingTab.removeOnLayoutChangeListener(mOnLayoutChangeListener); @@ -180,32 +139,14 @@ protected void changeState(@NonNull HoverViewState nextState) { mHoverView.mScreen.getExitView().setVisibility(GONE); - mHasControl = false; mIsDocked = false; deactivateDragger(); - mDragListener = null; mFloatingTab = null; - - mHoverView.setState(nextState); - mHoverView = null; + super.giveUpControl(nextState); } @Override public void setMenu(@Nullable final HoverMenu menu) { - mHoverView.mMenu = menu; - - // If the menu is null or empty then we can't be collapsed, close the menu. - if (null == menu || menu.getSectionCount() == 0) { - close(); - return; - } - - mHoverView.restoreVisualState(); - - if (null == mHoverView.mSelectedSectionId || null == mHoverView.mMenu.getSection(mHoverView.mSelectedSectionId)) { - mHoverView.mSelectedSectionId = mHoverView.mMenu.getSection(0).getId(); - } - listenForMenuChanges(); } @@ -262,29 +203,19 @@ public void onBackPressed() { // No-op } - public void setListener(@Nullable Listener listener) { - mListener = listener; - } - private void onPickedUpByUser() { mIsDocked = false; mHoverView.mScreen.getExitView().setVisibility(VISIBLE); - if (null != mListener) { - mListener.onDragStart(); - } restoreHoverViewAlphaValue(); + mHoverView.notifyOnDragStart(); } private void onDroppedByUser() { mHoverView.mScreen.getExitView().setVisibility(GONE); - if (null != mListener) { - mListener.onDragEnd(); - } - boolean droppedOnExit = mHoverView.mScreen.getExitView().isInExitZone(mFloatingTab.getPosition()); if (droppedOnExit) { Log.d(TAG, "User dropped floating tab on exit."); - close(); + mHoverView.close(); } else { int tabSize = mHoverView.getResources().getDimensionPixelSize(R.dimen.hover_tab_size); Point screenSize = new Point(mHoverView.mScreen.getWidth(), mHoverView.mScreen.getHeight()); @@ -314,10 +245,7 @@ private void onDroppedByUser() { private void onTap() { Log.d(TAG, "Floating tab was tapped."); - expand(); - if (null != mListener) { - mListener.onTap(); - } + mHoverView.notifyOnTap(); } private void sendToDock() { @@ -327,7 +255,7 @@ private void sendToDock() { mFloatingTab.dock(new Runnable() { @Override public void run() { - if (!mHasControl) { + if (!hasControl()) { return; } onDocked(); @@ -365,13 +293,10 @@ private void onDocked() { boolean didJustCollapse = !mIsCollapsed; mIsCollapsed = true; mHoverView.saveVisualState(); - if (null != mListener) { - if (didJustCollapse) { - mHoverView.notifyListenersCollapsed(); - mListener.onCollapsed(); - } - mListener.onDocked(); + if (didJustCollapse) { + mOnStateChanged.run(); } + mHoverView.notifyOnDocked(); } protected void moveTabTo(@NonNull Point position) { @@ -397,23 +322,6 @@ protected void restoreHoverViewAlphaValue() { mHoverView.setAlpha(1f); } - public interface Listener { - void onCollapsing(); - - void onCollapsed(); - - void onDragStart(); - - void onDragEnd(); - - void onDocked(); - - void onTap(); - - // TODO: do we need this? - void onExited(); - } - protected static final class FloatingTabDragListener implements Dragger.DragListener { private final HoverViewStateCollapsed mOwner; diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java index 90050fb..7d0b123 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java @@ -44,54 +44,38 @@ class HoverViewStateExpanded extends BaseHoverViewState { private static final int TAB_SPACING_IN_PX = 200; private static final int TAB_APPEARANCE_DELAY_IN_MS = 100; - private boolean mHasControl = false; - private HoverView mHoverView; private boolean mHasMenu = false; private FloatingTab mSelectedTab; private final List mChainedTabs = new ArrayList<>(); private final List mTabChains = new ArrayList<>(); private final Map mSections = new HashMap<>(); private Point mDock; - private Listener mListener; + private int mTabsToUnchainCount; + private Runnable mOnStateChanged; private final Runnable mShowTabsRunnable = new Runnable() { @Override public void run() { - if (!mHasControl) { + if (!hasControl()) { return; } - if (mHoverView.useShadeView()) { - mHoverView.mScreen.getShadeView().show(); - } + mHoverView.mScreen.getShadeView().show(); mHoverView.mScreen.getContentDisplay().selectedTabIs(mSelectedTab); HoverMenu.Section selectedSection = null != mHoverView.mSelectedSectionId ? mHoverView.mMenu.getSection(mHoverView.mSelectedSectionId) : mHoverView.mMenu.getSection(0); mHoverView.mScreen.getContentDisplay().displayContent(selectedSection.getContent()); - mHoverView.mScreen.getContentDisplay().setVisibility(View.VISIBLE); - - mHoverView.notifyListenersExpanded(); - if (null != mListener) { - mListener.onExpanded(); - } + mOnStateChanged.run(); } }; - HoverViewStateExpanded() { } - @Override - public void takeControl(@NonNull HoverView hoverView) { + public void takeControl(@NonNull HoverView hoverView, Runnable onStateChanged) { + super.takeControl(hoverView, onStateChanged); Log.d(TAG, "Taking control."); - super.takeControl(hoverView); - if (mHasControl) { - throw new RuntimeException("Cannot take control of a FloatingTab when we already control one."); - } - - mHasControl = true; - mHoverView = hoverView; - mHoverView.mState = this; + mOnStateChanged = onStateChanged; mHoverView.makeTouchableInWindow(); mHoverView.requestFocus(); // For handling hardware back button presses. mDock = new Point( @@ -102,8 +86,6 @@ public void takeControl(@NonNull HoverView hoverView) { Log.d(TAG, "Already has menu. Expanding."); setMenu(mHoverView.mMenu); } - - mHoverView.makeTouchableInWindow(); } private void expandMenu() { @@ -120,11 +102,6 @@ private void expandMenu() { } else { mSelectedTab.dock(mShowTabsRunnable); } - - mHoverView.notifyListenersExpanding(); - if (null != mListener) { - mListener.onExpanding(); - } } private void createChainedTabs() { @@ -198,58 +175,20 @@ public void run() { } @Override - public void preview() { - changeState(mHoverView.mPreviewed); - } - - @Override - public void expand() { - Log.d(TAG, "Instructed to expand, but already expanded."); - } - - @Override - public void collapse() { - Log.d(TAG, "Collapsing."); - changeState(mHoverView.mCollapsed); - } - - @Override - public void close() { - Log.d(TAG, "Closing."); - changeState(mHoverView.mClosed); - } - - private void changeState(@NonNull final HoverViewState nextState) { + public void giveUpControl(@NonNull final HoverViewState nextState) { Log.d(TAG, "Giving up control."); - if (!mHasControl) { - throw new RuntimeException("Cannot give control to another HoverMenuController when we don't have the HoverTab."); - } - if (null != mHoverView.mMenu) { mHoverView.mMenu.setUpdatedCallback(null); } - - mHasControl = false; mHasMenu = false; mHoverView.mScreen.getContentDisplay().selectedTabIs(null); mHoverView.mScreen.getContentDisplay().displayContent(null); mHoverView.mScreen.getContentDisplay().setVisibility(View.GONE); - if (mHoverView.useShadeView()) { - mHoverView.mScreen.getShadeView().hide(); - } - mHoverView.setState(nextState); - unchainTabs(new Runnable() { - @Override - public void run() { - Log.d(TAG, "Running unchained runnable."); - // We wait to nullify our HoverMenuView because some final animations need it. - // TODO: maybe the answer is for the collapse state to handle what happens to the tabs and content display and shade? - mHoverView = null; - } - }); + mHoverView.mScreen.getShadeView().hide(); + unchainTabs(null); + super.giveUpControl(nextState); } - private int mTabsToUnchainCount; private void unchainTabs(@Nullable final Runnable onUnChained) { int selectedTabIndex = 0; for (int i = 0; i < mChainedTabs.size(); ++i) { @@ -301,20 +240,6 @@ public void run() { @Override public void setMenu(@Nullable HoverMenu menu) { Log.d(TAG, "Setting menu."); - mHoverView.mMenu = menu; - - // Expanded menus can't be null/empty. If it is then go to closed state. - if (null == mHoverView.mMenu || mHoverView.mMenu.getSectionCount() == 0) { - close(); - return; - } - - mHoverView.restoreVisualState(); - - if (null == mHoverView.mSelectedSectionId || null == mHoverView.mMenu.getSection(mHoverView.mSelectedSectionId)) { - mHoverView.mSelectedSectionId = mHoverView.mMenu.getSection(0).getId(); - } - mHoverView.mMenu.setUpdatedCallback(new ListUpdateCallback() { @Override public void onInserted(int position, int count) { @@ -353,10 +278,10 @@ public void onChanged(int position, int count, Object payload) { } }); - if (mHasControl && !mHasMenu) { + if (hasControl() && !mHasMenu) { Log.d(TAG, "Has control. Received initial menu. Expanding menu."); expandMenu(); - } else if (mHasControl) { + } else if (hasControl()) { Log.d(TAG, "Has control. Already had menu. Switching menu."); transitionDisplayFromOldMenuToNew(); } @@ -390,7 +315,7 @@ public boolean respondsToBackButton() { @Override public void onBackPressed() { - collapse(); + mHoverView.collapse(); } private void createTabsForIndices(int ... sectionIndices) { @@ -523,7 +448,7 @@ private void onTabSelected(@NonNull FloatingTab selectedTab) { if (!section.getId().equals(mHoverView.mSelectedSectionId)) { selectSection(section); } else { - collapse(); + mHoverView.collapse(); } } @@ -534,18 +459,4 @@ private void selectSection(@NonNull HoverMenu.Section section) { contentDisplay.selectedTabIs(mSelectedTab); contentDisplay.displayContent(section.getContent()); } - - // TODO: do we need this? - public void setListener(@NonNull Listener listener) { - mListener = listener; - } - - public interface Listener { - void onExpanding(); - - void onExpanded(); - - // TODO: do we need this? - void onCollapseRequested(); - } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index 32523a4..652ce7c 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -31,37 +31,27 @@ class HoverViewStatePreviewed extends HoverViewStateCollapsed { private TabMessageView mMessageView; @Override - public void takeControl(@NonNull HoverView hoverView) { - super.takeControl(hoverView); - mHoverView.mState = this; - mHoverView.notifyListenersPreviewing(); + public void takeControl(@NonNull HoverView hoverView, final Runnable onStateChanged) { + super.takeControl(hoverView, onStateChanged); + Log.d(TAG, "Taking control."); mMessageView = mHoverView.mScreen.getTabMessageView(mHoverView.mSelectedSectionId); mMessageView.appear(mHoverView.mCollapsedDock, new Runnable() { @Override public void run() { - mHoverView.notifyListenersPreviewed(); + onStateChanged.run(); } }); } @Override - protected void changeState(@NonNull final HoverViewState nextState) { + public void giveUpControl(@NonNull final HoverViewState nextState) { + Log.d(TAG, "Giving up control."); if (nextState instanceof HoverViewStateCollapsed) { mMessageView.disappear(true); } else { mMessageView.disappear(false); } - super.changeState(nextState); - } - - @Override - public void preview() { - Log.d(TAG, "Instructed to preview, but already previewed."); - } - - @Override - public void collapse() { - changeState(mHoverView.mCollapsed); + super.giveUpControl(nextState); } @Override From 597400dbfe6ff95c90b65b3e5b9db89fa39deeac Mon Sep 17 00:00:00 2001 From: Haley Date: Mon, 18 Feb 2019 19:56:38 +0900 Subject: [PATCH 009/105] =?UTF-8?q?[BZZRWRDD-262]=20Anchored=20=EC=9D=BC?= =?UTF-8?q?=EB=95=8C=20Drag=EC=97=86=EC=9D=B4=20=ED=84=B0=EC=B9=98?= =?UTF-8?q?=EB=A7=8C=20=EA=B0=80=EB=8A=A5=ED=95=98=EB=8F=84=EB=A1=9D=20Dra?= =?UTF-8?q?gger=EC=9D=98=20=EC=9D=BC=EB=B6=80=EB=A5=BC=20TouchController?= =?UTF-8?q?=20=EB=A1=9C=20=EB=B6=84=EB=A6=AC=ED=95=98=EA=B3=A0=20Window,?= =?UTF-8?q?=20View=20=EA=B3=B5=ED=86=B5=20=EC=9A=94=EC=86=8C=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC=20(#9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hover/BaseTouchController.java | 85 +++++++++ .../java/io/mattcarroll/hover/Dragger.java | 127 +++++++++---- .../java/io/mattcarroll/hover/HoverView.java | 21 ++- .../io/mattcarroll/hover/HoverViewState.java | 2 + .../hover/HoverViewStateAnchored.java | 53 ++++-- .../hover/HoverViewStateClosed.java | 5 + .../hover/HoverViewStateCollapsed.java | 18 +- .../hover/HoverViewStateExpanded.java | 5 + .../hover/HoverViewStatePreviewed.java | 5 + .../mattcarroll/hover/HoverViewStateType.java | 9 + .../mattcarroll/hover/view/InViewDragger.java | 162 ++--------------- .../hover/window/InWindowDragger.java | 170 ++---------------- hover/src/main/res/values/dimens.xml | 1 + 13 files changed, 309 insertions(+), 354 deletions(-) create mode 100644 hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java create mode 100644 hover/src/main/java/io/mattcarroll/hover/HoverViewStateType.java diff --git a/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java b/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java new file mode 100644 index 0000000..e69bde4 --- /dev/null +++ b/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java @@ -0,0 +1,85 @@ +package io.mattcarroll.hover; + +import android.graphics.PointF; +import android.graphics.Rect; +import android.support.annotation.NonNull; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; + +public abstract class BaseTouchController { + private static final String TAG = "BaseTouchController"; + + protected View mTouchView; + protected TouchListener mTouchListener; + protected boolean mIsActivated; + private boolean mIsDebugMode; + + private View.OnTouchListener mDragTouchListener = new View.OnTouchListener() { + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + switch (motionEvent.getAction()) { + case MotionEvent.ACTION_DOWN: + Log.d(TAG, "ACTION_DOWN"); + mTouchListener.onPress(); + return true; + case MotionEvent.ACTION_UP: + Log.d(TAG, "ACTION_UP"); + mTouchListener.onTap(); + return true; + default: + return false; + } + } + }; + + public abstract View createTouchView(@NonNull Rect rect); + + public abstract void destroyTouchView(@NonNull View touchView); + + public abstract void moveTouchViewTo(@NonNull View touchView, @NonNull PointF position); + + public void activate(@NonNull TouchListener touchListener, @NonNull Rect rect) { + if (!mIsActivated) { + Log.d(TAG, "Activating."); + mIsActivated = true; + mTouchListener = touchListener; + mTouchView = createTouchView(rect); + moveTouchViewTo(mTouchView, new PointF(rect.left, rect.top)); + mTouchView.setOnTouchListener(mDragTouchListener); + + updateTouchControlViewAppearance(); + } + } + + public void deactivate() { + if (mIsActivated) { + Log.d(TAG, "Deactivating."); + mTouchView.setOnTouchListener(null); + destroyTouchView(mTouchView); + mIsActivated = false; + mTouchView = null; + } + } + + public void enableDebugMode(boolean isDebugMode) { + mIsDebugMode = isDebugMode; + updateTouchControlViewAppearance(); + } + + private void updateTouchControlViewAppearance() { + if (null != mTouchView) { + if (mIsDebugMode) { + mTouchView.setBackgroundColor(0x44FF0000); + } else { + mTouchView.setBackgroundColor(0x00000000); + } + } + } + + public interface TouchListener { + void onPress(); + + void onTap(); + } +} diff --git a/hover/src/main/java/io/mattcarroll/hover/Dragger.java b/hover/src/main/java/io/mattcarroll/hover/Dragger.java index 0e2572d..e163cb2 100644 --- a/hover/src/main/java/io/mattcarroll/hover/Dragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/Dragger.java @@ -15,44 +15,115 @@ */ package io.mattcarroll.hover; +import android.graphics.PointF; import android.graphics.Rect; import android.support.annotation.NonNull; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; /** * Reports user drag behavior on the screen to a {@link DragListener}. */ -public interface Dragger { +public abstract class Dragger extends BaseTouchController { + private static final String TAG = "Dragger"; - /** - * Starts reporting user drag behavior given a drag area represented by {@code controlBounds}. - * @param dragListener listener that receives information about drag behavior - * @param rect Rect area to be draggable - */ - void activate(@NonNull DragListener dragListener, @NonNull Rect rect); + private final int mTapTouchSlop; + private DragListener mDragListener; + private boolean mIsDragging; - /** - * Stops monitoring and reporting user drag behavior. - */ - void deactivate(); + private PointF mOriginalViewPosition = new PointF(); + private PointF mCurrentViewPosition = new PointF(); + private PointF mOriginalTouchPosition = new PointF(); - /** - * Enable/Disable debug mode. In debug mode this Dragger will paint its touch area with a - * translucent color. - * @param debugMode true for debug mode, false otherwise - */ - void enableDebugMode(boolean debugMode); + protected final View.OnTouchListener mDragTouchListener = new View.OnTouchListener() { + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + switch (motionEvent.getAction()) { + case MotionEvent.ACTION_DOWN: + Log.d(TAG, "ACTION_DOWN"); + mIsDragging = false; - interface DragListener { + mOriginalViewPosition = convertCornerToCenter(getTouchViewPosition(mTouchView)); + mCurrentViewPosition = new PointF(mOriginalViewPosition.x, mOriginalViewPosition.y); + mOriginalTouchPosition.set(motionEvent.getRawX(), motionEvent.getRawY()); + mTouchListener.onPress(); + return true; + case MotionEvent.ACTION_MOVE: + Log.d(TAG, "ACTION_MOVE. motionX: " + motionEvent.getRawX() + ", motionY: " + motionEvent.getRawY()); + float dragDeltaX = motionEvent.getRawX() - mOriginalTouchPosition.x; + float dragDeltaY = motionEvent.getRawY() - mOriginalTouchPosition.y; + mCurrentViewPosition = new PointF( + mOriginalViewPosition.x + dragDeltaX, + mOriginalViewPosition.y + dragDeltaY + ); - /** - * The user has pressed within the draggable area at the given position. - * @param x x-coordinate of the user's press (in the parent View's coordinate space) - * @param y y-coordiante of the user's press (in the parent View's coordinate space) - */ - void onPress(float x, float y); + if (mIsDragging || !isTouchWithinSlopOfOriginalTouch(dragDeltaX, dragDeltaY)) { + if (!mIsDragging) { + // Dragging just started + Log.d(TAG, "MOVE Start Drag."); + mIsDragging = true; + mDragListener.onDragStart(mCurrentViewPosition.x, mCurrentViewPosition.y); + } else { + PointF cornerPosition = convertCenterToCorner(mCurrentViewPosition); + moveTouchViewTo(mTouchView, cornerPosition); + mDragListener.onDragTo(mCurrentViewPosition.x, mCurrentViewPosition.y); + } + } + + return true; + case MotionEvent.ACTION_UP: + Log.d(TAG, "ACTION_UP"); + if (!mIsDragging) { + Log.d(TAG, "Reporting as a tap."); + mTouchListener.onTap(); + } else { + Log.d(TAG, "Reporting as a drag release at: " + mCurrentViewPosition); + mDragListener.onReleasedAt(mCurrentViewPosition.x, mCurrentViewPosition.y); + } + return true; + default: + return false; + } + } + }; + + public Dragger(int mTapTouchSlop) { + this.mTapTouchSlop = mTapTouchSlop; + } + + public abstract PointF getTouchViewPosition(@NonNull View touchView); + + public void activate(@NonNull DragListener dragListener, @NonNull Rect rect) { + super.activate(dragListener, rect); + mDragListener = dragListener; + mTouchView.setOnTouchListener(mDragTouchListener); + } + + private boolean isTouchWithinSlopOfOriginalTouch(float dx, float dy) { + double distance = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)); + Log.d(TAG, "Drag distance " + distance + " vs slop allowance " + mTapTouchSlop); + return distance < mTapTouchSlop; + } + + private PointF convertCornerToCenter(@NonNull PointF cornerPosition) { + return new PointF( + cornerPosition.x + (mTouchView.getWidth() / 2f), + cornerPosition.y + (mTouchView.getHeight() / 2f) + ); + } + + private PointF convertCenterToCorner(@NonNull PointF centerPosition) { + return new PointF( + centerPosition.x - (mTouchView.getWidth() / 2f), + centerPosition.y - (mTouchView.getHeight() / 2f) + ); + } + public interface DragListener extends TouchListener { /** * The user has begun dragging. + * * @param x x-coordinate of the user's drag start (in the parent View's coordinate space) * @param y y-coordiante of the user's drag start (in the parent View's coordinate space) */ @@ -60,6 +131,7 @@ interface DragListener { /** * The user has dragged to the given coordinates. + * * @param x x-coordinate of the user's drag (in the parent View's coordinate space) * @param y y-coordiante of the user's drag (in the parent View's coordinate space) */ @@ -67,15 +139,10 @@ interface DragListener { /** * The user has stopped touching the drag area. + * * @param x x-coordinate of the user's release (in the parent View's coordinate space) * @param y y-coordiante of the user's release (in the parent View's coordinate space) */ void onReleasedAt(float x, float y); - - /** - * The user tapped the drag area (instead of dragging it). - */ - void onTap(); - } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverView.java b/hover/src/main/java/io/mattcarroll/hover/HoverView.java index 923122d..972abc3 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverView.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverView.java @@ -232,11 +232,9 @@ void restoreVisualState() { persistentState.restore(this, mMenu); } - // TODO: when to call this? public void release() { Log.d(TAG, "Released."); mDragger.deactivate(); - // TODO: should we also release the screen? } public void enableDebugMode(boolean debugMode) { @@ -354,21 +352,21 @@ public void removeOnInteractionListener(@NonNull OnInteractionListener onInterac mOnInteractionListeners.remove(onInteractionListener); } - void notifyOnTap() { + void notifyOnTap(HoverViewState state) { for (OnInteractionListener onInteractionListener : mOnInteractionListeners) { - onInteractionListener.onTap(); + onInteractionListener.onTap(state.getStateType()); } } - void notifyOnDragStart() { + void notifyOnDragStart(HoverViewState state) { for (OnInteractionListener onInteractionListener : mOnInteractionListeners) { - onInteractionListener.onDragStart(); + onInteractionListener.onDragStart(state.getStateType()); } } - void notifyOnDocked() { + void notifyOnDocked(HoverViewState state) { for (OnInteractionListener onInteractionListener : mOnInteractionListeners) { - onInteractionListener.onDocked(); + onInteractionListener.onDocked(state.getStateType()); } } @@ -397,6 +395,7 @@ public void removeFromWindow() { if (mIsAddedToWindow) { mWindowViewController.removeView(this); mIsAddedToWindow = false; + release(); } } @@ -609,10 +608,10 @@ public void onAnchored() { } public interface OnInteractionListener { - void onTap(); + void onTap(HoverViewStateType stateType); - void onDragStart(); + void onDragStart(HoverViewStateType stateType); - void onDocked(); + void onDocked(HoverViewStateType stateType); } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewState.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewState.java index c080668..6a175af 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewState.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewState.java @@ -49,4 +49,6 @@ interface HoverViewState { * {@link #respondsToBackButton()} returns true. */ void onBackPressed(); + + HoverViewStateType getStateType(); } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java index 992ed73..7a2c5ec 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java @@ -1,17 +1,26 @@ package io.mattcarroll.hover; import android.graphics.Point; +import android.graphics.Rect; import android.support.annotation.NonNull; import android.util.Log; -public class HoverViewStateAnchored extends BaseHoverViewState { +class HoverViewStateAnchored extends BaseHoverViewState { private static final String TAG = "HoverViewStateAnchored"; - private static final int ANCHOR_TAB_X_OFFSET_IN_PX = 100; - private static final int ANCHOR_TAB_Y_OFFSET_IN_PX = 100; private FloatingTab mSelectedTab; - private Point mDock; + private HoverMenu.Section mSelectedSection; + private final BaseTouchController.TouchListener mTouchListener = new BaseTouchController.TouchListener() { + @Override + public void onPress() { + } + + @Override + public void onTap() { + mHoverView.notifyOnTap(HoverViewStateAnchored.this); + } + }; @Override public void takeControl(@NonNull HoverView hoverView, final Runnable onStateChanged) { @@ -19,20 +28,28 @@ public void takeControl(@NonNull HoverView hoverView, final Runnable onStateChan Log.d(TAG, "Taking control."); mHoverView.makeUntouchableInWindow(); mHoverView.clearFocus(); - mDock = new Point( - mHoverView.mScreen.getWidth() - ANCHOR_TAB_X_OFFSET_IN_PX, - ANCHOR_TAB_Y_OFFSET_IN_PX + final int pointMargin = hoverView.getContext().getResources().getDimensionPixelSize(R.dimen.hover_tab_anchor_margin); + final Point anchorPoint = new Point( + mHoverView.mScreen.getWidth() - pointMargin, + mHoverView.mScreen.getHeight() - pointMargin ); - HoverMenu.Section section = mHoverView.mMenu.getSection(0); - mSelectedTab = mHoverView.mScreen.createChainedTab(section); - mSelectedTab.setDock(new PositionDock(mDock)); + mSelectedSection = mHoverView.mMenu.getSection(mHoverView.mSelectedSectionId); + if (mSelectedSection == null) { + mSelectedSection = mHoverView.mMenu.getSection(0); + } + mSelectedTab = mHoverView.mScreen.getChainedTab(mSelectedSection.getId()); + if (mSelectedTab == null) { + mSelectedTab = mHoverView.mScreen.createChainedTab(mSelectedSection); + } + mSelectedTab.setDock(new PositionDock(anchorPoint)); mSelectedTab.dock(new Runnable() { @Override public void run() { if (!hasControl()) { return; } + activateTouchController(); onStateChanged.run(); } }); @@ -41,9 +58,20 @@ public void run() { @Override public void giveUpControl(@NonNull HoverViewState nextState) { Log.d(TAG, "Giving up control."); + deactivateTouchController(); super.giveUpControl(nextState); } + private void activateTouchController() { + final Rect visibleRect = new Rect(); + mSelectedTab.getGlobalVisibleRect(visibleRect); + mHoverView.mDragger.activate(mTouchListener, visibleRect); + } + + private void deactivateTouchController() { + mHoverView.mDragger.deactivate(); + } + @Override public boolean respondsToBackButton() { return false; @@ -52,4 +80,9 @@ public boolean respondsToBackButton() { @Override public void onBackPressed() { } + + @Override + public HoverViewStateType getStateType() { + return HoverViewStateType.ANCHORED; + } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java index acddf2a..40f3da2 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java @@ -69,4 +69,9 @@ public void giveUpControl(@NonNull HoverViewState nextState) { Log.d(TAG, "Giving up control."); super.giveUpControl(nextState); } + + @Override + public HoverViewStateType getStateType() { + return HoverViewStateType.CLOSED; + } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index dd1b887..cb2ab16 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -207,7 +207,7 @@ private void onPickedUpByUser() { mIsDocked = false; mHoverView.mScreen.getExitView().setVisibility(VISIBLE); restoreHoverViewAlphaValue(); - mHoverView.notifyOnDragStart(); + mHoverView.notifyOnDragStart(this); } private void onDroppedByUser() { @@ -245,7 +245,7 @@ private void onDroppedByUser() { private void onTap() { Log.d(TAG, "Floating tab was tapped."); - mHoverView.notifyOnTap(); + mHoverView.notifyOnTap(this); } private void sendToDock() { @@ -296,7 +296,7 @@ private void onDocked() { if (didJustCollapse) { mOnStateChanged.run(); } - mHoverView.notifyOnDocked(); + mHoverView.notifyOnDocked(this); } protected void moveTabTo(@NonNull Point position) { @@ -322,6 +322,11 @@ protected void restoreHoverViewAlphaValue() { mHoverView.setAlpha(1f); } + @Override + public HoverViewStateType getStateType() { + return HoverViewStateType.COLLAPSED; + } + protected static final class FloatingTabDragListener implements Dragger.DragListener { private final HoverViewStateCollapsed mOwner; @@ -330,9 +335,6 @@ protected FloatingTabDragListener(@NonNull HoverViewStateCollapsed owner) { mOwner = owner; } - @Override - public void onPress(float x, float y) { } - @Override public void onDragStart(float x, float y) { mOwner.onPickedUpByUser(); @@ -348,6 +350,10 @@ public void onReleasedAt(float x, float y) { mOwner.onDroppedByUser(); } + @Override + public void onPress() { + } + @Override public void onTap() { mOwner.onTap(); diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java index 7d0b123..483639a 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java @@ -459,4 +459,9 @@ private void selectSection(@NonNull HoverMenu.Section section) { contentDisplay.selectedTabIs(mSelectedTab); contentDisplay.displayContent(section.getContent()); } + + @Override + public HoverViewStateType getStateType() { + return HoverViewStateType.EXPANDED; + } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index 652ce7c..3ce8bcd 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -74,4 +74,9 @@ protected void activateDragger() { mHoverView.mDragger.activate(mDragListener, tabRect); } + + @Override + public HoverViewStateType getStateType() { + return HoverViewStateType.PREVIEWED; + } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateType.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateType.java new file mode 100644 index 0000000..7435290 --- /dev/null +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateType.java @@ -0,0 +1,9 @@ +package io.mattcarroll.hover; + +public enum HoverViewStateType { + CLOSED, + COLLAPSED, + PREVIEWED, + EXPANDED, + ANCHORED, +} diff --git a/hover/src/main/java/io/mattcarroll/hover/view/InViewDragger.java b/hover/src/main/java/io/mattcarroll/hover/view/InViewDragger.java index 1811bc2..ce0e528 100644 --- a/hover/src/main/java/io/mattcarroll/hover/view/InViewDragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/view/InViewDragger.java @@ -18,8 +18,6 @@ import android.graphics.PointF; import android.graphics.Rect; import android.support.annotation.NonNull; -import android.util.Log; -import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -29,165 +27,43 @@ /** * {@link Dragger} implementation that works within a {@link ViewGroup}. */ -public class InViewDragger implements Dragger { - +public class InViewDragger extends Dragger { private static final String TAG = "InViewDragger"; private final ViewGroup mContainer; - private final int mTapTouchSlop; - private boolean mIsActivated; - private boolean mIsDragging; - private boolean mIsDebugMode = false; - private View mDragView; - private DragListener mDragListener; - private PointF mOriginalViewPosition = new PointF(); - private PointF mCurrentViewPosition = new PointF(); - private PointF mOriginalTouchPosition = new PointF(); - - private final View.OnTouchListener mDragTouchListener = new View.OnTouchListener() { - @Override - public boolean onTouch(View view, MotionEvent motionEvent) { - switch (motionEvent.getAction()) { - case MotionEvent.ACTION_DOWN: - Log.d(TAG, "ACTION_DOWN"); - mIsDragging = false; - - mOriginalViewPosition = getDragViewCenterPosition(); - mCurrentViewPosition = new PointF(mOriginalViewPosition.x, mOriginalViewPosition.y); - mOriginalTouchPosition.set(motionEvent.getRawX(), motionEvent.getRawY()); - - mDragListener.onPress(mCurrentViewPosition.x, mCurrentViewPosition.y); - - return true; - case MotionEvent.ACTION_MOVE: - Log.v(TAG, "ACTION_MOVE. motionX: " + motionEvent.getRawX() + ", motionY: " + motionEvent.getRawY()); - float dragDeltaX = motionEvent.getRawX() - mOriginalTouchPosition.x; - float dragDeltaY = motionEvent.getRawY() - mOriginalTouchPosition.y; - mCurrentViewPosition = new PointF( - mOriginalViewPosition.x + dragDeltaX, - mOriginalViewPosition.y + dragDeltaY - ); - - if (mIsDragging || !isTouchWithinSlopOfOriginalTouch(dragDeltaX, dragDeltaY)) { - if (!mIsDragging) { - // Dragging just started - Log.d(TAG, "MOVE Start Drag."); - mIsDragging = true; - mDragListener.onDragStart(mCurrentViewPosition.x, mCurrentViewPosition.y); - } else { - moveDragViewTo(mCurrentViewPosition); - mDragListener.onDragTo(mCurrentViewPosition.x, mCurrentViewPosition.y); - } - } - - return true; - case MotionEvent.ACTION_UP: - if (!mIsDragging) { - Log.d(TAG, "ACTION_UP: Tap."); - mDragListener.onTap(); - } else { - Log.d(TAG, "ACTION_UP: Released from dragging."); - mDragListener.onReleasedAt(mCurrentViewPosition.x, mCurrentViewPosition.y); - } - - return true; - default: - return false; - } - } - }; public InViewDragger(@NonNull ViewGroup container, int touchSlop) { + super(touchSlop); mContainer = container; - mTapTouchSlop = touchSlop; } @Override - public void enableDebugMode(boolean isDebugMode) { - mIsDebugMode = isDebugMode; - updateTouchControlViewAppearance(); - } - - @Override - public void activate(@NonNull DragListener dragListener, @NonNull Rect rect) { - if (!mIsActivated) { - Log.d(TAG, "Activating."); - mIsActivated = true; - mDragListener = dragListener; - createTouchControlView(rect); - } - } - - @Override - public void deactivate() { - if (mIsActivated) { - Log.d(TAG, "Deactivating."); - mIsActivated = false; - destroyTouchControlView(); - } - } - - private void createTouchControlView(@NonNull Rect rect) { - mDragView = new View(mContainer.getContext()); - mDragView.setId(R.id.hover_drag_view); + public View createTouchView(@NonNull Rect rect) { + View dragView = new View(mContainer.getContext()); + dragView.setId(R.id.hover_drag_view); final int width = rect.right - rect.left; final int height = rect.bottom - rect.top; - mDragView.setLayoutParams(new ViewGroup.LayoutParams(width, height)); - mDragView.setOnTouchListener(mDragTouchListener); - mContainer.addView(mDragView); - - moveDragViewTo(new PointF((rect.right + rect.left) / 2, (rect.bottom + rect.top) / 2)); - updateTouchControlViewAppearance(); - } - - private void destroyTouchControlView() { - mContainer.removeView(mDragView); - - mDragView.setOnTouchListener(null); - mDragView = null; - } - - private void updateTouchControlViewAppearance() { - if (null != mDragView) { - if (mIsDebugMode) { - Log.d(TAG, "Making mDragView red: " + mDragView.hashCode()); - mDragView.setBackgroundColor(0x44FF0000); - } else { - mDragView.setBackgroundColor(0x00000000); - } - } - } - - private boolean isTouchWithinSlopOfOriginalTouch(float dx, float dy) { - double distance = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)); - return distance < mTapTouchSlop; + dragView.setLayoutParams(new ViewGroup.LayoutParams(width, height)); + mContainer.addView(dragView); + return dragView; } - private PointF getDragViewCenterPosition() { - return convertCornerToCenter(new PointF( - mDragView.getX(), - mDragView.getY() - )); - } - - private void moveDragViewTo(PointF centerPosition) { - Log.d(TAG, "Moving drag view (" + mDragView.hashCode() + ") to: " + centerPosition); - PointF cornerPosition = convertCenterToCorner(centerPosition); - mDragView.setX(cornerPosition.x); - mDragView.setY(cornerPosition.y); + @Override + public void destroyTouchView(@NonNull View touchView) { + mContainer.removeView(touchView); } - private PointF convertCornerToCenter(@NonNull PointF cornerPosition) { + @Override + public PointF getTouchViewPosition(@NonNull View touchView) { return new PointF( - cornerPosition.x + (mDragView.getWidth() / 2), - cornerPosition.y + (mDragView.getHeight() / 2) + touchView.getX(), + touchView.getY() ); } - private PointF convertCenterToCorner(@NonNull PointF centerPosition) { - return new PointF( - centerPosition.x - (mDragView.getWidth() / 2), - centerPosition.y - (mDragView.getHeight() / 2) - ); + @Override + public void moveTouchViewTo(@NonNull View touchView, @NonNull PointF position) { + touchView.setX(position.x); + touchView.setY(position.y); } } diff --git a/hover/src/main/java/io/mattcarroll/hover/window/InWindowDragger.java b/hover/src/main/java/io/mattcarroll/hover/window/InWindowDragger.java index aac914a..d65759f 100755 --- a/hover/src/main/java/io/mattcarroll/hover/window/InWindowDragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/window/InWindowDragger.java @@ -16,12 +16,9 @@ package io.mattcarroll.hover.window; import android.content.Context; -import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; import android.support.annotation.NonNull; -import android.util.Log; -import android.view.MotionEvent; import android.view.View; import io.mattcarroll.hover.Dragger; @@ -29,176 +26,41 @@ /** * {@link Dragger} implementation that works within a {@code Window}. */ -public class InWindowDragger implements Dragger { - +public class InWindowDragger extends Dragger { private static final String TAG = "InWindowDragger"; private final Context mContext; private final WindowViewController mWindowViewController; - private final float mTapTouchSlop; - private View mDragView; - private Dragger.DragListener mDragListener; - private boolean mIsActivated; - private boolean mIsDragging; - private boolean mIsDebugMode; - - private PointF mOriginalViewPosition = new PointF(); - private PointF mCurrentViewPosition = new PointF(); - private PointF mOriginalTouchPosition = new PointF(); - - private View.OnTouchListener mDragTouchListener = new View.OnTouchListener() { - @Override - public boolean onTouch(View view, MotionEvent motionEvent) { - switch (motionEvent.getAction()) { - case MotionEvent.ACTION_DOWN: - Log.d(TAG, "ACTION_DOWN"); - mIsDragging = false; - - mOriginalViewPosition = getDragViewCenterPosition(); - mCurrentViewPosition = new PointF(mOriginalViewPosition.x, mOriginalViewPosition.y); - mOriginalTouchPosition.set(motionEvent.getRawX(), motionEvent.getRawY()); - - mDragListener.onPress(mCurrentViewPosition.x, mCurrentViewPosition.y); - - return true; - case MotionEvent.ACTION_MOVE: - Log.d(TAG, "ACTION_MOVE. motionX: " + motionEvent.getRawX() + ", motionY: " + motionEvent.getRawY()); - float dragDeltaX = motionEvent.getRawX() - mOriginalTouchPosition.x; - float dragDeltaY = motionEvent.getRawY() - mOriginalTouchPosition.y; - mCurrentViewPosition = new PointF( - mOriginalViewPosition.x + dragDeltaX, - mOriginalViewPosition.y + dragDeltaY - ); - - if (mIsDragging || !isTouchWithinSlopOfOriginalTouch(dragDeltaX, dragDeltaY)) { - if (!mIsDragging) { - // Dragging just started - Log.d(TAG, "MOVE Start Drag."); - mIsDragging = true; - mDragListener.onDragStart(mCurrentViewPosition.x, mCurrentViewPosition.y); - } else { - moveDragViewTo(mCurrentViewPosition); - mDragListener.onDragTo(mCurrentViewPosition.x, mCurrentViewPosition.y); - } - } - - return true; - case MotionEvent.ACTION_UP: - Log.d(TAG, "ACTION_UP"); - if (!mIsDragging) { - Log.d(TAG, "Reporting as a tap."); - mDragListener.onTap(); - } else { - Log.d(TAG, "Reporting as a drag release at: " + mCurrentViewPosition); - mDragListener.onReleasedAt(mCurrentViewPosition.x, mCurrentViewPosition.y); - } - return true; - default: - return false; - } - } - }; - - /** - * Note: {@code view} must already be added to the {@code Window}. - * @param context context - * @param windowViewController windowViewController - * @param tapTouchSlop tapTouchSlop - */ public InWindowDragger(@NonNull Context context, @NonNull WindowViewController windowViewController, - float tapTouchSlop) { + int tapTouchSlop) { + super(tapTouchSlop); mContext = context; mWindowViewController = windowViewController; - mTapTouchSlop = tapTouchSlop; - } - - @Override - public void activate(@NonNull DragListener dragListener, @NonNull Rect rect) { - if (!mIsActivated) { - Log.d(TAG, "Activating."); - createTouchControlView(rect); - mDragListener = dragListener; - mDragView.setOnTouchListener(mDragTouchListener); - mIsActivated = true; - } - } - - @Override - public void deactivate() { - if (mIsActivated) { - Log.d(TAG, "Deactivating."); - mDragView.setOnTouchListener(null); - destroyTouchControlView(); - mIsActivated = false; - } } @Override - public void enableDebugMode(boolean isDebugMode) { - mIsDebugMode = isDebugMode; - updateTouchControlViewAppearance(); - } - - private void createTouchControlView(@NonNull Rect rect) { - mDragView = new View(mContext); + public View createTouchView(@NonNull Rect rect) { + View dragView = new View(mContext); final int width = rect.right - rect.left; final int height = rect.bottom - rect.top; - mWindowViewController.addView(width, height, true, mDragView); - mWindowViewController.moveViewTo(mDragView, rect.left, rect.top); - mDragView.setOnTouchListener(mDragTouchListener); - - updateTouchControlViewAppearance(); - } - - private void destroyTouchControlView() { - mWindowViewController.removeView(mDragView); - mDragView = null; - } - - private void updateTouchControlViewAppearance() { - if (null != mDragView) { - if (mIsDebugMode) { - mDragView.setBackgroundColor(0x44FF0000); - } else { - mDragView.setBackgroundColor(0x00000000); - } - } + mWindowViewController.addView(width, height, true, dragView); + return dragView; } - private boolean isTouchWithinSlopOfOriginalTouch(float dx, float dy) { - double distance = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)); - Log.d(TAG, "Drag distance " + distance + " vs slop allowance " + mTapTouchSlop); - return distance < mTapTouchSlop; - } - - private PointF getDragViewCenterPosition() { - Point cornerPosition = mWindowViewController.getViewPosition(mDragView); - return convertCornerToCenter(new PointF( - cornerPosition.x, - cornerPosition.y - )); - } - - private void moveDragViewTo(PointF centerPosition) { - Log.d(TAG, "Center position: " + centerPosition); - PointF cornerPosition = convertCenterToCorner(centerPosition); - Log.d(TAG, "Corner position: " + cornerPosition); - mWindowViewController.moveViewTo(mDragView, (int) cornerPosition.x, (int) cornerPosition.y); + @Override + public void destroyTouchView(@NonNull View touchView) { + mWindowViewController.removeView(touchView); } - private PointF convertCornerToCenter(@NonNull PointF cornerPosition) { - return new PointF( - cornerPosition.x + (mDragView.getWidth() / 2), - cornerPosition.y + (mDragView.getHeight() / 2) - ); + @Override + public PointF getTouchViewPosition(@NonNull View touchView) { + return new PointF(mWindowViewController.getViewPosition(touchView)); } - private PointF convertCenterToCorner(@NonNull PointF centerPosition) { - return new PointF( - centerPosition.x - (mDragView.getWidth() / 2), - centerPosition.y - (mDragView.getHeight() / 2) - ); + @Override + public void moveTouchViewTo(@NonNull View touchView, @NonNull PointF position) { + mWindowViewController.moveViewTo(touchView, (int) position.x, (int) position.y); } } diff --git a/hover/src/main/res/values/dimens.xml b/hover/src/main/res/values/dimens.xml index 0023349..51aeba3 100755 --- a/hover/src/main/res/values/dimens.xml +++ b/hover/src/main/res/values/dimens.xml @@ -6,4 +6,5 @@ 75dp 32dp 24dp + 32dp From 9111eca1d310d2a150042dcfe161c12a344bb400 Mon Sep 17 00:00:00 2001 From: Haley Date: Tue, 19 Feb 2019 18:40:07 +0900 Subject: [PATCH 010/105] =?UTF-8?q?[BZZRWRDD-262]=20Floating=20Tab=20?= =?UTF-8?q?=EC=95=84=EC=9D=B4=EC=BD=98,=20=EC=82=AC=EC=9D=B4=EC=A6=88=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=EC=8B=9C=ED=82=A4=EA=B8=B0=20(for=20Anchored?= =?UTF-8?q?State)=20(#10)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Anchored 일때 shrink, 나올 때 expand * selected 조정해서 아이콘 변경시키기 --- .../io/mattcarroll/hover/FloatingTab.java | 21 ++++++++++++++++--- .../hover/HoverViewStateAnchored.java | 15 ++++++++----- hover/src/main/res/values/dimens.xml | 3 ++- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java index 5684abc..e3ab65d 100644 --- a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java +++ b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java @@ -75,14 +75,16 @@ public FloatingTab(@NonNull Context context, @NonNull String tabId) { @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); + updateSize(); + addOnLayoutChangeListener(mOnLayoutChangeListener); + } + private void updateSize() { // Make this View the desired size. - ViewGroup.LayoutParams layoutParams = getLayoutParams(); + final ViewGroup.LayoutParams layoutParams = getLayoutParams(); layoutParams.width = mTabSize; layoutParams.height = mTabSize; setLayoutParams(layoutParams); - - addOnLayoutChangeListener(mOnLayoutChangeListener); } @Override @@ -169,6 +171,19 @@ public void disappearImmediate() { setVisibility(GONE); } + public void shrink() { + mTabSize = getResources().getDimensionPixelSize(R.dimen.hover_tab_size_shrunk); + updateSize(); + setPadding(0, 0, 0, 0); + } + + public void expand() { + mTabSize = getResources().getDimensionPixelSize(R.dimen.hover_tab_size); + updateSize(); + int padding = getResources().getDimensionPixelSize(R.dimen.hover_tab_margin); + setPadding(padding, padding, padding, padding); + } + @NonNull public String getTabId() { return mId; diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java index 7a2c5ec..a1a0518 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java @@ -28,11 +28,6 @@ public void takeControl(@NonNull HoverView hoverView, final Runnable onStateChan Log.d(TAG, "Taking control."); mHoverView.makeUntouchableInWindow(); mHoverView.clearFocus(); - final int pointMargin = hoverView.getContext().getResources().getDimensionPixelSize(R.dimen.hover_tab_anchor_margin); - final Point anchorPoint = new Point( - mHoverView.mScreen.getWidth() - pointMargin, - mHoverView.mScreen.getHeight() - pointMargin - ); mSelectedSection = mHoverView.mMenu.getSection(mHoverView.mSelectedSectionId); if (mSelectedSection == null) { @@ -42,6 +37,14 @@ public void takeControl(@NonNull HoverView hoverView, final Runnable onStateChan if (mSelectedTab == null) { mSelectedTab = mHoverView.mScreen.createChainedTab(mSelectedSection); } + + mSelectedTab.shrink(); + mSelectedTab.setSelected(true); + final int anchorMargin = hoverView.getContext().getResources().getDimensionPixelSize(R.dimen.hover_tab_anchor_margin) + (mSelectedTab.getTabSize() / 2); + final Point anchorPoint = new Point( + mHoverView.mScreen.getWidth() - anchorMargin, + mHoverView.mScreen.getHeight() - anchorMargin + ); mSelectedTab.setDock(new PositionDock(anchorPoint)); mSelectedTab.dock(new Runnable() { @Override @@ -59,6 +62,8 @@ public void run() { public void giveUpControl(@NonNull HoverViewState nextState) { Log.d(TAG, "Giving up control."); deactivateTouchController(); + mSelectedTab.expand(); + mSelectedTab.setSelected(false); super.giveUpControl(nextState); } diff --git a/hover/src/main/res/values/dimens.xml b/hover/src/main/res/values/dimens.xml index 51aeba3..d0eaac0 100755 --- a/hover/src/main/res/values/dimens.xml +++ b/hover/src/main/res/values/dimens.xml @@ -1,10 +1,11 @@ 72dp + 48dp + 12dp 8dp 7dp 40dp 75dp 32dp 24dp - 32dp From 564a53cfa6dda6d153e04aecfc28df334e997744 Mon Sep 17 00:00:00 2001 From: Haley Date: Thu, 21 Feb 2019 12:04:39 +0900 Subject: [PATCH 011/105] [BZZRWRDD-262] Disable 'clipping' to use shadow around child view (#11) --- hover/src/main/java/io/mattcarroll/hover/FloatingTab.java | 2 ++ hover/src/main/java/io/mattcarroll/hover/Screen.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java index e3ab65d..784a857 100644 --- a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java +++ b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java @@ -67,6 +67,8 @@ public FloatingTab(@NonNull Context context, @NonNull String tabId) { super(context); mId = tabId; mTabSize = getResources().getDimensionPixelSize(R.dimen.hover_tab_size); + setClipChildren(false); + setClipToPadding(false); int padding = getResources().getDimensionPixelSize(R.dimen.hover_tab_margin); setPadding(padding, padding, padding, padding); diff --git a/hover/src/main/java/io/mattcarroll/hover/Screen.java b/hover/src/main/java/io/mattcarroll/hover/Screen.java index 1c4212a..e186ba0 100644 --- a/hover/src/main/java/io/mattcarroll/hover/Screen.java +++ b/hover/src/main/java/io/mattcarroll/hover/Screen.java @@ -45,6 +45,8 @@ class Screen { Screen(@NonNull ViewGroup hoverMenuContainer) { mContainer = hoverMenuContainer; + mContainer.setClipChildren(false); + mContainer.setClipToPadding(false); mShadeView = new ShadeView(mContainer.getContext()); mContainer.addView(mShadeView, new WindowManager.LayoutParams( From b7489496f42e06a032c4282195d457fd477388cb Mon Sep 17 00:00:00 2001 From: Haley Date: Thu, 21 Feb 2019 15:18:16 +0900 Subject: [PATCH 012/105] [BZZRWRDD-262] Disable 'clipping' to use shadow around child view - in TabMessageView (#12) --- hover/src/main/java/io/mattcarroll/hover/TabMessageView.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java index fb9db06..49502a2 100644 --- a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java +++ b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java @@ -45,6 +45,8 @@ public void onDockChange(@NonNull Dock dock) { public TabMessageView(@NonNull Context context, @NonNull View messageView, @NonNull FloatingTab floatingTab) { super(context); + setClipToPadding(false); + setClipChildren(false); mFloatingTab = floatingTab; addView(messageView); setVisibility(GONE); From ddc33d07c43cbbec913509c264be545a2a68b377 Mon Sep 17 00:00:00 2001 From: Haley Date: Fri, 22 Feb 2019 22:26:05 +0900 Subject: [PATCH 013/105] =?UTF-8?q?Previewed=20state=20=EC=97=90=EC=84=9C?= =?UTF-8?q?=20OnStateChanged=20=EC=BD=9C=EB=B0=B1=EC=9D=B4=20=EB=91=90?= =?UTF-8?q?=EB=B2=88=20=EB=B6=88=EB=A6=AC=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#14)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/mattcarroll/hover/HoverViewStateCollapsed.java | 4 +++- .../java/io/mattcarroll/hover/HoverViewStatePreviewed.java | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index cb2ab16..519f05e 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -294,7 +294,9 @@ private void onDocked() { mIsCollapsed = true; mHoverView.saveVisualState(); if (didJustCollapse) { - mOnStateChanged.run(); + if (mOnStateChanged != null) { + mOnStateChanged.run(); + } } mHoverView.notifyOnDocked(this); } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index 3ce8bcd..f777b21 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -32,7 +32,7 @@ class HoverViewStatePreviewed extends HoverViewStateCollapsed { @Override public void takeControl(@NonNull HoverView hoverView, final Runnable onStateChanged) { - super.takeControl(hoverView, onStateChanged); + super.takeControl(hoverView, null); Log.d(TAG, "Taking control."); mMessageView = mHoverView.mScreen.getTabMessageView(mHoverView.mSelectedSectionId); mMessageView.appear(mHoverView.mCollapsedDock, new Runnable() { From 7c9e0e3ab81664aa158f1b3ac0c6dc8270ad0778 Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Sun, 24 Feb 2019 14:47:49 +0900 Subject: [PATCH 014/105] =?UTF-8?q?=EB=B7=B0=20=EC=82=AC=EC=9D=B4=EC=A6=88?= =?UTF-8?q?=EA=B0=80=20=EC=95=84=EB=8B=8C=20Window=20default=20display=20s?= =?UTF-8?q?ize=20=EB=A5=BC=20=ED=95=AD=EC=83=81=20=EC=B0=B8=EC=A1=B0?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20&=20TouchController=EA=B0=80=20?= =?UTF-8?q?=EC=97=AC=EB=9F=AC=EA=B0=9C=EC=9D=98=20View=EB=A5=BC=20?= =?UTF-8?q?=EB=B0=9B=EC=95=84=EC=99=80=EC=84=9C=20=ED=84=B0=EC=B9=98=20?= =?UTF-8?q?=EC=98=81=EC=97=AD=EC=9D=84=20=EC=83=9D=EC=84=B1=20=ED=95=A0=20?= =?UTF-8?q?=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?(#13)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Container View 크기가 바뀔 때 (뷰 영역 or Screen Orientation 변화) FloatingTab, TouchController 의 위치 계산이 잘못되는 버그 수정 --- .../hover/BaseTouchController.java | 69 +++++++++++++++---- .../io/mattcarroll/hover/ContentDisplay.java | 3 +- .../java/io/mattcarroll/hover/Dragger.java | 27 ++++---- .../io/mattcarroll/hover/FloatingTab.java | 43 ++---------- .../mattcarroll/hover/HoverFrameLayout.java | 61 ++++++++++++++++ .../java/io/mattcarroll/hover/HoverView.java | 7 ++ .../hover/HoverViewStateAnchored.java | 21 +++--- .../hover/HoverViewStateCollapsed.java | 26 ++++--- .../hover/HoverViewStateExpanded.java | 2 +- .../hover/HoverViewStatePreviewed.java | 22 +++--- .../java/io/mattcarroll/hover/Screen.java | 8 --- .../java/io/mattcarroll/hover/SideDock.java | 10 ++- .../java/io/mattcarroll/hover/TabChain.java | 2 +- .../io/mattcarroll/hover/TabMessageView.java | 19 ++--- .../mattcarroll/hover/view/InViewDragger.java | 6 +- .../hover/window/InWindowDragger.java | 4 +- hover/src/main/res/values/dimens.xml | 3 +- 17 files changed, 211 insertions(+), 122 deletions(-) create mode 100644 hover/src/main/java/io/mattcarroll/hover/HoverFrameLayout.java diff --git a/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java b/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java index e69bde4..8f3cbed 100644 --- a/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java +++ b/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java @@ -7,13 +7,18 @@ import android.view.MotionEvent; import android.view.View; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + public abstract class BaseTouchController { private static final String TAG = "BaseTouchController"; - protected View mTouchView; + protected Map mTouchViewMap = new HashMap<>(); protected TouchListener mTouchListener; protected boolean mIsActivated; private boolean mIsDebugMode; + private List mViewList; private View.OnTouchListener mDragTouchListener = new View.OnTouchListener() { @Override @@ -33,21 +38,45 @@ public boolean onTouch(View view, MotionEvent motionEvent) { } }; + private final HoverFrameLayout.OnPositionChangeListener mOnLayoutChangeListener = new HoverFrameLayout.OnPositionChangeListener() { + @Override + public void onPositionChange(@NonNull View view) { + moveTouchViewTo(mTouchViewMap.get(view.getTag()), new PointF(view.getX(), view.getY())); + } + + @Override + public void onDockChange(@NonNull Dock dock) { + + } + }; + public abstract View createTouchView(@NonNull Rect rect); public abstract void destroyTouchView(@NonNull View touchView); public abstract void moveTouchViewTo(@NonNull View touchView, @NonNull PointF position); - public void activate(@NonNull TouchListener touchListener, @NonNull Rect rect) { + public void activate(@NonNull TouchListener touchListener, @NonNull List viewList) { if (!mIsActivated) { Log.d(TAG, "Activating."); mIsActivated = true; mTouchListener = touchListener; - mTouchView = createTouchView(rect); - moveTouchViewTo(mTouchView, new PointF(rect.left, rect.top)); - mTouchView.setOnTouchListener(mDragTouchListener); - + mViewList = viewList; + mTouchViewMap.clear(); + for (int i = 0; i < mViewList.size(); i++) { + View view = mViewList.get(i); + String tag = "view" + i; + view.setTag(tag); + Rect rect = new Rect(); + view.getDrawingRect(rect); + View touchView = createTouchView(rect); + moveTouchViewTo(touchView, new PointF(view.getX(), view.getY())); + touchView.setOnTouchListener(mDragTouchListener); + mTouchViewMap.put(tag, touchView); + if (view instanceof HoverFrameLayout) { + ((HoverFrameLayout) view).addOnPositionChangeListener(mOnLayoutChangeListener); + } + } updateTouchControlViewAppearance(); } } @@ -55,10 +84,20 @@ public void activate(@NonNull TouchListener touchListener, @NonNull Rect rect) { public void deactivate() { if (mIsActivated) { Log.d(TAG, "Deactivating."); - mTouchView.setOnTouchListener(null); - destroyTouchView(mTouchView); + for (View view : mViewList) { + view.setOnTouchListener(null); + if (view instanceof HoverFrameLayout) { + ((HoverFrameLayout) view).removeOnPositionChangeListener(mOnLayoutChangeListener); + } + } + + for (View touchView : mTouchViewMap.values()) { + destroyTouchView(touchView); + } + mIsActivated = false; - mTouchView = null; + mTouchViewMap.clear(); + mViewList = null; } } @@ -68,11 +107,13 @@ public void enableDebugMode(boolean isDebugMode) { } private void updateTouchControlViewAppearance() { - if (null != mTouchView) { - if (mIsDebugMode) { - mTouchView.setBackgroundColor(0x44FF0000); - } else { - mTouchView.setBackgroundColor(0x00000000); + for (View touchView : mTouchViewMap.values()) { + if (null != touchView) { + if (mIsDebugMode) { + touchView.setBackgroundColor(0x44FF0000); + } else { + touchView.setBackgroundColor(0x00000000); + } } } } diff --git a/hover/src/main/java/io/mattcarroll/hover/ContentDisplay.java b/hover/src/main/java/io/mattcarroll/hover/ContentDisplay.java index 553d38d..bc89049 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ContentDisplay.java +++ b/hover/src/main/java/io/mattcarroll/hover/ContentDisplay.java @@ -62,7 +62,8 @@ public void onGlobalLayout() { private final FloatingTab.OnPositionChangeListener mOnTabPositionChangeListener = new FloatingTab.OnPositionChangeListener() { @Override - public void onPositionChange(@NonNull Point position) { + public void onPositionChange(@NonNull View view) { + final Point position = new Point((int) view.getX() + (view.getWidth() / 2), (int) view.getY() + (view.getHeight() / 2)); Log.d(TAG, mSelectedTab + " tab moved to " + position); updateTabSelectorPosition(); diff --git a/hover/src/main/java/io/mattcarroll/hover/Dragger.java b/hover/src/main/java/io/mattcarroll/hover/Dragger.java index e163cb2..81965bf 100644 --- a/hover/src/main/java/io/mattcarroll/hover/Dragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/Dragger.java @@ -16,12 +16,13 @@ package io.mattcarroll.hover; import android.graphics.PointF; -import android.graphics.Rect; import android.support.annotation.NonNull; import android.util.Log; import android.view.MotionEvent; import android.view.View; +import java.util.List; + /** * Reports user drag behavior on the screen to a {@link DragListener}. */ @@ -44,7 +45,7 @@ public boolean onTouch(View view, MotionEvent motionEvent) { Log.d(TAG, "ACTION_DOWN"); mIsDragging = false; - mOriginalViewPosition = convertCornerToCenter(getTouchViewPosition(mTouchView)); + mOriginalViewPosition = convertCornerToCenter(view, getTouchViewPosition(view)); mCurrentViewPosition = new PointF(mOriginalViewPosition.x, mOriginalViewPosition.y); mOriginalTouchPosition.set(motionEvent.getRawX(), motionEvent.getRawY()); mTouchListener.onPress(); @@ -65,8 +66,6 @@ public boolean onTouch(View view, MotionEvent motionEvent) { mIsDragging = true; mDragListener.onDragStart(mCurrentViewPosition.x, mCurrentViewPosition.y); } else { - PointF cornerPosition = convertCenterToCorner(mCurrentViewPosition); - moveTouchViewTo(mTouchView, cornerPosition); mDragListener.onDragTo(mCurrentViewPosition.x, mCurrentViewPosition.y); } } @@ -94,10 +93,12 @@ public Dragger(int mTapTouchSlop) { public abstract PointF getTouchViewPosition(@NonNull View touchView); - public void activate(@NonNull DragListener dragListener, @NonNull Rect rect) { - super.activate(dragListener, rect); + public void activate(@NonNull DragListener dragListener, @NonNull List viewList) { + super.activate(dragListener, viewList); mDragListener = dragListener; - mTouchView.setOnTouchListener(mDragTouchListener); + for (View touchView : mTouchViewMap.values()) { + touchView.setOnTouchListener(mDragTouchListener); + } } private boolean isTouchWithinSlopOfOriginalTouch(float dx, float dy) { @@ -106,17 +107,17 @@ private boolean isTouchWithinSlopOfOriginalTouch(float dx, float dy) { return distance < mTapTouchSlop; } - private PointF convertCornerToCenter(@NonNull PointF cornerPosition) { + private PointF convertCornerToCenter(View touchView, @NonNull PointF cornerPosition) { return new PointF( - cornerPosition.x + (mTouchView.getWidth() / 2f), - cornerPosition.y + (mTouchView.getHeight() / 2f) + cornerPosition.x + (touchView.getWidth() / 2f), + cornerPosition.y + (touchView.getHeight() / 2f) ); } - private PointF convertCenterToCorner(@NonNull PointF centerPosition) { + private PointF convertCenterToCorner(View touchView, @NonNull PointF centerPosition) { return new PointF( - centerPosition.x - (mTouchView.getWidth() / 2f), - centerPosition.y - (mTouchView.getHeight() / 2f) + centerPosition.x - (touchView.getWidth() / 2f), + centerPosition.y - (touchView.getHeight() / 2f) ); } diff --git a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java index 784a857..edc55ad 100644 --- a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java +++ b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java @@ -30,9 +30,6 @@ import android.view.animation.OvershootInterpolator; import android.widget.FrameLayout; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; - /** * {@code FloatingTab} is the cornerstone of a {@link HoverView}. When a {@code HoverView} is * collapsed, it is reduced to a single {@code FloatingTab} that the user can drag and drop. When @@ -45,7 +42,7 @@ * * {@code FloatingTab}s position themselves based on their center. */ -class FloatingTab extends FrameLayout { +class FloatingTab extends HoverFrameLayout { private static final String TAG = "FloatingTab"; private static final int APPEARING_ANIMATION_DURATION = 300; @@ -54,12 +51,11 @@ class FloatingTab extends FrameLayout { private int mTabSize; private View mTabView; private Dock mDock; - private final Set mOnPositionChangeListeners = new CopyOnWriteArraySet<>(); private final OnLayoutChangeListener mOnLayoutChangeListener = new OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { - notifyListenersOfPositionChange(); + notifyListenersOfPositionChange(FloatingTab.this); } }; @@ -229,7 +225,7 @@ public Point getDockPosition() { public void setDock(@NonNull Dock dock) { mDock = dock; - notifyListenersOfDockChange(); + notifyListenersOfDockChange(mDock); } public void dock() { @@ -259,7 +255,7 @@ public void onAnimationEnd(Animator animation) { if (null != onDocked) { onDocked.run(); } - notifyListenersOfPositionChange(); + notifyListenersOfPositionChange(FloatingTab.this); } @Override @@ -272,7 +268,7 @@ public void onAnimationRepeat(Animator animation) { } xAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { - notifyListenersOfPositionChange(); + notifyListenersOfPositionChange(FloatingTab.this); } }); } @@ -285,7 +281,7 @@ public void moveTo(@NonNull Point floatPosition) { Point cornerPosition = convertCenterToCorner(floatPosition); setX(cornerPosition.x); setY(cornerPosition.y); - notifyListenersOfPositionChange(); + notifyListenersOfPositionChange(FloatingTab.this); } private Point convertCenterToCorner(@NonNull Point centerPosition) { @@ -295,36 +291,9 @@ private Point convertCenterToCorner(@NonNull Point centerPosition) { ); } - public void addOnPositionChangeListener(@Nullable OnPositionChangeListener listener) { - mOnPositionChangeListeners.add(listener); - } - - public void removeOnPositionChangeListener(@NonNull OnPositionChangeListener listener) { - mOnPositionChangeListeners.remove(listener); - } - - private void notifyListenersOfPositionChange() { - Point position = getPosition(); - for (OnPositionChangeListener listener : mOnPositionChangeListeners) { - listener.onPositionChange(position); - } - } - - private void notifyListenersOfDockChange() { - for (OnPositionChangeListener listener : mOnPositionChangeListeners) { - listener.onDockChange(mDock); - } - } - // This method is declared in this class simply to make it clear that its part of our public // contract and not just an inherited method. public void setOnClickListener(@Nullable View.OnClickListener onClickListener) { super.setOnClickListener(onClickListener); } - - public interface OnPositionChangeListener { - void onPositionChange(@NonNull Point tabPosition); - - void onDockChange(@NonNull Dock dock); - } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverFrameLayout.java b/hover/src/main/java/io/mattcarroll/hover/HoverFrameLayout.java new file mode 100644 index 0000000..0e6dfc4 --- /dev/null +++ b/hover/src/main/java/io/mattcarroll/hover/HoverFrameLayout.java @@ -0,0 +1,61 @@ +package io.mattcarroll.hover; + +import android.annotation.TargetApi; +import android.content.Context; +import android.os.Build; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.view.View; +import android.widget.FrameLayout; + +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; + +class HoverFrameLayout extends FrameLayout { + + private final Set mOnPositionChangeListeners = new CopyOnWriteArraySet<>(); + + public HoverFrameLayout(@NonNull Context context) { + super(context); + } + + public HoverFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public HoverFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public HoverFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + public void addOnPositionChangeListener(@Nullable OnPositionChangeListener listener) { + mOnPositionChangeListeners.add(listener); + } + + public void removeOnPositionChangeListener(@NonNull OnPositionChangeListener listener) { + mOnPositionChangeListeners.remove(listener); + } + + protected void notifyListenersOfPositionChange(View view) { + for (OnPositionChangeListener listener : mOnPositionChangeListeners) { + listener.onPositionChange(view); + } + } + + protected void notifyListenersOfDockChange(Dock dock) { + for (OnPositionChangeListener listener : mOnPositionChangeListeners) { + listener.onDockChange(dock); + } + } + + interface OnPositionChangeListener { + void onPositionChange(@NonNull View view); + + void onDockChange(@NonNull Dock dock); + } +} diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverView.java b/hover/src/main/java/io/mattcarroll/hover/HoverView.java index 972abc3..3d721f6 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverView.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverView.java @@ -18,6 +18,7 @@ import android.content.Context; import android.content.SharedPreferences; import android.content.res.TypedArray; +import android.graphics.Point; import android.os.Parcel; import android.os.Parcelable; import android.support.annotation.NonNull; @@ -413,6 +414,12 @@ void makeUntouchableInWindow() { } } + public Point getScreenSize() { + final Point screenSize = new Point(); + ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getSize(screenSize); + return screenSize; + } + // State of the HoverMenuView that is persisted across configuration change and other brief OS // interruptions. This state is written/read when HoverMenuView's onSaveInstanceState() and // onRestoreInstanceState() are called. diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java index a1a0518..7a6a6bf 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java @@ -1,9 +1,11 @@ package io.mattcarroll.hover; import android.graphics.Point; -import android.graphics.Rect; import android.support.annotation.NonNull; import android.util.Log; +import android.view.View; + +import java.util.ArrayList; class HoverViewStateAnchored extends BaseHoverViewState { @@ -23,7 +25,7 @@ public void onTap() { }; @Override - public void takeControl(@NonNull HoverView hoverView, final Runnable onStateChanged) { + public void takeControl(@NonNull final HoverView hoverView, final Runnable onStateChanged) { super.takeControl(hoverView, onStateChanged); Log.d(TAG, "Taking control."); mHoverView.makeUntouchableInWindow(); @@ -40,11 +42,10 @@ public void takeControl(@NonNull HoverView hoverView, final Runnable onStateChan mSelectedTab.shrink(); mSelectedTab.setSelected(true); - final int anchorMargin = hoverView.getContext().getResources().getDimensionPixelSize(R.dimen.hover_tab_anchor_margin) + (mSelectedTab.getTabSize() / 2); - final Point anchorPoint = new Point( - mHoverView.mScreen.getWidth() - anchorMargin, - mHoverView.mScreen.getHeight() - anchorMargin - ); + final int anchorMarginX = hoverView.getContext().getResources().getDimensionPixelSize(R.dimen.hover_tab_anchor_margin_x) + (mSelectedTab.getTabSize() / 2); + final int anchorMarginY = hoverView.getContext().getResources().getDimensionPixelSize(R.dimen.hover_tab_anchor_margin_y) + (mSelectedTab.getTabSize() / 2); + final Point anchorPoint = mHoverView.getScreenSize(); + anchorPoint.offset(-anchorMarginX, -anchorMarginY); mSelectedTab.setDock(new PositionDock(anchorPoint)); mSelectedTab.dock(new Runnable() { @Override @@ -68,9 +69,9 @@ public void giveUpControl(@NonNull HoverViewState nextState) { } private void activateTouchController() { - final Rect visibleRect = new Rect(); - mSelectedTab.getGlobalVisibleRect(visibleRect); - mHoverView.mDragger.activate(mTouchListener, visibleRect); + final ArrayList list = new ArrayList<>(); + list.add(mSelectedTab); + mHoverView.mDragger.activate(mTouchListener, list); } private void deactivateTouchController() { diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 519f05e..5b03922 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -16,7 +16,6 @@ package io.mattcarroll.hover; import android.graphics.Point; -import android.graphics.Rect; import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -24,6 +23,8 @@ import android.util.Log; import android.view.View; +import java.util.ArrayList; + import static android.view.View.GONE; import static android.view.View.INVISIBLE; import static android.view.View.VISIBLE; @@ -62,7 +63,7 @@ public void run() { }; private Runnable mOnStateChanged; - private final View.OnLayoutChangeListener mOnLayoutChangeListener = new View.OnLayoutChangeListener() { + protected final View.OnLayoutChangeListener mOnLayoutChangeListener = new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { if (hasControl() && mIsDocked) { @@ -110,9 +111,16 @@ public void run() { if (wasFloatingTabVisible) { sendToDock(); } else { - mFloatingTab.appear(null); moveToDock(); - onDocked(); + mFloatingTab.appear(new Runnable() { + @Override + public void run() { + if (!hasControl()) { + return; + } + onDocked(); + } + }); } } }); @@ -218,7 +226,7 @@ private void onDroppedByUser() { mHoverView.close(); } else { int tabSize = mHoverView.getResources().getDimensionPixelSize(R.dimen.hover_tab_size); - Point screenSize = new Point(mHoverView.mScreen.getWidth(), mHoverView.mScreen.getHeight()); + Point screenSize = mHoverView.getScreenSize(); float tabHorizontalPositionPercent = (float) mFloatingTab.getPosition().x / screenSize.x; float tabVerticalPosition = (float) mFloatingTab.getPosition().y / screenSize.y; if (tabVerticalPosition < MIN_TAB_VERTICAL_POSITION) { @@ -266,7 +274,7 @@ public void run() { private void moveToDock() { Log.d(TAG, "Moving floating tag to dock."); Point dockPosition = mHoverView.mCollapsedDock.sidePosition().calculateDockPosition( - new Point(mHoverView.mScreen.getWidth(), mHoverView.mScreen.getHeight()), + mHoverView.getScreenSize(), mFloatingTab.getTabSize() ); mFloatingTab.moveTo(dockPosition); @@ -306,9 +314,9 @@ protected void moveTabTo(@NonNull Point position) { } protected void activateDragger() { - final Rect visibleRect = new Rect(); - mFloatingTab.getGlobalVisibleRect(visibleRect); - mHoverView.mDragger.activate(mDragListener, visibleRect); + ArrayList list = new ArrayList<>(); + list.add(mFloatingTab); + mHoverView.mDragger.activate(mDragListener, list); } protected void deactivateDragger() { diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java index 483639a..7472693 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java @@ -79,7 +79,7 @@ public void takeControl(@NonNull HoverView hoverView, Runnable onStateChanged) { mHoverView.makeTouchableInWindow(); mHoverView.requestFocus(); // For handling hardware back button presses. mDock = new Point( - mHoverView.mScreen.getWidth() - ANCHOR_TAB_X_OFFSET_IN_PX, + mHoverView.getScreenSize().x - ANCHOR_TAB_X_OFFSET_IN_PX, ANCHOR_TAB_Y_OFFSET_IN_PX ); if (null != mHoverView.mMenu) { diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index f777b21..78e104d 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -16,9 +16,11 @@ package io.mattcarroll.hover; import android.graphics.Point; -import android.graphics.Rect; import android.support.annotation.NonNull; import android.util.Log; +import android.view.View; + +import java.util.ArrayList; /** * {@link HoverViewState} that operates the {@link HoverView} when it is closed. Closed means that @@ -38,6 +40,9 @@ public void takeControl(@NonNull HoverView hoverView, final Runnable onStateChan mMessageView.appear(mHoverView.mCollapsedDock, new Runnable() { @Override public void run() { + if (!hasControl()) { + return; + } onStateChanged.run(); } }); @@ -56,6 +61,10 @@ public void giveUpControl(@NonNull final HoverViewState nextState) { @Override protected void moveTabTo(@NonNull Point position) { + if (mHoverView == null) { + return; + } + final int floatingTabOffset = mMessageView.getWidth() / 2; if (mHoverView.mCollapsedDock.sidePosition().getSide() == SideDock.SidePosition.RIGHT) { mFloatingTab.moveTo(new Point(position.x + floatingTabOffset, position.y)); @@ -66,13 +75,10 @@ protected void moveTabTo(@NonNull Point position) { @Override protected void activateDragger() { - final Rect tabRect = new Rect(); - final Rect messageRect = new Rect(); - mFloatingTab.getGlobalVisibleRect(tabRect); - mMessageView.getGlobalVisibleRect(messageRect); - tabRect.union(messageRect); - - mHoverView.mDragger.activate(mDragListener, tabRect); + final ArrayList list = new ArrayList<>(); + list.add(mFloatingTab); + list.add(mMessageView); + mHoverView.mDragger.activate(mDragListener, list); } @Override diff --git a/hover/src/main/java/io/mattcarroll/hover/Screen.java b/hover/src/main/java/io/mattcarroll/hover/Screen.java index e186ba0..a9bbcea 100644 --- a/hover/src/main/java/io/mattcarroll/hover/Screen.java +++ b/hover/src/main/java/io/mattcarroll/hover/Screen.java @@ -76,14 +76,6 @@ public void enableDrugMode(boolean debugMode) { } } - public int getWidth() { - return mContainer.getWidth(); - } - - public int getHeight() { - return mContainer.getHeight(); - } - @NonNull public FloatingTab createChainedTab(@NonNull HoverMenu.Section section) { String tabId = section.getId().toString(); diff --git a/hover/src/main/java/io/mattcarroll/hover/SideDock.java b/hover/src/main/java/io/mattcarroll/hover/SideDock.java index 0d55ac3..978cbe9 100644 --- a/hover/src/main/java/io/mattcarroll/hover/SideDock.java +++ b/hover/src/main/java/io/mattcarroll/hover/SideDock.java @@ -19,7 +19,6 @@ import android.support.annotation.IntDef; import android.support.annotation.NonNull; import android.util.Log; -import android.view.ViewGroup; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -33,12 +32,12 @@ public class SideDock extends Dock { private static final String TAG = "SideDock"; - private ViewGroup mContainerView; + private HoverView mHoverView; private int mTabSize; private SidePosition mSidePosition; - SideDock(@NonNull ViewGroup containerView, int tabSize, @NonNull SidePosition sidePosition) { - mContainerView = containerView; + SideDock(@NonNull HoverView hoverView, int tabSize, @NonNull SidePosition sidePosition) { + mHoverView = hoverView; mTabSize = tabSize; mSidePosition = sidePosition; } @@ -46,8 +45,7 @@ public class SideDock extends Dock { @NonNull @Override public Point position() { - Point screenSize = new Point(mContainerView.getWidth(), mContainerView.getHeight()); - return mSidePosition.calculateDockPosition(screenSize, mTabSize); + return mSidePosition.calculateDockPosition(mHoverView.getScreenSize(), mTabSize); } @NonNull diff --git a/hover/src/main/java/io/mattcarroll/hover/TabChain.java b/hover/src/main/java/io/mattcarroll/hover/TabChain.java index 7c53a45..5221056 100644 --- a/hover/src/main/java/io/mattcarroll/hover/TabChain.java +++ b/hover/src/main/java/io/mattcarroll/hover/TabChain.java @@ -40,7 +40,7 @@ class TabChain { private final FloatingTab.OnPositionChangeListener mOnPredecessorPositionChange = new FloatingTab.OnPositionChangeListener() { @Override - public void onPositionChange(@NonNull Point position) { + public void onPositionChange(@NonNull View view) { // No-op. We only care when our predecessor's dock changes. } diff --git a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java index 49502a2..acd7668 100644 --- a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java +++ b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java @@ -11,25 +11,27 @@ import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.TranslateAnimation; -import android.widget.FrameLayout; -public class TabMessageView extends FrameLayout { +public class TabMessageView extends HoverFrameLayout { private static final String TAG = "TabMessageView"; private final FloatingTab mFloatingTab; private SideDock mSideDock; - private final FloatingTab.OnPositionChangeListener mOnTabPositionChangeListener = new FloatingTab.OnPositionChangeListener() { + private final OnPositionChangeListener mOnTabPositionChangeListener = new OnPositionChangeListener() { @Override - public void onPositionChange(@NonNull Point position) { + public void onPositionChange(@NonNull View view) { + final Point position = mFloatingTab.getPosition(); Log.d(TAG, mFloatingTab + " tab moved to " + position); + final float tabSizeHalf = mFloatingTab.getTabSize() / 2f; if (mSideDock != null && mSideDock.sidePosition().getSide() == SideDock.SidePosition.RIGHT) { - setX(position.x - (mFloatingTab.getTabSize() / 2) - getWidth()); - setY(position.y - (mFloatingTab.getTabSize() / 2)); + setX(position.x - tabSizeHalf - getWidth()); + setY(position.y - tabSizeHalf); } else { - setX(position.x + (mFloatingTab.getTabSize() / 2)); - setY(position.y - (mFloatingTab.getTabSize() / 2)); + setX(position.x + tabSizeHalf); + setY(position.y - tabSizeHalf); } + notifyListenersOfPositionChange(TabMessageView.this); } @Override @@ -40,6 +42,7 @@ public void onDockChange(@NonNull Dock dock) { appear(sideDock, null); } } + notifyListenersOfDockChange(dock); } }; diff --git a/hover/src/main/java/io/mattcarroll/hover/view/InViewDragger.java b/hover/src/main/java/io/mattcarroll/hover/view/InViewDragger.java index ce0e528..f24215f 100644 --- a/hover/src/main/java/io/mattcarroll/hover/view/InViewDragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/view/InViewDragger.java @@ -62,8 +62,8 @@ public PointF getTouchViewPosition(@NonNull View touchView) { } @Override - public void moveTouchViewTo(@NonNull View touchView, @NonNull PointF position) { - touchView.setX(position.x); - touchView.setY(position.y); + public void moveTouchViewTo(@NonNull View touchView, @NonNull PointF cornerPosition) { + touchView.setX(cornerPosition.x); + touchView.setY(cornerPosition.y); } } diff --git a/hover/src/main/java/io/mattcarroll/hover/window/InWindowDragger.java b/hover/src/main/java/io/mattcarroll/hover/window/InWindowDragger.java index d65759f..030f11e 100755 --- a/hover/src/main/java/io/mattcarroll/hover/window/InWindowDragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/window/InWindowDragger.java @@ -60,7 +60,7 @@ public PointF getTouchViewPosition(@NonNull View touchView) { } @Override - public void moveTouchViewTo(@NonNull View touchView, @NonNull PointF position) { - mWindowViewController.moveViewTo(touchView, (int) position.x, (int) position.y); + public void moveTouchViewTo(@NonNull View touchView, @NonNull PointF cornerPosition) { + mWindowViewController.moveViewTo(touchView, (int) cornerPosition.x, (int) cornerPosition.y); } } diff --git a/hover/src/main/res/values/dimens.xml b/hover/src/main/res/values/dimens.xml index d0eaac0..8e9f9ac 100755 --- a/hover/src/main/res/values/dimens.xml +++ b/hover/src/main/res/values/dimens.xml @@ -1,7 +1,8 @@ 72dp 48dp - 12dp + 12dp + 32dp 8dp 7dp 40dp From 5b9e24e43862007a85852570acca5df4fe6771b3 Mon Sep 17 00:00:00 2001 From: Haley Date: Sun, 24 Feb 2019 19:15:29 +0900 Subject: [PATCH 015/105] =?UTF-8?q?Preview=20=EB=AA=A8=EB=93=9C=EC=97=90?= =?UTF-8?q?=EC=84=9C=20MessageView=20UI=EA=B0=80=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=20=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8D=98=20?= =?UTF-8?q?=ED=98=84=EC=83=81=20=EC=88=98=EC=A0=95=20(#15)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hover/HoverViewStateCollapsed.java | 2 +- .../hover/HoverViewStatePreviewed.java | 1 + .../main/java/io/mattcarroll/hover/Screen.java | 13 ++++++------- .../java/io/mattcarroll/hover/TabMessageView.java | 15 +++++++++++++-- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 5b03922..aeba6db 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -47,7 +47,7 @@ class HoverViewStateCollapsed extends BaseHoverViewState { protected FloatingTab mFloatingTab; protected final Dragger.DragListener mDragListener = new FloatingTabDragListener(this); - private HoverMenu.Section mSelectedSection; + protected HoverMenu.Section mSelectedSection; private int mSelectedSectionIndex = -1; private boolean mIsCollapsed = false; private boolean mIsDocked = false; diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index 78e104d..29e6475 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -37,6 +37,7 @@ public void takeControl(@NonNull HoverView hoverView, final Runnable onStateChan super.takeControl(hoverView, null); Log.d(TAG, "Taking control."); mMessageView = mHoverView.mScreen.getTabMessageView(mHoverView.mSelectedSectionId); + mMessageView.setMessageView(mSelectedSection.getTabMessageView()); mMessageView.appear(mHoverView.mCollapsedDock, new Runnable() { @Override public void run() { diff --git a/hover/src/main/java/io/mattcarroll/hover/Screen.java b/hover/src/main/java/io/mattcarroll/hover/Screen.java index a9bbcea..40bea6a 100644 --- a/hover/src/main/java/io/mattcarroll/hover/Screen.java +++ b/hover/src/main/java/io/mattcarroll/hover/Screen.java @@ -79,11 +79,11 @@ public void enableDrugMode(boolean debugMode) { @NonNull public FloatingTab createChainedTab(@NonNull HoverMenu.Section section) { String tabId = section.getId().toString(); - return createChainedTab(tabId, section.getTabView(), section.getTabMessageView()); + return createChainedTab(tabId, section.getTabView()); } @NonNull - public FloatingTab createChainedTab(@NonNull String tabId, @NonNull View tabView, @Nullable View tabMessageView) { + public FloatingTab createChainedTab(@NonNull String tabId, @NonNull View tabView) { Log.d(TAG, "Existing tabs..."); for (String existingTabId : mTabs.keySet()) { Log.d(TAG, existingTabId); @@ -97,11 +97,9 @@ public FloatingTab createChainedTab(@NonNull String tabId, @NonNull View tabView chainedTab.enableDebugMode(mIsDebugMode); mContainer.addView(chainedTab); mTabs.put(tabId, chainedTab); - if (tabMessageView != null) { - final TabMessageView messageView = new TabMessageView(tabView.getContext(), tabMessageView, chainedTab); - mContainer.addView(messageView); - mTabMessageViews.put(tabId, messageView); - } + final TabMessageView messageView = new TabMessageView(tabView.getContext(), chainedTab); + mContainer.addView(messageView); + mTabMessageViews.put(tabId, messageView); return chainedTab; } } @@ -119,6 +117,7 @@ public FloatingTab getChainedTab(@Nullable String tabId) { public void destroyChainedTab(@NonNull FloatingTab chainedTab) { mTabs.remove(chainedTab.getTabId()); + mTabMessageViews.remove(chainedTab.getTabId()); chainedTab.setTabView(null); mContainer.removeView(chainedTab); } diff --git a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java index acd7668..fb6da9b 100644 --- a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java +++ b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java @@ -17,6 +17,7 @@ public class TabMessageView extends HoverFrameLayout { private final FloatingTab mFloatingTab; private SideDock mSideDock; + private View mMessageView; private final OnPositionChangeListener mOnTabPositionChangeListener = new OnPositionChangeListener() { @Override @@ -46,15 +47,25 @@ public void onDockChange(@NonNull Dock dock) { } }; - public TabMessageView(@NonNull Context context, @NonNull View messageView, @NonNull FloatingTab floatingTab) { + public TabMessageView(@NonNull Context context, @NonNull FloatingTab floatingTab) { super(context); setClipToPadding(false); setClipChildren(false); mFloatingTab = floatingTab; - addView(messageView); setVisibility(GONE); } + public void setMessageView(@Nullable View view) { + if (view == mMessageView) { + return; + } + removeAllViews(); + mMessageView = view; + if (mMessageView != null) { + addView(mMessageView); + } + } + public void appear(final SideDock dock, @Nullable final Runnable onAppeared) { mSideDock = dock; mFloatingTab.addOnPositionChangeListener(mOnTabPositionChangeListener); From 7da49d3cfa57b14b0f202bee69291f2a411bb22c Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Mon, 25 Feb 2019 14:58:32 +0900 Subject: [PATCH 016/105] =?UTF-8?q?=EC=84=9C=EB=B9=84=EC=8A=A4=EA=B0=80=20?= =?UTF-8?q?=EC=A2=85=EB=A3=8C=EB=90=A0=20=EB=95=8C=20onDock=20event?= =?UTF-8?q?=EA=B0=80=20=EB=B6=88=EB=A6=B4=20=EA=B2=BD=EC=9A=B0,=20?= =?UTF-8?q?=EC=84=9C=EB=B9=84=EC=8A=A4=EB=8A=94=20=EC=A2=85=EB=A3=8C=20?= =?UTF-8?q?=EB=90=98=EC=A7=80=EB=A7=8C=20=ED=84=B0=EC=B9=98=EC=98=81?= =?UTF-8?q?=EC=97=AD=EC=9D=B4=20=EB=82=A8=EC=95=84=EC=9E=88=EB=8A=94=20?= =?UTF-8?q?=EC=9D=B4=EC=8A=88=20=EC=88=98=EC=A0=95=20(#16)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/io/mattcarroll/hover/HoverViewStateAnchored.java | 2 +- .../java/io/mattcarroll/hover/HoverViewStateCollapsed.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java index 7a6a6bf..4c1fa47 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java @@ -50,7 +50,7 @@ public void takeControl(@NonNull final HoverView hoverView, final Runnable onSta mSelectedTab.dock(new Runnable() { @Override public void run() { - if (!hasControl()) { + if (!hasControl() || !mHoverView.mIsAddedToWindow) { return; } activateTouchController(); diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index aeba6db..fbfd6c1 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -293,6 +293,9 @@ private void initDockPosition() { private void onDocked() { Log.d(TAG, "Docked. Activating dragger."); + if (!mHoverView.mIsAddedToWindow) { + return; + } mIsDocked = true; activateDragger(); scheduleHoverViewAlphaChange(); From c5e72b2d39f1b9405c841bcbb98498fce07874e1 Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Mon, 4 Mar 2019 10:18:22 +0900 Subject: [PATCH 017/105] =?UTF-8?q?[BZZRWRDD-272]=20Preview=20=EA=B0=80=20?= =?UTF-8?q?=EB=96=B4=EC=9D=84=20=EB=95=8C=20=EB=93=9C=EB=9E=98=EA=B7=B8?= =?UTF-8?q?=ED=95=98=EB=A9=B4=20=EC=B5=9C=EC=B4=88=20=ED=84=B0=EC=B9=98?= =?UTF-8?q?=ED=95=9C=20=EC=9C=84=EC=B9=98=EC=97=90=EC=84=9C=20=EB=B7=B0?= =?UTF-8?q?=EA=B0=80=20=EC=9D=B4=EB=8F=99=EB=90=9C=20=EC=83=81=ED=83=9C?= =?UTF-8?q?=EB=A1=9C=20=EB=93=9C=EB=9E=98=EA=B7=B8=20=EB=90=A8=20(#17)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * preview를 보여줄 때 floatingTab을 drag할때 preview가 drag되는 이슈 수정 * OnPositionChangedListener를 다시 FloatingTab으로 옮기고, onLayoutChanged 이벤트에 대한 touchView의 이동은 개별 view에서 관리하도록 수정 --- .../hover/BaseTouchController.java | 18 ++---- .../io/mattcarroll/hover/ContentDisplay.java | 3 +- .../java/io/mattcarroll/hover/Dragger.java | 15 +++-- .../io/mattcarroll/hover/FloatingTab.java | 43 +++++++++++-- .../mattcarroll/hover/HoverFrameLayout.java | 61 ------------------- .../hover/HoverViewStateCollapsed.java | 10 +-- .../hover/HoverViewStatePreviewed.java | 6 +- .../java/io/mattcarroll/hover/TabChain.java | 2 +- .../io/mattcarroll/hover/TabMessageView.java | 10 ++- 9 files changed, 66 insertions(+), 102 deletions(-) delete mode 100644 hover/src/main/java/io/mattcarroll/hover/HoverFrameLayout.java diff --git a/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java b/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java index 8f3cbed..863b9f2 100644 --- a/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java +++ b/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java @@ -38,16 +38,11 @@ public boolean onTouch(View view, MotionEvent motionEvent) { } }; - private final HoverFrameLayout.OnPositionChangeListener mOnLayoutChangeListener = new HoverFrameLayout.OnPositionChangeListener() { + private final View.OnLayoutChangeListener mOnLayoutChangeListener = new View.OnLayoutChangeListener() { @Override - public void onPositionChange(@NonNull View view) { + public void onLayoutChange(View view, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { moveTouchViewTo(mTouchViewMap.get(view.getTag()), new PointF(view.getX(), view.getY())); } - - @Override - public void onDockChange(@NonNull Dock dock) { - - } }; public abstract View createTouchView(@NonNull Rect rect); @@ -72,10 +67,9 @@ public void activate(@NonNull TouchListener touchListener, @NonNull List v View touchView = createTouchView(rect); moveTouchViewTo(touchView, new PointF(view.getX(), view.getY())); touchView.setOnTouchListener(mDragTouchListener); + touchView.setTag(tag); mTouchViewMap.put(tag, touchView); - if (view instanceof HoverFrameLayout) { - ((HoverFrameLayout) view).addOnPositionChangeListener(mOnLayoutChangeListener); - } + view.addOnLayoutChangeListener(mOnLayoutChangeListener); } updateTouchControlViewAppearance(); } @@ -86,9 +80,7 @@ public void deactivate() { Log.d(TAG, "Deactivating."); for (View view : mViewList) { view.setOnTouchListener(null); - if (view instanceof HoverFrameLayout) { - ((HoverFrameLayout) view).removeOnPositionChangeListener(mOnLayoutChangeListener); - } + view.removeOnLayoutChangeListener(mOnLayoutChangeListener); } for (View touchView : mTouchViewMap.values()) { diff --git a/hover/src/main/java/io/mattcarroll/hover/ContentDisplay.java b/hover/src/main/java/io/mattcarroll/hover/ContentDisplay.java index bc89049..553d38d 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ContentDisplay.java +++ b/hover/src/main/java/io/mattcarroll/hover/ContentDisplay.java @@ -62,8 +62,7 @@ public void onGlobalLayout() { private final FloatingTab.OnPositionChangeListener mOnTabPositionChangeListener = new FloatingTab.OnPositionChangeListener() { @Override - public void onPositionChange(@NonNull View view) { - final Point position = new Point((int) view.getX() + (view.getWidth() / 2), (int) view.getY() + (view.getHeight() / 2)); + public void onPositionChange(@NonNull Point position) { Log.d(TAG, mSelectedTab + " tab moved to " + position); updateTabSelectorPosition(); diff --git a/hover/src/main/java/io/mattcarroll/hover/Dragger.java b/hover/src/main/java/io/mattcarroll/hover/Dragger.java index 81965bf..a62bb4a 100644 --- a/hover/src/main/java/io/mattcarroll/hover/Dragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/Dragger.java @@ -64,9 +64,9 @@ public boolean onTouch(View view, MotionEvent motionEvent) { // Dragging just started Log.d(TAG, "MOVE Start Drag."); mIsDragging = true; - mDragListener.onDragStart(mCurrentViewPosition.x, mCurrentViewPosition.y); + mDragListener.onDragStart(view, mCurrentViewPosition.x, mCurrentViewPosition.y); } else { - mDragListener.onDragTo(mCurrentViewPosition.x, mCurrentViewPosition.y); + mDragListener.onDragTo(view, mCurrentViewPosition.x, mCurrentViewPosition.y); } } @@ -78,7 +78,7 @@ public boolean onTouch(View view, MotionEvent motionEvent) { mTouchListener.onTap(); } else { Log.d(TAG, "Reporting as a drag release at: " + mCurrentViewPosition); - mDragListener.onReleasedAt(mCurrentViewPosition.x, mCurrentViewPosition.y); + mDragListener.onReleasedAt(view, mCurrentViewPosition.x, mCurrentViewPosition.y); } return true; default: @@ -125,25 +125,28 @@ public interface DragListener extends TouchListener { /** * The user has begun dragging. * + * @param view the view that is being dragged * @param x x-coordinate of the user's drag start (in the parent View's coordinate space) * @param y y-coordiante of the user's drag start (in the parent View's coordinate space) */ - void onDragStart(float x, float y); + void onDragStart(View view, float x, float y); /** * The user has dragged to the given coordinates. * + * @param view the view that is being dragged * @param x x-coordinate of the user's drag (in the parent View's coordinate space) * @param y y-coordiante of the user's drag (in the parent View's coordinate space) */ - void onDragTo(float x, float y); + void onDragTo(View view, float x, float y); /** * The user has stopped touching the drag area. * + * @param view the view that is being dragged * @param x x-coordinate of the user's release (in the parent View's coordinate space) * @param y y-coordiante of the user's release (in the parent View's coordinate space) */ - void onReleasedAt(float x, float y); + void onReleasedAt(View view, float x, float y); } } diff --git a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java index edc55ad..784a857 100644 --- a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java +++ b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java @@ -30,6 +30,9 @@ import android.view.animation.OvershootInterpolator; import android.widget.FrameLayout; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; + /** * {@code FloatingTab} is the cornerstone of a {@link HoverView}. When a {@code HoverView} is * collapsed, it is reduced to a single {@code FloatingTab} that the user can drag and drop. When @@ -42,7 +45,7 @@ * * {@code FloatingTab}s position themselves based on their center. */ -class FloatingTab extends HoverFrameLayout { +class FloatingTab extends FrameLayout { private static final String TAG = "FloatingTab"; private static final int APPEARING_ANIMATION_DURATION = 300; @@ -51,11 +54,12 @@ class FloatingTab extends HoverFrameLayout { private int mTabSize; private View mTabView; private Dock mDock; + private final Set mOnPositionChangeListeners = new CopyOnWriteArraySet<>(); private final OnLayoutChangeListener mOnLayoutChangeListener = new OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { - notifyListenersOfPositionChange(FloatingTab.this); + notifyListenersOfPositionChange(); } }; @@ -225,7 +229,7 @@ public Point getDockPosition() { public void setDock(@NonNull Dock dock) { mDock = dock; - notifyListenersOfDockChange(mDock); + notifyListenersOfDockChange(); } public void dock() { @@ -255,7 +259,7 @@ public void onAnimationEnd(Animator animation) { if (null != onDocked) { onDocked.run(); } - notifyListenersOfPositionChange(FloatingTab.this); + notifyListenersOfPositionChange(); } @Override @@ -268,7 +272,7 @@ public void onAnimationRepeat(Animator animation) { } xAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { - notifyListenersOfPositionChange(FloatingTab.this); + notifyListenersOfPositionChange(); } }); } @@ -281,7 +285,7 @@ public void moveTo(@NonNull Point floatPosition) { Point cornerPosition = convertCenterToCorner(floatPosition); setX(cornerPosition.x); setY(cornerPosition.y); - notifyListenersOfPositionChange(FloatingTab.this); + notifyListenersOfPositionChange(); } private Point convertCenterToCorner(@NonNull Point centerPosition) { @@ -291,9 +295,36 @@ private Point convertCenterToCorner(@NonNull Point centerPosition) { ); } + public void addOnPositionChangeListener(@Nullable OnPositionChangeListener listener) { + mOnPositionChangeListeners.add(listener); + } + + public void removeOnPositionChangeListener(@NonNull OnPositionChangeListener listener) { + mOnPositionChangeListeners.remove(listener); + } + + private void notifyListenersOfPositionChange() { + Point position = getPosition(); + for (OnPositionChangeListener listener : mOnPositionChangeListeners) { + listener.onPositionChange(position); + } + } + + private void notifyListenersOfDockChange() { + for (OnPositionChangeListener listener : mOnPositionChangeListeners) { + listener.onDockChange(mDock); + } + } + // This method is declared in this class simply to make it clear that its part of our public // contract and not just an inherited method. public void setOnClickListener(@Nullable View.OnClickListener onClickListener) { super.setOnClickListener(onClickListener); } + + public interface OnPositionChangeListener { + void onPositionChange(@NonNull Point tabPosition); + + void onDockChange(@NonNull Dock dock); + } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverFrameLayout.java b/hover/src/main/java/io/mattcarroll/hover/HoverFrameLayout.java deleted file mode 100644 index 0e6dfc4..0000000 --- a/hover/src/main/java/io/mattcarroll/hover/HoverFrameLayout.java +++ /dev/null @@ -1,61 +0,0 @@ -package io.mattcarroll.hover; - -import android.annotation.TargetApi; -import android.content.Context; -import android.os.Build; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.util.AttributeSet; -import android.view.View; -import android.widget.FrameLayout; - -import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; - -class HoverFrameLayout extends FrameLayout { - - private final Set mOnPositionChangeListeners = new CopyOnWriteArraySet<>(); - - public HoverFrameLayout(@NonNull Context context) { - super(context); - } - - public HoverFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - } - - public HoverFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public HoverFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - public void addOnPositionChangeListener(@Nullable OnPositionChangeListener listener) { - mOnPositionChangeListeners.add(listener); - } - - public void removeOnPositionChangeListener(@NonNull OnPositionChangeListener listener) { - mOnPositionChangeListeners.remove(listener); - } - - protected void notifyListenersOfPositionChange(View view) { - for (OnPositionChangeListener listener : mOnPositionChangeListeners) { - listener.onPositionChange(view); - } - } - - protected void notifyListenersOfDockChange(Dock dock) { - for (OnPositionChangeListener listener : mOnPositionChangeListeners) { - listener.onDockChange(dock); - } - } - - interface OnPositionChangeListener { - void onPositionChange(@NonNull View view); - - void onDockChange(@NonNull Dock dock); - } -} diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index fbfd6c1..edd84a4 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -312,7 +312,7 @@ private void onDocked() { mHoverView.notifyOnDocked(this); } - protected void moveTabTo(@NonNull Point position) { + protected void moveTabTo(View touchView, @NonNull Point position) { mFloatingTab.moveTo(position); } @@ -349,17 +349,17 @@ protected FloatingTabDragListener(@NonNull HoverViewStateCollapsed owner) { } @Override - public void onDragStart(float x, float y) { + public void onDragStart(View touchView, float x, float y) { mOwner.onPickedUpByUser(); } @Override - public void onDragTo(float x, float y) { - mOwner.moveTabTo(new Point((int) x, (int) y)); + public void onDragTo(View touchView, float x, float y) { + mOwner.moveTabTo(touchView, new Point((int) x, (int) y)); } @Override - public void onReleasedAt(float x, float y) { + public void onReleasedAt(View touchView, float x, float y) { mOwner.onDroppedByUser(); } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index 29e6475..5a6bdec 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -61,13 +61,15 @@ public void giveUpControl(@NonNull final HoverViewState nextState) { } @Override - protected void moveTabTo(@NonNull Point position) { + protected void moveTabTo(View touchView, @NonNull Point position) { if (mHoverView == null) { return; } final int floatingTabOffset = mMessageView.getWidth() / 2; - if (mHoverView.mCollapsedDock.sidePosition().getSide() == SideDock.SidePosition.RIGHT) { + if (touchView.getTag() != null && touchView.getTag().equals(mFloatingTab.getTag())) { + mFloatingTab.moveTo(position); + } else if (mHoverView.mCollapsedDock.sidePosition().getSide() == SideDock.SidePosition.RIGHT) { mFloatingTab.moveTo(new Point(position.x + floatingTabOffset, position.y)); } else { mFloatingTab.moveTo(new Point(position.x - floatingTabOffset, position.y)); diff --git a/hover/src/main/java/io/mattcarroll/hover/TabChain.java b/hover/src/main/java/io/mattcarroll/hover/TabChain.java index 5221056..7c53a45 100644 --- a/hover/src/main/java/io/mattcarroll/hover/TabChain.java +++ b/hover/src/main/java/io/mattcarroll/hover/TabChain.java @@ -40,7 +40,7 @@ class TabChain { private final FloatingTab.OnPositionChangeListener mOnPredecessorPositionChange = new FloatingTab.OnPositionChangeListener() { @Override - public void onPositionChange(@NonNull View view) { + public void onPositionChange(@NonNull Point position) { // No-op. We only care when our predecessor's dock changes. } diff --git a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java index fb6da9b..c9537ff 100644 --- a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java +++ b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java @@ -11,18 +11,18 @@ import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.TranslateAnimation; +import android.widget.FrameLayout; -public class TabMessageView extends HoverFrameLayout { +public class TabMessageView extends FrameLayout { private static final String TAG = "TabMessageView"; private final FloatingTab mFloatingTab; private SideDock mSideDock; private View mMessageView; - private final OnPositionChangeListener mOnTabPositionChangeListener = new OnPositionChangeListener() { + private final FloatingTab.OnPositionChangeListener mOnTabPositionChangeListener = new FloatingTab.OnPositionChangeListener() { @Override - public void onPositionChange(@NonNull View view) { - final Point position = mFloatingTab.getPosition(); + public void onPositionChange(@NonNull Point position) { Log.d(TAG, mFloatingTab + " tab moved to " + position); final float tabSizeHalf = mFloatingTab.getTabSize() / 2f; if (mSideDock != null && mSideDock.sidePosition().getSide() == SideDock.SidePosition.RIGHT) { @@ -32,7 +32,6 @@ public void onPositionChange(@NonNull View view) { setX(position.x + tabSizeHalf); setY(position.y - tabSizeHalf); } - notifyListenersOfPositionChange(TabMessageView.this); } @Override @@ -43,7 +42,6 @@ public void onDockChange(@NonNull Dock dock) { appear(sideDock, null); } } - notifyListenersOfDockChange(dock); } }; From 61a1a64852e45a6d764d4ed37f6c4737df1166f2 Mon Sep 17 00:00:00 2001 From: Haley Date: Tue, 5 Mar 2019 17:49:53 +0900 Subject: [PATCH 018/105] =?UTF-8?q?[BZZRWRDD-280]=20Docked=20=EC=97=AC?= =?UTF-8?q?=EB=B6=80=EC=99=80=20=EC=83=81=EA=B4=80=20=EC=97=86=EC=9D=B4=20?= =?UTF-8?q?Orientation=20Changed=20=EA=B0=80=20=EB=B6=88=EB=A6=AC=EB=A9=B4?= =?UTF-8?q?=20FloatingTab=20=EC=9D=84=20=EC=A0=95=EC=83=81=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/mattcarroll/hover/FloatingTab.java | 9 ++++++++ .../hover/HoverViewStateCollapsed.java | 23 ------------------- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java index 784a857..2014cd3 100644 --- a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java +++ b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java @@ -20,6 +20,7 @@ import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.Context; +import android.content.res.Configuration; import android.graphics.Color; import android.graphics.Point; import android.support.annotation.NonNull; @@ -89,6 +90,14 @@ private void updateSize() { setLayoutParams(layoutParams); } + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + if (mDock != null) { + moveTo(mDock.position()); + } + } + @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index edd84a4..8f045f7 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -50,7 +50,6 @@ class HoverViewStateCollapsed extends BaseHoverViewState { protected HoverMenu.Section mSelectedSection; private int mSelectedSectionIndex = -1; private boolean mIsCollapsed = false; - private boolean mIsDocked = false; private Handler mHandler = new Handler(); private Runnable mAlphaChanger = new Runnable() { @Override @@ -63,18 +62,6 @@ public void run() { }; private Runnable mOnStateChanged; - protected final View.OnLayoutChangeListener mOnLayoutChangeListener = new View.OnLayoutChangeListener() { - @Override - public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { - if (hasControl() && mIsDocked) { - // We're docked. Adjust the tab position in case the screen was rotated. This should - // only be a concern when displaying as a window overlay, but not when displaying - // within a view hierarchy. - moveToDock(); - } - } - }; - @Override public void takeControl(@NonNull HoverView hoverView, final Runnable onStateChanged) { super.takeControl(hoverView, onStateChanged); @@ -125,8 +112,6 @@ public void run() { } }); - mFloatingTab.addOnLayoutChangeListener(mOnLayoutChangeListener); - if (null != mHoverView.mMenu) { listenForMenuChanges(); } @@ -139,15 +124,12 @@ public void giveUpControl(@NonNull HoverViewState nextState) { Log.d(TAG, "Giving up control."); restoreHoverViewAlphaValue(); - mFloatingTab.removeOnLayoutChangeListener(mOnLayoutChangeListener); - if (null != mHoverView.mMenu) { mHoverView.mMenu.setUpdatedCallback(null); } mHoverView.mScreen.getExitView().setVisibility(GONE); - mIsDocked = false; deactivateDragger(); mFloatingTab = null; super.giveUpControl(nextState); @@ -171,15 +153,12 @@ public void onRemoved(int position, int count) { if (mSelectedSectionIndex == position) { Log.d(TAG, "Selected tab removed. Displaying a new tab."); // TODO: externalize a selection strategy for when the selected section disappears - mFloatingTab.removeOnLayoutChangeListener(mOnLayoutChangeListener); mHoverView.mScreen.destroyChainedTab(mFloatingTab); mSelectedSectionIndex = mSelectedSectionIndex > 0 ? mSelectedSectionIndex - 1 : 0; mSelectedSection = mHoverView.mMenu.getSection(mSelectedSectionIndex); mHoverView.mSelectedSectionId = mSelectedSection.getId(); mFloatingTab = mHoverView.mScreen.createChainedTab(mSelectedSection); - - mFloatingTab.addOnLayoutChangeListener(mOnLayoutChangeListener); } } @@ -212,7 +191,6 @@ public void onBackPressed() { } private void onPickedUpByUser() { - mIsDocked = false; mHoverView.mScreen.getExitView().setVisibility(VISIBLE); restoreHoverViewAlphaValue(); mHoverView.notifyOnDragStart(this); @@ -296,7 +274,6 @@ private void onDocked() { if (!mHoverView.mIsAddedToWindow) { return; } - mIsDocked = true; activateDragger(); scheduleHoverViewAlphaChange(); From d63e86c8d0b8f54d20c2e056ec83c6e4cf295309 Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Wed, 6 Mar 2019 16:41:28 +0900 Subject: [PATCH 019/105] =?UTF-8?q?[BZZRWRDD-284]=20Floating=20Button?= =?UTF-8?q?=EC=9D=84=20=EC=95=84=EB=9E=98=EB=A1=9C=20=EB=93=9C=EB=9E=98?= =?UTF-8?q?=EA=B7=B8=ED=95=98=EB=A9=B4=20=EB=B2=84=ED=8A=BC=EC=9D=B4=20?= =?UTF-8?q?=EC=95=88=EB=B3=B4=EC=9D=B4=EB=8A=94=20=ED=98=84=EC=83=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#19)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Floating 버튼이 아래쪽으로 내려가 보이지 않는 이슈 수정 * Drag 후 바로 tap을 할 경우 hover view가 null일때가 있어 NPE가 발생하는 이슈 해결 * Dragger가 deactivate 된 상태에서도 callback을 계속 전달해 NPE 발생하는 이슈 수정 --- .../hover/BaseTouchController.java | 1 + .../java/io/mattcarroll/hover/Dragger.java | 34 +++++++++++++++---- .../java/io/mattcarroll/hover/HoverView.java | 10 ++++-- .../hover/HoverViewStateCollapsed.java | 11 +++--- .../mattcarroll/hover/view/InViewDragger.java | 8 +++++ .../hover/window/InWindowDragger.java | 6 ++++ .../hover/window/WindowViewController.java | 6 ++++ 7 files changed, 62 insertions(+), 14 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java b/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java index 863b9f2..8559463 100644 --- a/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java +++ b/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java @@ -90,6 +90,7 @@ public void deactivate() { mIsActivated = false; mTouchViewMap.clear(); mViewList = null; + mTouchListener = null; } } diff --git a/hover/src/main/java/io/mattcarroll/hover/Dragger.java b/hover/src/main/java/io/mattcarroll/hover/Dragger.java index a62bb4a..c3c89f1 100644 --- a/hover/src/main/java/io/mattcarroll/hover/Dragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/Dragger.java @@ -15,6 +15,7 @@ */ package io.mattcarroll.hover; +import android.graphics.Point; import android.graphics.PointF; import android.support.annotation.NonNull; import android.util.Log; @@ -48,9 +49,14 @@ public boolean onTouch(View view, MotionEvent motionEvent) { mOriginalViewPosition = convertCornerToCenter(view, getTouchViewPosition(view)); mCurrentViewPosition = new PointF(mOriginalViewPosition.x, mOriginalViewPosition.y); mOriginalTouchPosition.set(motionEvent.getRawX(), motionEvent.getRawY()); - mTouchListener.onPress(); + if (mTouchListener != null) { + mTouchListener.onPress(); + } return true; case MotionEvent.ACTION_MOVE: + if (mDragListener == null) { + return false; + } Log.d(TAG, "ACTION_MOVE. motionX: " + motionEvent.getRawX() + ", motionY: " + motionEvent.getRawY()); float dragDeltaX = motionEvent.getRawX() - mOriginalTouchPosition.x; float dragDeltaY = motionEvent.getRawY() - mOriginalTouchPosition.y; @@ -75,8 +81,10 @@ public boolean onTouch(View view, MotionEvent motionEvent) { Log.d(TAG, "ACTION_UP"); if (!mIsDragging) { Log.d(TAG, "Reporting as a tap."); - mTouchListener.onTap(); - } else { + if (mTouchListener != null) { + mTouchListener.onTap(); + } + } else if (mDragListener != null) { Log.d(TAG, "Reporting as a drag release at: " + mCurrentViewPosition); mDragListener.onReleasedAt(view, mCurrentViewPosition.x, mCurrentViewPosition.y); } @@ -93,11 +101,23 @@ public Dragger(int mTapTouchSlop) { public abstract PointF getTouchViewPosition(@NonNull View touchView); + public abstract Point getContainerSize(); + public void activate(@NonNull DragListener dragListener, @NonNull List viewList) { - super.activate(dragListener, viewList); - mDragListener = dragListener; - for (View touchView : mTouchViewMap.values()) { - touchView.setOnTouchListener(mDragTouchListener); + if (!mIsActivated) { + super.activate(dragListener, viewList); + mDragListener = dragListener; + for (View touchView : mTouchViewMap.values()) { + touchView.setOnTouchListener(mDragTouchListener); + } + } + } + + @Override + public void deactivate() { + if (mIsActivated) { + super.deactivate(); + mDragListener = null; } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverView.java b/hover/src/main/java/io/mattcarroll/hover/HoverView.java index 3d721f6..3207c39 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverView.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverView.java @@ -415,9 +415,13 @@ void makeUntouchableInWindow() { } public Point getScreenSize() { - final Point screenSize = new Point(); - ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getSize(screenSize); - return screenSize; + if (mDragger == null) { + final Point screenSize = new Point(); + ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getSize(screenSize); + return screenSize; + } else { + return mDragger.getContainerSize(); + } } // State of the HoverMenuView that is persisted across configuration change and other brief OS diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 8f045f7..becf4af 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -205,12 +205,13 @@ private void onDroppedByUser() { } else { int tabSize = mHoverView.getResources().getDimensionPixelSize(R.dimen.hover_tab_size); Point screenSize = mHoverView.getScreenSize(); - float tabHorizontalPositionPercent = (float) mFloatingTab.getPosition().x / screenSize.x; + final float tabHorizontalPositionPercent = (float) mFloatingTab.getPosition().x / screenSize.x; + final float viewHeightPercent = mFloatingTab.getHeight() / 2f / screenSize.y; float tabVerticalPosition = (float) mFloatingTab.getPosition().y / screenSize.y; if (tabVerticalPosition < MIN_TAB_VERTICAL_POSITION) { tabVerticalPosition = MIN_TAB_VERTICAL_POSITION; - } else if (tabVerticalPosition > MAX_TAB_VERTICAL_POSITION) { - tabVerticalPosition = MAX_TAB_VERTICAL_POSITION; + } else if (tabVerticalPosition > MAX_TAB_VERTICAL_POSITION - viewHeightPercent) { + tabVerticalPosition = MAX_TAB_VERTICAL_POSITION - viewHeightPercent; } Log.d(TAG, "Dropped at horizontal " + tabHorizontalPositionPercent + ", vertical " + tabVerticalPosition); SideDock.SidePosition sidePosition = new SideDock.SidePosition( @@ -231,7 +232,9 @@ private void onDroppedByUser() { private void onTap() { Log.d(TAG, "Floating tab was tapped."); - mHoverView.notifyOnTap(this); + if (mHoverView != null) { + mHoverView.notifyOnTap(this); + } } private void sendToDock() { diff --git a/hover/src/main/java/io/mattcarroll/hover/view/InViewDragger.java b/hover/src/main/java/io/mattcarroll/hover/view/InViewDragger.java index f24215f..f26f642 100644 --- a/hover/src/main/java/io/mattcarroll/hover/view/InViewDragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/view/InViewDragger.java @@ -15,6 +15,7 @@ */ package io.mattcarroll.hover.view; +import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; import android.support.annotation.NonNull; @@ -61,6 +62,13 @@ public PointF getTouchViewPosition(@NonNull View touchView) { ); } + @Override + public Point getContainerSize() { + Rect area = new Rect(); + mContainer.getGlobalVisibleRect(area); + return new Point(area.right, area.bottom); + } + @Override public void moveTouchViewTo(@NonNull View touchView, @NonNull PointF cornerPosition) { touchView.setX(cornerPosition.x); diff --git a/hover/src/main/java/io/mattcarroll/hover/window/InWindowDragger.java b/hover/src/main/java/io/mattcarroll/hover/window/InWindowDragger.java index 030f11e..213c25a 100755 --- a/hover/src/main/java/io/mattcarroll/hover/window/InWindowDragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/window/InWindowDragger.java @@ -16,6 +16,7 @@ package io.mattcarroll.hover.window; import android.content.Context; +import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; import android.support.annotation.NonNull; @@ -59,6 +60,11 @@ public PointF getTouchViewPosition(@NonNull View touchView) { return new PointF(mWindowViewController.getViewPosition(touchView)); } + @Override + public Point getContainerSize() { + return mWindowViewController.getWindowSize(); + } + @Override public void moveTouchViewTo(@NonNull View touchView, @NonNull PointF cornerPosition) { mWindowViewController.moveViewTo(touchView, (int) cornerPosition.x, (int) cornerPosition.y); diff --git a/hover/src/main/java/io/mattcarroll/hover/window/WindowViewController.java b/hover/src/main/java/io/mattcarroll/hover/window/WindowViewController.java index b037678..bd2cd7a 100755 --- a/hover/src/main/java/io/mattcarroll/hover/window/WindowViewController.java +++ b/hover/src/main/java/io/mattcarroll/hover/window/WindowViewController.java @@ -104,4 +104,10 @@ public void makeUntouchable(View view) { mWindowManager.updateViewLayout(view, params); } + public Point getWindowSize() { + final Point windowSize = new Point(); + mWindowManager.getDefaultDisplay().getSize(windowSize); + return new Point(windowSize.x, windowSize.y); + } + } From ce78fbb145fd0045be6c3aafce7ac5f4dfad4637 Mon Sep 17 00:00:00 2001 From: SeoJungHong Date: Thu, 7 Mar 2019 22:53:47 +0900 Subject: [PATCH 020/105] Add publisher.gradle file for bintray upload --- build.gradle | 13 +++++------- hover/build.gradle | 46 +++++------------------------------------- hover/publisher.gradle | 36 +++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 49 deletions(-) create mode 100644 hover/publisher.gradle diff --git a/build.gradle b/build.gradle index e209835..f897f9e 100644 --- a/build.gradle +++ b/build.gradle @@ -7,20 +7,17 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:3.2.1' - - // For Bintray publishing - classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.2' - classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' } } +plugins { + id "com.jfrog.bintray" version "1.8.0" + id "com.github.dcendents.android-maven" version "2.0" +} + allprojects { repositories { google() jcenter() } } - -task clean(type: Delete) { - delete rootProject.buildDir -} diff --git a/hover/build.gradle b/hover/build.gradle index 64c497f..0968e50 100644 --- a/hover/build.gradle +++ b/hover/build.gradle @@ -1,7 +1,8 @@ apply plugin: 'com.android.library' apply plugin: 'checkstyle' -version = '0.9.8' +project.group = 'com.buzzvil' +project.version = '1.0.0-rc' android { compileSdkVersion project.compileSdkVersion.toInteger() @@ -27,45 +28,6 @@ dependencies { testImplementation 'junit:junit:4.12' } -// For Bintray publishing -ext { - bintrayRepo = 'maven' - bintrayName = 'hover' - - publishedGroupId = 'io.mattcarroll.hover' - artifact = 'hover' - libraryName = 'Hover' - - libraryDescription = 'An Android implementation of a floating menu.' - - siteUrl = 'http://google.github.io/hover/' - gitUrl = 'https://github.com/google/hover.git' - - libraryVersion = version - - developerId = 'matthew-carroll' - developerName = 'Matt Carroll' - developerEmail = 'me@mattcarroll.io' - - licenseName = 'The Apache Software License, Version 2.0' - licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt' - allLicenses = ["Apache-2.0"] -} - -apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle' -apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/bintrayv1.gradle' - -// The following is used to add our dependencies to the classpath for Javadoc linking. -afterEvaluate { - javadoc.classpath += files(android.libraryVariants.collect { variant -> - variant.javaCompile.classpath.files - }) -} - -// This disabled Javadoc tasks because its breaking the release build. Since Javadocs are -// not mission critical, they will remain disabled until the issue can be debugged. -tasks.withType(Javadoc).all { enabled = false } - //------ Checkstyle ------- task checkstyle(type: Checkstyle) { showViolations = true @@ -85,4 +47,6 @@ project.afterEvaluate { preBuild.dependsOn('checkstyle') assemble.dependsOn('lint') check.dependsOn('checkstyle') -} \ No newline at end of file +} + +apply from: 'publisher.gradle' diff --git a/hover/publisher.gradle b/hover/publisher.gradle new file mode 100644 index 0000000..e203028 --- /dev/null +++ b/hover/publisher.gradle @@ -0,0 +1,36 @@ +apply plugin: 'com.jfrog.bintray' +apply plugin: 'com.github.dcendents.android-maven' + +group = project.group +version = project.version + +Properties prop = new Properties() +String propFileName = 'local.properties' + +try { + File file = project.rootProject.file(propFileName, PathValidation.EXISTS) + prop.load(file.newDataInputStream()) +} catch (InvalidUserDataException e) { + print("File not found : " + propFileName) +} + +bintray { + user = project.hasProperty('user') ? project.user : prop.getProperty("bintray.user") + key = project.hasProperty('key') ? project.key : prop.getProperty("bintray.apikey") + configurations = ['archives'] + publish = false + + pkg { + repo = 'maven' + name = 'hover' + desc = 'Buzzvil hover Android SDK' + userOrg = 'buzzvil' + licenses = ['Apache-2.0'] + vcsUrl = 'https://github.com/Buzzvil/hover' + publicDownloadNumbers = true + version { + name = project.version + released = new Date() + } + } +} From 5451ea77206af5a0f7fb65d9565eb77d0b06c5b9 Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Fri, 8 Mar 2019 18:35:58 +0900 Subject: [PATCH 021/105] =?UTF-8?q?StateAnchored=EB=A5=BC=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=20=ED=95=98=EA=B3=A0=20StateHidden=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#20)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/mattcarroll/hover/HoverView.java | 12 +-- .../hover/HoverViewStateAnchored.java | 94 ------------------- .../hover/HoverViewStateHidden.java | 39 ++++++++ .../mattcarroll/hover/HoverViewStateType.java | 2 +- hover/src/main/res/values/dimens.xml | 2 - 5 files changed, 46 insertions(+), 103 deletions(-) delete mode 100644 hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java create mode 100644 hover/src/main/java/io/mattcarroll/hover/HoverViewStateHidden.java diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverView.java b/hover/src/main/java/io/mattcarroll/hover/HoverView.java index 3207c39..749b57d 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverView.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverView.java @@ -89,7 +89,7 @@ public static HoverView createForView(@NonNull Context context) { private final HoverViewState mCollapsed = new HoverViewStateCollapsed(); private final HoverViewState mPreviewed = new HoverViewStatePreviewed(); private final HoverViewState mExpanded = new HoverViewStateExpanded(); - private final HoverViewState mAnchored = new HoverViewStateAnchored(); + private final HoverViewState mHidden = new HoverViewStateHidden(); final WindowViewController mWindowViewController; final Dragger mDragger; final Screen mScreen; @@ -322,12 +322,12 @@ public void run() { }); } - public void anchor() { - setState(mAnchored, new Runnable() { + public void hide() { + setState(mHidden, new Runnable() { @Override public void run() { for (OnStateChangeListener onStateChangeListener : mOnStateChangeListeners) { - onStateChangeListener.onAnchored(); + onStateChangeListener.onHidden(); } } }); @@ -593,7 +593,7 @@ public interface OnStateChangeListener { void onClosed(); - void onAnchored(); + void onHidden(); } public static class DefaultOnStateChangeListener implements OnStateChangeListener { @@ -614,7 +614,7 @@ public void onClosed() { } @Override - public void onAnchored() { + public void onHidden() { } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java deleted file mode 100644 index 4c1fa47..0000000 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateAnchored.java +++ /dev/null @@ -1,94 +0,0 @@ -package io.mattcarroll.hover; - -import android.graphics.Point; -import android.support.annotation.NonNull; -import android.util.Log; -import android.view.View; - -import java.util.ArrayList; - -class HoverViewStateAnchored extends BaseHoverViewState { - - private static final String TAG = "HoverViewStateAnchored"; - - private FloatingTab mSelectedTab; - private HoverMenu.Section mSelectedSection; - private final BaseTouchController.TouchListener mTouchListener = new BaseTouchController.TouchListener() { - @Override - public void onPress() { - } - - @Override - public void onTap() { - mHoverView.notifyOnTap(HoverViewStateAnchored.this); - } - }; - - @Override - public void takeControl(@NonNull final HoverView hoverView, final Runnable onStateChanged) { - super.takeControl(hoverView, onStateChanged); - Log.d(TAG, "Taking control."); - mHoverView.makeUntouchableInWindow(); - mHoverView.clearFocus(); - - mSelectedSection = mHoverView.mMenu.getSection(mHoverView.mSelectedSectionId); - if (mSelectedSection == null) { - mSelectedSection = mHoverView.mMenu.getSection(0); - } - mSelectedTab = mHoverView.mScreen.getChainedTab(mSelectedSection.getId()); - if (mSelectedTab == null) { - mSelectedTab = mHoverView.mScreen.createChainedTab(mSelectedSection); - } - - mSelectedTab.shrink(); - mSelectedTab.setSelected(true); - final int anchorMarginX = hoverView.getContext().getResources().getDimensionPixelSize(R.dimen.hover_tab_anchor_margin_x) + (mSelectedTab.getTabSize() / 2); - final int anchorMarginY = hoverView.getContext().getResources().getDimensionPixelSize(R.dimen.hover_tab_anchor_margin_y) + (mSelectedTab.getTabSize() / 2); - final Point anchorPoint = mHoverView.getScreenSize(); - anchorPoint.offset(-anchorMarginX, -anchorMarginY); - mSelectedTab.setDock(new PositionDock(anchorPoint)); - mSelectedTab.dock(new Runnable() { - @Override - public void run() { - if (!hasControl() || !mHoverView.mIsAddedToWindow) { - return; - } - activateTouchController(); - onStateChanged.run(); - } - }); - } - - @Override - public void giveUpControl(@NonNull HoverViewState nextState) { - Log.d(TAG, "Giving up control."); - deactivateTouchController(); - mSelectedTab.expand(); - mSelectedTab.setSelected(false); - super.giveUpControl(nextState); - } - - private void activateTouchController() { - final ArrayList list = new ArrayList<>(); - list.add(mSelectedTab); - mHoverView.mDragger.activate(mTouchListener, list); - } - - private void deactivateTouchController() { - mHoverView.mDragger.deactivate(); - } - - @Override - public boolean respondsToBackButton() { - return false; - } - - @Override - public void onBackPressed() { - } - - @Override - public HoverViewStateType getStateType() { - return HoverViewStateType.ANCHORED; - } -} diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateHidden.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateHidden.java new file mode 100644 index 0000000..37010b3 --- /dev/null +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateHidden.java @@ -0,0 +1,39 @@ +package io.mattcarroll.hover; + +import android.support.annotation.NonNull; +import android.util.Log; +import android.view.View; + +class HoverViewStateHidden extends BaseHoverViewState { + + private static final String TAG = "HoverViewStateHidden"; + + @Override + public void takeControl(@NonNull final HoverView hoverView, final Runnable onStateChanged) { + super.takeControl(hoverView, onStateChanged); + Log.d(TAG, "Taking control."); + mHoverView.makeUntouchableInWindow(); + mHoverView.setVisibility(View.GONE); + } + + @Override + public void giveUpControl(@NonNull HoverViewState nextState) { + Log.d(TAG, "Giving up control."); + mHoverView.setVisibility(View.VISIBLE); + super.giveUpControl(nextState); + } + + @Override + public boolean respondsToBackButton() { + return false; + } + + @Override + public void onBackPressed() { + } + + @Override + public HoverViewStateType getStateType() { + return HoverViewStateType.HIDDEN; + } +} diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateType.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateType.java index 7435290..a1ae900 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateType.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateType.java @@ -5,5 +5,5 @@ public enum HoverViewStateType { COLLAPSED, PREVIEWED, EXPANDED, - ANCHORED, + HIDDEN, } diff --git a/hover/src/main/res/values/dimens.xml b/hover/src/main/res/values/dimens.xml index 8e9f9ac..9090645 100755 --- a/hover/src/main/res/values/dimens.xml +++ b/hover/src/main/res/values/dimens.xml @@ -1,8 +1,6 @@ 72dp 48dp - 12dp - 32dp 8dp 7dp 40dp From 35d2211ea5918c5f6e4ba3e72e3887bd2e5c6355 Mon Sep 17 00:00:00 2001 From: Haley Date: Mon, 11 Mar 2019 14:09:48 +0900 Subject: [PATCH 022/105] =?UTF-8?q?[BZZRWRDD-296]=20Detailed=20UI=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9=20-=20ExitView=20=EC=95=84=EC=9D=B4=EC=BD=98?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD,=20Alpha=20=EA=B0=92=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=20(#21)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * exit view 변경 * Alpha 0.4 로 변경 --- .../hover/HoverViewStateCollapsed.java | 2 +- hover/src/main/res/drawable-hdpi/ic_delete.png | Bin 22319 -> 0 bytes hover/src/main/res/drawable/ic_exit.xml | 14 ++++++++++++++ .../main/res/layout/view_hover_menu_exit.xml | 14 ++++++-------- hover/src/main/res/values/dimens.xml | 2 +- 5 files changed, 22 insertions(+), 10 deletions(-) delete mode 100644 hover/src/main/res/drawable-hdpi/ic_delete.png create mode 100644 hover/src/main/res/drawable/ic_exit.xml diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index becf4af..75dafbd 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -56,7 +56,7 @@ class HoverViewStateCollapsed extends BaseHoverViewState { public void run() { final HoverViewState state = mHoverView.getState(); if (!(state instanceof HoverViewStatePreviewed) && state instanceof HoverViewStateCollapsed) { - mHoverView.setAlpha(0.5f); + mHoverView.setAlpha(0.4f); } } }; diff --git a/hover/src/main/res/drawable-hdpi/ic_delete.png b/hover/src/main/res/drawable-hdpi/ic_delete.png deleted file mode 100644 index 8189a8acbf116bac5ace14ec0c073ee8c1ea7531..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22319 zcmeI42{hE-`}p6M>}wRVG*m*yjIob>Uq{)pm5iA&_8CkFF_fi^q_Ra?q{tE>QH>>( zED_3@ElDC068@u_^6As(`=9Ump6~B>e&?8jhkKvrx$pbB&wcK5Ipf4Wb3=BPZ7cu) zup1lcS&}7j?URXt{Ix~{*+>@5cq4m%0AS@=`=kLQ1-9T3d~8RiE$wq+=ROJa3A#+`pTpaQA77J;%lPoV8M?|m29lI8L^6AoG$TiQ-%K0}wXPfQ2wMwLM}a#)kk+ zP&+FVKtiOEph7XLobPl}4$u&f(~t-W%BD<2UO+22PUi-oWk5qrPZqZVGU);5MwH7i zun!D4?+$;{4iM89QbK3|$Md3FXfhK35Dz9+4{%cjZnx||sSnse0bWBt-xgAmnOA3j>xCBM^~`bhe)=|UW;LBU+3puKOEW_0XrCBNWbv9 z`q?M5ETNWj%*S1N-^3e!En{8%D%>tsYwS{PC&fE#vDr6HFZJ{+EKBT!&N<1)yV_RK zLj%%FbQ%K+K%s{QO-KUx=0OzQXVcwWb_CMUJOIp8;Hq9oFwqg+jt#a1u1;w#8)ohT zh_1%xd;!2oZ>Nm)(_+nfCIHaOjF2kS7W`DjFHK?)s@l|B#roA*@wm>;+G-sx9TqfE z$j@2wcBGC(bW@?Qlr!Xomasg@!Yw)x&mmK7bB{wE&-n$(lu;#78Np1i-N3|y6zz_s zaXD$XBaVqLC2B#m%7}jRshyxFvAh;yrU?p0vX&>UK{iIhGwOb{DlrEP?kA`=0I=Oc!GB# z{ETw7UQn638l5}J(#(md#yeuS*>dZ)74E-HS8-wv)p940eshFAiCK|8PzQt*(KfO( zvon8bbQ2`BQ=YqFV^zAz+_|WjHGvTZjR@HaD~L`)++7X zd_ottyZkJz@ty0|ZJXN++I%c`j7#52lQ-J7Bk@T$+OvpJ<-9a#Peas5`bf=)+=$?a z=!_#vx{H?Y^#!XT3CpJ*CIX{eqw=E+m}Ho?&9zj^zMEI9xfS9abn>p0S{7Ku+~koz zoT}1vY^$+pR^HVM?c3b=+~(a2-V*L}_gxS%PinPoYaBOxoAj3MQy?3A^p<1wu~-R# zG=4^YtUw@tL9*Emf%a1Z_0~`&*@@(_6wVZ!jh$4fROpt3rz{stE{IagemACwp%6;RuCV@jFegLIb2Kl9z=mPO0bIx}u^hXCh}? zY&m=0Rg-Zz*>~X*!JK(aB0Fg|>|{Uhl;n`4;0<}Ra#_p)&zy@%7wvM5axHQVCmtx~ zPiCjzc%WZlzZAitU2n4cz-~iqeDkLCF{@Wrec3G8TM_E;xqO)%&n&?!6?%b>e6l|z zXFPNwW|-l!`;R;r`yzA{vTVKV{Uv+Okj;*vm~AIR4_h<8+G7P@oSHDCzUQNb?!g)@ z-7Mq=0px2v-vuOgc}yWBj{JU62gTT}S4^hxQhGJ(R;mkd4mrQW4SkysZ#Y}w=dnh%K& z5|7?LdS+Rjkv--WN3O7gaG3vHKVJBLczBaJ9UY8!qK(l&p16 zw@Pa_#PVUw{g2JYo;qO~*(j5wA(JLp*Vpi1#Dp;CdvGwgZ7w~nIIVi}W>3Kf#SiWu zVtOw>lfNvPVK3+3TGOEW+G6y%ChO%3P|tzeVS9D=Mqo?Ec0f>&1lzo>!m_NuoO$FF zpT=hmzstiK!)i+XuzveP&y+}I4P}jcYj7Edq6T!scdVjUgIAve*~DEmSh^Dt+7XVl zOAEoFqL1P<;XRnoMXx5cPiK~EZ_$pA%!?eY$`f^Kcz-rebbc(kIicB|BWhpR+s;-- z7ieouaEnJNigFIJ!9{W=FfRu>&jFA)~_}u%1 zN`)gkAIoJ)kCq?bed}zc8M|3u8a!ibY5>R^rVf7~d+c1oSznzTQAA=X_8s<(Ye3^| zOjOazW1mxH5RnUvPdtmy-ri&nW+~OV@z&ZwqDzXg2#c|GebjW~smjINj6F@0&x)V+ zoK?Csb$NAibM@xIbER3)rnX>VyEhMRd#Dtt`5x(E8Q!vKPxO9<+iLetmP&bd?9H9D zP09~@ARdhHjBu)Y8d+6B<2k`#7S zzm(_=8WoJeJ$;nYd;adN+}d(_N?7urX_gTLO zlGG&8Q*o?RxBS{8wR@GA>?h4ls+!ine;TJU-PK`^B9v;6yx9>>c0 zWsN5fdu(WI5FM@^m?h(-;(5*d6FK7x7ni&b=9zo@PS(@4(JeFX;3(}Xf6*b_rfzK+ z-??YPkfVP4!GoI4-m!*Lp*d+ zXHpH)tWuX8T^#T4eWvle^Id=NSHqs|oR{R)?2nktT0e2`9*=BK#Ll#wPQQ?TG)!i( z*SY6vX~-C=dBB4cH+7$jFxaNQdTLCyQnmTO%ss+PQO_uk?LFJn0{9{CcZ7FpD~auU z>nko*q~@0&@GSoj{GcSnb$(nhL#es%(}N=)x2|?}WT>e3J(vx~%|D)>8`#ebSoLex=(N)1m3O())6%H{631m^u5r*KnR8>R8K4!dyJ3?xy&Z z_{M1V=!pzv4HcCkO~2*wui3gS=oaw|zLl#hjrn|AAz=$06J5>Elb>Hnnn_B0G$PTd&q>J;zfD~jD!6>M#JV;4JMpi*lNkvH-1S9_p zfht2_P%u;lt{?}8!azS>Vj3*u@6`Ozu5e2|gCE0@e^M87BM|U#2qZ8tP$p1L2Iq%` z$f~HQK%g)P3&Lvj@jnOh@&Cb&Oc4@<#6x6dppZWqp;13=@Q3}pzC9Wm1;Kb>yfHomf3ltIAMMCU z5s06re;m%+`;V6X1pNT=41N&#qou#~5j+NBiSfrB_CsOx1ISOZ<4+IoPq4)Nf=h)f zvict#;VD;{KR?&c?tjEcaCiNO2U+X+M>9;2`#+ei^?Wz`7E|AsT8&H{uIqpDHxi41;C--akYA1KG{40!+}OvTfb>COjP*3g4KnWTXt=VH3fcvVM1x&r6=7g` zMR^yni;^rFtSGOdjFFRvDJdu_e8Yi2tT+FgYdsw5@Y)t4yZ)YS&^Q#?{m)Q>%e%_E zxF8iUU?@^q5iBdKqzra}qLjc$l&pd)8ZE0L2mLwFI%j_yXs@3;IT<3o*6FOx1x+3d zBZqcDx+tK)7?cVUERRt@lfA2;zzTA5vaSkHl!}WShBB8wxcS>qM(+OP$UCwwBFS<2 zE!|mReE-@?>F{#@mbUOnKYz^Hu2vVLZ0nzS?q?cXv-y@C;7HV3!qY&lg*pbU2Kh_t zugCgn`NPcp@5@OYg75yR|f3;D*yZWZ}&rbYtu7p6OA4VHXju7g0@pr#} zHT-=5HOSf#;pP5cSPFk+z<;(7F7hyPz(X-$C0S*8u)G{h39RC(f(9!qqFrH%7NiK~re*PM+ zemHLs5|8(CMx?) z{2%X4>dw6H%et{QDW}f&Z2Q-fk8+y+{iIy0wa6ud-uL)4Sld-=$@>3)Fp|$Ua@h)B z$DLBDP@7VJGyltO{NbHkoKUKjf3JA>{&4He|KuI_pOz@!NBM)BU!zgTuLHd97*zY2 ztKhmgFPt9&hsJ2gsX_kKyw2yZZt|Zv_I>{ghlanUp$^DcUsq99MNtt9laXETW}V(T zKWmo&IJv?ipZ4F9s0P{QZ*9Np+pSefUWdO`LP{_w`2~?(`})IlefRIC_W#;+efRIC zzbtKh+zA@6AEW)&yv}Ovrt%%C75R3KS)1DLO}}gJa}UCJ+3C5H>tp}5I!_j+{KM$? zo^FQIs}tQAkiFH*isf ziK4WDi$a1bxq*u+OcbRJToe*i$qigoVWKE);G&SAN^any3KKK9Kx=`m)(z2>HGE zAe50M0sw+{k^f!PF#uRxCChODI1B}Vcg_F+PX+)!+_^)K4FG_x*jP{7I;i`7y5nh^ z4uSe`e}isKYDQjN-)ouHYKS9JoiAAKoaJpL{-p!bLx6N@VGqO8LQI=u) zii0uOkDDusrIu)N;#d{8o)?^HRLp^wzjg6T;Ul`3qn&WbKe;gVos~25v`}F^b0+LA5D&-^ zqoquTWF{*QOVBVz)R3^qgT<%{5Px5}Im7$U82&?7tcFFHB$0#Vo0|m6KM0Rr^ z%U21?c`qvxd;czb|IPGbj>)Pn+N4}i9gujJv(36{c8c~9<9=nDOQ+mP+lhB*rZh9X zCrxD~Y``R;$+QF9(&zFxp43E>Gnw8LrB zkXBUcn=GM#6Go;l#!toPC)YQwF98y%eCxmT=GNOWy(v8CqZ@BReWUea zn%>Asw)4R~zUAGS)``={yI~dxt?k@L%Ju5ZPZ~K!pP1k7?ZG3sazznQi+c?Sj~B7O z^I{BRsf^JT^`YHLbIp`Zr0Ip|1BZNEUE0&hfKb7Nnl#G{=kgUAsLk$F zoh4^G{_FHT4VO912qQ^)W!-KMN52@Ae9XMp0oZy@1>D3Gz3Ep*5O>ncMPyxkazmZO zn<>YkK*GRpA;ne;Ibz^5d+J$A`j9mxq9l09(Sw^>9eF%*KC4D-2PTA*Y)}unTdms+ zZ%&4EnF41>tR&@{l4XZU96{(azhKA38*u~5qnUR^XoG~3F}FUC0ggg}SCFjz!4106 zp2g=+8L39h4}n8JLAu~slbwQb#i^NFa2~yyQ8H3zvn-gLuXC6jaJ#1{X!ju~N79w1 zfWJ9BN@=0A_##4!XZmW?*TuN6MuojF^H#$pIz$OC36+eUQ>613R!TtTclX9yXgTJk z5+%Pl4&mm@=*nmZl%2%%uPHu8u`NgJr!~)G+@b}^OdqPskXhd1%cDA1CE>iM^}Xt9 zg43RgI;a~DlylZ-pgr#E{j0)3b@;HGep^l0p+Z61ap4({`Y!XkxQetLy3{AR+nXPs zv^Ar!@WhZnZ99oQNcH-Arb0L8C`^_~@}47a#zR(jh}BqDPNS0FSm=$Ei55u1@+uu( zwQte30`IZTxJ|Qo&X1e-97KVuDsgN6jn8_3BO9cb+vV!^J3HatV$g)k^$^{!<`sj> zj=5V%W~PyjJ78v56Fn}Bh$DC)#r_OXD&TZiW01i_ZgH{Z?jqVTi#FNC_|pQffYh0h zu|QA?G;1?Wa`1|$l}Dlc8%*9{#hyqO=fcq>mtY3Aq>E~1Wnb@eaug}Nr>O~AT_SZe zF&GEXm7$zy4_}DGah_TPwFFn{7lpmA@fYWQtkvZ(`u>u(=Ibgy-Kw!c@9t@o&2a;> z9Ht?iFv;eyt3r;3v{QGj53&p7nIvZH=W#vnL2FiF!DqF-MacLT^U(g8<=#c#f;-cw^cTw8_YOAG7%9iiX7^cP8M5@zLSh4O)m$QFDtymUg!D53eU& zHspI8!ko|WdDN3=93A6yX588Ifk))^bGTtY7bFipZ7@2#E~pml!M!sjR4}P*3kzwa zdDMI8%uT(sgc+Jrf#$w*Q*`pcA-rOkxd@+cXL|4@3)9FpEsdZL(~qXpRT&PPuklwJ z+8vJ5X(+%T&TgHtkeUC|JhzEqlsLi08LCypRm#++7ba<5(AWiph3d?3U1VxAdU&Q? z+kLYZznIaU#a)~5X9lYu8O!8s(N29*-^!@GgJ{am$C2n|Efsk;k<+PATJy^ov|^j8 z-VC=jy*+54ZXCldR&;sD*^tgS$mj)&Ng0~>RV{mEF=JV!^1*7@C6Ky=Ee|>(lsFvi z|G+=_=(DV*9z#iPa*JU08FrTdu2wC$MUIM*+~N^l-}D;M_6C|m+nVQ_oW~(b=4T1X z%F8gUry$HItXtpt{luuW`ihf)X!!OgebM_R&72;`k3r+V98Be&aWwkuRBO^Yfd62` z(a2IB?l_rrnw+IWqJv z-MPzbuu0l&Y2=ojk!kE>{ZYlm5jVJSRzi!nxFb$9g7E<%3pUZu4qFJF5IZ%JePu8H z+)&=im>1^&BVobEt&L4(Ch;K8UH*oteIe<^Aau##pi11=+Eb+3L4kbMO@(#%VK2k5 zA${keY3VMS-dY5~XQ*gUJfGFysO@t3xyvt8Nws}@o*uSfC*J2)sJf7U`rgT-XI$zd z_aT+r*j9WV-w}uU1^{-pLDdjqf$UOJ`e4J}OH3c+FFBs(+soz1^P1M+x~g;S*-TN? z{`+TTZ?Os#OP$WNKnXA2X=#56jWl>wU6O}5=%A%K_54j((-M~Z(_Kp z8s>4*KH1jiXjEAW7MnF`l=bo!i@YROvh|&Ej(|f)U8w^Sn+3Vux%ai@Yss2LRw5tU z>U9qFdivJ|y!ESec19PpHFDi)XWZzWI;Eb(?~R!9v>I&nKTWq1rxf_Q-mhd%$$}M7 z>q1Q^M1&D&HLtEzWhcg+aF{_Px;lOoPmQx(n#o`R)TXQiBexjD)1>CrPK0 z)kBZo9C~Zv6$1_3w4L@L>-#&gs4dWTUwc{CoJq5ha5l4D$4Mecl~W(Axs!+5x)HJKGh` z*Y$w&E`09jmw?w{m6EP8#rJ4}L~w3>#{-EK5yy~Wcej3|rx zpIw0SsIQr~Z975l!mA1W>km#dmBv(#sO1};dQ-yNtv?bi(Z++ROVb~@1%K5|g6 zF8l1l$J8>*xBCSZ3@_vd^A81ZzXFebOqDU+3;)SFd_zA z>=^YjqRb)4hc@K198s{bH;@JAIv4n2hclL~^GU%)=eJuE9?MSKTQ~1+xe7EL5Xsd? z2dTFoDA-1dCs&B%T4?dkq17{ou13z`6m(cK_LRONU7)#qgmFP3!|>u44)r=cAc_Yx z3tcKLxx(5q)o0+G#*rj)+u{qu+uLJJq@8LIA;cE7M~K`n7m{tQF-|~K);n%*-P{z_ z1)-N&E(`mxQk=kL8pG+Wh=9SoYjkg~=_wBDcipFlT>ZjTnQpOzIH>i=!@+*CMmkp8 z`vO1Bh%9{&*Mje+4$lL4!0sxKYKV*K60bkah_6OJ!T(|2Bwsrr%&Aq$K4w5Pkw;6y zjaHm4&`nV7YV-Jbt471N*9ew$s5oHEOWbZtGdy?Cev?HmDJkasv^U8y_`PY-$2Jha zBhzW#!!%jT-f4a?Ts^f!{7HSgdj78Y>j9hN-2_+e1c<5LwK^j29sOk$*e;w~A+4wx Ry7qs^jP=d+@^zde{~y}E^x^;j diff --git a/hover/src/main/res/drawable/ic_exit.xml b/hover/src/main/res/drawable/ic_exit.xml new file mode 100644 index 0000000..4b1a61a --- /dev/null +++ b/hover/src/main/res/drawable/ic_exit.xml @@ -0,0 +1,14 @@ + + + + diff --git a/hover/src/main/res/layout/view_hover_menu_exit.xml b/hover/src/main/res/layout/view_hover_menu_exit.xml index f3cb63b..581bf75 100644 --- a/hover/src/main/res/layout/view_hover_menu_exit.xml +++ b/hover/src/main/res/layout/view_hover_menu_exit.xml @@ -1,16 +1,15 @@ - + android:layout_height="match_parent"> + + android:background="@drawable/gradient_black_to_transparent" /> + + android:src="@drawable/ic_exit" /> \ No newline at end of file diff --git a/hover/src/main/res/values/dimens.xml b/hover/src/main/res/values/dimens.xml index 9090645..a35074c 100755 --- a/hover/src/main/res/values/dimens.xml +++ b/hover/src/main/res/values/dimens.xml @@ -3,7 +3,7 @@ 48dp 8dp 7dp - 40dp + 72dp 75dp 32dp 24dp From 8707ccf2eb905772ba0e9105f01238ba62c4e9e4 Mon Sep 17 00:00:00 2001 From: SeoJungHong Date: Mon, 11 Mar 2019 16:09:21 +0900 Subject: [PATCH 023/105] Bump version to 1.0.0-rc.1 --- hover/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hover/build.gradle b/hover/build.gradle index 0968e50..e221d20 100644 --- a/hover/build.gradle +++ b/hover/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.library' apply plugin: 'checkstyle' project.group = 'com.buzzvil' -project.version = '1.0.0-rc' +project.version = '1.0.0-rc.1' android { compileSdkVersion project.compileSdkVersion.toInteger() From 78d0d3e54919e05563c7b3a508e95aa93cbc0ecc Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Wed, 20 Mar 2019 14:11:59 +0900 Subject: [PATCH 024/105] =?UTF-8?q?Hidden=20State=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=A0=84=ED=99=98=EB=90=A0=20=EB=95=8C=20Animation=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#22)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Hidden State으로 전환될 때 hover view에 셋팅된 position 값이 있을 경우 그 position으로 이동 후 숨김처리할 수 있도록 변경 * Hidden State로 전환 중 빠르게 다른 State으로 넘어갈 경우 NPE가 발생하는 이슈 수정 * log 제거 --- .../java/io/mattcarroll/hover/HoverView.java | 14 ++++++ .../hover/HoverViewStateHidden.java | 47 ++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverView.java b/hover/src/main/java/io/mattcarroll/hover/HoverView.java index 749b57d..8f5a91e 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverView.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverView.java @@ -101,6 +101,7 @@ public static HoverView createForView(@NonNull Context context) { boolean mIsTouchableInWindow; boolean mIsDebugMode = false; int mTabSize; + private PositionDock mPositionToHide; OnExitListener mOnExitListener; private final Set mOnStateChangeListeners = new CopyOnWriteArraySet<>(); private final Set mOnInteractionListeners = new CopyOnWriteArraySet<>(); @@ -245,6 +246,19 @@ public void enableDebugMode(boolean debugMode) { mScreen.enableDrugMode(debugMode); } + public void setPositionToHide(Point position) { + if (position == null) { + this.mPositionToHide = null; + } else { + this.mPositionToHide = new PositionDock(position); + } + } + + @Nullable + public PositionDock getPositionToHide() { + return mPositionToHide; + } + void setState(@NonNull HoverViewState newState, Runnable onStateChanged) { if (mState != newState) { if (mState != null) { diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateHidden.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateHidden.java index 37010b3..c2f7fc0 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateHidden.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateHidden.java @@ -1,5 +1,7 @@ package io.mattcarroll.hover; +import android.os.Handler; +import android.os.Looper; import android.support.annotation.NonNull; import android.util.Log; import android.view.View; @@ -8,17 +10,60 @@ class HoverViewStateHidden extends BaseHoverViewState { private static final String TAG = "HoverViewStateHidden"; + private FloatingTab mSelectedTab; + @Override public void takeControl(@NonNull final HoverView hoverView, final Runnable onStateChanged) { super.takeControl(hoverView, onStateChanged); Log.d(TAG, "Taking control."); mHoverView.makeUntouchableInWindow(); - mHoverView.setVisibility(View.GONE); + mHoverView.clearFocus(); + + HoverMenu.Section mSelectedSection = mHoverView.mMenu.getSection(mHoverView.mSelectedSectionId); + if (mSelectedSection == null) { + mSelectedSection = mHoverView.mMenu.getSection(0); + } + + mSelectedTab = mHoverView.mScreen.getChainedTab(mSelectedSection.getId()); + if (mSelectedTab == null) { + mSelectedTab = mHoverView.mScreen.createChainedTab(mSelectedSection); + } + + mSelectedTab.shrink(); + mSelectedTab.setSelected(true); + + final PositionDock positionToHide = mHoverView.getPositionToHide(); + if (positionToHide == null) { + mHoverView.setVisibility(View.GONE); + onStateChanged.run(); + return; + } + + mSelectedTab.setDock(positionToHide); + mSelectedTab.dock(new Runnable() { + @Override + public void run() { + if (!hasControl() || !mHoverView.mIsAddedToWindow) { + return; + } + onStateChanged.run(); + new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { + @Override + public void run() { + if (mHoverView != null) { + mHoverView.setVisibility(View.GONE); + } + } + }, 50); + } + }); } @Override public void giveUpControl(@NonNull HoverViewState nextState) { Log.d(TAG, "Giving up control."); + mSelectedTab.setSelected(false); + mSelectedTab.expand(); mHoverView.setVisibility(View.VISIBLE); super.giveUpControl(nextState); } From 3298e5d8371b91ba7eceeb98a1f4087efe2fbf73 Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Wed, 3 Apr 2019 16:35:18 +0900 Subject: [PATCH 025/105] Bump version to 1.0.0-rc.2 --- hover/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hover/build.gradle b/hover/build.gradle index e221d20..f9124fa 100644 --- a/hover/build.gradle +++ b/hover/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.library' apply plugin: 'checkstyle' project.group = 'com.buzzvil' -project.version = '1.0.0-rc.1' +project.version = '1.0.0-rc.2' android { compileSdkVersion project.compileSdkVersion.toInteger() From 9c3f5f099bc3050045c0841e1d69fc3c34e4a5cd Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Thu, 11 Apr 2019 15:55:15 +0900 Subject: [PATCH 026/105] =?UTF-8?q?Collapsed=20state=EC=9D=BC=20=EB=95=8C?= =?UTF-8?q?=20=EC=9D=BC=EC=A0=95=20=EC=8B=9C=EA=B0=84=EC=9D=B4=20=EC=A7=80?= =?UTF-8?q?=EB=82=98=EB=A9=B4=20=EB=B0=98=ED=88=AC=EB=AA=85=ED=95=B4?= =?UTF-8?q?=EC=A7=80=EA=B1=B0=EB=82=98=20=EC=95=84=EC=9D=B4=EC=BD=98?= =?UTF-8?q?=EC=9D=B4=20=EC=82=AC=EB=9D=BC=EC=A7=88=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=84=A4=EC=A0=95=ED=95=A0=20=EC=88=98=20?= =?UTF-8?q?=EC=9E=88=EA=B2=8C=20=EB=B3=80=EA=B2=BD=20(#23)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Collapsed state일 때 일정 시간이 지나면 반투명해지거나 아이콘이 사라질 수 있도록 설정할 수 있게 변경 * Alpha 값을 상수로 변경 --- hover/src/main/java/io/mattcarroll/hover/HoverView.java | 9 +++++++++ .../io/mattcarroll/hover/HoverViewStateCollapsed.java | 7 ++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverView.java b/hover/src/main/java/io/mattcarroll/hover/HoverView.java index 8f5a91e..2a741de 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverView.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverView.java @@ -105,6 +105,7 @@ public static HoverView createForView(@NonNull Context context) { OnExitListener mOnExitListener; private final Set mOnStateChangeListeners = new CopyOnWriteArraySet<>(); private final Set mOnInteractionListeners = new CopyOnWriteArraySet<>(); + private boolean mKeepVisible; // Public for use with XML inflation. Clients should use static methods for construction. public HoverView(@NonNull Context context, @Nullable AttributeSet attrs) { @@ -347,6 +348,14 @@ public void run() { }); } + public void setKeepVisible(boolean keepVisible) { + this.mKeepVisible = keepVisible; + } + + public boolean shouldKeepVisible() { + return mKeepVisible; + } + public void setOnExitListener(@Nullable OnExitListener listener) { mOnExitListener = listener; } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 75dafbd..3f3272a 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -44,6 +44,7 @@ class HoverViewStateCollapsed extends BaseHoverViewState { private static final float MIN_TAB_VERTICAL_POSITION = 0.0f; private static final float MAX_TAB_VERTICAL_POSITION = 1.0f; private static final long ALPHA_IDLE_MILLIS = 5000; + private static final float ALPHA_IDLE_VALUE = 0.4f; protected FloatingTab mFloatingTab; protected final Dragger.DragListener mDragListener = new FloatingTabDragListener(this); @@ -56,7 +57,11 @@ class HoverViewStateCollapsed extends BaseHoverViewState { public void run() { final HoverViewState state = mHoverView.getState(); if (!(state instanceof HoverViewStatePreviewed) && state instanceof HoverViewStateCollapsed) { - mHoverView.setAlpha(0.4f); + if (mHoverView.shouldKeepVisible()) { + mHoverView.setAlpha(ALPHA_IDLE_VALUE); + } else { + mHoverView.close(); + } } } }; From 2f30071977fcbdb403c45241235f10ec1d113d99 Mon Sep 17 00:00:00 2001 From: ybbarng Date: Fri, 12 Apr 2019 15:02:55 +0900 Subject: [PATCH 027/105] =?UTF-8?q?Pop=20=EB=93=9C=EB=9E=98=EA=B7=B8=20?= =?UTF-8?q?=EC=8B=9C=20Preview=EA=B0=80=20=EC=82=AC=EB=9D=BC=EC=A7=80?= =?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hover/HoverViewStateCollapsed.java | 4 ++-- .../hover/HoverViewStatePreviewed.java | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 3f3272a..59bd2d8 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -195,7 +195,7 @@ public void onBackPressed() { // No-op } - private void onPickedUpByUser() { + protected void onPickedUpByUser() { mHoverView.mScreen.getExitView().setVisibility(VISIBLE); restoreHoverViewAlphaValue(); mHoverView.notifyOnDragStart(this); @@ -277,7 +277,7 @@ private void initDockPosition() { } } - private void onDocked() { + protected void onDocked() { Log.d(TAG, "Docked. Activating dragger."); if (!mHoverView.mIsAddedToWindow) { return; diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index 5a6bdec..5a1b105 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -31,6 +31,7 @@ class HoverViewStatePreviewed extends HoverViewStateCollapsed { private static final String TAG = "HoverViewStatePreviewed"; private TabMessageView mMessageView; + private boolean mCollapseOnDocked = false; @Override public void takeControl(@NonNull HoverView hoverView, final Runnable onStateChanged) { @@ -52,7 +53,7 @@ public void run() { @Override public void giveUpControl(@NonNull final HoverViewState nextState) { Log.d(TAG, "Giving up control."); - if (nextState instanceof HoverViewStateCollapsed) { + if (nextState instanceof HoverViewStateCollapsed && !mCollapseOnDocked) { mMessageView.disappear(true); } else { mMessageView.disappear(false); @@ -76,6 +77,13 @@ protected void moveTabTo(View touchView, @NonNull Point position) { } } + @Override + protected void onPickedUpByUser() { + mMessageView.disappear(true); + mCollapseOnDocked = true; + super.onPickedUpByUser(); + } + @Override protected void activateDragger() { final ArrayList list = new ArrayList<>(); @@ -84,6 +92,15 @@ protected void activateDragger() { mHoverView.mDragger.activate(mDragListener, list); } + @Override + protected void onDocked() { + super.onDocked(); + if (mCollapseOnDocked) { + mHoverView.collapse(); + mCollapseOnDocked = false; + } + } + @Override public HoverViewStateType getStateType() { return HoverViewStateType.PREVIEWED; From c85d82aae0c3e4aabdd0a9a26f4dde78a3c93a3d Mon Sep 17 00:00:00 2001 From: ybbarng Date: Fri, 12 Apr 2019 15:55:51 +0900 Subject: [PATCH 028/105] =?UTF-8?q?=EB=B6=88=ED=95=84=EC=9A=94=ED=95=98?= =?UTF-8?q?=EA=B2=8C=20=EB=9C=A8=EB=8A=94=20=EB=A1=9C=EA=B7=B8=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hover/src/main/java/io/mattcarroll/hover/TabMessageView.java | 1 - 1 file changed, 1 deletion(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java index c9537ff..f73c403 100644 --- a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java +++ b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java @@ -23,7 +23,6 @@ public class TabMessageView extends FrameLayout { private final FloatingTab.OnPositionChangeListener mOnTabPositionChangeListener = new FloatingTab.OnPositionChangeListener() { @Override public void onPositionChange(@NonNull Point position) { - Log.d(TAG, mFloatingTab + " tab moved to " + position); final float tabSizeHalf = mFloatingTab.getTabSize() / 2f; if (mSideDock != null && mSideDock.sidePosition().getSide() == SideDock.SidePosition.RIGHT) { setX(position.x - tabSizeHalf - getWidth()); From 26b0e9965720cf0f37f96351143e2fa9c02a59f1 Mon Sep 17 00:00:00 2001 From: ybbarng Date: Fri, 12 Apr 2019 16:29:03 +0900 Subject: [PATCH 029/105] =?UTF-8?q?=EB=B6=88=ED=95=84=EC=9A=94=ED=95=98?= =?UTF-8?q?=EA=B2=8C=20=EC=9C=84=EC=B9=98=20=EB=A1=9C=EA=B7=B8=EA=B0=80=20?= =?UTF-8?q?=EB=9C=A8=EA=B3=A0=20=EA=B3=84=EC=82=B0=EC=9D=84=20=EB=B0=98?= =?UTF-8?q?=EB=B3=B5=EC=A0=81=EC=9C=BC=EB=A1=9C=20=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=EC=9D=84=20=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit getWidth()가 0인 경우에는 아직 올바른 위치가 아니므로 실행하지 않고 이전과 다른 position, side (왼쪽, 오른쪽)이면 새로 그린다. --- .../hover/HoverViewStateCollapsed.java | 4 ++-- .../io/mattcarroll/hover/TabMessageView.java | 24 ++++++++++++++++--- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 59bd2d8..6fd4d03 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -33,9 +33,9 @@ * {@link HoverViewState} that operates the {@link HoverView} when it is collapsed. Collapsed means * that the only thing visible is the selected {@link FloatingTab}. This tab docks itself against * the left or right sides of the screen. The user can drag the tab around and drop it. - * + *

* If the tab is tapped, the {@code HoverView} is transitioned to its expanded state. - * + *

* If the tab is dropped on the exit region, the {@code HoverView} is transitioned to its closed state. */ class HoverViewStateCollapsed extends BaseHoverViewState { diff --git a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java index f73c403..438ce00 100644 --- a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java +++ b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java @@ -21,16 +21,27 @@ public class TabMessageView extends FrameLayout { private View mMessageView; private final FloatingTab.OnPositionChangeListener mOnTabPositionChangeListener = new FloatingTab.OnPositionChangeListener() { + private static final int DEFAULT_SIDE = SideDock.SidePosition.LEFT; + + private Point mLastPosition; + private int mLastSide; + @Override public void onPositionChange(@NonNull Point position) { + final Integer side = getSide(); + if (side.equals(mLastSide) && position.equals(mLastPosition) || getWidth() == 0) { + return; + } + Log.d(TAG, mFloatingTab + " tab moved to " + position); final float tabSizeHalf = mFloatingTab.getTabSize() / 2f; - if (mSideDock != null && mSideDock.sidePosition().getSide() == SideDock.SidePosition.RIGHT) { + if (side == SideDock.SidePosition.RIGHT) { setX(position.x - tabSizeHalf - getWidth()); - setY(position.y - tabSizeHalf); } else { setX(position.x + tabSizeHalf); - setY(position.y - tabSizeHalf); } + setY(position.y - tabSizeHalf); + mLastPosition = position; + mLastSide = side; } @Override @@ -42,6 +53,13 @@ public void onDockChange(@NonNull Dock dock) { } } } + + private int getSide() { + if (mSideDock != null) { + return mSideDock.sidePosition().getSide(); + } + return DEFAULT_SIDE; + } }; public TabMessageView(@NonNull Context context, @NonNull FloatingTab floatingTab) { From b6654a05a0e593dfe7419f421b46b3852689945e Mon Sep 17 00:00:00 2001 From: ybbarng Date: Mon, 15 Apr 2019 11:14:52 +0900 Subject: [PATCH 030/105] =?UTF-8?q?collapse=20animation=EC=9D=80=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=ED=95=98=EB=8A=94=20=EB=B6=80=EB=B6=84?= =?UTF-8?q?=EC=9D=84=20=EC=A1=B0=EA=B8=88=20=EB=8D=94=20=EC=83=81=EC=84=B8?= =?UTF-8?q?=ED=95=98=EA=B2=8C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/mattcarroll/hover/HoverViewStatePreviewed.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index 5a1b105..597b302 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -32,6 +32,7 @@ class HoverViewStatePreviewed extends HoverViewStateCollapsed { private static final String TAG = "HoverViewStatePreviewed"; private TabMessageView mMessageView; private boolean mCollapseOnDocked = false; + private boolean mTurnOffNextCollapseAnimation = false; @Override public void takeControl(@NonNull HoverView hoverView, final Runnable onStateChanged) { @@ -53,8 +54,9 @@ public void run() { @Override public void giveUpControl(@NonNull final HoverViewState nextState) { Log.d(TAG, "Giving up control."); - if (nextState instanceof HoverViewStateCollapsed && !mCollapseOnDocked) { - mMessageView.disappear(true); + if (nextState instanceof HoverViewStateCollapsed) { + mMessageView.disappear(!mTurnOffNextCollapseAnimation); + mTurnOffNextCollapseAnimation = false; } else { mMessageView.disappear(false); } @@ -96,6 +98,7 @@ protected void activateDragger() { protected void onDocked() { super.onDocked(); if (mCollapseOnDocked) { + mTurnOffNextCollapseAnimation = true; mHoverView.collapse(); mCollapseOnDocked = false; } From 588648a2378a3560d473e8476263b12603a57a41 Mon Sep 17 00:00:00 2001 From: ybbarng Date: Mon, 15 Apr 2019 12:00:34 +0900 Subject: [PATCH 031/105] =?UTF-8?q?animation=20=EC=83=81=ED=83=9C=EB=A5=BC?= =?UTF-8?q?=20=EB=8B=A4=EB=A3=A8=EB=8A=94=20=EB=B3=80=EC=88=98=20=EB=8C=80?= =?UTF-8?q?=EC=8B=A0=EC=97=90=20=EC=95=88=EC=A0=84=ED=95=98=EA=B2=8C=20vis?= =?UTF-8?q?ibility=EB=A1=9C=20=EC=95=A0=EB=8B=88=EB=A9=94=EC=9D=B4?= =?UTF-8?q?=EC=85=98=20=EC=A0=81=EC=9A=A9=20=EC=97=AC=EB=B6=80=EB=A5=BC=20?= =?UTF-8?q?=EC=B2=B4=ED=81=AC=20=ED=95=98=EB=8F=84=EB=A1=9D=20=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/mattcarroll/hover/HoverViewStatePreviewed.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index 597b302..c7f40a0 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -32,7 +32,6 @@ class HoverViewStatePreviewed extends HoverViewStateCollapsed { private static final String TAG = "HoverViewStatePreviewed"; private TabMessageView mMessageView; private boolean mCollapseOnDocked = false; - private boolean mTurnOffNextCollapseAnimation = false; @Override public void takeControl(@NonNull HoverView hoverView, final Runnable onStateChanged) { @@ -54,9 +53,9 @@ public void run() { @Override public void giveUpControl(@NonNull final HoverViewState nextState) { Log.d(TAG, "Giving up control."); - if (nextState instanceof HoverViewStateCollapsed) { - mMessageView.disappear(!mTurnOffNextCollapseAnimation); - mTurnOffNextCollapseAnimation = false; + if (nextState instanceof HoverViewStateCollapsed + && mMessageView.getVisibility() == View.VISIBLE) { + mMessageView.disappear(true); } else { mMessageView.disappear(false); } @@ -98,7 +97,6 @@ protected void activateDragger() { protected void onDocked() { super.onDocked(); if (mCollapseOnDocked) { - mTurnOffNextCollapseAnimation = true; mHoverView.collapse(); mCollapseOnDocked = false; } From 88c5ae840d7873ff7022820910cbf7174349ca05 Mon Sep 17 00:00:00 2001 From: ybbarng Date: Mon, 15 Apr 2019 12:02:43 +0900 Subject: [PATCH 032/105] =?UTF-8?q?View=EC=97=90=EC=84=9C=20=EC=95=8C?= =?UTF-8?q?=EC=95=84=EC=84=9C=20Visibility=EC=97=90=20=EB=94=B0=EB=9D=BC?= =?UTF-8?q?=20=EC=95=A0=EB=8B=88=EB=A9=94=EC=9D=B4=EC=85=98=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=20=EC=97=AC=EB=B6=80=EB=A5=BC=20=EA=B2=B0=EC=A0=95?= =?UTF-8?q?=ED=95=98=EA=B2=8C=20=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hover/HoverViewStatePreviewed.java | 3 +- .../io/mattcarroll/hover/TabMessageView.java | 54 ++++++++++--------- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index c7f40a0..9af7e96 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -53,8 +53,7 @@ public void run() { @Override public void giveUpControl(@NonNull final HoverViewState nextState) { Log.d(TAG, "Giving up control."); - if (nextState instanceof HoverViewStateCollapsed - && mMessageView.getVisibility() == View.VISIBLE) { + if (nextState instanceof HoverViewStateCollapsed) { mMessageView.disappear(true); } else { mMessageView.disappear(false); diff --git a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java index 438ce00..8e01e3f 100644 --- a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java +++ b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java @@ -84,40 +84,42 @@ public void setMessageView(@Nullable View view) { public void appear(final SideDock dock, @Nullable final Runnable onAppeared) { mSideDock = dock; mFloatingTab.addOnPositionChangeListener(mOnTabPositionChangeListener); - final AnimationSet animation = new AnimationSet(true); - final AlphaAnimation alpha = new AlphaAnimation(0, 1); - final float fromXDelta = getResources().getDimensionPixelSize(R.dimen.hover_message_animate_translation_x) - * (dock.sidePosition().getSide() == SideDock.SidePosition.LEFT ? -1 : 1); - final float fromYDelta = getResources().getDimensionPixelSize(R.dimen.hover_message_animate_translation_y); - TranslateAnimation translate = new TranslateAnimation(fromXDelta, 0, fromYDelta, 0); - animation.setDuration(300); - animation.setInterpolator(new LinearOutSlowInInterpolator()); - animation.addAnimation(alpha); - animation.addAnimation(translate); - animation.setAnimationListener(new Animation.AnimationListener() { - @Override - public void onAnimationStart(Animation animation) { - } + if (getVisibility() != View.VISIBLE) { + final AnimationSet animation = new AnimationSet(true); + final AlphaAnimation alpha = new AlphaAnimation(0, 1); + final float fromXDelta = getResources().getDimensionPixelSize(R.dimen.hover_message_animate_translation_x) + * (dock.sidePosition().getSide() == SideDock.SidePosition.LEFT ? -1 : 1); + final float fromYDelta = getResources().getDimensionPixelSize(R.dimen.hover_message_animate_translation_y); + TranslateAnimation translate = new TranslateAnimation(fromXDelta, 0, fromYDelta, 0); + animation.setDuration(300); + animation.setInterpolator(new LinearOutSlowInInterpolator()); + animation.addAnimation(alpha); + animation.addAnimation(translate); + animation.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + } - @Override - public void onAnimationEnd(Animation animation) { - if (onAppeared != null) { - onAppeared.run(); + @Override + public void onAnimationEnd(Animation animation) { + if (onAppeared != null) { + onAppeared.run(); + } } - } - @Override - public void onAnimationRepeat(Animation animation) { - } - }); - startAnimation(animation); - setVisibility(VISIBLE); + @Override + public void onAnimationRepeat(Animation animation) { + } + }); + startAnimation(animation); + setVisibility(VISIBLE); + } } public void disappear(final boolean withAnimation) { mFloatingTab.removeOnPositionChangeListener(mOnTabPositionChangeListener); mSideDock = null; - if (withAnimation) { + if (withAnimation && getVisibility() == View.VISIBLE) { final AnimationSet animation = new AnimationSet(true); final AlphaAnimation alpha = new AlphaAnimation(1, 0); alpha.setDuration(300); From d82ae05c7001dac21eb24c1430b1cd6cc899071c Mon Sep 17 00:00:00 2001 From: ybbarng Date: Mon, 15 Apr 2019 12:03:03 +0900 Subject: [PATCH 033/105] =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=EA=B0=80=20?= =?UTF-8?q?Drop=ED=95=9C=20=EA=B2=BD=EC=9A=B0=20=EB=B3=80=EC=88=98=20?= =?UTF-8?q?=EC=B4=88=EA=B8=B0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/mattcarroll/hover/HoverViewStateCollapsed.java | 2 +- .../java/io/mattcarroll/hover/HoverViewStatePreviewed.java | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 6fd4d03..f2be9a9 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -201,7 +201,7 @@ protected void onPickedUpByUser() { mHoverView.notifyOnDragStart(this); } - private void onDroppedByUser() { + protected void onDroppedByUser() { mHoverView.mScreen.getExitView().setVisibility(GONE); boolean droppedOnExit = mHoverView.mScreen.getExitView().isInExitZone(mFloatingTab.getPosition()); if (droppedOnExit) { diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index 9af7e96..8979e85 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -84,6 +84,12 @@ protected void onPickedUpByUser() { super.onPickedUpByUser(); } + @Override + protected void onDroppedByUser() { + mCollapseOnDocked = false; + super.onDroppedByUser(); + } + @Override protected void activateDragger() { final ArrayList list = new ArrayList<>(); From 64edd367641f44389ff52fbdb5f1117818dee0c4 Mon Sep 17 00:00:00 2001 From: ybbarng Date: Mon, 15 Apr 2019 12:04:53 +0900 Subject: [PATCH 034/105] =?UTF-8?q?=EC=B4=88=EA=B8=B0=ED=99=94=ED=95=9C?= =?UTF-8?q?=EB=8B=A4=EB=8A=94=20=EC=9D=98=EB=AF=B8=EB=A5=BC=20=EC=82=B4?= =?UTF-8?q?=EB=A0=A4=EC=84=9C=20init()=EC=9D=B4=EB=9D=BC=EB=8A=94=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/mattcarroll/hover/HoverViewStatePreviewed.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index 8979e85..683d4d0 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -33,6 +33,10 @@ class HoverViewStatePreviewed extends HoverViewStateCollapsed { private TabMessageView mMessageView; private boolean mCollapseOnDocked = false; + HoverViewStatePreviewed() { + init(); + } + @Override public void takeControl(@NonNull HoverView hoverView, final Runnable onStateChanged) { super.takeControl(hoverView, null); @@ -86,7 +90,7 @@ protected void onPickedUpByUser() { @Override protected void onDroppedByUser() { - mCollapseOnDocked = false; + init(); super.onDroppedByUser(); } @@ -111,4 +115,8 @@ protected void onDocked() { public HoverViewStateType getStateType() { return HoverViewStateType.PREVIEWED; } + + private void init() { + mCollapseOnDocked = false; + } } From 956c51ad5fd1faf9f48f8dbfceded72f57f2c2c6 Mon Sep 17 00:00:00 2001 From: ybbarng Date: Mon, 15 Apr 2019 12:30:41 +0900 Subject: [PATCH 035/105] =?UTF-8?q?Pop=EC=9D=84=20=EB=86=93=EB=8A=94=20?= =?UTF-8?q?=EA=B2=BD=EC=9A=B0=EA=B0=80=20=EC=95=84=EB=8B=88=EB=9D=BC=20?= =?UTF-8?q?=EB=B2=84=EB=A6=AC=EB=8A=94=20=EA=B2=BD=EC=9A=B0=EC=97=90=20ini?= =?UTF-8?q?t()=EC=9D=84=20=ED=98=B8=EC=B6=9C=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hover/HoverViewStateCollapsed.java | 16 ++++++++++++---- .../hover/HoverViewStatePreviewed.java | 4 ++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index f2be9a9..a9435bd 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -60,7 +60,7 @@ public void run() { if (mHoverView.shouldKeepVisible()) { mHoverView.setAlpha(ALPHA_IDLE_VALUE); } else { - mHoverView.close(); + onClose(false); } } } @@ -201,12 +201,11 @@ protected void onPickedUpByUser() { mHoverView.notifyOnDragStart(this); } - protected void onDroppedByUser() { + private void onDroppedByUser() { mHoverView.mScreen.getExitView().setVisibility(GONE); boolean droppedOnExit = mHoverView.mScreen.getExitView().isInExitZone(mFloatingTab.getPosition()); if (droppedOnExit) { - Log.d(TAG, "User dropped floating tab on exit."); - mHoverView.close(); + onClose(true); } else { int tabSize = mHoverView.getResources().getDimensionPixelSize(R.dimen.hover_tab_size); Point screenSize = mHoverView.getScreenSize(); @@ -235,6 +234,15 @@ protected void onDroppedByUser() { } } + protected void onClose(final boolean userDropped) { + if (userDropped) { + Log.d(TAG, "User dropped floating tab on exit."); + } else { + Log.d(TAG, "Auto dropped."); + } + mHoverView.close(); + } + private void onTap() { Log.d(TAG, "Floating tab was tapped."); if (mHoverView != null) { diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index 683d4d0..323ed7f 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -89,9 +89,9 @@ protected void onPickedUpByUser() { } @Override - protected void onDroppedByUser() { + protected void onClose(final boolean userDropped) { + super.onClose(userDropped); init(); - super.onDroppedByUser(); } @Override From a6710e73a4930dc83067d93b0f274b9b77ca3592 Mon Sep 17 00:00:00 2001 From: ybbarng Date: Mon, 15 Apr 2019 12:44:35 +0900 Subject: [PATCH 036/105] =?UTF-8?q?Pop=EA=B3=BC=20Preview=EC=9D=98=20drag?= =?UTF-8?q?=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=EB=A5=BC=20=EC=84=9C=EB=A1=9C=20?= =?UTF-8?q?=EB=8B=A4=EB=A5=B4=EA=B2=8C=20=EA=B5=AC=EB=B6=84=ED=95=98?= =?UTF-8?q?=EA=B3=A0=20=EB=94=B0=EB=A1=9C=20=EC=B2=98=EB=A6=AC=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hover/BaseTouchController.java | 139 +++++++++------ .../java/io/mattcarroll/hover/Dragger.java | 160 ++++++++---------- .../hover/HoverViewStateCollapsed.java | 29 ++-- .../hover/HoverViewStatePreviewed.java | 59 ++++--- .../io/mattcarroll/hover/TabMessageView.java | 5 + 5 files changed, 219 insertions(+), 173 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java b/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java index 8559463..6787a5f 100644 --- a/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java +++ b/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java @@ -3,6 +3,7 @@ import android.graphics.PointF; import android.graphics.Rect; import android.support.annotation.NonNull; +import android.support.v4.util.Pair; import android.util.Log; import android.view.MotionEvent; import android.view.View; @@ -14,34 +15,14 @@ public abstract class BaseTouchController { private static final String TAG = "BaseTouchController"; - protected Map mTouchViewMap = new HashMap<>(); - protected TouchListener mTouchListener; + protected Map mTouchViewMap = new HashMap<>(); protected boolean mIsActivated; private boolean mIsDebugMode; - private List mViewList; - - private View.OnTouchListener mDragTouchListener = new View.OnTouchListener() { - @Override - public boolean onTouch(View view, MotionEvent motionEvent) { - switch (motionEvent.getAction()) { - case MotionEvent.ACTION_DOWN: - Log.d(TAG, "ACTION_DOWN"); - mTouchListener.onPress(); - return true; - case MotionEvent.ACTION_UP: - Log.d(TAG, "ACTION_UP"); - mTouchListener.onTap(); - return true; - default: - return false; - } - } - }; private final View.OnLayoutChangeListener mOnLayoutChangeListener = new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View view, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { - moveTouchViewTo(mTouchViewMap.get(view.getTag()), new PointF(view.getX(), view.getY())); + moveTouchViewTo(mTouchViewMap.get(view.getTag()).mTouchView, new PointF(view.getX(), view.getY())); } }; @@ -51,25 +32,17 @@ public void onLayoutChange(View view, int left, int top, int right, int bottom, public abstract void moveTouchViewTo(@NonNull View touchView, @NonNull PointF position); - public void activate(@NonNull TouchListener touchListener, @NonNull List viewList) { + public void activate(final List> viewList) { if (!mIsActivated) { Log.d(TAG, "Activating."); mIsActivated = true; - mTouchListener = touchListener; - mViewList = viewList; - mTouchViewMap.clear(); - for (int i = 0; i < mViewList.size(); i++) { - View view = mViewList.get(i); - String tag = "view" + i; - view.setTag(tag); - Rect rect = new Rect(); - view.getDrawingRect(rect); - View touchView = createTouchView(rect); - moveTouchViewTo(touchView, new PointF(view.getX(), view.getY())); - touchView.setOnTouchListener(mDragTouchListener); - touchView.setTag(tag); - mTouchViewMap.put(tag, touchView); - view.addOnLayoutChangeListener(mOnLayoutChangeListener); + + clearTouchViewMap(); + for (int i = 0; i < viewList.size(); i++) { + final Pair viewItem = viewList.get(i); + final String tag = "view" + i; + final TouchViewItem touchViewItem = createTouchViewItem(viewItem.first, viewItem.second, tag); + mTouchViewMap.put(tag, touchViewItem); } updateTouchControlViewAppearance(); } @@ -78,19 +51,8 @@ public void activate(@NonNull TouchListener touchListener, @NonNull List v public void deactivate() { if (mIsActivated) { Log.d(TAG, "Deactivating."); - for (View view : mViewList) { - view.setOnTouchListener(null); - view.removeOnLayoutChangeListener(mOnLayoutChangeListener); - } - - for (View touchView : mTouchViewMap.values()) { - destroyTouchView(touchView); - } - + clearTouchViewMap(); mIsActivated = false; - mTouchViewMap.clear(); - mViewList = null; - mTouchListener = null; } } @@ -99,8 +61,34 @@ public void enableDebugMode(boolean isDebugMode) { updateTouchControlViewAppearance(); } + private TouchViewItem createTouchViewItem(final View originalView, final TouchListener listener, final String tag) { + originalView.setTag(tag); + + Rect rect = new Rect(); + originalView.getDrawingRect(rect); + View touchView = createTouchView(rect); + moveTouchViewTo(touchView, new PointF(originalView.getX(), originalView.getY())); + touchView.setTag(tag); + final TouchViewItem touchViewItem = new TouchViewItem<>(originalView, touchView, listener); + setEventListener(touchViewItem); + originalView.addOnLayoutChangeListener(mOnLayoutChangeListener); + return touchViewItem; + } + + protected void setEventListener(final TouchViewItem touchViewItem) { + touchViewItem.mTouchView.setOnTouchListener(new TouchDetector<>(touchViewItem.mOriginalView, touchViewItem.mTouchListener)); + } + + private void clearTouchViewMap() { + for (final TouchViewItem touchViewItem : mTouchViewMap.values()) { + touchViewItem.destroy(); + } + mTouchViewMap.clear(); + } + private void updateTouchControlViewAppearance() { - for (View touchView : mTouchViewMap.values()) { + for (final TouchViewItem touchViewItemItem : mTouchViewMap.values()) { + final View touchView = touchViewItemItem.mTouchView; if (null != touchView) { if (mIsDebugMode) { touchView.setBackgroundColor(0x44FF0000); @@ -112,8 +100,53 @@ private void updateTouchControlViewAppearance() { } public interface TouchListener { - void onPress(); + void onPress(View view); + + void onTap(View view); + } + + protected class TouchDetector implements View.OnTouchListener { + + protected final View mOriginalView; + protected final T mEventListener; + + TouchDetector(final View originalView, final T touchListener) { + this.mOriginalView = originalView; + this.mEventListener = touchListener; + } + + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + switch (motionEvent.getAction()) { + case MotionEvent.ACTION_DOWN: + Log.d(TAG, "ACTION_DOWN"); + mEventListener.onPress(mOriginalView); + return true; + case MotionEvent.ACTION_UP: + Log.d(TAG, "ACTION_UP"); + mEventListener.onTap(mOriginalView); + return true; + default: + return false; + } + } + } + + protected class TouchViewItem { + final View mOriginalView; + final View mTouchView; + final T mTouchListener; - void onTap(); + TouchViewItem(final View originalView, final View touchView, final T touchListener) { + this.mOriginalView = originalView; + this.mTouchView = touchView; + this.mTouchListener = touchListener; + } + + void destroy() { + mOriginalView.setOnTouchListener(null); + mOriginalView.removeOnLayoutChangeListener(mOnLayoutChangeListener); + destroyTouchView(mTouchView); + } } } diff --git a/hover/src/main/java/io/mattcarroll/hover/Dragger.java b/hover/src/main/java/io/mattcarroll/hover/Dragger.java index c3c89f1..58af2ab 100644 --- a/hover/src/main/java/io/mattcarroll/hover/Dragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/Dragger.java @@ -22,8 +22,6 @@ import android.view.MotionEvent; import android.view.View; -import java.util.List; - /** * Reports user drag behavior on the screen to a {@link DragListener}. */ @@ -31,69 +29,6 @@ public abstract class Dragger extends BaseTouchController { private static final String TAG = "Dragger"; private final int mTapTouchSlop; - private DragListener mDragListener; - private boolean mIsDragging; - - private PointF mOriginalViewPosition = new PointF(); - private PointF mCurrentViewPosition = new PointF(); - private PointF mOriginalTouchPosition = new PointF(); - - protected final View.OnTouchListener mDragTouchListener = new View.OnTouchListener() { - @Override - public boolean onTouch(View view, MotionEvent motionEvent) { - switch (motionEvent.getAction()) { - case MotionEvent.ACTION_DOWN: - Log.d(TAG, "ACTION_DOWN"); - mIsDragging = false; - - mOriginalViewPosition = convertCornerToCenter(view, getTouchViewPosition(view)); - mCurrentViewPosition = new PointF(mOriginalViewPosition.x, mOriginalViewPosition.y); - mOriginalTouchPosition.set(motionEvent.getRawX(), motionEvent.getRawY()); - if (mTouchListener != null) { - mTouchListener.onPress(); - } - return true; - case MotionEvent.ACTION_MOVE: - if (mDragListener == null) { - return false; - } - Log.d(TAG, "ACTION_MOVE. motionX: " + motionEvent.getRawX() + ", motionY: " + motionEvent.getRawY()); - float dragDeltaX = motionEvent.getRawX() - mOriginalTouchPosition.x; - float dragDeltaY = motionEvent.getRawY() - mOriginalTouchPosition.y; - mCurrentViewPosition = new PointF( - mOriginalViewPosition.x + dragDeltaX, - mOriginalViewPosition.y + dragDeltaY - ); - - if (mIsDragging || !isTouchWithinSlopOfOriginalTouch(dragDeltaX, dragDeltaY)) { - if (!mIsDragging) { - // Dragging just started - Log.d(TAG, "MOVE Start Drag."); - mIsDragging = true; - mDragListener.onDragStart(view, mCurrentViewPosition.x, mCurrentViewPosition.y); - } else { - mDragListener.onDragTo(view, mCurrentViewPosition.x, mCurrentViewPosition.y); - } - } - - return true; - case MotionEvent.ACTION_UP: - Log.d(TAG, "ACTION_UP"); - if (!mIsDragging) { - Log.d(TAG, "Reporting as a tap."); - if (mTouchListener != null) { - mTouchListener.onTap(); - } - } else if (mDragListener != null) { - Log.d(TAG, "Reporting as a drag release at: " + mCurrentViewPosition); - mDragListener.onReleasedAt(view, mCurrentViewPosition.x, mCurrentViewPosition.y); - } - return true; - default: - return false; - } - } - }; public Dragger(int mTapTouchSlop) { this.mTapTouchSlop = mTapTouchSlop; @@ -103,22 +38,9 @@ public Dragger(int mTapTouchSlop) { public abstract Point getContainerSize(); - public void activate(@NonNull DragListener dragListener, @NonNull List viewList) { - if (!mIsActivated) { - super.activate(dragListener, viewList); - mDragListener = dragListener; - for (View touchView : mTouchViewMap.values()) { - touchView.setOnTouchListener(mDragTouchListener); - } - } - } - @Override - public void deactivate() { - if (mIsActivated) { - super.deactivate(); - mDragListener = null; - } + protected void setEventListener(final TouchViewItem touchViewItem) { + touchViewItem.mTouchView.setOnTouchListener(new DragDetector(touchViewItem.mOriginalView, (DragListener) touchViewItem.mTouchListener)); } private boolean isTouchWithinSlopOfOriginalTouch(float dx, float dy) { @@ -146,8 +68,8 @@ public interface DragListener extends TouchListener { * The user has begun dragging. * * @param view the view that is being dragged - * @param x x-coordinate of the user's drag start (in the parent View's coordinate space) - * @param y y-coordiante of the user's drag start (in the parent View's coordinate space) + * @param x x-coordinate of the user's drag start (in the parent View's coordinate space) + * @param y y-coordiante of the user's drag start (in the parent View's coordinate space) */ void onDragStart(View view, float x, float y); @@ -155,8 +77,8 @@ public interface DragListener extends TouchListener { * The user has dragged to the given coordinates. * * @param view the view that is being dragged - * @param x x-coordinate of the user's drag (in the parent View's coordinate space) - * @param y y-coordiante of the user's drag (in the parent View's coordinate space) + * @param x x-coordinate of the user's drag (in the parent View's coordinate space) + * @param y y-coordiante of the user's drag (in the parent View's coordinate space) */ void onDragTo(View view, float x, float y); @@ -164,9 +86,75 @@ public interface DragListener extends TouchListener { * The user has stopped touching the drag area. * * @param view the view that is being dragged - * @param x x-coordinate of the user's release (in the parent View's coordinate space) - * @param y y-coordiante of the user's release (in the parent View's coordinate space) + * @param x x-coordinate of the user's release (in the parent View's coordinate space) + * @param y y-coordiante of the user's release (in the parent View's coordinate space) */ void onReleasedAt(View view, float x, float y); } + + private class DragDetector extends TouchDetector { + private boolean mIsDragging; + private PointF mOriginalViewPosition = new PointF(); + private PointF mCurrentViewPosition = new PointF(); + private PointF mOriginalTouchPosition = new PointF(); + + public DragDetector(final View originalView, final DragListener dragListener) { + super(originalView, dragListener); + } + + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + switch (motionEvent.getAction()) { + case MotionEvent.ACTION_DOWN: + Log.d(TAG, "ACTION_DOWN"); + mIsDragging = false; + + mOriginalViewPosition = convertCornerToCenter(view, getTouchViewPosition(view)); + mCurrentViewPosition = new PointF(mOriginalViewPosition.x, mOriginalViewPosition.y); + mOriginalTouchPosition.set(motionEvent.getRawX(), motionEvent.getRawY()); + if (mEventListener != null) { + mEventListener.onPress(mOriginalView); + } + return true; + case MotionEvent.ACTION_MOVE: + if (mEventListener == null) { + return false; + } + Log.d(TAG, "ACTION_MOVE. motionX: " + motionEvent.getRawX() + ", motionY: " + motionEvent.getRawY()); + float dragDeltaX = motionEvent.getRawX() - mOriginalTouchPosition.x; + float dragDeltaY = motionEvent.getRawY() - mOriginalTouchPosition.y; + mCurrentViewPosition = new PointF( + mOriginalViewPosition.x + dragDeltaX, + mOriginalViewPosition.y + dragDeltaY + ); + + if (mIsDragging || !isTouchWithinSlopOfOriginalTouch(dragDeltaX, dragDeltaY)) { + if (!mIsDragging) { + // Dragging just started + Log.d(TAG, "MOVE Start Drag."); + mIsDragging = true; + mEventListener.onDragStart(mOriginalView, mCurrentViewPosition.x, mCurrentViewPosition.y); + } else { + mEventListener.onDragTo(mOriginalView, mCurrentViewPosition.x, mCurrentViewPosition.y); + } + } + + return true; + case MotionEvent.ACTION_UP: + Log.d(TAG, "ACTION_UP"); + if (!mIsDragging) { + Log.d(TAG, "Reporting as a tap."); + if (mEventListener != null) { + mEventListener.onTap(mOriginalView); + } + } else if (mEventListener != null) { + Log.d(TAG, "Reporting as a drag release at: " + mCurrentViewPosition); + mEventListener.onReleasedAt(mOriginalView, mCurrentViewPosition.x, mCurrentViewPosition.y); + } + return true; + default: + return false; + } + } + } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index a9435bd..774875a 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -19,6 +19,7 @@ import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v4.util.Pair; import android.support.v7.util.ListUpdateCallback; import android.util.Log; import android.view.View; @@ -47,7 +48,7 @@ class HoverViewStateCollapsed extends BaseHoverViewState { private static final float ALPHA_IDLE_VALUE = 0.4f; protected FloatingTab mFloatingTab; - protected final Dragger.DragListener mDragListener = new FloatingTabDragListener(this); + protected final Dragger.DragListener mFloatingTabDragListener = new FloatingTabDragListener(this); protected HoverMenu.Section mSelectedSection; private int mSelectedSectionIndex = -1; private boolean mIsCollapsed = false; @@ -68,8 +69,8 @@ public void run() { private Runnable mOnStateChanged; @Override - public void takeControl(@NonNull HoverView hoverView, final Runnable onStateChanged) { - super.takeControl(hoverView, onStateChanged); + public void takeControl(@NonNull HoverView floatingTab, final Runnable onStateChanged) { + super.takeControl(floatingTab, onStateChanged); Log.d(TAG, "Taking control."); mOnStateChanged = onStateChanged; mHoverView.makeUntouchableInWindow(); @@ -243,7 +244,7 @@ protected void onClose(final boolean userDropped) { mHoverView.close(); } - private void onTap() { + protected void onTap() { Log.d(TAG, "Floating tab was tapped."); if (mHoverView != null) { mHoverView.notifyOnTap(this); @@ -305,14 +306,14 @@ protected void onDocked() { mHoverView.notifyOnDocked(this); } - protected void moveTabTo(View touchView, @NonNull Point position) { + void moveFloatingTabTo(View floatingTab, @NonNull Point position) { mFloatingTab.moveTo(position); } protected void activateDragger() { - ArrayList list = new ArrayList<>(); - list.add(mFloatingTab); - mHoverView.mDragger.activate(mDragListener, list); + ArrayList> list = new ArrayList<>(); + list.add(new Pair<>(mFloatingTab, mFloatingTabDragListener)); + mHoverView.mDragger.activate(list); } protected void deactivateDragger() { @@ -342,26 +343,26 @@ protected FloatingTabDragListener(@NonNull HoverViewStateCollapsed owner) { } @Override - public void onDragStart(View touchView, float x, float y) { + public void onDragStart(View floatingTab, float x, float y) { mOwner.onPickedUpByUser(); } @Override - public void onDragTo(View touchView, float x, float y) { - mOwner.moveTabTo(touchView, new Point((int) x, (int) y)); + public void onDragTo(View floatingTab, float x, float y) { + mOwner.moveFloatingTabTo(floatingTab, new Point((int) x, (int) y)); } @Override - public void onReleasedAt(View touchView, float x, float y) { + public void onReleasedAt(View floatingTab, float x, float y) { mOwner.onDroppedByUser(); } @Override - public void onPress() { + public void onPress(View floatingTab) { } @Override - public void onTap() { + public void onTap(View floatingTab) { mOwner.onTap(); } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index 323ed7f..d1b8b29 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -17,6 +17,7 @@ import android.graphics.Point; import android.support.annotation.NonNull; +import android.support.v4.util.Pair; import android.util.Log; import android.view.View; @@ -31,6 +32,7 @@ class HoverViewStatePreviewed extends HoverViewStateCollapsed { private static final String TAG = "HoverViewStatePreviewed"; private TabMessageView mMessageView; + protected final Dragger.DragListener mMessageViewDragListener = new MessageViewDragListener(this); private boolean mCollapseOnDocked = false; HoverViewStatePreviewed() { @@ -65,22 +67,6 @@ public void giveUpControl(@NonNull final HoverViewState nextState) { super.giveUpControl(nextState); } - @Override - protected void moveTabTo(View touchView, @NonNull Point position) { - if (mHoverView == null) { - return; - } - - final int floatingTabOffset = mMessageView.getWidth() / 2; - if (touchView.getTag() != null && touchView.getTag().equals(mFloatingTab.getTag())) { - mFloatingTab.moveTo(position); - } else if (mHoverView.mCollapsedDock.sidePosition().getSide() == SideDock.SidePosition.RIGHT) { - mFloatingTab.moveTo(new Point(position.x + floatingTabOffset, position.y)); - } else { - mFloatingTab.moveTo(new Point(position.x - floatingTabOffset, position.y)); - } - } - @Override protected void onPickedUpByUser() { mMessageView.disappear(true); @@ -96,10 +82,10 @@ protected void onClose(final boolean userDropped) { @Override protected void activateDragger() { - final ArrayList list = new ArrayList<>(); - list.add(mFloatingTab); - list.add(mMessageView); - mHoverView.mDragger.activate(mDragListener, list); + ArrayList> list = new ArrayList<>(); + list.add(new Pair<>(mFloatingTab, mFloatingTabDragListener)); + list.add(new Pair<>(mMessageView, mMessageViewDragListener)); + mHoverView.mDragger.activate(list); } @Override @@ -119,4 +105,37 @@ public HoverViewStateType getStateType() { private void init() { mCollapseOnDocked = false; } + + protected static final class MessageViewDragListener implements Dragger.DragListener { + + private final HoverViewStateCollapsed mOwner; + + protected MessageViewDragListener(@NonNull HoverViewStateCollapsed owner) { + mOwner = owner; + } + + @Override + public void onDragStart(View messageView, float x, float y) { + } + + @Override + public void onDragTo(View messageView, float x, float y) { + if (messageView instanceof TabMessageView) { + ((TabMessageView) messageView).moveTo(new Point((int) x, (int) y)); + } + } + + @Override + public void onReleasedAt(View messageView, float x, float y) { + } + + @Override + public void onPress(View messageView) { + } + + @Override + public void onTap(View messageView) { + mOwner.onTap(); + } + } } diff --git a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java index 8e01e3f..fd230da 100644 --- a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java +++ b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java @@ -128,4 +128,9 @@ public void disappear(final boolean withAnimation) { } setVisibility(GONE); } + + public void moveTo(@NonNull Point newPosition) { + setX(newPosition.x); + setY(newPosition.y); + } } From cb06f0a73e19e2ee355103de83fd765cee92b696 Mon Sep 17 00:00:00 2001 From: ybbarng Date: Mon, 15 Apr 2019 15:23:42 +0900 Subject: [PATCH 037/105] =?UTF-8?q?=ED=95=A8=EC=88=98=EC=9D=98=20=EC=8B=A4?= =?UTF-8?q?=EC=A0=9C=20=EB=8F=99=EC=9E=91=EC=97=90=20=EB=A7=9E=EA=B2=8C=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hover/src/main/java/io/mattcarroll/hover/FloatingTab.java | 8 ++++---- .../io/mattcarroll/hover/HoverViewStateCollapsed.java | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java index 2014cd3..101ef5d 100644 --- a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java +++ b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java @@ -94,7 +94,7 @@ private void updateSize() { protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (mDock != null) { - moveTo(mDock.position()); + moveCenterTo(mDock.position()); } } @@ -287,11 +287,11 @@ public void onAnimationUpdate(ValueAnimator animation) { } public void dockImmediately() { - moveTo(mDock.position()); + moveCenterTo(mDock.position()); } - public void moveTo(@NonNull Point floatPosition) { - Point cornerPosition = convertCenterToCorner(floatPosition); + public void moveCenterTo(@NonNull Point centerPosition) { + Point cornerPosition = convertCenterToCorner(centerPosition); setX(cornerPosition.x); setY(cornerPosition.y); notifyListenersOfPositionChange(); diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 774875a..6a5ecb0 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -272,7 +272,7 @@ private void moveToDock() { mHoverView.getScreenSize(), mFloatingTab.getTabSize() ); - mFloatingTab.moveTo(dockPosition); + mFloatingTab.moveCenterTo(dockPosition); } private void initDockPosition() { @@ -307,7 +307,7 @@ protected void onDocked() { } void moveFloatingTabTo(View floatingTab, @NonNull Point position) { - mFloatingTab.moveTo(position); + mFloatingTab.moveCenterTo(position); } protected void activateDragger() { From baede9b0eaa5fa820090671ee50857afe9680457 Mon Sep 17 00:00:00 2001 From: ybbarng Date: Mon, 15 Apr 2019 18:24:00 +0900 Subject: [PATCH 038/105] =?UTF-8?q?onLayoutChangeListener=20=EB=8C=80?= =?UTF-8?q?=EC=8B=A0=EC=97=90=20onPositionChangeListener=EB=A5=BC=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit View에 애니메이션을 위해 setX(), setY()를 사용하는 경우 onLayoutChangeListener()가 불리지 않기 때문에, 이것에 의존해서 touchView가 원본 View를 추적하게 하는 것은 오작동의 우려가 있다. 따라서 onPositionChangeListener를 커스텀으로 만들어서 애니메이션 등으로 변경이 되었을 때 빠르게 업데이트가 가능하게 변경하였다. 이를 위해 삭제되었던 HoverFrameLayout을 다시 살리고 약간 수정하였다. --- .../hover/BaseTouchController.java | 53 ++++++++------ .../io/mattcarroll/hover/ContentDisplay.java | 8 +-- .../java/io/mattcarroll/hover/Dragger.java | 8 ++- .../io/mattcarroll/hover/FloatingTab.java | 66 ++++++----------- .../mattcarroll/hover/HoverFrameLayout.java | 72 +++++++++++++++++++ .../hover/HoverViewStateCollapsed.java | 2 +- .../hover/HoverViewStatePreviewed.java | 21 +++++- .../java/io/mattcarroll/hover/TabChain.java | 8 +-- .../io/mattcarroll/hover/TabMessageView.java | 30 +++++--- 9 files changed, 176 insertions(+), 92 deletions(-) create mode 100644 hover/src/main/java/io/mattcarroll/hover/HoverFrameLayout.java diff --git a/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java b/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java index 6787a5f..dbbb798 100644 --- a/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java +++ b/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java @@ -19,9 +19,9 @@ public abstract class BaseTouchController { protected boolean mIsActivated; private boolean mIsDebugMode; - private final View.OnLayoutChangeListener mOnLayoutChangeListener = new View.OnLayoutChangeListener() { + private final HoverFrameLayout.OnPositionChangeListener mOnPositionChangeListener = new HoverFrameLayout.OnPositionChangeListener() { @Override - public void onLayoutChange(View view, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { + public void onPositionChange(@NonNull View view) { moveTouchViewTo(mTouchViewMap.get(view.getTag()).mTouchView, new PointF(view.getX(), view.getY())); } }; @@ -32,14 +32,14 @@ public void onLayoutChange(View view, int left, int top, int right, int bottom, public abstract void moveTouchViewTo(@NonNull View touchView, @NonNull PointF position); - public void activate(final List> viewList) { + public void activate(final List> viewList) { if (!mIsActivated) { Log.d(TAG, "Activating."); mIsActivated = true; clearTouchViewMap(); for (int i = 0; i < viewList.size(); i++) { - final Pair viewItem = viewList.get(i); + final Pair viewItem = viewList.get(i); final String tag = "view" + i; final TouchViewItem touchViewItem = createTouchViewItem(viewItem.first, viewItem.second, tag); mTouchViewMap.put(tag, touchViewItem); @@ -61,22 +61,12 @@ public void enableDebugMode(boolean isDebugMode) { updateTouchControlViewAppearance(); } - private TouchViewItem createTouchViewItem(final View originalView, final TouchListener listener, final String tag) { - originalView.setTag(tag); - - Rect rect = new Rect(); - originalView.getDrawingRect(rect); - View touchView = createTouchView(rect); - moveTouchViewTo(touchView, new PointF(originalView.getX(), originalView.getY())); - touchView.setTag(tag); - final TouchViewItem touchViewItem = new TouchViewItem<>(originalView, touchView, listener); - setEventListener(touchViewItem); - originalView.addOnLayoutChangeListener(mOnLayoutChangeListener); - return touchViewItem; + private TouchViewItem createTouchViewItem(final HoverFrameLayout originalView, final TouchListener listener, final String tag) { + return new TouchViewItem<>(originalView, createTouchViewFrom(originalView), listener, tag); } - protected void setEventListener(final TouchViewItem touchViewItem) { - touchViewItem.mTouchView.setOnTouchListener(new TouchDetector<>(touchViewItem.mOriginalView, touchViewItem.mTouchListener)); + protected TouchDetector createTouchDetector(final View originalView, final TouchListener touchListener) { + return new TouchDetector<>(originalView, touchListener); } private void clearTouchViewMap() { @@ -99,6 +89,19 @@ private void updateTouchControlViewAppearance() { } } + private Rect getRectFrom(final View view) { + final Rect rect = new Rect(); + view.getDrawingRect(rect); + return rect; + + } + + private View createTouchViewFrom(final View originalView) { + final View touchView = createTouchView(getRectFrom(originalView)); + moveTouchViewTo(touchView, new PointF(originalView.getX(), originalView.getY())); + return touchView; + } + public interface TouchListener { void onPress(View view); @@ -133,19 +136,25 @@ public boolean onTouch(View view, MotionEvent motionEvent) { } protected class TouchViewItem { - final View mOriginalView; + final HoverFrameLayout mOriginalView; final View mTouchView; final T mTouchListener; - TouchViewItem(final View originalView, final View touchView, final T touchListener) { + TouchViewItem(final HoverFrameLayout originalView, final View touchView, final T touchListener, final String tag) { this.mOriginalView = originalView; this.mTouchView = touchView; this.mTouchListener = touchListener; + + mOriginalView.setTag(tag); + mTouchView.setTag(tag); + + mTouchView.setOnTouchListener(createTouchDetector(mOriginalView, mTouchListener)); + mOriginalView.addOnPositionChangeListener(mOnPositionChangeListener); } void destroy() { - mOriginalView.setOnTouchListener(null); - mOriginalView.removeOnLayoutChangeListener(mOnLayoutChangeListener); + mTouchView.setOnTouchListener(null); + mOriginalView.removeOnPositionChangeListener(mOnPositionChangeListener); destroyTouchView(mTouchView); } } diff --git a/hover/src/main/java/io/mattcarroll/hover/ContentDisplay.java b/hover/src/main/java/io/mattcarroll/hover/ContentDisplay.java index 553d38d..3f3de18 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ContentDisplay.java +++ b/hover/src/main/java/io/mattcarroll/hover/ContentDisplay.java @@ -62,7 +62,8 @@ public void onGlobalLayout() { private final FloatingTab.OnPositionChangeListener mOnTabPositionChangeListener = new FloatingTab.OnPositionChangeListener() { @Override - public void onPositionChange(@NonNull Point position) { + public void onPositionChange(@NonNull View view) { + final Point position = new Point((int) view.getX() + (view.getWidth() / 2), (int) view.getY() + (view.getHeight() / 2)); Log.d(TAG, mSelectedTab + " tab moved to " + position); updateTabSelectorPosition(); @@ -71,11 +72,6 @@ public void onPositionChange(@NonNull Point position) { // We have received an affirmative position for the selected tab. Show tab selector. mTabSelectorView.setVisibility(VISIBLE); } - - @Override - public void onDockChange(@NonNull Dock dock) { - // No-op. - } }; public ContentDisplay(@NonNull Context context) { diff --git a/hover/src/main/java/io/mattcarroll/hover/Dragger.java b/hover/src/main/java/io/mattcarroll/hover/Dragger.java index 58af2ab..813522d 100644 --- a/hover/src/main/java/io/mattcarroll/hover/Dragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/Dragger.java @@ -39,8 +39,12 @@ public Dragger(int mTapTouchSlop) { public abstract Point getContainerSize(); @Override - protected void setEventListener(final TouchViewItem touchViewItem) { - touchViewItem.mTouchView.setOnTouchListener(new DragDetector(touchViewItem.mOriginalView, (DragListener) touchViewItem.mTouchListener)); + protected TouchDetector createTouchDetector(final View originalView, TouchListener touchListener) { + if (touchListener instanceof DragListener) { + return new DragDetector(originalView, (DragListener) touchListener); + } else { + return super.createTouchDetector(originalView, touchListener); + } } private boolean isTouchWithinSlopOfOriginalTouch(float dx, float dy) { diff --git a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java index 101ef5d..8db2499 100644 --- a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java +++ b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java @@ -31,22 +31,19 @@ import android.view.animation.OvershootInterpolator; import android.widget.FrameLayout; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; - /** * {@code FloatingTab} is the cornerstone of a {@link HoverView}. When a {@code HoverView} is * collapsed, it is reduced to a single {@code FloatingTab} that the user can drag and drop. When * a {@code HoverView} is expanded, that one {@code FloatingTab} slides to a row of tabs that appear * and offer a menu system. - * + *

* A {@code FloatingTab} can move around the screen in various ways. A {@code FloatingTab} can place * itself at a "dock position", or slide from its current position to its "dock position", or * position itself at an arbitrary location on screen. - * + *

* {@code FloatingTab}s position themselves based on their center. */ -class FloatingTab extends FrameLayout { +class FloatingTab extends HoverFrameLayout { private static final String TAG = "FloatingTab"; private static final int APPEARING_ANIMATION_DURATION = 300; @@ -55,14 +52,6 @@ class FloatingTab extends FrameLayout { private int mTabSize; private View mTabView; private Dock mDock; - private final Set mOnPositionChangeListeners = new CopyOnWriteArraySet<>(); - - private final OnLayoutChangeListener mOnLayoutChangeListener = new OnLayoutChangeListener() { - @Override - public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { - notifyListenersOfPositionChange(); - } - }; public FloatingTab(@NonNull Context context, @NonNull String tabId) { super(context); @@ -79,7 +68,6 @@ public FloatingTab(@NonNull Context context, @NonNull String tabId) { protected void onAttachedToWindow() { super.onAttachedToWindow(); updateSize(); - addOnLayoutChangeListener(mOnLayoutChangeListener); } private void updateSize() { @@ -101,7 +89,6 @@ protected void onConfigurationChanged(Configuration newConfig) { @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - removeOnLayoutChangeListener(mOnLayoutChangeListener); } public void enableDebugMode(boolean debugMode) { @@ -159,7 +146,8 @@ public void disappear(@Nullable final Runnable onDisappeared) { animatorSet.addListener(new Animator.AnimatorListener() { @Override - public void onAnimationStart(Animator animation) { } + public void onAnimationStart(Animator animation) { + } @Override public void onAnimationEnd(Animator animation) { @@ -171,10 +159,12 @@ public void onAnimationEnd(Animator animation) { } @Override - public void onAnimationCancel(Animator animation) { } + public void onAnimationCancel(Animator animation) { + } @Override - public void onAnimationRepeat(Animator animation) { } + public void onAnimationRepeat(Animator animation) { + } }); } @@ -261,27 +251,30 @@ public void dock(@Nullable final Runnable onDocked) { animatorSet.addListener(new Animator.AnimatorListener() { @Override - public void onAnimationStart(Animator animation) { } + public void onAnimationStart(Animator animation) { + } @Override public void onAnimationEnd(Animator animation) { if (null != onDocked) { onDocked.run(); } - notifyListenersOfPositionChange(); + notifyListenersOfPositionChange(FloatingTab.this); } @Override - public void onAnimationCancel(Animator animation) { } + public void onAnimationCancel(Animator animation) { + } @Override - public void onAnimationRepeat(Animator animation) { } + public void onAnimationRepeat(Animator animation) { + } }); xAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { - notifyListenersOfPositionChange(); + notifyListenersOfPositionChange(FloatingTab.this); } }); } @@ -294,7 +287,7 @@ public void moveCenterTo(@NonNull Point centerPosition) { Point cornerPosition = convertCenterToCorner(centerPosition); setX(cornerPosition.x); setY(cornerPosition.y); - notifyListenersOfPositionChange(); + notifyListenersOfPositionChange(this); } private Point convertCenterToCorner(@NonNull Point centerPosition) { @@ -304,24 +297,11 @@ private Point convertCenterToCorner(@NonNull Point centerPosition) { ); } - public void addOnPositionChangeListener(@Nullable OnPositionChangeListener listener) { - mOnPositionChangeListeners.add(listener); - } - - public void removeOnPositionChangeListener(@NonNull OnPositionChangeListener listener) { - mOnPositionChangeListeners.remove(listener); - } - - private void notifyListenersOfPositionChange() { - Point position = getPosition(); - for (OnPositionChangeListener listener : mOnPositionChangeListeners) { - listener.onPositionChange(position); - } - } - private void notifyListenersOfDockChange() { for (OnPositionChangeListener listener : mOnPositionChangeListeners) { - listener.onDockChange(mDock); + if (listener instanceof OnFloatingTabChangeListener) { + ((OnFloatingTabChangeListener) listener).onDockChange(mDock); + } } } @@ -331,9 +311,7 @@ public void setOnClickListener(@Nullable View.OnClickListener onClickListener) { super.setOnClickListener(onClickListener); } - public interface OnPositionChangeListener { - void onPositionChange(@NonNull Point tabPosition); - + public interface OnFloatingTabChangeListener extends OnPositionChangeListener { void onDockChange(@NonNull Dock dock); } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverFrameLayout.java b/hover/src/main/java/io/mattcarroll/hover/HoverFrameLayout.java new file mode 100644 index 0000000..947d549 --- /dev/null +++ b/hover/src/main/java/io/mattcarroll/hover/HoverFrameLayout.java @@ -0,0 +1,72 @@ +package io.mattcarroll.hover; + +import android.annotation.TargetApi; +import android.content.Context; +import android.os.Build; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.view.View; +import android.widget.FrameLayout; + +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; + +class HoverFrameLayout extends FrameLayout { + + protected final Set mOnPositionChangeListeners = new CopyOnWriteArraySet<>(); + private final OnLayoutChangeListener mOnLayoutChangeListener = new OnLayoutChangeListener() { + @Override + public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { + notifyListenersOfPositionChange(v); + } + }; + + public HoverFrameLayout(@NonNull Context context) { + super(context); + } + + public HoverFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public HoverFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public HoverFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + public void addOnPositionChangeListener(@Nullable OnPositionChangeListener listener) { + mOnPositionChangeListeners.add(listener); + } + + public void removeOnPositionChangeListener(@NonNull OnPositionChangeListener listener) { + mOnPositionChangeListeners.remove(listener); + } + + protected void notifyListenersOfPositionChange(final View view) { + for (OnPositionChangeListener listener : mOnPositionChangeListeners) { + listener.onPositionChange(view); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + addOnLayoutChangeListener(mOnLayoutChangeListener); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + removeOnLayoutChangeListener(mOnLayoutChangeListener); + } + + interface OnPositionChangeListener { + void onPositionChange(@NonNull View view); + } +} + diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 6a5ecb0..506753c 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -311,7 +311,7 @@ void moveFloatingTabTo(View floatingTab, @NonNull Point position) { } protected void activateDragger() { - ArrayList> list = new ArrayList<>(); + ArrayList> list = new ArrayList<>(); list.add(new Pair<>(mFloatingTab, mFloatingTabDragListener)); mHoverView.mDragger.activate(list); } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index d1b8b29..a6d1d36 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -82,7 +82,7 @@ protected void onClose(final boolean userDropped) { @Override protected void activateDragger() { - ArrayList> list = new ArrayList<>(); + ArrayList> list = new ArrayList<>(); list.add(new Pair<>(mFloatingTab, mFloatingTabDragListener)); list.add(new Pair<>(mMessageView, mMessageViewDragListener)); mHoverView.mDragger.activate(list); @@ -109,24 +109,36 @@ private void init() { protected static final class MessageViewDragListener implements Dragger.DragListener { private final HoverViewStateCollapsed mOwner; + private float mOriginalX; + private float mOriginalY; protected MessageViewDragListener(@NonNull HoverViewStateCollapsed owner) { mOwner = owner; + init(); } @Override public void onDragStart(View messageView, float x, float y) { + mOriginalX = messageView.getX() + messageView.getWidth() / 2; + mOriginalY = messageView.getY() + messageView.getHeight() / 2; + if (messageView instanceof TabMessageView) { + ((TabMessageView) messageView).moveCenterTo(new Point((int) x, (int) mOriginalY)); + } } @Override public void onDragTo(View messageView, float x, float y) { if (messageView instanceof TabMessageView) { - ((TabMessageView) messageView).moveTo(new Point((int) x, (int) y)); + ((TabMessageView) messageView).moveCenterTo(new Point((int) x, (int) mOriginalY)); } } @Override public void onReleasedAt(View messageView, float x, float y) { + if (messageView instanceof TabMessageView) { + ((TabMessageView) messageView).moveCenterTo(new Point((int) mOriginalX, (int) mOriginalY)); + } + init(); } @Override @@ -137,5 +149,10 @@ public void onPress(View messageView) { public void onTap(View messageView) { mOwner.onTap(); } + + private void init() { + mOriginalX = 0; + mOriginalY = 0; + } } } diff --git a/hover/src/main/java/io/mattcarroll/hover/TabChain.java b/hover/src/main/java/io/mattcarroll/hover/TabChain.java index 7c53a45..ac5bf9e 100644 --- a/hover/src/main/java/io/mattcarroll/hover/TabChain.java +++ b/hover/src/main/java/io/mattcarroll/hover/TabChain.java @@ -21,9 +21,6 @@ import android.util.Log; import android.view.View; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; - /** * Connects one {@link FloatingTab}s position to that of another {@link FloatingTab}. The space * between the tabs can be configured at construction time. @@ -36,11 +33,10 @@ class TabChain { private final int mTabSpacingInPx; private Point mLockedPosition; private FloatingTab mPredecessorTab; - private final Set mOnPositionChangeListeners = new CopyOnWriteArraySet(); - private final FloatingTab.OnPositionChangeListener mOnPredecessorPositionChange = new FloatingTab.OnPositionChangeListener() { + private final FloatingTab.OnFloatingTabChangeListener mOnPredecessorPositionChange = new FloatingTab.OnFloatingTabChangeListener() { @Override - public void onPositionChange(@NonNull Point position) { + public void onPositionChange(@NonNull View view) { // No-op. We only care when our predecessor's dock changes. } diff --git a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java index fd230da..a7feb39 100644 --- a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java +++ b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java @@ -11,23 +11,26 @@ import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.TranslateAnimation; -import android.widget.FrameLayout; -public class TabMessageView extends FrameLayout { +public class TabMessageView extends HoverFrameLayout { private static final String TAG = "TabMessageView"; private final FloatingTab mFloatingTab; private SideDock mSideDock; private View mMessageView; - private final FloatingTab.OnPositionChangeListener mOnTabPositionChangeListener = new FloatingTab.OnPositionChangeListener() { + private final FloatingTab.OnFloatingTabChangeListener mOnFloatingTabChangeListener = new FloatingTab.OnFloatingTabChangeListener() { private static final int DEFAULT_SIDE = SideDock.SidePosition.LEFT; private Point mLastPosition; private int mLastSide; @Override - public void onPositionChange(@NonNull Point position) { + public void onPositionChange(View view) { + if (!(view instanceof FloatingTab)) { + return; + } + final Point position = ((FloatingTab) view).getPosition(); final Integer side = getSide(); if (side.equals(mLastSide) && position.equals(mLastPosition) || getWidth() == 0) { return; @@ -83,7 +86,7 @@ public void setMessageView(@Nullable View view) { public void appear(final SideDock dock, @Nullable final Runnable onAppeared) { mSideDock = dock; - mFloatingTab.addOnPositionChangeListener(mOnTabPositionChangeListener); + mFloatingTab.addOnPositionChangeListener(mOnFloatingTabChangeListener); if (getVisibility() != View.VISIBLE) { final AnimationSet animation = new AnimationSet(true); final AlphaAnimation alpha = new AlphaAnimation(0, 1); @@ -117,7 +120,7 @@ public void onAnimationRepeat(Animation animation) { } public void disappear(final boolean withAnimation) { - mFloatingTab.removeOnPositionChangeListener(mOnTabPositionChangeListener); + mFloatingTab.removeOnPositionChangeListener(mOnFloatingTabChangeListener); mSideDock = null; if (withAnimation && getVisibility() == View.VISIBLE) { final AnimationSet animation = new AnimationSet(true); @@ -129,8 +132,17 @@ public void disappear(final boolean withAnimation) { setVisibility(GONE); } - public void moveTo(@NonNull Point newPosition) { - setX(newPosition.x); - setY(newPosition.y); + public void moveCenterTo(@NonNull Point floatPosition) { + Point cornerPosition = convertCenterToCorner(floatPosition); + setX(cornerPosition.x); + setY(cornerPosition.y); + notifyListenersOfPositionChange(this); + } + + private Point convertCenterToCorner(@NonNull Point centerPosition) { + return new Point( + (int) (centerPosition.x - (getWidth() / 2)), + (int) (centerPosition.y - (getHeight() / 2)) + ); } } From 0bfb97c78652d50f2170d96fd907d8777cdc99df Mon Sep 17 00:00:00 2001 From: ybbarng Date: Mon, 15 Apr 2019 18:47:01 +0900 Subject: [PATCH 039/105] =?UTF-8?q?=EB=93=9C=EB=9E=98=EA=B7=B8=20=EC=A0=95?= =?UTF-8?q?=EB=8F=84=EC=97=90=20=EB=94=B0=EB=9D=BC=20alpha=20=EA=B0=92=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/mattcarroll/hover/HoverViewStatePreviewed.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index a6d1d36..f6a5aee 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -108,6 +108,7 @@ private void init() { protected static final class MessageViewDragListener implements Dragger.DragListener { + private static final float ALPHA_THRESHOLD = 400; private final HoverViewStateCollapsed mOwner; private float mOriginalX; private float mOriginalY; @@ -123,6 +124,7 @@ public void onDragStart(View messageView, float x, float y) { mOriginalY = messageView.getY() + messageView.getHeight() / 2; if (messageView instanceof TabMessageView) { ((TabMessageView) messageView).moveCenterTo(new Point((int) x, (int) mOriginalY)); + updateAlpha(messageView, x); } } @@ -130,6 +132,7 @@ public void onDragStart(View messageView, float x, float y) { public void onDragTo(View messageView, float x, float y) { if (messageView instanceof TabMessageView) { ((TabMessageView) messageView).moveCenterTo(new Point((int) x, (int) mOriginalY)); + updateAlpha(messageView, x); } } @@ -137,6 +140,7 @@ public void onDragTo(View messageView, float x, float y) { public void onReleasedAt(View messageView, float x, float y) { if (messageView instanceof TabMessageView) { ((TabMessageView) messageView).moveCenterTo(new Point((int) mOriginalX, (int) mOriginalY)); + updateAlpha(messageView, mOriginalX); } init(); } @@ -154,5 +158,9 @@ private void init() { mOriginalX = 0; mOriginalY = 0; } + + private void updateAlpha(final View view, final float current) { + view.setAlpha(1 - Math.max(0, Math.min(1, (Math.abs(current - mOriginalX) / ALPHA_THRESHOLD)))); + } } } From fde6d82823c8d0cfd066fff9399c9d34e7460aa9 Mon Sep 17 00:00:00 2001 From: ybbarng Date: Tue, 16 Apr 2019 12:55:00 +0900 Subject: [PATCH 040/105] =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=EB=A5=BC=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20HoverMenu=EC=97=90=20=EC=83=81=ED=83=9C=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/mattcarroll/hover/HoverMenu.java | 17 ++++++++++++++++- .../hover/HoverViewStateCollapsed.java | 11 +++++++++++ .../hover/HoverViewStatePreviewed.java | 6 ++++-- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverMenu.java b/hover/src/main/java/io/mattcarroll/hover/HoverMenu.java index 6ebe213..21dcaad 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverMenu.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverMenu.java @@ -26,7 +26,7 @@ /** * A {@code HoverMenu} models the structure of a menu that appears within a {@link HoverView}. - * + *

* A {@code HoverMenu} includes an ordered list of {@link Section}s. Each {@code Section} has a tab * {@code View} that represents the section, and the {@link Content} of the given section. */ @@ -34,8 +34,13 @@ public abstract class HoverMenu { private static final String TAG = "HoverMenu"; + public enum HoverMenuState { + IDLE, REMOVE_PREVIEW + } + private List

mSections = new ArrayList<>(); private ListUpdateCallback mListUpdateCallback; + private HoverMenuState mState = HoverMenuState.IDLE; public abstract String getId(); @@ -59,6 +64,8 @@ public int getSectionIndex(@NonNull Section section) { @NonNull public abstract List
getSections(); + protected abstract void onHoverMenuStateChanged(HoverMenuState state); + void setUpdatedCallback(@Nullable ListUpdateCallback listUpdatedCallback) { mListUpdateCallback = listUpdatedCallback; } @@ -77,6 +84,14 @@ public void notifyMenuChanged() { } } + public void setState(final HoverMenuState newState) { + final boolean changed = this.mState != newState; + this.mState = newState; + if (changed) { + onHoverMenuStateChanged(this.mState); + } + } + public static class SectionId { private String mId; diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 506753c..3c66189 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -123,6 +123,7 @@ public void run() { } scheduleHoverViewAlphaChange(); + setHoverMenuMode(HoverMenu.HoverMenuState.IDLE); } @Override @@ -329,6 +330,16 @@ protected void restoreHoverViewAlphaValue() { mHoverView.setAlpha(1f); } + protected void setHoverMenuMode(final HoverMenu.HoverMenuState state) { + if (mHoverView == null) { + return; + } + if (mHoverView.mMenu == null) { + return; + } + mHoverView.mMenu.setState(state); + } + @Override public HoverViewStateType getStateType() { return HoverViewStateType.COLLAPSED; diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index f6a5aee..cf8f987 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -120,11 +120,12 @@ protected MessageViewDragListener(@NonNull HoverViewStateCollapsed owner) { @Override public void onDragStart(View messageView, float x, float y) { - mOriginalX = messageView.getX() + messageView.getWidth() / 2; - mOriginalY = messageView.getY() + messageView.getHeight() / 2; if (messageView instanceof TabMessageView) { + mOriginalX = messageView.getX() + messageView.getWidth() / 2; + mOriginalY = messageView.getY() + messageView.getHeight() / 2; ((TabMessageView) messageView).moveCenterTo(new Point((int) x, (int) mOriginalY)); updateAlpha(messageView, x); + mOwner.setHoverMenuMode(HoverMenu.HoverMenuState.REMOVE_PREVIEW); } } @@ -142,6 +143,7 @@ public void onReleasedAt(View messageView, float x, float y) { ((TabMessageView) messageView).moveCenterTo(new Point((int) mOriginalX, (int) mOriginalY)); updateAlpha(messageView, mOriginalX); } + mOwner.setHoverMenuMode(HoverMenu.HoverMenuState.IDLE); init(); } From 41edfe7013c32308858fe341eab9c6f78cd6baa9 Mon Sep 17 00:00:00 2001 From: ybbarng Date: Tue, 16 Apr 2019 13:21:13 +0900 Subject: [PATCH 041/105] =?UTF-8?q?=EC=9D=BC=EC=A0=95=20=EA=B1=B0=EB=A6=AC?= =?UTF-8?q?=20=EC=9D=B4=EC=83=81=20=EB=93=9C=EB=9E=98=EA=B7=B8=ED=95=98?= =?UTF-8?q?=EB=A9=B4=20Preview=EB=A5=BC=20=EB=81=84=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hover/HoverViewStatePreviewed.java | 26 +++++++++++++++++-- .../io/mattcarroll/hover/TabMessageView.java | 5 +++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index cf8f987..f551185 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -106,9 +106,20 @@ private void init() { mCollapseOnDocked = false; } + private void hidePreview(final float startAlpha) { + if (mHoverView == null) { + return; + } + if (mMessageView != null) { + mMessageView.disappear(false, startAlpha); + } + mHoverView.collapse(); + } + protected static final class MessageViewDragListener implements Dragger.DragListener { private static final float ALPHA_THRESHOLD = 400; + private static final float COLLAPSE_THRESHOLD = 300; private final HoverViewStateCollapsed mOwner; private float mOriginalX; private float mOriginalY; @@ -133,15 +144,22 @@ public void onDragStart(View messageView, float x, float y) { public void onDragTo(View messageView, float x, float y) { if (messageView instanceof TabMessageView) { ((TabMessageView) messageView).moveCenterTo(new Point((int) x, (int) mOriginalY)); + Log.d("ALPHA", "" + (Math.abs(x - mOriginalX) / 200)); updateAlpha(messageView, x); } } @Override - public void onReleasedAt(View messageView, float x, float y) { + public void onReleasedAt(final View messageView, float x, float y) { if (messageView instanceof TabMessageView) { ((TabMessageView) messageView).moveCenterTo(new Point((int) mOriginalX, (int) mOriginalY)); updateAlpha(messageView, mOriginalX); + if (Math.abs(x - mOriginalX) > COLLAPSE_THRESHOLD) { + updateAlpha(messageView, mOriginalX); + if (mOwner instanceof HoverViewStatePreviewed) { + ((HoverViewStatePreviewed) mOwner).hidePreview(getAlpha(x)); + } + } } mOwner.setHoverMenuMode(HoverMenu.HoverMenuState.IDLE); init(); @@ -162,7 +180,11 @@ private void init() { } private void updateAlpha(final View view, final float current) { - view.setAlpha(1 - Math.max(0, Math.min(1, (Math.abs(current - mOriginalX) / ALPHA_THRESHOLD)))); + view.setAlpha(getAlpha(current)); + } + + private float getAlpha(final float current) { + return 1 - Math.max(0, Math.min(1, (Math.abs(current - mOriginalX) / ALPHA_THRESHOLD))); } } } diff --git a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java index a7feb39..cfeb438 100644 --- a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java +++ b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java @@ -120,11 +120,14 @@ public void onAnimationRepeat(Animation animation) { } public void disappear(final boolean withAnimation) { + disappear(withAnimation, 1); + } + public void disappear(final boolean withAnimation, float startAlpha) { mFloatingTab.removeOnPositionChangeListener(mOnFloatingTabChangeListener); mSideDock = null; if (withAnimation && getVisibility() == View.VISIBLE) { final AnimationSet animation = new AnimationSet(true); - final AlphaAnimation alpha = new AlphaAnimation(1, 0); + final AlphaAnimation alpha = new AlphaAnimation(startAlpha, 0); alpha.setDuration(300); animation.addAnimation(alpha); startAnimation(animation); From e07a2ed9fcff7008d7d76c55cec1720d5ab9d7e1 Mon Sep 17 00:00:00 2001 From: ybbarng Date: Tue, 16 Apr 2019 14:43:37 +0900 Subject: [PATCH 042/105] =?UTF-8?q?Menu=EA=B0=80=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EB=90=98=EB=A9=B4=20View=EB=A5=BC=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=ED=95=98=EB=8F=84=EB=A1=9D=20=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HoverView를 유지한 채로 새로운 Menu로 교체하는 경우, 코드 상으로는 새로운 TabView에 접근하는데 시각적으로는 새로운 TabView에 접근하는 문제가 있었음 따라서 Menu가 새로 설정될 때, TabView를 업데이트하도록 함 --- hover/src/main/java/io/mattcarroll/hover/HoverView.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverView.java b/hover/src/main/java/io/mattcarroll/hover/HoverView.java index 2a741de..322446f 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverView.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverView.java @@ -290,6 +290,10 @@ public void setMenu(@Nullable HoverMenu menu) { if (null == mSelectedSectionId || null == mMenu.getSection(mSelectedSectionId)) { mSelectedSectionId = mMenu.getSection(0).getId(); } + final FloatingTab selectedTab = mScreen.getChainedTab(mSelectedSectionId); + if (selectedTab != null) { + selectedTab.setTabView(mMenu.getSection(mSelectedSectionId).getTabView()); + } mState.setMenu(menu); } From 66002150e549cb0767ac676372194998573b21dd Mon Sep 17 00:00:00 2001 From: ybbarng Date: Tue, 16 Apr 2019 15:42:27 +0900 Subject: [PATCH 043/105] =?UTF-8?q?Preview=EA=B0=80=20=EB=B3=B4=EC=9D=B4?= =?UTF-8?q?=EA=B8=B0=20=EC=8B=9C=EC=9E=91=ED=95=98=EA=B3=A0=20=EB=82=98?= =?UTF-8?q?=EC=84=9C=20=EC=95=BD=201=EC=B4=88=EA=B0=84=20=ED=84=B0?= =?UTF-8?q?=EC=B9=98=EA=B0=80=20=EC=95=88=EB=90=98=EB=8A=94=20=EB=B2=84?= =?UTF-8?q?=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java | 1 + 1 file changed, 1 insertion(+) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index f551185..4aa4d7e 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -52,6 +52,7 @@ public void run() { return; } onStateChanged.run(); + activateDragger(); } }); } From 1d586d7f6c681c3fec61b98e7488c8b9e2c852d9 Mon Sep 17 00:00:00 2001 From: ybbarng Date: Tue, 16 Apr 2019 15:42:44 +0900 Subject: [PATCH 044/105] =?UTF-8?q?Preview=EA=B0=80=20Pop=EC=9D=98=20?= =?UTF-8?q?=EC=95=84=EB=9E=98=EC=AA=BD=EC=97=90=20=EC=9C=84=EC=B9=98?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hover/src/main/java/io/mattcarroll/hover/Screen.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/Screen.java b/hover/src/main/java/io/mattcarroll/hover/Screen.java index 40bea6a..ea6dfb4 100644 --- a/hover/src/main/java/io/mattcarroll/hover/Screen.java +++ b/hover/src/main/java/io/mattcarroll/hover/Screen.java @@ -95,10 +95,10 @@ public FloatingTab createChainedTab(@NonNull String tabId, @NonNull View tabView FloatingTab chainedTab = new FloatingTab(mContainer.getContext(), tabId); chainedTab.setTabView(tabView); chainedTab.enableDebugMode(mIsDebugMode); - mContainer.addView(chainedTab); mTabs.put(tabId, chainedTab); final TabMessageView messageView = new TabMessageView(tabView.getContext(), chainedTab); mContainer.addView(messageView); + mContainer.addView(chainedTab); mTabMessageViews.put(tabId, messageView); return chainedTab; } From 75a011834aa91b4460d8e92138c9e0730ba25ab2 Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Wed, 17 Apr 2019 15:07:36 +0900 Subject: [PATCH 045/105] Bump version to 1.0.0-rc.3 --- hover/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hover/build.gradle b/hover/build.gradle index f9124fa..81f55b8 100644 --- a/hover/build.gradle +++ b/hover/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.library' apply plugin: 'checkstyle' project.group = 'com.buzzvil' -project.version = '1.0.0-rc.2' +project.version = '1.0.0-rc.3' android { compileSdkVersion project.compileSdkVersion.toInteger() From 016aeb59ac7a17bcb5ac9e53f50869f5eba120e2 Mon Sep 17 00:00:00 2001 From: ybbarng Date: Thu, 18 Apr 2019 17:47:16 +0900 Subject: [PATCH 046/105] =?UTF-8?q?LongPress=ED=95=98=EB=8A=94=20=EA=B2=BD?= =?UTF-8?q?=EC=9A=B0=20=EB=93=9C=EB=9E=98=EA=B7=B8=EB=A1=9C=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/mattcarroll/hover/Dragger.java | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/Dragger.java b/hover/src/main/java/io/mattcarroll/hover/Dragger.java index 813522d..30ce3ac 100644 --- a/hover/src/main/java/io/mattcarroll/hover/Dragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/Dragger.java @@ -19,6 +19,7 @@ import android.graphics.PointF; import android.support.annotation.NonNull; import android.util.Log; +import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; @@ -97,6 +98,8 @@ public interface DragListener extends TouchListener { } private class DragDetector extends TouchDetector { + + private final GestureDetector mGestureDetector; private boolean mIsDragging; private PointF mOriginalViewPosition = new PointF(); private PointF mCurrentViewPosition = new PointF(); @@ -104,10 +107,16 @@ private class DragDetector extends TouchDetector { public DragDetector(final View originalView, final DragListener dragListener) { super(originalView, dragListener); + mGestureDetector = new GestureDetector(null, new GestureDetector.SimpleOnGestureListener() { + public void onLongPress(final MotionEvent e) { + tryDragStart("LONG_PRESS"); + } + }); } @Override public boolean onTouch(View view, MotionEvent motionEvent) { + mGestureDetector.onTouchEvent(motionEvent); switch (motionEvent.getAction()) { case MotionEvent.ACTION_DOWN: Log.d(TAG, "ACTION_DOWN"); @@ -133,12 +142,7 @@ public boolean onTouch(View view, MotionEvent motionEvent) { ); if (mIsDragging || !isTouchWithinSlopOfOriginalTouch(dragDeltaX, dragDeltaY)) { - if (!mIsDragging) { - // Dragging just started - Log.d(TAG, "MOVE Start Drag."); - mIsDragging = true; - mEventListener.onDragStart(mOriginalView, mCurrentViewPosition.x, mCurrentViewPosition.y); - } else { + if (!tryDragStart("ACTION_MOVE")) { mEventListener.onDragTo(mOriginalView, mCurrentViewPosition.x, mCurrentViewPosition.y); } } @@ -160,5 +164,16 @@ public boolean onTouch(View view, MotionEvent motionEvent) { return false; } } + + private boolean tryDragStart(final String reason) { + if (mIsDragging) { + return false; + } + // Dragging is just started by reason + Log.d(TAG, "" + reason + " starts drag."); + mIsDragging = true; + mEventListener.onDragStart(mOriginalView, mCurrentViewPosition.x, mCurrentViewPosition.y); + return true; + } } } From 4bdbdc62f1f62e608121125acd7457b91ba2f1b2 Mon Sep 17 00:00:00 2001 From: ybbarng Date: Thu, 18 Apr 2019 17:51:32 +0900 Subject: [PATCH 047/105] =?UTF-8?q?TabMessageView=EC=9D=98=20TouchDown?= =?UTF-8?q?=EA=B3=BC=20TouchUp=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hover/BaseTouchController.java | 13 +++-- .../java/io/mattcarroll/hover/Dragger.java | 14 ++--- .../java/io/mattcarroll/hover/HoverView.java | 52 ++++++++++++++----- .../hover/HoverViewStateCollapsed.java | 10 ++-- .../hover/HoverViewStatePreviewed.java | 34 +++++++++--- 5 files changed, 86 insertions(+), 37 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java b/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java index dbbb798..0da9dda 100644 --- a/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java +++ b/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java @@ -103,17 +103,21 @@ private View createTouchViewFrom(final View originalView) { } public interface TouchListener { - void onPress(View view); - void onTap(View view); + + void onTouchDown(View view); + + void onTouchUp(View view); } protected class TouchDetector implements View.OnTouchListener { + @NonNull protected final View mOriginalView; + @NonNull protected final T mEventListener; - TouchDetector(final View originalView, final T touchListener) { + TouchDetector(@NonNull final View originalView, @NonNull final T touchListener) { this.mOriginalView = originalView; this.mEventListener = touchListener; } @@ -123,10 +127,11 @@ public boolean onTouch(View view, MotionEvent motionEvent) { switch (motionEvent.getAction()) { case MotionEvent.ACTION_DOWN: Log.d(TAG, "ACTION_DOWN"); - mEventListener.onPress(mOriginalView); + mEventListener.onTouchDown(mOriginalView); return true; case MotionEvent.ACTION_UP: Log.d(TAG, "ACTION_UP"); + mEventListener.onTouchUp(mOriginalView); mEventListener.onTap(mOriginalView); return true; default: diff --git a/hover/src/main/java/io/mattcarroll/hover/Dragger.java b/hover/src/main/java/io/mattcarroll/hover/Dragger.java index 30ce3ac..8a7a1ce 100644 --- a/hover/src/main/java/io/mattcarroll/hover/Dragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/Dragger.java @@ -125,14 +125,9 @@ public boolean onTouch(View view, MotionEvent motionEvent) { mOriginalViewPosition = convertCornerToCenter(view, getTouchViewPosition(view)); mCurrentViewPosition = new PointF(mOriginalViewPosition.x, mOriginalViewPosition.y); mOriginalTouchPosition.set(motionEvent.getRawX(), motionEvent.getRawY()); - if (mEventListener != null) { - mEventListener.onPress(mOriginalView); - } + mEventListener.onTouchDown(view); return true; case MotionEvent.ACTION_MOVE: - if (mEventListener == null) { - return false; - } Log.d(TAG, "ACTION_MOVE. motionX: " + motionEvent.getRawX() + ", motionY: " + motionEvent.getRawY()); float dragDeltaX = motionEvent.getRawX() - mOriginalTouchPosition.x; float dragDeltaY = motionEvent.getRawY() - mOriginalTouchPosition.y; @@ -150,12 +145,11 @@ public boolean onTouch(View view, MotionEvent motionEvent) { return true; case MotionEvent.ACTION_UP: Log.d(TAG, "ACTION_UP"); + mEventListener.onTouchUp(view); if (!mIsDragging) { Log.d(TAG, "Reporting as a tap."); - if (mEventListener != null) { - mEventListener.onTap(mOriginalView); - } - } else if (mEventListener != null) { + mEventListener.onTap(mOriginalView); + } else { Log.d(TAG, "Reporting as a drag release at: " + mCurrentViewPosition); mEventListener.onReleasedAt(mOriginalView, mCurrentViewPosition.x, mCurrentViewPosition.y); } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverView.java b/hover/src/main/java/io/mattcarroll/hover/HoverView.java index 322446f..fdac665 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverView.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverView.java @@ -104,7 +104,8 @@ public static HoverView createForView(@NonNull Context context) { private PositionDock mPositionToHide; OnExitListener mOnExitListener; private final Set mOnStateChangeListeners = new CopyOnWriteArraySet<>(); - private final Set mOnInteractionListeners = new CopyOnWriteArraySet<>(); + private final Set mOnFloatingTabInteractionListeners = new CopyOnWriteArraySet<>(); + private final Set mOnTabMessageViewInteractionListeners = new CopyOnWriteArraySet<>(); private boolean mKeepVisible; // Public for use with XML inflation. Clients should use static methods for construction. @@ -372,29 +373,50 @@ public void removeOnStateChangeListener(@NonNull OnStateChangeListener onStateCh mOnStateChangeListeners.remove(onStateChangeListener); } - public void addOnInteractionListener(@NonNull OnInteractionListener onInteractionListener) { - mOnInteractionListeners.add(onInteractionListener); + public void addOnFloatingTabInteractionListener(@NonNull OnFloatingTabInteractionListener onFloatingTabInteractionListener) { + mOnFloatingTabInteractionListeners.add(onFloatingTabInteractionListener); } - public void removeOnInteractionListener(@NonNull OnInteractionListener onInteractionListener) { - mOnInteractionListeners.remove(onInteractionListener); + public void removeOnFloatingTabInteractionListener(@NonNull OnFloatingTabInteractionListener onFloatingTabInteractionListener) { + mOnFloatingTabInteractionListeners.remove(onFloatingTabInteractionListener); } + public void addOnTabMessageViewInteractionListener(@NonNull OnTabMessageViewInteractionListener onTabMessageViewInteractionListener) { + mOnTabMessageViewInteractionListeners.add(onTabMessageViewInteractionListener); + } + + public void removeOnTabMessageViewInteractionListener(@NonNull OnTabMessageViewInteractionListener onTabMessageViewInteractionListener) { + mOnTabMessageViewInteractionListeners.remove(onTabMessageViewInteractionListener); + } + + void notifyOnTap(HoverViewState state) { - for (OnInteractionListener onInteractionListener : mOnInteractionListeners) { - onInteractionListener.onTap(state.getStateType()); + for (OnFloatingTabInteractionListener onFloatingTabInteractionListener : mOnFloatingTabInteractionListeners) { + onFloatingTabInteractionListener.onTap(state.getStateType()); } } void notifyOnDragStart(HoverViewState state) { - for (OnInteractionListener onInteractionListener : mOnInteractionListeners) { - onInteractionListener.onDragStart(state.getStateType()); + for (OnFloatingTabInteractionListener onFloatingTabInteractionListener : mOnFloatingTabInteractionListeners) { + onFloatingTabInteractionListener.onDragStart(state.getStateType()); } } void notifyOnDocked(HoverViewState state) { - for (OnInteractionListener onInteractionListener : mOnInteractionListeners) { - onInteractionListener.onDocked(state.getStateType()); + for (OnFloatingTabInteractionListener onFloatingTabInteractionListener : mOnFloatingTabInteractionListeners) { + onFloatingTabInteractionListener.onDocked(state.getStateType()); + } + } + + void notifyMessageViewOnTouchDown() { + for (final OnTabMessageViewInteractionListener listener : mOnTabMessageViewInteractionListeners) { + listener.onTouchDown(); + } + } + + void notifyMessageViewOnTouchUp() { + for (final OnTabMessageViewInteractionListener listener : mOnTabMessageViewInteractionListeners) { + listener.onTouchUp(); } } @@ -645,11 +667,17 @@ public void onHidden() { } } - public interface OnInteractionListener { + public interface OnFloatingTabInteractionListener { void onTap(HoverViewStateType stateType); void onDragStart(HoverViewStateType stateType); void onDocked(HoverViewStateType stateType); } + + public interface OnTabMessageViewInteractionListener { + void onTouchDown(); + + void onTouchUp(); + } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 3c66189..8b555e8 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -369,12 +369,16 @@ public void onReleasedAt(View floatingTab, float x, float y) { } @Override - public void onPress(View floatingTab) { + public void onTap(View floatingTab) { + mOwner.onTap(); } @Override - public void onTap(View floatingTab) { - mOwner.onTap(); + public void onTouchDown(View floatingTab) { + } + + @Override + public void onTouchUp(View floatingTab) { } } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index 4aa4d7e..c9d6d28 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -117,15 +117,29 @@ private void hidePreview(final float startAlpha) { mHoverView.collapse(); } + private void notifyTabMessageViewOnTouchDown() { + if (mHoverView == null) { + return; + } + mHoverView.notifyMessageViewOnTouchDown(); + } + + private void notifyTabMessageViewOnTouchUp() { + if (mHoverView == null) { + return; + } + mHoverView.notifyMessageViewOnTouchUp(); + } + protected static final class MessageViewDragListener implements Dragger.DragListener { private static final float ALPHA_THRESHOLD = 400; private static final float COLLAPSE_THRESHOLD = 300; - private final HoverViewStateCollapsed mOwner; + private final HoverViewStatePreviewed mOwner; private float mOriginalX; private float mOriginalY; - protected MessageViewDragListener(@NonNull HoverViewStateCollapsed owner) { + protected MessageViewDragListener(@NonNull HoverViewStatePreviewed owner) { mOwner = owner; init(); } @@ -157,9 +171,7 @@ public void onReleasedAt(final View messageView, float x, float y) { updateAlpha(messageView, mOriginalX); if (Math.abs(x - mOriginalX) > COLLAPSE_THRESHOLD) { updateAlpha(messageView, mOriginalX); - if (mOwner instanceof HoverViewStatePreviewed) { - ((HoverViewStatePreviewed) mOwner).hidePreview(getAlpha(x)); - } + mOwner.hidePreview(getAlpha(x)); } } mOwner.setHoverMenuMode(HoverMenu.HoverMenuState.IDLE); @@ -167,12 +179,18 @@ public void onReleasedAt(final View messageView, float x, float y) { } @Override - public void onPress(View messageView) { + public void onTap(View messageView) { + mOwner.onTap(); } @Override - public void onTap(View messageView) { - mOwner.onTap(); + public void onTouchDown(View messageView) { + mOwner.notifyTabMessageViewOnTouchDown(); + } + + @Override + public void onTouchUp(View messageView) { + mOwner.notifyTabMessageViewOnTouchUp(); } private void init() { From c6bdab2ea5e8b30877066dc9dc8e2f0f4b971ed3 Mon Sep 17 00:00:00 2001 From: ybbarng Date: Fri, 19 Apr 2019 18:34:13 +0900 Subject: [PATCH 048/105] =?UTF-8?q?view.setAlpha(0.x)=EB=A5=BC=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=ED=95=A0=20=EB=95=8C=20=EA=B7=B8=EB=A6=BC=EC=9E=90?= =?UTF-8?q?=EA=B0=80=20=EC=9E=98=EB=A6=AC=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 원래는 setClipToPadding(false)로 해결되지만, alpha값을 주는 경우에는 올바르게 처리되지 않으므로 ParentView에 넉넉한 padding을 주어 해결한다. https://stackoverflow.com/questions/27477371/android-elevation-not-showing-a-shadow --- .../main/java/io/mattcarroll/hover/TabMessageView.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java index cfeb438..8f29234 100644 --- a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java +++ b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java @@ -67,10 +67,13 @@ private int getSide() { public TabMessageView(@NonNull Context context, @NonNull FloatingTab floatingTab) { super(context); - setClipToPadding(false); - setClipChildren(false); mFloatingTab = floatingTab; setVisibility(GONE); + + // To prevent child's shadow clipping + setClipToPadding(false); + setClipChildren(false); + setPadding(10, 20, 10, 20); } public void setMessageView(@Nullable View view) { @@ -122,6 +125,7 @@ public void onAnimationRepeat(Animation animation) { public void disappear(final boolean withAnimation) { disappear(withAnimation, 1); } + public void disappear(final boolean withAnimation, float startAlpha) { mFloatingTab.removeOnPositionChangeListener(mOnFloatingTabChangeListener); mSideDock = null; From fa71ace0a2c00b8c39b1f2e5e9b12fb48aa6e4b4 Mon Sep 17 00:00:00 2001 From: ybbarng Date: Mon, 22 Apr 2019 10:43:33 +0900 Subject: [PATCH 049/105] =?UTF-8?q?callback=EC=9D=98=20=EC=9D=BC=EA=B4=80?= =?UTF-8?q?=EC=84=B1=EC=9D=84=20=EC=9C=84=ED=95=B4=20View=EB=A5=BC=20?= =?UTF-8?q?=EB=A6=AC=ED=84=B4=ED=95=98=EB=8A=94=20=ED=98=95=ED=83=9C?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/mattcarroll/hover/HoverView.java | 12 ++++++------ .../hover/HoverViewStatePreviewed.java | 16 ++++++++++------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverView.java b/hover/src/main/java/io/mattcarroll/hover/HoverView.java index fdac665..392fe61 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverView.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverView.java @@ -408,15 +408,15 @@ void notifyOnDocked(HoverViewState state) { } } - void notifyMessageViewOnTouchDown() { + void notifyMessageViewOnTouchDown(final TabMessageView tabMessageView) { for (final OnTabMessageViewInteractionListener listener : mOnTabMessageViewInteractionListeners) { - listener.onTouchDown(); + listener.onTouchDown(tabMessageView); } } - void notifyMessageViewOnTouchUp() { + void notifyMessageViewOnTouchUp(final TabMessageView tabMessageView) { for (final OnTabMessageViewInteractionListener listener : mOnTabMessageViewInteractionListeners) { - listener.onTouchUp(); + listener.onTouchUp(tabMessageView); } } @@ -676,8 +676,8 @@ public interface OnFloatingTabInteractionListener { } public interface OnTabMessageViewInteractionListener { - void onTouchDown(); + void onTouchDown(TabMessageView tabMessageView); - void onTouchUp(); + void onTouchUp(TabMessageView tabMessageView); } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index c9d6d28..8920ab9 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -117,18 +117,18 @@ private void hidePreview(final float startAlpha) { mHoverView.collapse(); } - private void notifyTabMessageViewOnTouchDown() { + private void notifyTabMessageViewOnTouchDown(final TabMessageView tabMessageView) { if (mHoverView == null) { return; } - mHoverView.notifyMessageViewOnTouchDown(); + mHoverView.notifyMessageViewOnTouchDown(tabMessageView); } - private void notifyTabMessageViewOnTouchUp() { + private void notifyTabMessageViewOnTouchUp(final TabMessageView tabMessageView) { if (mHoverView == null) { return; } - mHoverView.notifyMessageViewOnTouchUp(); + mHoverView.notifyMessageViewOnTouchUp(tabMessageView); } protected static final class MessageViewDragListener implements Dragger.DragListener { @@ -185,12 +185,16 @@ public void onTap(View messageView) { @Override public void onTouchDown(View messageView) { - mOwner.notifyTabMessageViewOnTouchDown(); + if (messageView instanceof TabMessageView) { + mOwner.notifyTabMessageViewOnTouchDown((TabMessageView) messageView); + } } @Override public void onTouchUp(View messageView) { - mOwner.notifyTabMessageViewOnTouchUp(); + if (messageView instanceof TabMessageView) { + mOwner.notifyTabMessageViewOnTouchUp((TabMessageView) messageView); + } } private void init() { From a6248423ab1d74b69ca04b250f38f953b1d8e0ae Mon Sep 17 00:00:00 2001 From: ybbarng Date: Mon, 22 Apr 2019 12:29:20 +0900 Subject: [PATCH 050/105] =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EC=AA=BD=EC=97=90=EC=84=9C=20=EC=BB=A4=EC=8A=A4=ED=84=B0?= =?UTF-8?q?=EB=A7=88=EC=9D=B4=EC=A7=95=EC=9D=84=20=ED=95=A0=20=EC=88=98=20?= =?UTF-8?q?=EC=9E=88=EB=8F=84=EB=A1=9D=20=EC=95=A0=EB=8B=88=EB=A9=94?= =?UTF-8?q?=EC=9D=B4=EC=85=98=20=EC=B2=98=EB=A6=AC=20=EB=93=B1=EC=9D=84=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hover/BaseTouchController.java | 24 ++-- .../java/io/mattcarroll/hover/Dragger.java | 20 +-- .../java/io/mattcarroll/hover/HoverMenu.java | 15 --- .../java/io/mattcarroll/hover/HoverView.java | 31 +---- .../hover/HoverViewStateCollapsed.java | 27 ++-- .../hover/HoverViewStatePreviewed.java | 119 ++++++------------ 6 files changed, 70 insertions(+), 166 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java b/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java index 0da9dda..4e398e1 100644 --- a/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java +++ b/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java @@ -61,11 +61,11 @@ public void enableDebugMode(boolean isDebugMode) { updateTouchControlViewAppearance(); } - private TouchViewItem createTouchViewItem(final HoverFrameLayout originalView, final TouchListener listener, final String tag) { + private , V extends HoverFrameLayout> TouchViewItem createTouchViewItem(final V originalView, final T listener, final String tag) { return new TouchViewItem<>(originalView, createTouchViewFrom(originalView), listener, tag); } - protected TouchDetector createTouchDetector(final View originalView, final TouchListener touchListener) { + protected , V extends View> TouchDetector createTouchDetector(final V originalView, final T touchListener) { return new TouchDetector<>(originalView, touchListener); } @@ -102,22 +102,22 @@ private View createTouchViewFrom(final View originalView) { return touchView; } - public interface TouchListener { - void onTap(View view); + public interface TouchListener { + void onTap(V view); - void onTouchDown(View view); + void onTouchDown(V view); - void onTouchUp(View view); + void onTouchUp(V view); } - protected class TouchDetector implements View.OnTouchListener { + protected class TouchDetector, V extends View> implements View.OnTouchListener { @NonNull - protected final View mOriginalView; + protected final V mOriginalView; @NonNull protected final T mEventListener; - TouchDetector(@NonNull final View originalView, @NonNull final T touchListener) { + TouchDetector(@NonNull final V originalView, @NonNull final T touchListener) { this.mOriginalView = originalView; this.mEventListener = touchListener; } @@ -140,12 +140,12 @@ public boolean onTouch(View view, MotionEvent motionEvent) { } } - protected class TouchViewItem { - final HoverFrameLayout mOriginalView; + protected class TouchViewItem> { + final V mOriginalView; final View mTouchView; final T mTouchListener; - TouchViewItem(final HoverFrameLayout originalView, final View touchView, final T touchListener, final String tag) { + TouchViewItem(final V originalView, final View touchView, final T touchListener, final String tag) { this.mOriginalView = originalView; this.mTouchView = touchView; this.mTouchListener = touchListener; diff --git a/hover/src/main/java/io/mattcarroll/hover/Dragger.java b/hover/src/main/java/io/mattcarroll/hover/Dragger.java index 8a7a1ce..4e9b519 100644 --- a/hover/src/main/java/io/mattcarroll/hover/Dragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/Dragger.java @@ -40,9 +40,9 @@ public Dragger(int mTapTouchSlop) { public abstract Point getContainerSize(); @Override - protected TouchDetector createTouchDetector(final View originalView, TouchListener touchListener) { + protected , V extends View> TouchDetector createTouchDetector(final V originalView, final T touchListener) { if (touchListener instanceof DragListener) { - return new DragDetector(originalView, (DragListener) touchListener); + return new DragDetector<>(originalView, (DragListener) touchListener); } else { return super.createTouchDetector(originalView, touchListener); } @@ -68,7 +68,7 @@ private PointF convertCenterToCorner(View touchView, @NonNull PointF centerPosit ); } - public interface DragListener extends TouchListener { + public interface DragListener extends TouchListener { /** * The user has begun dragging. * @@ -76,7 +76,7 @@ public interface DragListener extends TouchListener { * @param x x-coordinate of the user's drag start (in the parent View's coordinate space) * @param y y-coordiante of the user's drag start (in the parent View's coordinate space) */ - void onDragStart(View view, float x, float y); + void onDragStart(V view, float x, float y); /** * The user has dragged to the given coordinates. @@ -85,7 +85,7 @@ public interface DragListener extends TouchListener { * @param x x-coordinate of the user's drag (in the parent View's coordinate space) * @param y y-coordiante of the user's drag (in the parent View's coordinate space) */ - void onDragTo(View view, float x, float y); + void onDragTo(V view, float x, float y); /** * The user has stopped touching the drag area. @@ -94,10 +94,10 @@ public interface DragListener extends TouchListener { * @param x x-coordinate of the user's release (in the parent View's coordinate space) * @param y y-coordiante of the user's release (in the parent View's coordinate space) */ - void onReleasedAt(View view, float x, float y); + void onReleasedAt(V view, float x, float y); } - private class DragDetector extends TouchDetector { + private class DragDetector, V extends View> extends TouchDetector { private final GestureDetector mGestureDetector; private boolean mIsDragging; @@ -105,7 +105,7 @@ private class DragDetector extends TouchDetector { private PointF mCurrentViewPosition = new PointF(); private PointF mOriginalTouchPosition = new PointF(); - public DragDetector(final View originalView, final DragListener dragListener) { + public DragDetector(final V originalView, final T dragListener) { super(originalView, dragListener); mGestureDetector = new GestureDetector(null, new GestureDetector.SimpleOnGestureListener() { public void onLongPress(final MotionEvent e) { @@ -125,7 +125,7 @@ public boolean onTouch(View view, MotionEvent motionEvent) { mOriginalViewPosition = convertCornerToCenter(view, getTouchViewPosition(view)); mCurrentViewPosition = new PointF(mOriginalViewPosition.x, mOriginalViewPosition.y); mOriginalTouchPosition.set(motionEvent.getRawX(), motionEvent.getRawY()); - mEventListener.onTouchDown(view); + mEventListener.onTouchDown(mOriginalView); return true; case MotionEvent.ACTION_MOVE: Log.d(TAG, "ACTION_MOVE. motionX: " + motionEvent.getRawX() + ", motionY: " + motionEvent.getRawY()); @@ -145,7 +145,7 @@ public boolean onTouch(View view, MotionEvent motionEvent) { return true; case MotionEvent.ACTION_UP: Log.d(TAG, "ACTION_UP"); - mEventListener.onTouchUp(view); + mEventListener.onTouchUp(mOriginalView); if (!mIsDragging) { Log.d(TAG, "Reporting as a tap."); mEventListener.onTap(mOriginalView); diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverMenu.java b/hover/src/main/java/io/mattcarroll/hover/HoverMenu.java index 21dcaad..0e2d807 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverMenu.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverMenu.java @@ -34,13 +34,8 @@ public abstract class HoverMenu { private static final String TAG = "HoverMenu"; - public enum HoverMenuState { - IDLE, REMOVE_PREVIEW - } - private List
mSections = new ArrayList<>(); private ListUpdateCallback mListUpdateCallback; - private HoverMenuState mState = HoverMenuState.IDLE; public abstract String getId(); @@ -64,8 +59,6 @@ public int getSectionIndex(@NonNull Section section) { @NonNull public abstract List
getSections(); - protected abstract void onHoverMenuStateChanged(HoverMenuState state); - void setUpdatedCallback(@Nullable ListUpdateCallback listUpdatedCallback) { mListUpdateCallback = listUpdatedCallback; } @@ -84,14 +77,6 @@ public void notifyMenuChanged() { } } - public void setState(final HoverMenuState newState) { - final boolean changed = this.mState != newState; - this.mState = newState; - if (changed) { - onHoverMenuStateChanged(this.mState); - } - } - public static class SectionId { private String mId; diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverView.java b/hover/src/main/java/io/mattcarroll/hover/HoverView.java index 392fe61..ec00717 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverView.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverView.java @@ -105,7 +105,6 @@ public static HoverView createForView(@NonNull Context context) { OnExitListener mOnExitListener; private final Set mOnStateChangeListeners = new CopyOnWriteArraySet<>(); private final Set mOnFloatingTabInteractionListeners = new CopyOnWriteArraySet<>(); - private final Set mOnTabMessageViewInteractionListeners = new CopyOnWriteArraySet<>(); private boolean mKeepVisible; // Public for use with XML inflation. Clients should use static methods for construction. @@ -275,6 +274,10 @@ public HoverViewState getState() { return mState; } + public void setMessageViewDragListener(@Nullable final Dragger.DragListener messageViewDragListener) { + ((HoverViewStatePreviewed) mPreviewed).setMessageViewDragListener(messageViewDragListener); + } + private void onBackPressed() { mState.onBackPressed(); } @@ -381,15 +384,6 @@ public void removeOnFloatingTabInteractionListener(@NonNull OnFloatingTabInterac mOnFloatingTabInteractionListeners.remove(onFloatingTabInteractionListener); } - public void addOnTabMessageViewInteractionListener(@NonNull OnTabMessageViewInteractionListener onTabMessageViewInteractionListener) { - mOnTabMessageViewInteractionListeners.add(onTabMessageViewInteractionListener); - } - - public void removeOnTabMessageViewInteractionListener(@NonNull OnTabMessageViewInteractionListener onTabMessageViewInteractionListener) { - mOnTabMessageViewInteractionListeners.remove(onTabMessageViewInteractionListener); - } - - void notifyOnTap(HoverViewState state) { for (OnFloatingTabInteractionListener onFloatingTabInteractionListener : mOnFloatingTabInteractionListeners) { onFloatingTabInteractionListener.onTap(state.getStateType()); @@ -408,18 +402,6 @@ void notifyOnDocked(HoverViewState state) { } } - void notifyMessageViewOnTouchDown(final TabMessageView tabMessageView) { - for (final OnTabMessageViewInteractionListener listener : mOnTabMessageViewInteractionListeners) { - listener.onTouchDown(tabMessageView); - } - } - - void notifyMessageViewOnTouchUp(final TabMessageView tabMessageView) { - for (final OnTabMessageViewInteractionListener listener : mOnTabMessageViewInteractionListeners) { - listener.onTouchUp(tabMessageView); - } - } - // Only call this if using HoverMenuView directly in a window. public void addToWindow() { if (!mIsAddedToWindow) { @@ -675,9 +657,4 @@ public interface OnFloatingTabInteractionListener { void onDocked(HoverViewStateType stateType); } - public interface OnTabMessageViewInteractionListener { - void onTouchDown(TabMessageView tabMessageView); - - void onTouchUp(TabMessageView tabMessageView); - } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 8b555e8..1ed6d8c 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -48,7 +48,7 @@ class HoverViewStateCollapsed extends BaseHoverViewState { private static final float ALPHA_IDLE_VALUE = 0.4f; protected FloatingTab mFloatingTab; - protected final Dragger.DragListener mFloatingTabDragListener = new FloatingTabDragListener(this); + protected final FloatingTabDragListener mFloatingTabDragListener = new FloatingTabDragListener(this); protected HoverMenu.Section mSelectedSection; private int mSelectedSectionIndex = -1; private boolean mIsCollapsed = false; @@ -123,7 +123,6 @@ public void run() { } scheduleHoverViewAlphaChange(); - setHoverMenuMode(HoverMenu.HoverMenuState.IDLE); } @Override @@ -330,22 +329,12 @@ protected void restoreHoverViewAlphaValue() { mHoverView.setAlpha(1f); } - protected void setHoverMenuMode(final HoverMenu.HoverMenuState state) { - if (mHoverView == null) { - return; - } - if (mHoverView.mMenu == null) { - return; - } - mHoverView.mMenu.setState(state); - } - @Override public HoverViewStateType getStateType() { return HoverViewStateType.COLLAPSED; } - protected static final class FloatingTabDragListener implements Dragger.DragListener { + protected static final class FloatingTabDragListener implements Dragger.DragListener { private final HoverViewStateCollapsed mOwner; @@ -354,31 +343,31 @@ protected FloatingTabDragListener(@NonNull HoverViewStateCollapsed owner) { } @Override - public void onDragStart(View floatingTab, float x, float y) { + public void onDragStart(FloatingTab floatingTab, float x, float y) { mOwner.onPickedUpByUser(); } @Override - public void onDragTo(View floatingTab, float x, float y) { + public void onDragTo(FloatingTab floatingTab, float x, float y) { mOwner.moveFloatingTabTo(floatingTab, new Point((int) x, (int) y)); } @Override - public void onReleasedAt(View floatingTab, float x, float y) { + public void onReleasedAt(FloatingTab floatingTab, float x, float y) { mOwner.onDroppedByUser(); } @Override - public void onTap(View floatingTab) { + public void onTap(FloatingTab floatingTab) { mOwner.onTap(); } @Override - public void onTouchDown(View floatingTab) { + public void onTouchDown(FloatingTab floatingTab) { } @Override - public void onTouchUp(View floatingTab) { + public void onTouchUp(FloatingTab floatingTab) { } } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index 8920ab9..6eb69a4 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -15,11 +15,9 @@ */ package io.mattcarroll.hover; -import android.graphics.Point; import android.support.annotation.NonNull; import android.support.v4.util.Pair; import android.util.Log; -import android.view.View; import java.util.ArrayList; @@ -32,10 +30,12 @@ class HoverViewStatePreviewed extends HoverViewStateCollapsed { private static final String TAG = "HoverViewStatePreviewed"; private TabMessageView mMessageView; - protected final Dragger.DragListener mMessageViewDragListener = new MessageViewDragListener(this); + private Dragger.DragListener mDefaultMessageViewDragListener; + private Dragger.DragListener mCustomMessageViewDragListener; private boolean mCollapseOnDocked = false; HoverViewStatePreviewed() { + mDefaultMessageViewDragListener = new DefaultMessageViewDragListener(); init(); } @@ -85,7 +85,7 @@ protected void onClose(final boolean userDropped) { protected void activateDragger() { ArrayList> list = new ArrayList<>(); list.add(new Pair<>(mFloatingTab, mFloatingTabDragListener)); - list.add(new Pair<>(mMessageView, mMessageViewDragListener)); + list.add(new Pair<>(mMessageView, mDefaultMessageViewDragListener)); mHoverView.mDragger.activate(list); } @@ -103,111 +103,64 @@ public HoverViewStateType getStateType() { return HoverViewStateType.PREVIEWED; } - private void init() { - mCollapseOnDocked = false; + public void setMessageViewDragListener(final Dragger.DragListener messageViewDragListener) { + this.mCustomMessageViewDragListener = messageViewDragListener; } - private void hidePreview(final float startAlpha) { - if (mHoverView == null) { - return; - } - if (mMessageView != null) { - mMessageView.disappear(false, startAlpha); - } - mHoverView.collapse(); - } - - private void notifyTabMessageViewOnTouchDown(final TabMessageView tabMessageView) { - if (mHoverView == null) { - return; - } - mHoverView.notifyMessageViewOnTouchDown(tabMessageView); - } - - private void notifyTabMessageViewOnTouchUp(final TabMessageView tabMessageView) { - if (mHoverView == null) { - return; - } - mHoverView.notifyMessageViewOnTouchUp(tabMessageView); + private void init() { + mCollapseOnDocked = false; } - protected static final class MessageViewDragListener implements Dragger.DragListener { - - private static final float ALPHA_THRESHOLD = 400; - private static final float COLLAPSE_THRESHOLD = 300; - private final HoverViewStatePreviewed mOwner; - private float mOriginalX; - private float mOriginalY; - - protected MessageViewDragListener(@NonNull HoverViewStatePreviewed owner) { - mOwner = owner; - init(); - } + private class DefaultMessageViewDragListener implements Dragger.DragListener { @Override - public void onDragStart(View messageView, float x, float y) { - if (messageView instanceof TabMessageView) { - mOriginalX = messageView.getX() + messageView.getWidth() / 2; - mOriginalY = messageView.getY() + messageView.getHeight() / 2; - ((TabMessageView) messageView).moveCenterTo(new Point((int) x, (int) mOriginalY)); - updateAlpha(messageView, x); - mOwner.setHoverMenuMode(HoverMenu.HoverMenuState.REMOVE_PREVIEW); + public void onDragStart(TabMessageView view, float x, float y) { + if (mCustomMessageViewDragListener == null) { + return; } + mCustomMessageViewDragListener.onDragStart(view, x, y); + } @Override - public void onDragTo(View messageView, float x, float y) { - if (messageView instanceof TabMessageView) { - ((TabMessageView) messageView).moveCenterTo(new Point((int) x, (int) mOriginalY)); - Log.d("ALPHA", "" + (Math.abs(x - mOriginalX) / 200)); - updateAlpha(messageView, x); + public void onDragTo(TabMessageView view, float x, float y) { + if (mCustomMessageViewDragListener == null) { + return; } + mCustomMessageViewDragListener.onDragTo(view, x, y); } @Override - public void onReleasedAt(final View messageView, float x, float y) { - if (messageView instanceof TabMessageView) { - ((TabMessageView) messageView).moveCenterTo(new Point((int) mOriginalX, (int) mOriginalY)); - updateAlpha(messageView, mOriginalX); - if (Math.abs(x - mOriginalX) > COLLAPSE_THRESHOLD) { - updateAlpha(messageView, mOriginalX); - mOwner.hidePreview(getAlpha(x)); - } + public void onReleasedAt(TabMessageView view, float x, float y) { + if (mCustomMessageViewDragListener == null) { + return; } - mOwner.setHoverMenuMode(HoverMenu.HoverMenuState.IDLE); - init(); + mCustomMessageViewDragListener.onReleasedAt(view, x, y); } @Override - public void onTap(View messageView) { - mOwner.onTap(); + public void onTap(TabMessageView view) { + if (mCustomMessageViewDragListener == null) { + return; + } + mCustomMessageViewDragListener.onTap(view); } @Override - public void onTouchDown(View messageView) { - if (messageView instanceof TabMessageView) { - mOwner.notifyTabMessageViewOnTouchDown((TabMessageView) messageView); + public void onTouchDown(TabMessageView view) { + if (mCustomMessageViewDragListener == null) { + return; } + mCustomMessageViewDragListener.onTouchDown(view); } @Override - public void onTouchUp(View messageView) { - if (messageView instanceof TabMessageView) { - mOwner.notifyTabMessageViewOnTouchUp((TabMessageView) messageView); + public void onTouchUp(TabMessageView view) { + if (mCustomMessageViewDragListener == null) { + return; } - } - - private void init() { - mOriginalX = 0; - mOriginalY = 0; - } - - private void updateAlpha(final View view, final float current) { - view.setAlpha(getAlpha(current)); - } - - private float getAlpha(final float current) { - return 1 - Math.max(0, Math.min(1, (Math.abs(current - mOriginalX) / ALPHA_THRESHOLD))); + mCustomMessageViewDragListener.onTouchUp(view); } } + } From ab082215d361eb43cb6307e0dc9457d93726ebd5 Mon Sep 17 00:00:00 2001 From: ybbarng Date: Mon, 22 Apr 2019 13:24:19 +0900 Subject: [PATCH 051/105] =?UTF-8?q?Pop=EC=9D=84=20=EB=93=9C=EB=9E=98?= =?UTF-8?q?=EA=B7=B8=ED=95=98=EB=A9=B4=20Preview=EB=A5=BC=20=EC=88=A8?= =?UTF-8?q?=EA=B8=B0=EB=8D=98=20=EB=B6=80=EB=B6=84=EB=8F=84=20=EB=B0=96?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=B2=98=EB=A6=AC=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/io/mattcarroll/hover/HoverView.java | 8 ++++++++ .../mattcarroll/hover/HoverViewStatePreviewed.java | 13 ------------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverView.java b/hover/src/main/java/io/mattcarroll/hover/HoverView.java index ec00717..0c09af7 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverView.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverView.java @@ -431,6 +431,14 @@ public void removeFromWindow() { } } + @Nullable + public TabMessageView getTabMessageView() { + if (mScreen == null) { + return null; + } + return mScreen.getTabMessageView(mSelectedSectionId); + } + void makeTouchableInWindow() { mIsTouchableInWindow = true; if (mIsAddedToWindow) { diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index 6eb69a4..75c1055 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -32,11 +32,9 @@ class HoverViewStatePreviewed extends HoverViewStateCollapsed { private TabMessageView mMessageView; private Dragger.DragListener mDefaultMessageViewDragListener; private Dragger.DragListener mCustomMessageViewDragListener; - private boolean mCollapseOnDocked = false; HoverViewStatePreviewed() { mDefaultMessageViewDragListener = new DefaultMessageViewDragListener(); - init(); } @Override @@ -70,15 +68,12 @@ public void giveUpControl(@NonNull final HoverViewState nextState) { @Override protected void onPickedUpByUser() { - mMessageView.disappear(true); - mCollapseOnDocked = true; super.onPickedUpByUser(); } @Override protected void onClose(final boolean userDropped) { super.onClose(userDropped); - init(); } @Override @@ -92,10 +87,6 @@ protected void activateDragger() { @Override protected void onDocked() { super.onDocked(); - if (mCollapseOnDocked) { - mHoverView.collapse(); - mCollapseOnDocked = false; - } } @Override @@ -107,10 +98,6 @@ public void setMessageViewDragListener(final Dragger.DragListener { @Override From 2e2a21a88288cb4675689f911d7cdf06ebbb8cac Mon Sep 17 00:00:00 2001 From: ybbarng Date: Mon, 22 Apr 2019 13:51:08 +0900 Subject: [PATCH 052/105] =?UTF-8?q?FloatingTab=20=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=EB=84=88=20=EC=AA=BD=EA=B3=BC=20=EC=9D=B4=EB=A6=84=EC=9D=84=20?= =?UTF-8?q?=EB=A7=9E=EC=B6=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hover/src/main/java/io/mattcarroll/hover/HoverView.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverView.java b/hover/src/main/java/io/mattcarroll/hover/HoverView.java index 0c09af7..bb0041d 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverView.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverView.java @@ -274,7 +274,7 @@ public HoverViewState getState() { return mState; } - public void setMessageViewDragListener(@Nullable final Dragger.DragListener messageViewDragListener) { + public void setTabMessageViewInteractionListener(@Nullable final OnTabMessageViewInteractionListener messageViewDragListener) { ((HoverViewStatePreviewed) mPreviewed).setMessageViewDragListener(messageViewDragListener); } @@ -665,4 +665,6 @@ public interface OnFloatingTabInteractionListener { void onDocked(HoverViewStateType stateType); } + public abstract static class OnTabMessageViewInteractionListener implements Dragger.DragListener { + } } From bef619bd9a85a372e097a8cef5231d4e8bb6943a Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Mon, 22 Apr 2019 14:35:30 +0900 Subject: [PATCH 053/105] =?UTF-8?q?=EB=82=AE=EC=9D=80=20=EB=B2=84=EC=A0=84?= =?UTF-8?q?=EC=9D=98=20=EC=95=88=EB=93=9C=EB=A1=9C=EC=9D=B4=EB=93=9C?= =?UTF-8?q?=EC=97=90=EC=84=9C=20alpha=EA=B0=92=EC=9D=B4=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=B2=84?= =?UTF-8?q?=EA=B7=B8=20=EC=88=98=EC=A0=95=20(#26)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index a9435bd..13f14ad 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -58,7 +58,7 @@ public void run() { final HoverViewState state = mHoverView.getState(); if (!(state instanceof HoverViewStatePreviewed) && state instanceof HoverViewStateCollapsed) { if (mHoverView.shouldKeepVisible()) { - mHoverView.setAlpha(ALPHA_IDLE_VALUE); + mFloatingTab.setAlpha(ALPHA_IDLE_VALUE); } else { onClose(false); } From 1a6da349481b19245275ff141e73b9f68acfa3dd Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Mon, 22 Apr 2019 15:24:44 +0900 Subject: [PATCH 054/105] Bump version to 1.0.0-rc.4 --- hover/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hover/build.gradle b/hover/build.gradle index 81f55b8..3528a61 100644 --- a/hover/build.gradle +++ b/hover/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.library' apply plugin: 'checkstyle' project.group = 'com.buzzvil' -project.version = '1.0.0-rc.3' +project.version = '1.0.0-rc.4' android { compileSdkVersion project.compileSdkVersion.toInteger() From a4291d45d8e67c80d01284f3e685fb9b1df4bbeb Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Mon, 22 Apr 2019 15:40:36 +0900 Subject: [PATCH 055/105] =?UTF-8?q?=ED=88=AC=EB=AA=85=ED=95=B4=EC=A7=84=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=EC=9D=B4=20=EC=9B=90=EB=9E=98=EB=8C=80?= =?UTF-8?q?=EB=A1=9C=20=EB=8F=8C=EC=95=84=EC=98=A4=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8A=94=20=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95=20(#27)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hover/build.gradle | 2 +- .../main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hover/build.gradle b/hover/build.gradle index 3528a61..ef864af 100644 --- a/hover/build.gradle +++ b/hover/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.library' apply plugin: 'checkstyle' project.group = 'com.buzzvil' -project.version = '1.0.0-rc.4' +project.version = '1.0.0-rc.5' android { compileSdkVersion project.compileSdkVersion.toInteger() diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 13f14ad..7419b19 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -325,7 +325,7 @@ private void scheduleHoverViewAlphaChange() { protected void restoreHoverViewAlphaValue() { mHandler.removeCallbacks(mAlphaChanger); - mHoverView.setAlpha(1f); + mFloatingTab.setAlpha(1f); } @Override From 0395587972879fb1e014694691031573873dc47c Mon Sep 17 00:00:00 2001 From: ybbarng Date: Mon, 22 Apr 2019 17:53:46 +0900 Subject: [PATCH 056/105] =?UTF-8?q?=EB=93=9C=EB=9E=98=EA=B7=B8=20=EC=A4=91?= =?UTF-8?q?=EA=B0=84=EC=97=90=20=ED=99=94=EB=A9=B4=EC=9D=84=20=EB=81=84?= =?UTF-8?q?=EB=A9=B4=20=EB=93=9C=EB=9E=98=EA=B7=B8=20Cancel=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 원인: Android 5.x에서는 화면 종료시 ACTION_UP이 호출되지만, 그 이후 어느 버전에서는 드래그 중에 화면을 끄면 ACTION_CANCEL이 불리므로 드래그 위치를 원래대로 보내는 로직이 동작하지 않는다. 이를 자연스럽게 처리하기 위해서 cancel callback을 만들어 처리할 수 있게 하였다. --- .../main/java/io/mattcarroll/hover/Dragger.java | 15 +++++++++++++++ .../hover/HoverViewStateCollapsed.java | 5 +++++ .../hover/HoverViewStatePreviewed.java | 7 +++++++ 3 files changed, 27 insertions(+) diff --git a/hover/src/main/java/io/mattcarroll/hover/Dragger.java b/hover/src/main/java/io/mattcarroll/hover/Dragger.java index 4e9b519..60d7394 100644 --- a/hover/src/main/java/io/mattcarroll/hover/Dragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/Dragger.java @@ -95,6 +95,13 @@ public interface DragListener extends TouchListener { * @param y y-coordiante of the user's release (in the parent View's coordinate space) */ void onReleasedAt(V view, float x, float y); + + /** + * The drag is cancelled (ex: due to screen off). + * + * @param view the view that is being dragged + */ + void onDragCancel(V view); } private class DragDetector, V extends View> extends TouchDetector { @@ -152,7 +159,15 @@ public boolean onTouch(View view, MotionEvent motionEvent) { } else { Log.d(TAG, "Reporting as a drag release at: " + mCurrentViewPosition); mEventListener.onReleasedAt(mOriginalView, mCurrentViewPosition.x, mCurrentViewPosition.y); + mIsDragging = false; + } + return true; + case MotionEvent.ACTION_CANCEL: + Log.d(TAG, "ACTION_CANCEL"); + if (mIsDragging) { + mEventListener.onDragCancel(mOriginalView); } + mIsDragging = false; return true; default: return false; diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 1ed6d8c..12bca92 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -357,6 +357,11 @@ public void onReleasedAt(FloatingTab floatingTab, float x, float y) { mOwner.onDroppedByUser(); } + @Override + public void onDragCancel(FloatingTab floatingTab) { + mOwner.onDroppedByUser(); + } + @Override public void onTap(FloatingTab floatingTab) { mOwner.onTap(); diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index 75c1055..f032375 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -124,6 +124,13 @@ public void onReleasedAt(TabMessageView view, float x, float y) { } mCustomMessageViewDragListener.onReleasedAt(view, x, y); } + @Override + public void onDragCancel(TabMessageView view) { + if (mCustomMessageViewDragListener == null) { + return; + } + mCustomMessageViewDragListener.onDragCancel(view); + } @Override public void onTap(TabMessageView view) { From 7e699467da5fea08cb3c2858a1374e211f594274 Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Thu, 2 May 2019 17:06:05 +0900 Subject: [PATCH 057/105] =?UTF-8?q?Collapsed=20State=EC=97=90=EC=84=9C=20i?= =?UTF-8?q?dle=20=EC=83=81=ED=83=9C=EA=B0=80=20=EB=90=98=EC=97=88=EC=9D=84?= =?UTF-8?q?=EB=95=8C=20=EB=8F=99=EC=9E=91=EC=9D=84=20=EC=99=B8=EB=B6=80?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=A0=95=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD=20(#28)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/mattcarroll/hover/HoverView.java | 17 ++++-- .../hover/HoverViewStateCollapsed.java | 58 +++++++++++-------- .../io/mattcarroll/hover/TabMessageView.java | 5 ++ 3 files changed, 51 insertions(+), 29 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverView.java b/hover/src/main/java/io/mattcarroll/hover/HoverView.java index bb0041d..0065b13 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverView.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverView.java @@ -26,6 +26,7 @@ import android.util.AttributeSet; import android.util.Log; import android.view.KeyEvent; +import android.view.View; import android.view.ViewConfiguration; import android.view.WindowManager; import android.widget.RelativeLayout; @@ -105,7 +106,7 @@ public static HoverView createForView(@NonNull Context context) { OnExitListener mOnExitListener; private final Set mOnStateChangeListeners = new CopyOnWriteArraySet<>(); private final Set mOnFloatingTabInteractionListeners = new CopyOnWriteArraySet<>(); - private boolean mKeepVisible; + private HoverViewIdleAction mIdleAction; // Public for use with XML inflation. Clients should use static methods for construction. public HoverView(@NonNull Context context, @Nullable AttributeSet attrs) { @@ -356,12 +357,12 @@ public void run() { }); } - public void setKeepVisible(boolean keepVisible) { - this.mKeepVisible = keepVisible; + public void setIdleAction(HoverViewIdleAction idleAction) { + this.mIdleAction = idleAction; } - public boolean shouldKeepVisible() { - return mKeepVisible; + public HoverViewIdleAction getIdleAction() { + return mIdleAction; } public void setOnExitListener(@Nullable OnExitListener listener) { @@ -667,4 +668,10 @@ public interface OnFloatingTabInteractionListener { public abstract static class OnTabMessageViewInteractionListener implements Dragger.DragListener { } + + public interface HoverViewIdleAction { + void changeState(View iconView); + + void restoreState(View iconView); + } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 4f39677..a5690e1 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -44,8 +44,7 @@ class HoverViewStateCollapsed extends BaseHoverViewState { private static final String TAG = "HoverViewStateCollapsed"; private static final float MIN_TAB_VERTICAL_POSITION = 0.0f; private static final float MAX_TAB_VERTICAL_POSITION = 1.0f; - private static final long ALPHA_IDLE_MILLIS = 5000; - private static final float ALPHA_IDLE_VALUE = 0.4f; + private static final long DEFAULT_IDLE_MILLIS = 5000; protected FloatingTab mFloatingTab; protected final FloatingTabDragListener mFloatingTabDragListener = new FloatingTabDragListener(this); @@ -53,19 +52,7 @@ class HoverViewStateCollapsed extends BaseHoverViewState { private int mSelectedSectionIndex = -1; private boolean mIsCollapsed = false; private Handler mHandler = new Handler(); - private Runnable mAlphaChanger = new Runnable() { - @Override - public void run() { - final HoverViewState state = mHoverView.getState(); - if (!(state instanceof HoverViewStatePreviewed) && state instanceof HoverViewStateCollapsed) { - if (mHoverView.shouldKeepVisible()) { - mFloatingTab.setAlpha(ALPHA_IDLE_VALUE); - } else { - onClose(false); - } - } - } - }; + private Runnable mIdleActionRunnable; private Runnable mOnStateChanged; @Override @@ -122,13 +109,13 @@ public void run() { listenForMenuChanges(); } - scheduleHoverViewAlphaChange(); + initIdleActionRunnable(); } @Override public void giveUpControl(@NonNull HoverViewState nextState) { Log.d(TAG, "Giving up control."); - restoreHoverViewAlphaValue(); + restoreHoverViewIdleAction(); if (null != mHoverView.mMenu) { mHoverView.mMenu.setUpdatedCallback(null); @@ -198,7 +185,7 @@ public void onBackPressed() { protected void onPickedUpByUser() { mHoverView.mScreen.getExitView().setVisibility(VISIBLE); - restoreHoverViewAlphaValue(); + restoreHoverViewIdleAction(); mHoverView.notifyOnDragStart(this); } @@ -292,7 +279,7 @@ protected void onDocked() { return; } activateDragger(); - scheduleHoverViewAlphaChange(); + scheduleHoverViewIdleAction(); // We consider ourselves having gone from "collapsing" to "collapsed" upon the very first dock. boolean didJustCollapse = !mIsCollapsed; @@ -320,13 +307,36 @@ protected void deactivateDragger() { mHoverView.mDragger.deactivate(); } - private void scheduleHoverViewAlphaChange() { - mHandler.postDelayed(mAlphaChanger, ALPHA_IDLE_MILLIS); + private void initIdleActionRunnable() { + this.mIdleActionRunnable = new Runnable() { + @Override + public void run() { + if (mHoverView == null) { + return; + } + + final HoverViewState state = mHoverView.getState(); + if (!(state instanceof HoverViewStatePreviewed) && state instanceof HoverViewStateCollapsed) { + final HoverView.HoverViewIdleAction idleAction = mHoverView.getIdleAction(); + if (idleAction != null) { + idleAction.changeState(mFloatingTab); + } + + } + } + }; + } + + private void scheduleHoverViewIdleAction() { + mHandler.postDelayed(mIdleActionRunnable, DEFAULT_IDLE_MILLIS); } - protected void restoreHoverViewAlphaValue() { - mHandler.removeCallbacks(mAlphaChanger); - mFloatingTab.setAlpha(1f); + protected void restoreHoverViewIdleAction() { + mHandler.removeCallbacks(mIdleActionRunnable); + final HoverView.HoverViewIdleAction idleAction = mHoverView.getIdleAction(); + if (idleAction != null) { + idleAction.restoreState(mFloatingTab); + } } @Override diff --git a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java index 8f29234..6badd87 100644 --- a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java +++ b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java @@ -87,6 +87,11 @@ public void setMessageView(@Nullable View view) { } } + @Nullable + public View getMessageView() { + return mMessageView; + } + public void appear(final SideDock dock, @Nullable final Runnable onAppeared) { mSideDock = dock; mFloatingTab.addOnPositionChangeListener(mOnFloatingTabChangeListener); From 715d89147845aa81ea98fef70ccb5d6bf104b11e Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Thu, 2 May 2019 17:39:45 +0900 Subject: [PATCH 058/105] =?UTF-8?q?OnExitListener=EA=B0=80=20=EC=9D=98?= =?UTF-8?q?=EB=AF=B8=EB=8C=80=EB=A1=9C=20=EB=8F=99=EC=9E=91=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#29)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/io/mattcarroll/hover/HoverViewStateClosed.java | 3 --- .../java/io/mattcarroll/hover/HoverViewStateCollapsed.java | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java index 40f3da2..6c6fb36 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java @@ -43,9 +43,6 @@ public void run() { return; } mHoverView.mScreen.destroyChainedTab(selectedTab); - if (null != mHoverView.mOnExitListener) { - mHoverView.mOnExitListener.onExit(); - } onStateChanged.run(); } }); diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index a5690e1..cc526ee 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -225,6 +225,9 @@ private void onDroppedByUser() { protected void onClose(final boolean userDropped) { if (userDropped) { Log.d(TAG, "User dropped floating tab on exit."); + if (null != mHoverView.mOnExitListener) { + mHoverView.mOnExitListener.onExit(); + } } else { Log.d(TAG, "Auto dropped."); } From bb30703b193b19666aae4691e935f67ebc8caad7 Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Wed, 8 May 2019 19:15:25 +0900 Subject: [PATCH 059/105] Bump version to 1.0.0-rc.6 --- hover/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hover/build.gradle b/hover/build.gradle index ef864af..5956b31 100644 --- a/hover/build.gradle +++ b/hover/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.library' apply plugin: 'checkstyle' project.group = 'com.buzzvil' -project.version = '1.0.0-rc.5' +project.version = '1.0.0-rc.6' android { compileSdkVersion project.compileSdkVersion.toInteger() From f91040f53a8aa54ba3e42d9a290b261ff72bdda1 Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Tue, 21 May 2019 15:58:14 +0900 Subject: [PATCH 060/105] Hover crash fix (#30) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * HoverViewStateCollapsed 상태에서 다른 state로 넘어갈 때 dragger가 deactivate 되는 동시에 터치를 할 경우 NPE가 발생하는 이슈 수정 * OverlayPermission이 없을 경우, window에 view를 추가하거나 layout을 update하지 못하는 이슈 수정 --- .../hover/HoverViewStateCollapsed.java | 14 +++++- .../hover/window/WindowViewController.java | 44 +++++++++++++++++-- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index cc526ee..ff37057 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -184,12 +184,20 @@ public void onBackPressed() { } protected void onPickedUpByUser() { + if (!hasControl()) { + return; + } + mHoverView.mScreen.getExitView().setVisibility(VISIBLE); restoreHoverViewIdleAction(); mHoverView.notifyOnDragStart(this); } private void onDroppedByUser() { + if (!hasControl()) { + return; + } + mHoverView.mScreen.getExitView().setVisibility(GONE); boolean droppedOnExit = mHoverView.mScreen.getExitView().isInExitZone(mFloatingTab.getPosition()); if (droppedOnExit) { @@ -223,6 +231,10 @@ private void onDroppedByUser() { } protected void onClose(final boolean userDropped) { + if (!hasControl()) { + return; + } + if (userDropped) { Log.d(TAG, "User dropped floating tab on exit."); if (null != mHoverView.mOnExitListener) { @@ -278,7 +290,7 @@ private void initDockPosition() { protected void onDocked() { Log.d(TAG, "Docked. Activating dragger."); - if (!mHoverView.mIsAddedToWindow) { + if (!hasControl() || !mHoverView.mIsAddedToWindow) { return; } activateDragger(); diff --git a/hover/src/main/java/io/mattcarroll/hover/window/WindowViewController.java b/hover/src/main/java/io/mattcarroll/hover/window/WindowViewController.java index bd2cd7a..1d76369 100755 --- a/hover/src/main/java/io/mattcarroll/hover/window/WindowViewController.java +++ b/hover/src/main/java/io/mattcarroll/hover/window/WindowViewController.java @@ -35,6 +35,10 @@ public WindowViewController(@NonNull WindowManager windowManager) { } public void addView(int width, int height, boolean isTouchable, @NonNull View view) { + addViewToWindow(view, buildLayoutParams(width, height, isTouchable)); + } + + private WindowManager.LayoutParams buildLayoutParams(final int width, final int height, final boolean isTouchable) { // If this view is untouchable then add the corresponding flag, otherwise set to zero which // won't have any effect on the OR'ing of flags. int touchableFlag = isTouchable ? 0 : WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; @@ -50,11 +54,13 @@ public void addView(int width, int height, boolean isTouchable, @NonNull View vi WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | touchableFlag, PixelFormat.TRANSLUCENT ); + + params.gravity = Gravity.TOP | Gravity.LEFT; params.x = 0; params.y = 0; - mWindowManager.addView(view, params); + return params; } public void removeView(@NonNull View view) { @@ -70,9 +76,14 @@ public Point getViewPosition(@NonNull View view) { public void moveViewTo(View view, int x, int y) { WindowManager.LayoutParams params = (WindowManager.LayoutParams) view.getLayoutParams(); + if (params == null) { + params = buildLayoutParams(view.getWidth(), view.getHeight(), true); + } + params.x = x; params.y = y; - mWindowManager.updateViewLayout(view, params); + + updateViewLayout(view, params); } public void showView(View view) { @@ -94,14 +105,39 @@ public void hideView(View view) { public void makeTouchable(View view) { WindowManager.LayoutParams params = (WindowManager.LayoutParams) view.getLayoutParams(); + if (params == null) { + params = buildLayoutParams(view.getWidth(), view.getHeight(), true); + } params.flags = params.flags & ~WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE & ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; - mWindowManager.updateViewLayout(view, params); + + updateViewLayout(view, params); } public void makeUntouchable(View view) { WindowManager.LayoutParams params = (WindowManager.LayoutParams) view.getLayoutParams(); + if (params == null) { + params = buildLayoutParams(view.getWidth(), view.getHeight(), true); + } params.flags = params.flags | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; - mWindowManager.updateViewLayout(view, params); + + updateViewLayout(view, params); + } + + private void updateViewLayout(final View view, final WindowManager.LayoutParams params) { + try { + mWindowManager.updateViewLayout(view, params); + } catch (IllegalArgumentException e) { + // View is not attached to the window manager + addViewToWindow(view, params); + } + } + + private void addViewToWindow(final View view, final WindowManager.LayoutParams params) { + try { + mWindowManager.addView(view, params); + } catch (WindowManager.BadTokenException e) { + // Permission denied. Cannot add the View to the Window. + } } public Point getWindowSize() { From 13eb141ab722297d16f06f1987f64c81c05b09bd Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Tue, 21 May 2019 16:00:34 +0900 Subject: [PATCH 061/105] Bump version to 1.0.0-rc.7 --- hover/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hover/build.gradle b/hover/build.gradle index 5956b31..ac8eeb2 100644 --- a/hover/build.gradle +++ b/hover/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.library' apply plugin: 'checkstyle' project.group = 'com.buzzvil' -project.version = '1.0.0-rc.6' +project.version = '1.0.0-rc.7' android { compileSdkVersion project.compileSdkVersion.toInteger() From 03e360d66892cd3b50fe1e18e42c3f1750bb4a24 Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Mon, 26 Aug 2019 12:29:20 +0900 Subject: [PATCH 062/105] Fix initialDocPosition on PopupConfig --- .../java/io/mattcarroll/hover/HoverView.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverView.java b/hover/src/main/java/io/mattcarroll/hover/HoverView.java index 0065b13..4ac199a 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverView.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverView.java @@ -30,15 +30,15 @@ import android.view.ViewConfiguration; import android.view.WindowManager; import android.widget.RelativeLayout; - -import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; - import io.mattcarroll.hover.view.InViewDragger; import io.mattcarroll.hover.window.InWindowDragger; import io.mattcarroll.hover.window.WindowViewController; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; + import static io.mattcarroll.hover.SideDock.SidePosition.LEFT; +import static io.mattcarroll.hover.SideDock.SidePosition.RIGHT; /** * {@code HoverMenuView} is a floating menu implementation. This implementation displays tabs along @@ -98,6 +98,7 @@ public static HoverView createForView(@NonNull Context context) { HoverMenu mMenu; HoverMenu.SectionId mSelectedSectionId; SideDock mCollapsedDock; + SideDock.SidePosition mInitialDockPosition; boolean mIsAddedToWindow; boolean mIsTouchableInWindow; boolean mIsDebugMode = false; @@ -139,6 +140,7 @@ private HoverView(@NonNull Context context, mDragger = dragger; mScreen = new Screen(this); mWindowViewController = windowViewController; + mInitialDockPosition = initialDockPosition; init(); @@ -574,7 +576,7 @@ private static class PersistentState { } public void restore(@NonNull HoverView hoverView, @NonNull HoverMenu menu) { - SideDock.SidePosition sidePosition = getSidePosition(menu.getId()); + SideDock.SidePosition sidePosition = getSidePosition(menu.getId(), hoverView.mInitialDockPosition); hoverView.mCollapsedDock = new SideDock( hoverView, hoverView.mTabSize, @@ -590,10 +592,10 @@ public void restore(@NonNull HoverView hoverView, @NonNull HoverMenu menu) { + ", Section ID: " + selectedSectionId); } - private SideDock.SidePosition getSidePosition(@NonNull String menuId) { + private SideDock.SidePosition getSidePosition(@NonNull String menuId, @Nullable SideDock.SidePosition initialDockPosition) { return new SideDock.SidePosition( - mPrefs.getInt(menuId + SAVED_STATE_DOCKS_SIDE, LEFT), - mPrefs.getFloat(menuId + SAVED_STATE_DOCK_POSITION, 0.5f) + mPrefs.getInt(menuId + SAVED_STATE_DOCKS_SIDE, initialDockPosition != null ? initialDockPosition.getSide() : RIGHT), + mPrefs.getFloat(menuId + SAVED_STATE_DOCK_POSITION, initialDockPosition != null ? initialDockPosition.getVerticalDockPositionPercentage() : 0.6f) ); } From 98869a11beaa7979721804f58e971f261072ed62 Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Thu, 5 Sep 2019 17:24:59 +0900 Subject: [PATCH 063/105] Add ExitView show/hide animation --- .../java/io/mattcarroll/hover/ExitView.java | 33 +++++++++++++++++++ .../hover/HoverViewStateCollapsed.java | 6 ++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/ExitView.java b/hover/src/main/java/io/mattcarroll/hover/ExitView.java index 6e79170..5a57aa0 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ExitView.java +++ b/hover/src/main/java/io/mattcarroll/hover/ExitView.java @@ -15,6 +15,8 @@ */ package io.mattcarroll.hover; +import android.animation.Animator; +import android.animation.ObjectAnimator; import android.content.Context; import android.graphics.Point; import android.support.annotation.NonNull; @@ -32,6 +34,7 @@ class ExitView extends RelativeLayout { private static final String TAG = "ExitView"; + private static final int FADE_DURATION = 250; private int mExitRadiusInPx; private View mExitIcon; @@ -71,4 +74,34 @@ private double calculateDistance(@NonNull Point p1, @NonNull Point p2) { Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2) ); } + + public void show() { + ObjectAnimator fadeOut = ObjectAnimator.ofFloat(this, "alpha", 1.0f); + fadeOut.setDuration(FADE_DURATION); + fadeOut.start(); + + setVisibility(VISIBLE); + } + + public void hide() { + ObjectAnimator fadeOut = ObjectAnimator.ofFloat(this, "alpha", 0.0f); + fadeOut.setDuration(FADE_DURATION); + fadeOut.start(); + + fadeOut.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { } + + @Override + public void onAnimationEnd(Animator animation) { + setVisibility(GONE); + } + + @Override + public void onAnimationCancel(Animator animation) { } + + @Override + public void onAnimationRepeat(Animator animation) { } + }); + } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index ff37057..e3f8d35 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -121,7 +121,7 @@ public void giveUpControl(@NonNull HoverViewState nextState) { mHoverView.mMenu.setUpdatedCallback(null); } - mHoverView.mScreen.getExitView().setVisibility(GONE); + mHoverView.mScreen.getExitView().hide(); deactivateDragger(); mFloatingTab = null; @@ -188,7 +188,7 @@ protected void onPickedUpByUser() { return; } - mHoverView.mScreen.getExitView().setVisibility(VISIBLE); + mHoverView.mScreen.getExitView().show(); restoreHoverViewIdleAction(); mHoverView.notifyOnDragStart(this); } @@ -198,7 +198,7 @@ private void onDroppedByUser() { return; } - mHoverView.mScreen.getExitView().setVisibility(GONE); + mHoverView.mScreen.getExitView().hide(); boolean droppedOnExit = mHoverView.mScreen.getExitView().isInExitZone(mFloatingTab.getPosition()); if (droppedOnExit) { onClose(true); From 8755b79b9795f70fca112a6fc34cbcb32da449d5 Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Fri, 6 Sep 2019 17:10:18 +0900 Subject: [PATCH 064/105] Add show/hide Animation test for ExitView --- .../java/io/mattcarroll/hover/ExitView.java | 257 +++++++++++++++++- .../hover/HoverViewStateCollapsed.java | 19 +- .../main/res/layout/view_hover_menu_exit.xml | 28 +- 3 files changed, 278 insertions(+), 26 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/ExitView.java b/hover/src/main/java/io/mattcarroll/hover/ExitView.java index 5a57aa0..5232c32 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ExitView.java +++ b/hover/src/main/java/io/mattcarroll/hover/ExitView.java @@ -17,6 +17,7 @@ import android.animation.Animator; import android.animation.ObjectAnimator; +import android.animation.PropertyValuesHolder; import android.content.Context; import android.graphics.Point; import android.support.annotation.NonNull; @@ -25,6 +26,7 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; import android.widget.RelativeLayout; /** @@ -34,9 +36,20 @@ class ExitView extends RelativeLayout { private static final String TAG = "ExitView"; - private static final int FADE_DURATION = 250; + private static final int FADE_DURATION = 300; private int mExitRadiusInPx; private View mExitIcon; + private View mExitGradient; + private ViewGroup mVgExit; +// private boolean mAnimated = false; +// public ViewPropertyAnimator exitEnterAnim; +// public ViewPropertyAnimator exitExitAnim; + public ObjectAnimator anim1 = null; + public ObjectAnimator anim2 = null; + public boolean isExitAnimated = false; + private float mDefaultScaleX = 1.0f; + private float mDefaultScaleY = 1.0f; + private float mDefaultRotation = 0f; public ExitView(@NonNull Context context) { this(context, null); @@ -51,17 +64,90 @@ private void init() { LayoutInflater.from(getContext()).inflate(R.layout.view_hover_menu_exit, this, true); mExitIcon = findViewById(R.id.view_exit); - + mVgExit = findViewById(R.id.vg_exit); + mExitGradient = findViewById(R.id.view_exit_gradient); mExitRadiusInPx = getResources().getDimensionPixelSize(R.dimen.hover_exit_radius); + + setAnimations(); + } + + private void setAnimations() { + PropertyValuesHolder pv1 = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 1.5f); + PropertyValuesHolder pv2 = PropertyValuesHolder.ofFloat("scaleY", 1.0f, 1.5f); + PropertyValuesHolder pv3 = PropertyValuesHolder.ofFloat("rotation", 0f, 90f); + anim1 = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, pv1, pv2, pv3); + anim1.setDuration(300L); + anim1.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animator) { + Log.d(TAG, "anim1 onAnimationStart"); + mExitIcon.setScaleY(mDefaultScaleY); + mExitIcon.setScaleX(mDefaultScaleX); + mExitIcon.setRotation(mDefaultRotation); + } + + @Override + public void onAnimationEnd(Animator animator) { + Log.d(TAG, "anim1 onAnimationEnd"); + } + + @Override + public void onAnimationCancel(Animator animator) { +// initExitButtonProperties(); + Log.d(TAG, "anim1 onAnimationCancel"); + mExitIcon.setScaleY(mDefaultScaleY); + mExitIcon.setScaleX(mDefaultScaleX); + mExitIcon.setRotation(mDefaultRotation); + } + + @Override + public void onAnimationRepeat(Animator animator) { + Log.d(TAG, "anim1 onAnimationRepeat"); + } + }); + + PropertyValuesHolder pva1 = PropertyValuesHolder.ofFloat("scaleX", 1.5f, 1.0f); + PropertyValuesHolder pva2 = PropertyValuesHolder.ofFloat("scaleY", 1.5f, 1.0f); + PropertyValuesHolder pva3 = PropertyValuesHolder.ofFloat("rotation", 90f, 0f); + anim2 = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, pva1, pva2, pva3); + anim2.setDuration(300L); + anim2.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animator) { + Log.d(TAG, "anim2 onAnimationStart"); + } + + @Override + public void onAnimationEnd(Animator animator) { + Log.d(TAG, "anim2 onAnimationEnd"); + } + + @Override + public void onAnimationCancel(Animator animator) { + Log.d(TAG, "anim2 onAnimationCancel"); + + } + + @Override + public void onAnimationRepeat(Animator animator) { + Log.d(TAG, "anim2 onAnimationRepeat"); + } + }); } - public boolean isInExitZone(@NonNull Point position) { + + public boolean isInExitZone(@NonNull Point position, int screenY, int threashold) { Point exitCenter = getExitZoneCenter(); - double distanceToExit = calculateDistance(position, exitCenter); - Log.d(TAG, "Drop point: " + position + ", Exit center: " + exitCenter + ", Distance: " + distanceToExit); - return distanceToExit <= mExitRadiusInPx; + return threashold < position.y; } +// public boolean isInExitZone(@NonNull Point position) { +// Point exitCenter = getExitZoneCenter(); +// double distanceToExit = calculateDistance(position, exitCenter); +// Log.d(TAG, "Drop point: " + position + ", Exit center: " + exitCenter + ", Distance: " + distanceToExit); +// return distanceToExit <= mExitRadiusInPx; +// } + private Point getExitZoneCenter() { return new Point( (int) (mExitIcon.getX() + (mExitIcon.getWidth() / 2)), @@ -75,20 +161,165 @@ private double calculateDistance(@NonNull Point p1, @NonNull Point p2) { ); } + public void startEnterExitAnim() { + if ((anim1 == null || !anim1.isRunning()) && !isExitAnimated) { + +// if (anim2 != null && anim2.isRunning()) { +// anim2.cancel(); +// } + anim1.start(); + isExitAnimated = true; + } + } + + public void startExitExitAnim() { + if ((anim2 == null || !anim2.isRunning()) && isExitAnimated) { +// if (anim1 != null && anim1.isRunning()) { +// anim1.cancel(); +// } + anim2.start(); + isExitAnimated = false; + } + } + + public void testEnterExitRange(Point position) { +// ObjectAnimator fadeOut = ObjectAnimator.ofFloat(mExitIcon, "scaleX", 1.0f, 1.5f); +// fadeOut.setDuration(FADE_DURATION); +// fadeOut.start(); +// +// +// ObjectAnimator aa = ObjectAnimator.ofFloat(mExitIcon, "scaleY", 1.0f, 1.5f); +// aa.setDuration(FADE_DURATION); +// aa.start(); + +// if (anim1 != null) { +// Log.d(TAG, "enterExitRange anim1.isRunning = " + anim1.isRunning()); +// } + + // case 1 done but seems slow. +// if (isInExitZone(position)) { +// if ((anim1 == null || !anim1.isRunning()) && !isExitAnimated) { +// +//// if (anim2 != null && anim2.isRunning()) { +//// anim2.cancel(); +//// } +// PropertyValuesHolder pv1 = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 1.5f); +// PropertyValuesHolder pv2 = PropertyValuesHolder.ofFloat("scaleY", 1.0f, 1.5f); +// PropertyValuesHolder pv3 = PropertyValuesHolder.ofFloat("rotation", 0f, 90f); +// anim1 = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, pv1, pv2, pv3); +// anim1.setDuration(300L); +// anim1.start(); +// isExitAnimated = true; +// } +// } else { +// if ((anim2 == null || !anim2.isRunning()) && isExitAnimated) { +//// if (anim1 != null && anim1.isRunning()) { +//// anim1.cancel(); +//// } +// PropertyValuesHolder pv1 = PropertyValuesHolder.ofFloat("scaleX", 1.5f, 1.0f); +// PropertyValuesHolder pv2 = PropertyValuesHolder.ofFloat("scaleY", 1.5f, 1.0f); +// PropertyValuesHolder pv3 = PropertyValuesHolder.ofFloat("rotation", 90f, 0f); +// anim2 = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, pv1, pv2, pv3); +// anim2.setDuration(300L); +// anim2.start(); +// isExitAnimated = false; +// } +// } + +// mExitIcon.rotation + + +// if (isInExitZone(position) && !mAnimated) { +// Log.d(TAG, "enterExitRange 1 isInExitZone(position) = " + isInExitZone(position) + ", Animated = " + mAnimated); +// +//// if (exitEnterAnim != null) +// exitEnterAnim = mExitIcon.animate() +// .scaleXBy(0.5f) +// .scaleYBy(0.5f) +// .rotationBy(90) +// .setDuration(300); +// exitEnterAnim.start(); +// mAnimated = true; +// } else if (mAnimated) { +// Log.d(TAG, "enterExitRange 2 isInExitZone(position) = " + isInExitZone(position) + ", Animated = " + mAnimated); +// exitExitAnim = mExitIcon.animate() +// .scaleXBy(0f) +// .scaleYBy(0f) +// .rotationBy(-90) +// .setDuration(300); +// exitExitAnim.start(); +// mAnimated = false; +// +// } + +// Log.d(TAG, "enterExitRange mExitIcon.getAnimation() == null = " + (mExitIcon.getAnimation() == null)); +// if (isInExitZone(position) && !mAnimated) { +// Log.d(TAG, "enterExitRange 1 isInExitZone(position) = " + isInExitZone(position) + ", Animated = " + mAnimated); +// +//// if (exitEnterAnim != null) +// if (mExitIcon.getAnimation() == null || mExitIcon.getAnimation().hasEnded()) { +// exitEnterAnim = mExitIcon.animate() +// .scaleXBy(0.5f) +// .scaleYBy(0.5f) +// .rotationBy(90) +// .setDuration(300); +// exitEnterAnim.start(); +// mAnimated = true; +// } +// } else if (mAnimated) { +// Log.d(TAG, "enterExitRange 2 isInExitZone(position) = " + isInExitZone(position) + ", Animated = " + mAnimated); +// if (mExitIcon.getAnimation() == null || mExitIcon.getAnimation().hasEnded()) { +// exitExitAnim = mExitIcon.animate() +// .scaleXBy(0f) +// .scaleYBy(0f) +// .rotationBy(-90) +// .setDuration(300); +// exitExitAnim.start(); +// mAnimated = false; +// } +// } + + setVisibility(VISIBLE); + } + public void show() { - ObjectAnimator fadeOut = ObjectAnimator.ofFloat(this, "alpha", 1.0f); - fadeOut.setDuration(FADE_DURATION); - fadeOut.start(); + resetExitButtonAnimation(); + + ObjectAnimator exitGradientAnimator = ObjectAnimator.ofFloat(mExitGradient, "alpha", EXIT_VIEW_TARGET_ALPHA); + exitGradientAnimator.setDuration(300L); + exitGradientAnimator.start(); + + ObjectAnimator vgExitAnimator = ObjectAnimator.ofFloat(mVgExit, "y", EXIT_VIEW_BASE_Y, EXIT_VIEW_TARGET_Y); + vgExitAnimator.setDuration(300L); + vgExitAnimator.start(); setVisibility(VISIBLE); } + public void resetExitButtonAnimation() { + Log.d(TAG, "resetExitButtonAnimation"); + isExitAnimated = false; + mExitIcon.setScaleY(mDefaultScaleY); + mExitIcon.setScaleX(mDefaultScaleX); + mExitIcon.setRotation(mDefaultRotation); + } + + public static final float EXIT_VIEW_TARGET_ALPHA = 1.0f; + public static final float EXIT_VIEW_TARGET_Y = 0f; + + public static final float EXIT_VIEW_BASE_ALPHA = 0f; + public static final float EXIT_VIEW_BASE_Y = 800f; + public void hide() { - ObjectAnimator fadeOut = ObjectAnimator.ofFloat(this, "alpha", 0.0f); - fadeOut.setDuration(FADE_DURATION); - fadeOut.start(); + ObjectAnimator vgExitAnimator = ObjectAnimator.ofFloat(mVgExit, "y", EXIT_VIEW_TARGET_Y, EXIT_VIEW_BASE_Y); + vgExitAnimator.setDuration(FADE_DURATION); + vgExitAnimator.start(); + + ObjectAnimator exitGradientAnimator = ObjectAnimator.ofFloat(mExitGradient, "alpha", EXIT_VIEW_BASE_ALPHA); + exitGradientAnimator.setDuration(FADE_DURATION); + exitGradientAnimator.start(); - fadeOut.addListener(new Animator.AnimatorListener() { + exitGradientAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index e3f8d35..34ad83d 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -26,9 +26,7 @@ import java.util.ArrayList; -import static android.view.View.GONE; import static android.view.View.INVISIBLE; -import static android.view.View.VISIBLE; /** * {@link HoverViewState} that operates the {@link HoverView} when it is collapsed. Collapsed means @@ -199,7 +197,9 @@ private void onDroppedByUser() { } mHoverView.mScreen.getExitView().hide(); - boolean droppedOnExit = mHoverView.mScreen.getExitView().isInExitZone(mFloatingTab.getPosition()); + int exitYThreshold = mHoverView.getScreenSize().y * 3 / 4; + + boolean droppedOnExit = mHoverView.mScreen.getExitView().isInExitZone(mFloatingTab.getPosition(), mHoverView.getScreenSize().y, exitYThreshold); if (droppedOnExit) { onClose(true); } else { @@ -309,6 +309,19 @@ protected void onDocked() { } void moveFloatingTabTo(View floatingTab, @NonNull Point position) { + Log.d(TAG, "TRACK_DEBUG moveFloatingTabTo position = " + position); + Point screenSize = mHoverView.getScreenSize(); + int exitYThreshold = screenSize.y * 3 / 4; + + Log.d(TAG, "TRACK_DEBUG moveFloatingTabTo screenSize.y = " + screenSize.y + ", exitYThreshold = " + exitYThreshold); + + if (exitYThreshold < position.y) { + mHoverView.mScreen.getExitView().startEnterExitAnim(); + } else { + mHoverView.mScreen.getExitView().startExitExitAnim(); + } + +// mHoverView.mScreen.getExitView().enterExitRange(position); mFloatingTab.moveCenterTo(position); } diff --git a/hover/src/main/res/layout/view_hover_menu_exit.xml b/hover/src/main/res/layout/view_hover_menu_exit.xml index 581bf75..f049b51 100644 --- a/hover/src/main/res/layout/view_hover_menu_exit.xml +++ b/hover/src/main/res/layout/view_hover_menu_exit.xml @@ -1,5 +1,5 @@ - @@ -10,12 +10,20 @@ android:layout_alignParentBottom="true" android:background="@drawable/gradient_black_to_transparent" /> - - \ No newline at end of file + + + + + + + \ No newline at end of file From 71b041e560851c6cff73687cb4f255bda4ed3d87 Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Mon, 9 Sep 2019 11:39:04 +0900 Subject: [PATCH 065/105] Set new exitZone --- .../java/io/mattcarroll/hover/ExitView.java | 49 +++++++++++++------ .../hover/HoverViewStateCollapsed.java | 10 +--- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/ExitView.java b/hover/src/main/java/io/mattcarroll/hover/ExitView.java index 5232c32..8da880b 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ExitView.java +++ b/hover/src/main/java/io/mattcarroll/hover/ExitView.java @@ -20,6 +20,7 @@ import android.animation.PropertyValuesHolder; import android.content.Context; import android.graphics.Point; +import android.graphics.Rect; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.AttributeSet; @@ -41,7 +42,7 @@ class ExitView extends RelativeLayout { private View mExitIcon; private View mExitGradient; private ViewGroup mVgExit; -// private boolean mAnimated = false; + // private boolean mAnimated = false; // public ViewPropertyAnimator exitEnterAnim; // public ViewPropertyAnimator exitExitAnim; public ObjectAnimator anim1 = null; @@ -135,18 +136,35 @@ public void onAnimationRepeat(Animator animator) { }); } + public boolean isInExitZone(@NonNull Point position, @NonNull Point screenSize) { + int exitXExcludeThresholdLeft = screenSize.x / 18; + int exitXExcludeThresholdRight = screenSize.x * 17 / 18; - public boolean isInExitZone(@NonNull Point position, int screenY, int threashold) { - Point exitCenter = getExitZoneCenter(); - return threashold < position.y; - } + Rect exitArea = new Rect( + 0 - mExitIcon.getWidth(), + screenSize.y * 4 / 6, + screenSize.x + mExitIcon.getWidth(), + screenSize.y + mExitIcon.getHeight() + ); + + Rect excludedXExitArea = new Rect( + 0 - mExitIcon.getWidth(), + screenSize.y * 4 / 6, + exitXExcludeThresholdLeft, + screenSize.y * 5 / 6 + ); + + Rect excludedXExitArea2 = new Rect( + exitXExcludeThresholdRight, + screenSize.y * 4 / 6, + screenSize.x + mExitIcon.getWidth(), + screenSize.y * 5 / 6 + ); -// public boolean isInExitZone(@NonNull Point position) { -// Point exitCenter = getExitZoneCenter(); -// double distanceToExit = calculateDistance(position, exitCenter); -// Log.d(TAG, "Drop point: " + position + ", Exit center: " + exitCenter + ", Distance: " + distanceToExit); -// return distanceToExit <= mExitRadiusInPx; -// } + return exitArea.contains(position.x, position.y) + && !excludedXExitArea.contains(position.x, position.y) + && !excludedXExitArea2.contains(position.x, position.y); + } private Point getExitZoneCenter() { return new Point( @@ -321,7 +339,8 @@ public void hide() { exitGradientAnimator.addListener(new Animator.AnimatorListener() { @Override - public void onAnimationStart(Animator animation) { } + public void onAnimationStart(Animator animation) { + } @Override public void onAnimationEnd(Animator animation) { @@ -329,10 +348,12 @@ public void onAnimationEnd(Animator animation) { } @Override - public void onAnimationCancel(Animator animation) { } + public void onAnimationCancel(Animator animation) { + } @Override - public void onAnimationRepeat(Animator animation) { } + public void onAnimationRepeat(Animator animation) { + } }); } } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 34ad83d..aa7d651 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -197,9 +197,8 @@ private void onDroppedByUser() { } mHoverView.mScreen.getExitView().hide(); - int exitYThreshold = mHoverView.getScreenSize().y * 3 / 4; - boolean droppedOnExit = mHoverView.mScreen.getExitView().isInExitZone(mFloatingTab.getPosition(), mHoverView.getScreenSize().y, exitYThreshold); + boolean droppedOnExit = mHoverView.mScreen.getExitView().isInExitZone(mFloatingTab.getPosition(), mHoverView.getScreenSize()); if (droppedOnExit) { onClose(true); } else { @@ -310,12 +309,7 @@ protected void onDocked() { void moveFloatingTabTo(View floatingTab, @NonNull Point position) { Log.d(TAG, "TRACK_DEBUG moveFloatingTabTo position = " + position); - Point screenSize = mHoverView.getScreenSize(); - int exitYThreshold = screenSize.y * 3 / 4; - - Log.d(TAG, "TRACK_DEBUG moveFloatingTabTo screenSize.y = " + screenSize.y + ", exitYThreshold = " + exitYThreshold); - - if (exitYThreshold < position.y) { + if (mHoverView.mScreen.getExitView().isInExitZone(position, mHoverView.getScreenSize())) { mHoverView.mScreen.getExitView().startEnterExitAnim(); } else { mHoverView.mScreen.getExitView().startExitExitAnim(); From 98fcadbae57b61ae2dc755e443dce720fa6d415f Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Mon, 9 Sep 2019 11:50:49 +0900 Subject: [PATCH 066/105] Add TODO --- hover/src/main/java/io/mattcarroll/hover/ExitView.java | 1 + 1 file changed, 1 insertion(+) diff --git a/hover/src/main/java/io/mattcarroll/hover/ExitView.java b/hover/src/main/java/io/mattcarroll/hover/ExitView.java index 8da880b..9ee20c1 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ExitView.java +++ b/hover/src/main/java/io/mattcarroll/hover/ExitView.java @@ -33,6 +33,7 @@ /** * Fullscreen View that provides an exit "drop zone" for users to exit the Hover Menu. */ +// TODO 2019.09.09 EXIT POP - Polish code, remove logs class ExitView extends RelativeLayout { private static final String TAG = "ExitView"; From b980abd39ca7a37a39444a0e6e94a5b64e791732 Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Mon, 9 Sep 2019 11:51:54 +0900 Subject: [PATCH 067/105] Add TODO --- hover/src/main/java/io/mattcarroll/hover/ExitView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/ExitView.java b/hover/src/main/java/io/mattcarroll/hover/ExitView.java index 9ee20c1..d64c18d 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ExitView.java +++ b/hover/src/main/java/io/mattcarroll/hover/ExitView.java @@ -33,7 +33,7 @@ /** * Fullscreen View that provides an exit "drop zone" for users to exit the Hover Menu. */ -// TODO 2019.09.09 EXIT POP - Polish code, remove logs +// TODO 2019.09.09 EXIT POP - Polish code, remove logs, check landscape mode class ExitView extends RelativeLayout { private static final String TAG = "ExitView"; From 293ae309b6fe954620ff1a2c595cc18c935fd26a Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Mon, 9 Sep 2019 19:04:15 +0900 Subject: [PATCH 068/105] Add Doc position calculation --- .../hover/HoverViewStateCollapsed.java | 92 ++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index aa7d651..7d491fd 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -52,6 +52,8 @@ class HoverViewStateCollapsed extends BaseHoverViewState { private Handler mHandler = new Handler(); private Runnable mIdleActionRunnable; private Runnable mOnStateChanged; + private Point mStartPoint = null; + private long mDragStartMillis = -1L; @Override public void takeControl(@NonNull HoverView floatingTab, final Runnable onStateChanged) { @@ -186,11 +188,90 @@ protected void onPickedUpByUser() { return; } + mStartPoint = mFloatingTab.getPosition(); + mDragStartMillis = System.currentTimeMillis(); + mHoverView.mScreen.getExitView().show(); restoreHoverViewIdleAction(); mHoverView.notifyOnDragStart(this); } + private double calculateDistance(@NonNull Point p1, @NonNull Point p2) { + return Math.sqrt( + Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2) + ); + } + + // Function to find the line given two points + Point lineFromPoints(Point p, Point q) { + int a = q.y - p.y; + int b = p.x - q.x; + int c = a * (p.x) + b * (p.y); + + if (b < 0) { + Log.d(TAG, "The line passing through points P and Q is: " + + a + "x " + b + "y = " + c); + } else { + Log.d(TAG, "The line passing through points P and Q is: " + + a + "x + " + b + "y = " + c); + } + + int xDirection = 0; + int yDirection = 0; + + if (p.x - q.x >= 0) { + xDirection = 0; + } else { + xDirection = 1; + } + + if (p.y - q.y >= 0) { + yDirection = 0; + } else { + yDirection = 1; + } + + // TODO handle DIVIDE BY ZERO + Log.d(TAG, "xDirection = " + xDirection); + Log.d(TAG, "yDirection = " + yDirection); + + Log.d(TAG, "x = 0 -> y = " + (c / b)); +// Log.d(TAG, "x = " + (c / a) + ", y = 0"); + Log.d(TAG, "x = mHoverView.getScreenSize().x -> y = " + ((c - a * mHoverView.getScreenSize().x) / b)); +// Log.d(TAG, "x = " + ((c - b * mHoverView.getScreenSize().y) / a) + ", y = mHoverView.getScreenSize().y"); + + if (xDirection == 0) { + return new Point(0, (c / b)); + } else { + return new Point(0, (c - a * mHoverView.getScreenSize().x) / b); + } + + } + + static Point lineLineIntersection(Point pointA, Point pointB, Point pointC, Point pointD) { + // Line AB represented as a1x + b1y = c1 + double a1 = pointB.y - pointA.y; + double b1 = pointA.x - pointB.x; + double c1 = a1 * (pointA.x) + b1 * (pointA.y); + + // Line CD represented as a2x + b2y = c2 + double a2 = pointD.y - pointC.y; + double b2 = pointC.x - pointD.x; + double c2 = a2 * (pointC.x) + b2 * (pointC.y); + + double determinant = a1 * b2 - a2 * b1; + + if (determinant == 0) { + // The lines are parallel. This is simplified + // by returning a pair of FLT_MAX + return new Point(Integer.MAX_VALUE, Integer.MAX_VALUE); + } else { + double x = (b2 * c1 - b1 * c2) / determinant; + double y = (a1 * c2 - a2 * c1) / determinant; + return new Point((int) x, (int) y); + } + } + private void onDroppedByUser() { if (!hasControl()) { return; @@ -198,15 +279,24 @@ private void onDroppedByUser() { mHoverView.mScreen.getExitView().hide(); + int diffPositionX = mStartPoint.x - mFloatingTab.getPosition().x; + int diffPositionY = mStartPoint.y - mFloatingTab.getPosition().y; + boolean droppedOnExit = mHoverView.mScreen.getExitView().isInExitZone(mFloatingTab.getPosition(), mHoverView.getScreenSize()); if (droppedOnExit) { onClose(true); } else { + + Log.d(TAG, "TRACK_DEBUG onDroppedByUser diffPositionX = " + diffPositionX + ", diffPositionY = " + diffPositionY); + Log.d(TAG, "TRACK_DEBUG onDroppedByUser distance = " + calculateDistance(mStartPoint, mFloatingTab.getPosition())); + Log.d(TAG, "TRACK_DEBUG onDroppedByUser diffTimeMillis = " + (System.currentTimeMillis() - mDragStartMillis)); +// lineFromPoints(mStartPoint, mFloatingTab.getPosition()); + int tabSize = mHoverView.getResources().getDimensionPixelSize(R.dimen.hover_tab_size); Point screenSize = mHoverView.getScreenSize(); final float tabHorizontalPositionPercent = (float) mFloatingTab.getPosition().x / screenSize.x; final float viewHeightPercent = mFloatingTab.getHeight() / 2f / screenSize.y; - float tabVerticalPosition = (float) mFloatingTab.getPosition().y / screenSize.y; + float tabVerticalPosition = (float) lineFromPoints(mStartPoint, mFloatingTab.getPosition()).y / screenSize.y; if (tabVerticalPosition < MIN_TAB_VERTICAL_POSITION) { tabVerticalPosition = MIN_TAB_VERTICAL_POSITION; } else if (tabVerticalPosition > MAX_TAB_VERTICAL_POSITION - viewHeightPercent) { From 551d2be81ca7a7b0ab4c52d2014c167a436de81f Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Tue, 10 Sep 2019 15:10:20 +0900 Subject: [PATCH 069/105] Add calculation --- .../hover/HoverViewStateCollapsed.java | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 7d491fd..9946a5e 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -287,6 +287,7 @@ private void onDroppedByUser() { onClose(true); } else { + float distance = (float) calculateDistance(mStartPoint, mFloatingTab.getPosition()); Log.d(TAG, "TRACK_DEBUG onDroppedByUser diffPositionX = " + diffPositionX + ", diffPositionY = " + diffPositionY); Log.d(TAG, "TRACK_DEBUG onDroppedByUser distance = " + calculateDistance(mStartPoint, mFloatingTab.getPosition())); Log.d(TAG, "TRACK_DEBUG onDroppedByUser diffTimeMillis = " + (System.currentTimeMillis() - mDragStartMillis)); @@ -294,9 +295,32 @@ private void onDroppedByUser() { int tabSize = mHoverView.getResources().getDimensionPixelSize(R.dimen.hover_tab_size); Point screenSize = mHoverView.getScreenSize(); - final float tabHorizontalPositionPercent = (float) mFloatingTab.getPosition().x / screenSize.x; + float tabHorizontalPositionPercent = (float) mFloatingTab.getPosition().x / screenSize.x; final float viewHeightPercent = mFloatingTab.getHeight() / 2f / screenSize.y; - float tabVerticalPosition = (float) lineFromPoints(mStartPoint, mFloatingTab.getPosition()).y / screenSize.y; +// float tabVerticalPosition = (float) lineFromPoints(mStartPoint, mFloatingTab.getPosition()).y / screenSize.y; + float tabVerticalPosition = (float) mFloatingTab.getPosition().y / screenSize.y; + + if (distance > 300) { + Log.d(TAG, "distance > 100"); + float positionY = lineFromPoints(mStartPoint, mFloatingTab.getPosition()).y; + positionY = (positionY - mFloatingTab.getPosition().y) * distance / 1000 + mFloatingTab.getPosition().y; +// tabVerticalPosition = (float) lineFromPoints(mStartPoint, mFloatingTab.getPosition()).y / screenSize.y; +// tabVerticalPosition = tabVerticalPosition * distance / 1000; + tabVerticalPosition = positionY / screenSize.y; + Log.d(TAG, "distance > 100 tabVerticalPosition = " + tabVerticalPosition); + + if (diffPositionX > 0) { + tabHorizontalPositionPercent = 0f; + } else { + tabHorizontalPositionPercent = 1f; + } + + } else { + Log.d(TAG, "is less than 100"); + tabVerticalPosition = (float) lineFromPoints(mStartPoint, mFloatingTab.getPosition()).y / screenSize.y; + tabVerticalPosition = tabVerticalPosition * 3 / 10; + } + if (tabVerticalPosition < MIN_TAB_VERTICAL_POSITION) { tabVerticalPosition = MIN_TAB_VERTICAL_POSITION; } else if (tabVerticalPosition > MAX_TAB_VERTICAL_POSITION - viewHeightPercent) { From 1a5d18b5bf3d7f20f4e343c6915ba8e7953b521d Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Tue, 10 Sep 2019 16:53:19 +0900 Subject: [PATCH 070/105] Add center align test code --- .../io/mattcarroll/hover/FloatingTab.java | 37 ++++++++ .../hover/HoverViewStateCollapsed.java | 88 ++++++++++++++----- .../java/io/mattcarroll/hover/SideDock.java | 1 - 3 files changed, 103 insertions(+), 23 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java index 8db2499..0a2f09d 100644 --- a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java +++ b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java @@ -279,6 +279,43 @@ public void onAnimationUpdate(ValueAnimator animation) { }); } + public void closeAnimation(Point targetPosition, @Nullable final Runnable onDocked) { + Point destinationCornerPosition = convertCenterToCorner(targetPosition); + Log.d(TAG, "Docking to destination point: " + destinationCornerPosition); + + ObjectAnimator xAnimation = ObjectAnimator.ofFloat(this, "x", targetPosition.x); + xAnimation.setDuration(500); + xAnimation.setInterpolator(new OvershootInterpolator()); + ObjectAnimator yAnimation = ObjectAnimator.ofFloat(this, "y", targetPosition.y); + yAnimation.setDuration(500); + yAnimation.setInterpolator(new OvershootInterpolator()); + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.play(xAnimation).with(yAnimation); + animatorSet.start(); + + animatorSet.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + } + + @Override + public void onAnimationEnd(Animator animation) { + if (null != onDocked) { + onDocked.run(); + } +// notifyListenersOfPositionChange(FloatingTab.this); + } + + @Override + public void onAnimationCancel(Animator animation) { + } + + @Override + public void onAnimationRepeat(Animator animation) { + } + }); + } + public void dockImmediately() { moveCenterTo(mDock.position()); } diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 9946a5e..83737e9 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -298,16 +298,18 @@ private void onDroppedByUser() { float tabHorizontalPositionPercent = (float) mFloatingTab.getPosition().x / screenSize.x; final float viewHeightPercent = mFloatingTab.getHeight() / 2f / screenSize.y; // float tabVerticalPosition = (float) lineFromPoints(mStartPoint, mFloatingTab.getPosition()).y / screenSize.y; - float tabVerticalPosition = (float) mFloatingTab.getPosition().y / screenSize.y; + float tabVerticalPositionPercent = (float) mFloatingTab.getPosition().y / screenSize.y; if (distance > 300) { Log.d(TAG, "distance > 100"); + Point targetPosition = lineFromPoints(mStartPoint, mFloatingTab.getPosition()); float positionY = lineFromPoints(mStartPoint, mFloatingTab.getPosition()).y; positionY = (positionY - mFloatingTab.getPosition().y) * distance / 1000 + mFloatingTab.getPosition().y; // tabVerticalPosition = (float) lineFromPoints(mStartPoint, mFloatingTab.getPosition()).y / screenSize.y; // tabVerticalPosition = tabVerticalPosition * distance / 1000; - tabVerticalPosition = positionY / screenSize.y; - Log.d(TAG, "distance > 100 tabVerticalPosition = " + tabVerticalPosition); + tabVerticalPositionPercent = positionY / screenSize.y; + Log.d(TAG, "distance > 100 tabVerticalPosition = " + tabVerticalPositionPercent); + if (diffPositionX > 0) { tabHorizontalPositionPercent = 0f; @@ -317,29 +319,59 @@ private void onDroppedByUser() { } else { Log.d(TAG, "is less than 100"); - tabVerticalPosition = (float) lineFromPoints(mStartPoint, mFloatingTab.getPosition()).y / screenSize.y; - tabVerticalPosition = tabVerticalPosition * 3 / 10; + tabVerticalPositionPercent = (float) lineFromPoints(mStartPoint, mFloatingTab.getPosition()).y / screenSize.y; + tabVerticalPositionPercent = tabVerticalPositionPercent * 3 / 10; } - if (tabVerticalPosition < MIN_TAB_VERTICAL_POSITION) { - tabVerticalPosition = MIN_TAB_VERTICAL_POSITION; - } else if (tabVerticalPosition > MAX_TAB_VERTICAL_POSITION - viewHeightPercent) { - tabVerticalPosition = MAX_TAB_VERTICAL_POSITION - viewHeightPercent; + int sideDockHorizontalPosition = SideDock.SidePosition.LEFT; + + if (tabVerticalPositionPercent < MIN_TAB_VERTICAL_POSITION) { + tabVerticalPositionPercent = MIN_TAB_VERTICAL_POSITION; + } else if (tabVerticalPositionPercent > MAX_TAB_VERTICAL_POSITION - viewHeightPercent) { + tabVerticalPositionPercent = MAX_TAB_VERTICAL_POSITION - viewHeightPercent; } - Log.d(TAG, "Dropped at horizontal " + tabHorizontalPositionPercent + ", vertical " + tabVerticalPosition); - SideDock.SidePosition sidePosition = new SideDock.SidePosition( - tabHorizontalPositionPercent <= 0.5 ? SideDock.SidePosition.LEFT : SideDock.SidePosition.RIGHT, - tabVerticalPosition - ); - mHoverView.mCollapsedDock = new SideDock( - mHoverView, - tabSize, - sidePosition - ); - mHoverView.saveVisualState(); - Log.d(TAG, "User dropped tab. Sending to new dock: " + mHoverView.mCollapsedDock); - sendToDock(); + Point targetPosition = new Point(); + targetPosition.x = (int) (tabHorizontalPositionPercent * (float) mHoverView.getScreenSize().x); + targetPosition.y = (int) (tabVerticalPositionPercent * (float) mHoverView.getScreenSize().y); + + Log.d(TAG, "targetPosition.x = " + targetPosition.x); + Log.d(TAG, "targetPosition.y = " + targetPosition.y); + boolean droppedOnExit2 = mHoverView.mScreen.getExitView().isInExitZone(targetPosition, mHoverView.getScreenSize()); + if (droppedOnExit2) { + Log.d(TAG, "Dropped at horizontal " + tabHorizontalPositionPercent + ", vertical " + tabVerticalPositionPercent); + int x = screenSize.x / 2 - ((int) (tabSize * 0.25 * 2)); + + int y = (int) (screenSize.y * tabVerticalPositionPercent) - ((int) (tabSize * 0.25 * 2)); + + targetPosition.x = x; + targetPosition.y = y; + closeWithAnimation(targetPosition); + } else { + + if (tabHorizontalPositionPercent <= 0.5) { + sideDockHorizontalPosition = SideDock.SidePosition.LEFT; + } else if (tabHorizontalPositionPercent <= 1.0) { + sideDockHorizontalPosition = SideDock.SidePosition.RIGHT; + } else { + sideDockHorizontalPosition = SideDock.SidePosition.RIGHT; + } + + Log.d(TAG, "Dropped at horizontal " + tabHorizontalPositionPercent + ", vertical " + tabVerticalPositionPercent); + SideDock.SidePosition sidePosition = new SideDock.SidePosition( + sideDockHorizontalPosition, + tabVerticalPositionPercent + ); + mHoverView.mCollapsedDock = new SideDock( + mHoverView, + tabSize, + sidePosition + ); + mHoverView.saveVisualState(); + Log.d(TAG, "User dropped tab. Sending to new dock: " + mHoverView.mCollapsedDock); + sendToDock(); + + } } } @@ -366,6 +398,18 @@ protected void onTap() { } } + private void closeWithAnimation(Point targetPoint) { + Log.d(TAG, "Sending floating tab to dock."); +// deactivateDragger(); +// mFloatingTab.setDock(mHoverView.mCollapsedDock); + mFloatingTab.closeAnimation(targetPoint, new Runnable() { + @Override + public void run() { + onClose(false); + } + }); + } + private void sendToDock() { Log.d(TAG, "Sending floating tab to dock."); deactivateDragger(); diff --git a/hover/src/main/java/io/mattcarroll/hover/SideDock.java b/hover/src/main/java/io/mattcarroll/hover/SideDock.java index 978cbe9..4b06583 100644 --- a/hover/src/main/java/io/mattcarroll/hover/SideDock.java +++ b/hover/src/main/java/io/mattcarroll/hover/SideDock.java @@ -65,7 +65,6 @@ public static class SidePosition { public @interface Side { } public static final int LEFT = 0; public static final int RIGHT = 1; - @Side private int mSide; private float mVerticalDockPositionPercentage; From d9f665e22930dd57ec0d8784c0266cbc7f29063d Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Wed, 11 Sep 2019 18:04:21 +0900 Subject: [PATCH 071/105] Improve touch UX --- .../hover/HoverViewStateCollapsed.java | 53 ++++++++++++------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 83737e9..1b76278 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -54,6 +54,8 @@ class HoverViewStateCollapsed extends BaseHoverViewState { private Runnable mOnStateChanged; private Point mStartPoint = null; private long mDragStartMillis = -1L; + private Point mPrevPoint = null; + private Point mCurrPoint = new Point(0, 0); @Override public void takeControl(@NonNull HoverView floatingTab, final Runnable onStateChanged) { @@ -235,6 +237,11 @@ Point lineFromPoints(Point p, Point q) { Log.d(TAG, "xDirection = " + xDirection); Log.d(TAG, "yDirection = " + yDirection); + // wrong + if (b == 0) { + b = 1; + Log.d(TAG, "Catch divide by 0!!!"); + } Log.d(TAG, "x = 0 -> y = " + (c / b)); // Log.d(TAG, "x = " + (c / a) + ", y = 0"); Log.d(TAG, "x = mHoverView.getScreenSize().x -> y = " + ((c - a * mHoverView.getScreenSize().x) / b)); @@ -245,7 +252,6 @@ Point lineFromPoints(Point p, Point q) { } else { return new Point(0, (c - a * mHoverView.getScreenSize().x) / b); } - } static Point lineLineIntersection(Point pointA, Point pointB, Point pointC, Point pointD) { @@ -279,33 +285,37 @@ private void onDroppedByUser() { mHoverView.mScreen.getExitView().hide(); - int diffPositionX = mStartPoint.x - mFloatingTab.getPosition().x; - int diffPositionY = mStartPoint.y - mFloatingTab.getPosition().y; + // TODO Prev can be null + int diffPositionX = mPrevPoint.x - mFloatingTab.getPosition().x; + int diffPositionY = mPrevPoint.y - mFloatingTab.getPosition().y; boolean droppedOnExit = mHoverView.mScreen.getExitView().isInExitZone(mFloatingTab.getPosition(), mHoverView.getScreenSize()); if (droppedOnExit) { - onClose(true); + onClose(false); } else { - float distance = (float) calculateDistance(mStartPoint, mFloatingTab.getPosition()); + float distance = (float) calculateDistance(mPrevPoint, mFloatingTab.getPosition()); Log.d(TAG, "TRACK_DEBUG onDroppedByUser diffPositionX = " + diffPositionX + ", diffPositionY = " + diffPositionY); - Log.d(TAG, "TRACK_DEBUG onDroppedByUser distance = " + calculateDistance(mStartPoint, mFloatingTab.getPosition())); + Log.d(TAG, "TRACK_DEBUG onDroppedByUser distance = " + calculateDistance(mPrevPoint, mFloatingTab.getPosition())); Log.d(TAG, "TRACK_DEBUG onDroppedByUser diffTimeMillis = " + (System.currentTimeMillis() - mDragStartMillis)); -// lineFromPoints(mStartPoint, mFloatingTab.getPosition()); +// lineFromPoints(mPrevPoint, mFloatingTab.getPosition()); int tabSize = mHoverView.getResources().getDimensionPixelSize(R.dimen.hover_tab_size); Point screenSize = mHoverView.getScreenSize(); float tabHorizontalPositionPercent = (float) mFloatingTab.getPosition().x / screenSize.x; final float viewHeightPercent = mFloatingTab.getHeight() / 2f / screenSize.y; -// float tabVerticalPosition = (float) lineFromPoints(mStartPoint, mFloatingTab.getPosition()).y / screenSize.y; +// float tabVerticalPosition = (float) lineFromPoints(mPrevPoint, mFloatingTab.getPosition()).y / screenSize.y; float tabVerticalPositionPercent = (float) mFloatingTab.getPosition().y / screenSize.y; - if (distance > 300) { + // TODO find best threshold + if (distance > 30) { Log.d(TAG, "distance > 100"); - Point targetPosition = lineFromPoints(mStartPoint, mFloatingTab.getPosition()); - float positionY = lineFromPoints(mStartPoint, mFloatingTab.getPosition()).y; - positionY = (positionY - mFloatingTab.getPosition().y) * distance / 1000 + mFloatingTab.getPosition().y; -// tabVerticalPosition = (float) lineFromPoints(mStartPoint, mFloatingTab.getPosition()).y / screenSize.y; +// Point targetPosition = lineFromPoints(mPrevPoint, mFloatingTab.getPosition()); + float positionY = lineFromPoints(mPrevPoint, mFloatingTab.getPosition()).y; + + // TODO fine best formula +// positionY = (positionY - mFloatingTab.getPosition().y) * distance / 100 + mFloatingTab.getPosition().y; +// tabVerticalPosition = (float) lineFromPoints(mPrevPoint, mFloatingTab.getPosition()).y / screenSize.y; // tabVerticalPosition = tabVerticalPosition * distance / 1000; tabVerticalPositionPercent = positionY / screenSize.y; Log.d(TAG, "distance > 100 tabVerticalPosition = " + tabVerticalPositionPercent); @@ -316,11 +326,11 @@ private void onDroppedByUser() { } else { tabHorizontalPositionPercent = 1f; } - } else { Log.d(TAG, "is less than 100"); - tabVerticalPositionPercent = (float) lineFromPoints(mStartPoint, mFloatingTab.getPosition()).y / screenSize.y; - tabVerticalPositionPercent = tabVerticalPositionPercent * 3 / 10; +// tabVerticalPositionPercent = (float) lineFromPoints(mPrevPoint, mFloatingTab.getPosition()).y / screenSize.y; +// tabVerticalPositionPercent = tabVerticalPositionPercent * 3 / 10; + tabVerticalPositionPercent = (float) mFloatingTab.getPosition().y / screenSize.y; } int sideDockHorizontalPosition = SideDock.SidePosition.LEFT; @@ -337,8 +347,8 @@ private void onDroppedByUser() { Log.d(TAG, "targetPosition.x = " + targetPosition.x); Log.d(TAG, "targetPosition.y = " + targetPosition.y); - boolean droppedOnExit2 = mHoverView.mScreen.getExitView().isInExitZone(targetPosition, mHoverView.getScreenSize()); - if (droppedOnExit2) { + boolean flickingExit = mHoverView.mScreen.getExitView().isInExitZone(targetPosition, mHoverView.getScreenSize()); + if (flickingExit) { Log.d(TAG, "Dropped at horizontal " + tabHorizontalPositionPercent + ", vertical " + tabVerticalPositionPercent); int x = screenSize.x / 2 - ((int) (tabSize * 0.25 * 2)); @@ -475,6 +485,13 @@ void moveFloatingTabTo(View floatingTab, @NonNull Point position) { // mHoverView.mScreen.getExitView().enterExitRange(position); mFloatingTab.moveCenterTo(position); + +// int treshold = 5; +// if (Math.abs(mCurrPoint.x - position.x) > treshold || Math.abs(mCurrPoint.y - position.y) > treshold) { +// Log.d(TAG, "TRACK_DEBUG moveFloatingTabTo position saved = " + position); + mPrevPoint = mCurrPoint; + mCurrPoint = position; +// } } protected void activateDragger() { From 3f57a7294d2430077a6cd5a67df8b88d7803ca46 Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Wed, 11 Sep 2019 18:44:19 +0900 Subject: [PATCH 072/105] Add TODOs --- .../hover/HoverViewStateCollapsed.java | 65 ++++++++++--------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 1b76278..345f3ac 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -254,29 +254,30 @@ Point lineFromPoints(Point p, Point q) { } } - static Point lineLineIntersection(Point pointA, Point pointB, Point pointC, Point pointD) { - // Line AB represented as a1x + b1y = c1 - double a1 = pointB.y - pointA.y; - double b1 = pointA.x - pointB.x; - double c1 = a1 * (pointA.x) + b1 * (pointA.y); - - // Line CD represented as a2x + b2y = c2 - double a2 = pointD.y - pointC.y; - double b2 = pointC.x - pointD.x; - double c2 = a2 * (pointC.x) + b2 * (pointC.y); - - double determinant = a1 * b2 - a2 * b1; - - if (determinant == 0) { - // The lines are parallel. This is simplified - // by returning a pair of FLT_MAX - return new Point(Integer.MAX_VALUE, Integer.MAX_VALUE); - } else { - double x = (b2 * c1 - b1 * c2) / determinant; - double y = (a1 * c2 - a2 * c1) / determinant; - return new Point((int) x, (int) y); - } - } + // TODO remove +// static Point lineLineIntersection(Point pointA, Point pointB, Point pointC, Point pointD) { +// // Line AB represented as a1x + b1y = c1 +// double a1 = pointB.y - pointA.y; +// double b1 = pointA.x - pointB.x; +// double c1 = a1 * (pointA.x) + b1 * (pointA.y); +// +// // Line CD represented as a2x + b2y = c2 +// double a2 = pointD.y - pointC.y; +// double b2 = pointC.x - pointD.x; +// double c2 = a2 * (pointC.x) + b2 * (pointC.y); +// +// double determinant = a1 * b2 - a2 * b1; +// +// if (determinant == 0) { +// // The lines are parallel. This is simplified +// // by returning a pair of FLT_MAX +// return new Point(Integer.MAX_VALUE, Integer.MAX_VALUE); +// } else { +// double x = (b2 * c1 - b1 * c2) / determinant; +// double y = (a1 * c2 - a2 * c1) / determinant; +// return new Point((int) x, (int) y); +// } +// } private void onDroppedByUser() { if (!hasControl()) { @@ -285,12 +286,18 @@ private void onDroppedByUser() { mHoverView.mScreen.getExitView().hide(); + // TODO check location + if (mPrevPoint == null) { + return; + } + // TODO Prev can be null int diffPositionX = mPrevPoint.x - mFloatingTab.getPosition().x; int diffPositionY = mPrevPoint.y - mFloatingTab.getPosition().y; boolean droppedOnExit = mHoverView.mScreen.getExitView().isInExitZone(mFloatingTab.getPosition(), mHoverView.getScreenSize()); if (droppedOnExit) { + // TODO check userDropped option onClose(false); } else { @@ -415,6 +422,7 @@ private void closeWithAnimation(Point targetPoint) { mFloatingTab.closeAnimation(targetPoint, new Runnable() { @Override public void run() { + // TODO check userDropped option onClose(false); } }); @@ -482,16 +490,9 @@ void moveFloatingTabTo(View floatingTab, @NonNull Point position) { } else { mHoverView.mScreen.getExitView().startExitExitAnim(); } - -// mHoverView.mScreen.getExitView().enterExitRange(position); mFloatingTab.moveCenterTo(position); - -// int treshold = 5; -// if (Math.abs(mCurrPoint.x - position.x) > treshold || Math.abs(mCurrPoint.y - position.y) > treshold) { -// Log.d(TAG, "TRACK_DEBUG moveFloatingTabTo position saved = " + position); - mPrevPoint = mCurrPoint; - mCurrPoint = position; -// } + mPrevPoint = mCurrPoint; + mCurrPoint = position; } protected void activateDragger() { From 28e839157cf12e303346d163d1172c49b2db37ce Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Tue, 17 Sep 2019 09:33:16 +0900 Subject: [PATCH 073/105] Polish exit Animation --- .../java/io/mattcarroll/hover/ExitView.java | 238 ++++++------------ .../io/mattcarroll/hover/FloatingTab.java | 1 - .../hover/HoverViewStateCollapsed.java | 168 ++++--------- hover/src/main/res/drawable/ic_exit.xml | 3 +- .../main/res/layout/view_hover_menu_exit.xml | 2 +- 5 files changed, 119 insertions(+), 293 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/ExitView.java b/hover/src/main/java/io/mattcarroll/hover/ExitView.java index d64c18d..8c19959 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ExitView.java +++ b/hover/src/main/java/io/mattcarroll/hover/ExitView.java @@ -23,11 +23,13 @@ import android.graphics.Rect; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v4.view.animation.PathInterpolatorCompat; import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.animation.Interpolator; import android.widget.RelativeLayout; /** @@ -38,20 +40,28 @@ class ExitView extends RelativeLayout { private static final String TAG = "ExitView"; - private static final int FADE_DURATION = 300; + private static final int FADE_DURATION = 250; + private static final int ENTER_EXIT_DURATION = 250; + private static final float EXIT_ICON_DEFAULT_SCALE_X = 1.0f; + private static final float EXIT_ICON_DEFAULT_SCALE_Y = 1.0f; + private static final float EXIT_ICON_TARGET_SCALE_X = 1.2f; + private static final float EXIT_ICON_TARGET_SCALE_Y = 1.2f; + private static final float EXIT_ICON_DEFAULT_ROTATION = 0f; + private static final float EXIT_ICON_TARGET_ROTATION = 90f; + private static final float EXIT_ICON_DEFAULT_ALPHA = 0.6f; + private static final float EXIT_ICON_TARGET_ALPHA = 0.75f; + private static final float EXIT_VIEW_TARGET_ALPHA = 1.0f; + private static final float EXIT_VIEW_TARGET_Y = 0f; + private static final float EXIT_VIEW_BASE_ALPHA = 0f; + private static final float EXIT_VIEW_BASE_Y = 800f; + private int mExitRadiusInPx; private View mExitIcon; private View mExitGradient; private ViewGroup mVgExit; - // private boolean mAnimated = false; -// public ViewPropertyAnimator exitEnterAnim; -// public ViewPropertyAnimator exitExitAnim; - public ObjectAnimator anim1 = null; - public ObjectAnimator anim2 = null; + public ObjectAnimator enterAnimation = null; + public ObjectAnimator exitAnimation = null; public boolean isExitAnimated = false; - private float mDefaultScaleX = 1.0f; - private float mDefaultScaleY = 1.0f; - private float mDefaultRotation = 0f; public ExitView(@NonNull Context context) { this(context, null); @@ -69,77 +79,84 @@ private void init() { mVgExit = findViewById(R.id.vg_exit); mExitGradient = findViewById(R.id.view_exit_gradient); mExitRadiusInPx = getResources().getDimensionPixelSize(R.dimen.hover_exit_radius); + mExitIcon.setAlpha(EXIT_ICON_DEFAULT_ALPHA); setAnimations(); } + private Interpolator getExitViewInterpolator() { + return PathInterpolatorCompat.create(0.75f, 0f, 0.25f, 1f); + } + private void setAnimations() { - PropertyValuesHolder pv1 = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 1.5f); - PropertyValuesHolder pv2 = PropertyValuesHolder.ofFloat("scaleY", 1.0f, 1.5f); - PropertyValuesHolder pv3 = PropertyValuesHolder.ofFloat("rotation", 0f, 90f); - anim1 = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, pv1, pv2, pv3); - anim1.setDuration(300L); - anim1.addListener(new Animator.AnimatorListener() { + PropertyValuesHolder enterAnimationScaleX = PropertyValuesHolder.ofFloat("scaleX", EXIT_ICON_DEFAULT_SCALE_X, EXIT_ICON_TARGET_SCALE_X); + PropertyValuesHolder enterAnimationScaleY = PropertyValuesHolder.ofFloat("scaleY", EXIT_ICON_DEFAULT_SCALE_Y, EXIT_ICON_TARGET_SCALE_Y); + PropertyValuesHolder enterAnimationRotate = PropertyValuesHolder.ofFloat("rotation", EXIT_ICON_DEFAULT_ROTATION, EXIT_ICON_TARGET_ROTATION); + PropertyValuesHolder enterAnimationAlpha = PropertyValuesHolder.ofFloat("alpha", EXIT_ICON_DEFAULT_ALPHA, EXIT_ICON_TARGET_ALPHA); + enterAnimation = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, enterAnimationScaleX, enterAnimationScaleY, enterAnimationRotate, enterAnimationAlpha); + enterAnimation.setDuration(ENTER_EXIT_DURATION); + enterAnimation.setInterpolator(getExitViewInterpolator()); + enterAnimation.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { - Log.d(TAG, "anim1 onAnimationStart"); - mExitIcon.setScaleY(mDefaultScaleY); - mExitIcon.setScaleX(mDefaultScaleX); - mExitIcon.setRotation(mDefaultRotation); + Log.d(TAG, "enterAnimation onAnimationStart"); + mExitIcon.setScaleY(EXIT_ICON_DEFAULT_SCALE_Y); + mExitIcon.setScaleX(EXIT_ICON_DEFAULT_SCALE_X); + mExitIcon.setRotation(EXIT_ICON_DEFAULT_ROTATION); } @Override public void onAnimationEnd(Animator animator) { - Log.d(TAG, "anim1 onAnimationEnd"); + Log.d(TAG, "enterAnimation onAnimationEnd"); } @Override public void onAnimationCancel(Animator animator) { -// initExitButtonProperties(); - Log.d(TAG, "anim1 onAnimationCancel"); - mExitIcon.setScaleY(mDefaultScaleY); - mExitIcon.setScaleX(mDefaultScaleX); - mExitIcon.setRotation(mDefaultRotation); + Log.d(TAG, "enterAnimation onAnimationCancel"); + mExitIcon.setScaleY(EXIT_ICON_DEFAULT_SCALE_Y); + mExitIcon.setScaleX(EXIT_ICON_DEFAULT_SCALE_X); + mExitIcon.setRotation(EXIT_ICON_DEFAULT_ROTATION); } @Override public void onAnimationRepeat(Animator animator) { - Log.d(TAG, "anim1 onAnimationRepeat"); + Log.d(TAG, "enterAnimation onAnimationRepeat"); } }); - PropertyValuesHolder pva1 = PropertyValuesHolder.ofFloat("scaleX", 1.5f, 1.0f); - PropertyValuesHolder pva2 = PropertyValuesHolder.ofFloat("scaleY", 1.5f, 1.0f); - PropertyValuesHolder pva3 = PropertyValuesHolder.ofFloat("rotation", 90f, 0f); - anim2 = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, pva1, pva2, pva3); - anim2.setDuration(300L); - anim2.addListener(new Animator.AnimatorListener() { + PropertyValuesHolder exitAnimationScaleX = PropertyValuesHolder.ofFloat("scaleX", EXIT_ICON_TARGET_SCALE_X, EXIT_ICON_DEFAULT_SCALE_X); + PropertyValuesHolder exitAnimationScaleY = PropertyValuesHolder.ofFloat("scaleY", EXIT_ICON_TARGET_SCALE_Y, EXIT_ICON_DEFAULT_SCALE_Y); + PropertyValuesHolder exitAnimationRotate = PropertyValuesHolder.ofFloat("rotation", EXIT_ICON_TARGET_ROTATION, EXIT_ICON_DEFAULT_ROTATION); + PropertyValuesHolder exitAnimationAlpha = PropertyValuesHolder.ofFloat("alpha", EXIT_ICON_TARGET_ALPHA, EXIT_ICON_DEFAULT_ALPHA); + exitAnimation = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, exitAnimationScaleX, exitAnimationScaleY, exitAnimationRotate, exitAnimationAlpha); + exitAnimation.setDuration(ENTER_EXIT_DURATION); + exitAnimation.setInterpolator(getExitViewInterpolator()); + exitAnimation.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { - Log.d(TAG, "anim2 onAnimationStart"); + Log.d(TAG, "exitAnimation onAnimationStart"); } @Override public void onAnimationEnd(Animator animator) { - Log.d(TAG, "anim2 onAnimationEnd"); + Log.d(TAG, "exitAnimation onAnimationEnd"); } @Override public void onAnimationCancel(Animator animator) { - Log.d(TAG, "anim2 onAnimationCancel"); - + Log.d(TAG, "exitAnimation onAnimationCancel"); } @Override public void onAnimationRepeat(Animator animator) { - Log.d(TAG, "anim2 onAnimationRepeat"); + Log.d(TAG, "exitAnimation onAnimationRepeat"); } }); } public boolean isInExitZone(@NonNull Point position, @NonNull Point screenSize) { - int exitXExcludeThresholdLeft = screenSize.x / 18; - int exitXExcludeThresholdRight = screenSize.x * 17 / 18; + int exitXExcludeThresholdLeft = screenSize.x / 10; + int exitXExcludeThresholdRight = screenSize.x * 9 / 10; Rect exitArea = new Rect( 0 - mExitIcon.getWidth(), @@ -148,14 +165,14 @@ public boolean isInExitZone(@NonNull Point position, @NonNull Point screenSize) screenSize.y + mExitIcon.getHeight() ); - Rect excludedXExitArea = new Rect( + Rect excludedXExitAreaLeft = new Rect( 0 - mExitIcon.getWidth(), screenSize.y * 4 / 6, exitXExcludeThresholdLeft, screenSize.y * 5 / 6 ); - Rect excludedXExitArea2 = new Rect( + Rect excludedXExitAreaRight = new Rect( exitXExcludeThresholdRight, screenSize.y * 4 / 6, screenSize.x + mExitIcon.getWidth(), @@ -163,8 +180,8 @@ public boolean isInExitZone(@NonNull Point position, @NonNull Point screenSize) ); return exitArea.contains(position.x, position.y) - && !excludedXExitArea.contains(position.x, position.y) - && !excludedXExitArea2.contains(position.x, position.y); + && !excludedXExitAreaLeft.contains(position.x, position.y) + && !excludedXExitAreaRight.contains(position.x, position.y); } private Point getExitZoneCenter() { @@ -181,135 +198,30 @@ private double calculateDistance(@NonNull Point p1, @NonNull Point p2) { } public void startEnterExitAnim() { - if ((anim1 == null || !anim1.isRunning()) && !isExitAnimated) { - -// if (anim2 != null && anim2.isRunning()) { -// anim2.cancel(); -// } - anim1.start(); + if (enterAnimation != null && !enterAnimation.isRunning() && !isExitAnimated) { + enterAnimation.start(); isExitAnimated = true; } } public void startExitExitAnim() { - if ((anim2 == null || !anim2.isRunning()) && isExitAnimated) { -// if (anim1 != null && anim1.isRunning()) { -// anim1.cancel(); -// } - anim2.start(); + if (exitAnimation != null && !exitAnimation.isRunning() && isExitAnimated) { + exitAnimation.start(); isExitAnimated = false; } } - public void testEnterExitRange(Point position) { -// ObjectAnimator fadeOut = ObjectAnimator.ofFloat(mExitIcon, "scaleX", 1.0f, 1.5f); -// fadeOut.setDuration(FADE_DURATION); -// fadeOut.start(); -// -// -// ObjectAnimator aa = ObjectAnimator.ofFloat(mExitIcon, "scaleY", 1.0f, 1.5f); -// aa.setDuration(FADE_DURATION); -// aa.start(); - -// if (anim1 != null) { -// Log.d(TAG, "enterExitRange anim1.isRunning = " + anim1.isRunning()); -// } - - // case 1 done but seems slow. -// if (isInExitZone(position)) { -// if ((anim1 == null || !anim1.isRunning()) && !isExitAnimated) { -// -//// if (anim2 != null && anim2.isRunning()) { -//// anim2.cancel(); -//// } -// PropertyValuesHolder pv1 = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 1.5f); -// PropertyValuesHolder pv2 = PropertyValuesHolder.ofFloat("scaleY", 1.0f, 1.5f); -// PropertyValuesHolder pv3 = PropertyValuesHolder.ofFloat("rotation", 0f, 90f); -// anim1 = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, pv1, pv2, pv3); -// anim1.setDuration(300L); -// anim1.start(); -// isExitAnimated = true; -// } -// } else { -// if ((anim2 == null || !anim2.isRunning()) && isExitAnimated) { -//// if (anim1 != null && anim1.isRunning()) { -//// anim1.cancel(); -//// } -// PropertyValuesHolder pv1 = PropertyValuesHolder.ofFloat("scaleX", 1.5f, 1.0f); -// PropertyValuesHolder pv2 = PropertyValuesHolder.ofFloat("scaleY", 1.5f, 1.0f); -// PropertyValuesHolder pv3 = PropertyValuesHolder.ofFloat("rotation", 90f, 0f); -// anim2 = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, pv1, pv2, pv3); -// anim2.setDuration(300L); -// anim2.start(); -// isExitAnimated = false; -// } -// } - -// mExitIcon.rotation - - -// if (isInExitZone(position) && !mAnimated) { -// Log.d(TAG, "enterExitRange 1 isInExitZone(position) = " + isInExitZone(position) + ", Animated = " + mAnimated); -// -//// if (exitEnterAnim != null) -// exitEnterAnim = mExitIcon.animate() -// .scaleXBy(0.5f) -// .scaleYBy(0.5f) -// .rotationBy(90) -// .setDuration(300); -// exitEnterAnim.start(); -// mAnimated = true; -// } else if (mAnimated) { -// Log.d(TAG, "enterExitRange 2 isInExitZone(position) = " + isInExitZone(position) + ", Animated = " + mAnimated); -// exitExitAnim = mExitIcon.animate() -// .scaleXBy(0f) -// .scaleYBy(0f) -// .rotationBy(-90) -// .setDuration(300); -// exitExitAnim.start(); -// mAnimated = false; -// -// } - -// Log.d(TAG, "enterExitRange mExitIcon.getAnimation() == null = " + (mExitIcon.getAnimation() == null)); -// if (isInExitZone(position) && !mAnimated) { -// Log.d(TAG, "enterExitRange 1 isInExitZone(position) = " + isInExitZone(position) + ", Animated = " + mAnimated); -// -//// if (exitEnterAnim != null) -// if (mExitIcon.getAnimation() == null || mExitIcon.getAnimation().hasEnded()) { -// exitEnterAnim = mExitIcon.animate() -// .scaleXBy(0.5f) -// .scaleYBy(0.5f) -// .rotationBy(90) -// .setDuration(300); -// exitEnterAnim.start(); -// mAnimated = true; -// } -// } else if (mAnimated) { -// Log.d(TAG, "enterExitRange 2 isInExitZone(position) = " + isInExitZone(position) + ", Animated = " + mAnimated); -// if (mExitIcon.getAnimation() == null || mExitIcon.getAnimation().hasEnded()) { -// exitExitAnim = mExitIcon.animate() -// .scaleXBy(0f) -// .scaleYBy(0f) -// .rotationBy(-90) -// .setDuration(300); -// exitExitAnim.start(); -// mAnimated = false; -// } -// } - - setVisibility(VISIBLE); - } - public void show() { resetExitButtonAnimation(); ObjectAnimator exitGradientAnimator = ObjectAnimator.ofFloat(mExitGradient, "alpha", EXIT_VIEW_TARGET_ALPHA); - exitGradientAnimator.setDuration(300L); + exitGradientAnimator.setDuration(FADE_DURATION); + exitGradientAnimator.setInterpolator(getExitViewInterpolator()); exitGradientAnimator.start(); ObjectAnimator vgExitAnimator = ObjectAnimator.ofFloat(mVgExit, "y", EXIT_VIEW_BASE_Y, EXIT_VIEW_TARGET_Y); - vgExitAnimator.setDuration(300L); + vgExitAnimator.setDuration(FADE_DURATION); + vgExitAnimator.setInterpolator(getExitViewInterpolator()); vgExitAnimator.start(); setVisibility(VISIBLE); @@ -318,24 +230,20 @@ public void show() { public void resetExitButtonAnimation() { Log.d(TAG, "resetExitButtonAnimation"); isExitAnimated = false; - mExitIcon.setScaleY(mDefaultScaleY); - mExitIcon.setScaleX(mDefaultScaleX); - mExitIcon.setRotation(mDefaultRotation); + mExitIcon.setScaleY(EXIT_ICON_DEFAULT_SCALE_Y); + mExitIcon.setScaleX(EXIT_ICON_DEFAULT_SCALE_X); + mExitIcon.setRotation(EXIT_ICON_DEFAULT_ROTATION); } - public static final float EXIT_VIEW_TARGET_ALPHA = 1.0f; - public static final float EXIT_VIEW_TARGET_Y = 0f; - - public static final float EXIT_VIEW_BASE_ALPHA = 0f; - public static final float EXIT_VIEW_BASE_Y = 800f; - public void hide() { ObjectAnimator vgExitAnimator = ObjectAnimator.ofFloat(mVgExit, "y", EXIT_VIEW_TARGET_Y, EXIT_VIEW_BASE_Y); vgExitAnimator.setDuration(FADE_DURATION); + vgExitAnimator.setInterpolator(getExitViewInterpolator()); vgExitAnimator.start(); ObjectAnimator exitGradientAnimator = ObjectAnimator.ofFloat(mExitGradient, "alpha", EXIT_VIEW_BASE_ALPHA); exitGradientAnimator.setDuration(FADE_DURATION); + exitGradientAnimator.setInterpolator(getExitViewInterpolator()); exitGradientAnimator.start(); exitGradientAnimator.addListener(new Animator.AnimatorListener() { diff --git a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java index 0a2f09d..7785207 100644 --- a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java +++ b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java @@ -303,7 +303,6 @@ public void onAnimationEnd(Animator animation) { if (null != onDocked) { onDocked.run(); } -// notifyListenersOfPositionChange(FloatingTab.this); } @Override diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 345f3ac..a39d6f1 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -43,6 +43,9 @@ class HoverViewStateCollapsed extends BaseHoverViewState { private static final float MIN_TAB_VERTICAL_POSITION = 0.0f; private static final float MAX_TAB_VERTICAL_POSITION = 1.0f; private static final long DEFAULT_IDLE_MILLIS = 5000; + private static final int POP_THROWING_THRESHOLD = 20; + private static final int NEGATIVE = -1; + private static final int POSITIVE = 1; protected FloatingTab mFloatingTab; protected final FloatingTabDragListener mFloatingTabDragListener = new FloatingTabDragListener(this); @@ -198,135 +201,72 @@ protected void onPickedUpByUser() { mHoverView.notifyOnDragStart(this); } - private double calculateDistance(@NonNull Point p1, @NonNull Point p2) { + private double calculateDistance(@NonNull Point point1, @NonNull Point point2) { return Math.sqrt( - Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2) + Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2) ); } - // Function to find the line given two points - Point lineFromPoints(Point p, Point q) { - int a = q.y - p.y; - int b = p.x - q.x; - int c = a * (p.x) + b * (p.y); - - if (b < 0) { - Log.d(TAG, "The line passing through points P and Q is: " - + a + "x " + b + "y = " + c); - } else { - Log.d(TAG, "The line passing through points P and Q is: " - + a + "x + " + b + "y = " + c); - } - - int xDirection = 0; - int yDirection = 0; - - if (p.x - q.x >= 0) { - xDirection = 0; - } else { - xDirection = 1; + /** + * Get target Y position from 2 points + * @param point1 first point + * @param point2 second point + * @return targetPoint + */ + private float getTargetYPosition(@NonNull Point point1, @NonNull Point point2) { + // STEP 1: get liner line equation from 2 points (ax + by = c) + float a = point2.y - point1.y; + float b = point1.x - point2.x; + float c = a * (point1.x) + b * (point1.y); + + // STEP 2: get x direction of the line + int xDirection = POSITIVE; + if (point1.x - point2.x >= 0) { + xDirection = NEGATIVE; } - if (p.y - q.y >= 0) { - yDirection = 0; - } else { - yDirection = 1; - } - - // TODO handle DIVIDE BY ZERO - Log.d(TAG, "xDirection = " + xDirection); - Log.d(TAG, "yDirection = " + yDirection); - - // wrong + // To avoid divide by zero exception if (b == 0) { b = 1; - Log.d(TAG, "Catch divide by 0!!!"); } - Log.d(TAG, "x = 0 -> y = " + (c / b)); -// Log.d(TAG, "x = " + (c / a) + ", y = 0"); - Log.d(TAG, "x = mHoverView.getScreenSize().x -> y = " + ((c - a * mHoverView.getScreenSize().x) / b)); -// Log.d(TAG, "x = " + ((c - b * mHoverView.getScreenSize().y) / a) + ", y = mHoverView.getScreenSize().y"); - if (xDirection == 0) { - return new Point(0, (c / b)); + // STEP 3: return target Y position ( y = (c - ax) / b) + if (xDirection == NEGATIVE) { + return c / b; } else { - return new Point(0, (c - a * mHoverView.getScreenSize().x) / b); + return (c - a * mHoverView.getScreenSize().x) / b; } } - // TODO remove -// static Point lineLineIntersection(Point pointA, Point pointB, Point pointC, Point pointD) { -// // Line AB represented as a1x + b1y = c1 -// double a1 = pointB.y - pointA.y; -// double b1 = pointA.x - pointB.x; -// double c1 = a1 * (pointA.x) + b1 * (pointA.y); -// -// // Line CD represented as a2x + b2y = c2 -// double a2 = pointD.y - pointC.y; -// double b2 = pointC.x - pointD.x; -// double c2 = a2 * (pointC.x) + b2 * (pointC.y); -// -// double determinant = a1 * b2 - a2 * b1; -// -// if (determinant == 0) { -// // The lines are parallel. This is simplified -// // by returning a pair of FLT_MAX -// return new Point(Integer.MAX_VALUE, Integer.MAX_VALUE); -// } else { -// double x = (b2 * c1 - b1 * c2) / determinant; -// double y = (a1 * c2 - a2 * c1) / determinant; -// return new Point((int) x, (int) y); -// } -// } - private void onDroppedByUser() { + Log.d(TAG, "TRACK_DEBUG HoverViewStateCollapsed onDroppedByUser"); + if (!hasControl()) { return; } mHoverView.mScreen.getExitView().hide(); - // TODO check location if (mPrevPoint == null) { - return; + mPrevPoint = mFloatingTab.getPosition(); } - // TODO Prev can be null int diffPositionX = mPrevPoint.x - mFloatingTab.getPosition().x; - int diffPositionY = mPrevPoint.y - mFloatingTab.getPosition().y; boolean droppedOnExit = mHoverView.mScreen.getExitView().isInExitZone(mFloatingTab.getPosition(), mHoverView.getScreenSize()); if (droppedOnExit) { - // TODO check userDropped option - onClose(false); + onClose(true); } else { - float distance = (float) calculateDistance(mPrevPoint, mFloatingTab.getPosition()); - Log.d(TAG, "TRACK_DEBUG onDroppedByUser diffPositionX = " + diffPositionX + ", diffPositionY = " + diffPositionY); - Log.d(TAG, "TRACK_DEBUG onDroppedByUser distance = " + calculateDistance(mPrevPoint, mFloatingTab.getPosition())); - Log.d(TAG, "TRACK_DEBUG onDroppedByUser diffTimeMillis = " + (System.currentTimeMillis() - mDragStartMillis)); -// lineFromPoints(mPrevPoint, mFloatingTab.getPosition()); int tabSize = mHoverView.getResources().getDimensionPixelSize(R.dimen.hover_tab_size); Point screenSize = mHoverView.getScreenSize(); float tabHorizontalPositionPercent = (float) mFloatingTab.getPosition().x / screenSize.x; final float viewHeightPercent = mFloatingTab.getHeight() / 2f / screenSize.y; -// float tabVerticalPosition = (float) lineFromPoints(mPrevPoint, mFloatingTab.getPosition()).y / screenSize.y; - float tabVerticalPositionPercent = (float) mFloatingTab.getPosition().y / screenSize.y; - - // TODO find best threshold - if (distance > 30) { - Log.d(TAG, "distance > 100"); -// Point targetPosition = lineFromPoints(mPrevPoint, mFloatingTab.getPosition()); - float positionY = lineFromPoints(mPrevPoint, mFloatingTab.getPosition()).y; - - // TODO fine best formula -// positionY = (positionY - mFloatingTab.getPosition().y) * distance / 100 + mFloatingTab.getPosition().y; -// tabVerticalPosition = (float) lineFromPoints(mPrevPoint, mFloatingTab.getPosition()).y / screenSize.y; -// tabVerticalPosition = tabVerticalPosition * distance / 1000; + float tabVerticalPositionPercent; + if (distance > POP_THROWING_THRESHOLD) { + float positionY = getTargetYPosition(mPrevPoint, mFloatingTab.getPosition()); tabVerticalPositionPercent = positionY / screenSize.y; - Log.d(TAG, "distance > 100 tabVerticalPosition = " + tabVerticalPositionPercent); - if (diffPositionX > 0) { tabHorizontalPositionPercent = 0f; @@ -334,14 +274,9 @@ private void onDroppedByUser() { tabHorizontalPositionPercent = 1f; } } else { - Log.d(TAG, "is less than 100"); -// tabVerticalPositionPercent = (float) lineFromPoints(mPrevPoint, mFloatingTab.getPosition()).y / screenSize.y; -// tabVerticalPositionPercent = tabVerticalPositionPercent * 3 / 10; tabVerticalPositionPercent = (float) mFloatingTab.getPosition().y / screenSize.y; } - int sideDockHorizontalPosition = SideDock.SidePosition.LEFT; - if (tabVerticalPositionPercent < MIN_TAB_VERTICAL_POSITION) { tabVerticalPositionPercent = MIN_TAB_VERTICAL_POSITION; } else if (tabVerticalPositionPercent > MAX_TAB_VERTICAL_POSITION - viewHeightPercent) { @@ -351,27 +286,16 @@ private void onDroppedByUser() { Point targetPosition = new Point(); targetPosition.x = (int) (tabHorizontalPositionPercent * (float) mHoverView.getScreenSize().x); targetPosition.y = (int) (tabVerticalPositionPercent * (float) mHoverView.getScreenSize().y); + boolean throwOnExit = mHoverView.mScreen.getExitView().isInExitZone(targetPosition, mHoverView.getScreenSize()); - Log.d(TAG, "targetPosition.x = " + targetPosition.x); - Log.d(TAG, "targetPosition.y = " + targetPosition.y); - boolean flickingExit = mHoverView.mScreen.getExitView().isInExitZone(targetPosition, mHoverView.getScreenSize()); - if (flickingExit) { - Log.d(TAG, "Dropped at horizontal " + tabHorizontalPositionPercent + ", vertical " + tabVerticalPositionPercent); - int x = screenSize.x / 2 - ((int) (tabSize * 0.25 * 2)); - - int y = (int) (screenSize.y * tabVerticalPositionPercent) - ((int) (tabSize * 0.25 * 2)); - - targetPosition.x = x; - targetPosition.y = y; - closeWithAnimation(targetPosition); + if (throwOnExit) { + targetPosition.x = screenSize.x / 2 - tabSize / 2; + targetPosition.y = (int) (screenSize.y * tabVerticalPositionPercent) - tabSize / 2; + closeWithThrowingAnimation(targetPosition); } else { - + int sideDockHorizontalPosition = SideDock.SidePosition.RIGHT; if (tabHorizontalPositionPercent <= 0.5) { sideDockHorizontalPosition = SideDock.SidePosition.LEFT; - } else if (tabHorizontalPositionPercent <= 1.0) { - sideDockHorizontalPosition = SideDock.SidePosition.RIGHT; - } else { - sideDockHorizontalPosition = SideDock.SidePosition.RIGHT; } Log.d(TAG, "Dropped at horizontal " + tabHorizontalPositionPercent + ", vertical " + tabVerticalPositionPercent); @@ -385,9 +309,7 @@ private void onDroppedByUser() { sidePosition ); mHoverView.saveVisualState(); - Log.d(TAG, "User dropped tab. Sending to new dock: " + mHoverView.mCollapsedDock); sendToDock(); - } } } @@ -415,15 +337,14 @@ protected void onTap() { } } - private void closeWithAnimation(Point targetPoint) { - Log.d(TAG, "Sending floating tab to dock."); -// deactivateDragger(); -// mFloatingTab.setDock(mHoverView.mCollapsedDock); + private void closeWithThrowingAnimation(Point targetPoint) { + Log.d(TAG, "closeWithThrowingAnimation"); + deactivateDragger(); mFloatingTab.closeAnimation(targetPoint, new Runnable() { @Override public void run() { - // TODO check userDropped option - onClose(false); + activateDragger(); + onClose(true); } }); } @@ -484,7 +405,6 @@ protected void onDocked() { } void moveFloatingTabTo(View floatingTab, @NonNull Point position) { - Log.d(TAG, "TRACK_DEBUG moveFloatingTabTo position = " + position); if (mHoverView.mScreen.getExitView().isInExitZone(position, mHoverView.getScreenSize())) { mHoverView.mScreen.getExitView().startEnterExitAnim(); } else { diff --git a/hover/src/main/res/drawable/ic_exit.xml b/hover/src/main/res/drawable/ic_exit.xml index 4b1a61a..68170a9 100644 --- a/hover/src/main/res/drawable/ic_exit.xml +++ b/hover/src/main/res/drawable/ic_exit.xml @@ -6,8 +6,7 @@ + android:fillColor="#000000" /> diff --git a/hover/src/main/res/layout/view_hover_menu_exit.xml b/hover/src/main/res/layout/view_hover_menu_exit.xml index f049b51..a7e3f95 100644 --- a/hover/src/main/res/layout/view_hover_menu_exit.xml +++ b/hover/src/main/res/layout/view_hover_menu_exit.xml @@ -21,7 +21,7 @@ android:layout_height="@dimen/hover_exit_icon_size" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" - android:layout_marginBottom="100dp" + android:layout_marginBottom="48dp" android:src="@drawable/ic_exit" /> From 95b4d356206194d29818704c9b7f425b0627200c Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Tue, 17 Sep 2019 16:14:00 +0900 Subject: [PATCH 074/105] Polish code --- .../hover/HoverViewStateCollapsed.java | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index a39d6f1..833959f 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -239,28 +239,21 @@ private float getTargetYPosition(@NonNull Point point1, @NonNull Point point2) { } private void onDroppedByUser() { - Log.d(TAG, "TRACK_DEBUG HoverViewStateCollapsed onDroppedByUser"); - if (!hasControl()) { return; } - mHoverView.mScreen.getExitView().hide(); if (mPrevPoint == null) { mPrevPoint = mFloatingTab.getPosition(); } - - int diffPositionX = mPrevPoint.x - mFloatingTab.getPosition().x; - - boolean droppedOnExit = mHoverView.mScreen.getExitView().isInExitZone(mFloatingTab.getPosition(), mHoverView.getScreenSize()); + Point screenSize = mHoverView.getScreenSize(); + boolean droppedOnExit = mHoverView.mScreen.getExitView().isInExitZone(mFloatingTab.getPosition(), screenSize); if (droppedOnExit) { onClose(true); } else { float distance = (float) calculateDistance(mPrevPoint, mFloatingTab.getPosition()); - int tabSize = mHoverView.getResources().getDimensionPixelSize(R.dimen.hover_tab_size); - Point screenSize = mHoverView.getScreenSize(); float tabHorizontalPositionPercent = (float) mFloatingTab.getPosition().x / screenSize.x; final float viewHeightPercent = mFloatingTab.getHeight() / 2f / screenSize.y; float tabVerticalPositionPercent; @@ -268,6 +261,7 @@ private void onDroppedByUser() { float positionY = getTargetYPosition(mPrevPoint, mFloatingTab.getPosition()); tabVerticalPositionPercent = positionY / screenSize.y; + int diffPositionX = mPrevPoint.x - mFloatingTab.getPosition().x; if (diffPositionX > 0) { tabHorizontalPositionPercent = 0f; } else { @@ -283,15 +277,15 @@ private void onDroppedByUser() { tabVerticalPositionPercent = MAX_TAB_VERTICAL_POSITION - viewHeightPercent; } - Point targetPosition = new Point(); - targetPosition.x = (int) (tabHorizontalPositionPercent * (float) mHoverView.getScreenSize().x); - targetPosition.y = (int) (tabVerticalPositionPercent * (float) mHoverView.getScreenSize().y); - boolean throwOnExit = mHoverView.mScreen.getExitView().isInExitZone(targetPosition, mHoverView.getScreenSize()); - + Point throwTargetPosition = new Point( + (int) (tabHorizontalPositionPercent * (float) mHoverView.getScreenSize().x), + (int) (tabVerticalPositionPercent * (float) mHoverView.getScreenSize().y)); + boolean throwOnExit = mHoverView.mScreen.getExitView().isInExitZone(throwTargetPosition, screenSize); if (throwOnExit) { - targetPosition.x = screenSize.x / 2 - tabSize / 2; - targetPosition.y = (int) (screenSize.y * tabVerticalPositionPercent) - tabSize / 2; - closeWithThrowingAnimation(targetPosition); + Point closeTargetPosition = new Point( + screenSize.x / 2 - tabSize / 2, + (int) (screenSize.y * tabVerticalPositionPercent) - tabSize / 2); + closeWithThrowingAnimation(closeTargetPosition); } else { int sideDockHorizontalPosition = SideDock.SidePosition.RIGHT; if (tabHorizontalPositionPercent <= 0.5) { From 74d97a4059251735a5815a1e02abaccf3a4f601f Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Tue, 17 Sep 2019 16:50:25 +0900 Subject: [PATCH 075/105] Add HandleDrop --- .../hover/HoverViewStateCollapsed.java | 103 ++++++++++-------- 1 file changed, 56 insertions(+), 47 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 833959f..f7f2294 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -252,60 +252,69 @@ private void onDroppedByUser() { if (droppedOnExit) { onClose(true); } else { - float distance = (float) calculateDistance(mPrevPoint, mFloatingTab.getPosition()); - int tabSize = mHoverView.getResources().getDimensionPixelSize(R.dimen.hover_tab_size); - float tabHorizontalPositionPercent = (float) mFloatingTab.getPosition().x / screenSize.x; - final float viewHeightPercent = mFloatingTab.getHeight() / 2f / screenSize.y; - float tabVerticalPositionPercent; - if (distance > POP_THROWING_THRESHOLD) { - float positionY = getTargetYPosition(mPrevPoint, mFloatingTab.getPosition()); - tabVerticalPositionPercent = positionY / screenSize.y; - - int diffPositionX = mPrevPoint.x - mFloatingTab.getPosition().x; - if (diffPositionX > 0) { - tabHorizontalPositionPercent = 0f; - } else { - tabHorizontalPositionPercent = 1f; - } + handleDrop(screenSize); + } + } + + private void handleDrop(Point screenSize) { + float distance = (float) calculateDistance(mPrevPoint, mFloatingTab.getPosition()); + int tabSize = mHoverView.getResources().getDimensionPixelSize(R.dimen.hover_tab_size); + float tabHorizontalPositionPercent = (float) mFloatingTab.getPosition().x / screenSize.x; + final float viewHeightPercent = mFloatingTab.getHeight() / 2f / screenSize.y; + float tabVerticalPositionPercent; + if (distance > POP_THROWING_THRESHOLD) { + float positionY = getTargetYPosition(mPrevPoint, mFloatingTab.getPosition()); + tabVerticalPositionPercent = positionY / screenSize.y; + + int diffPositionX = mPrevPoint.x - mFloatingTab.getPosition().x; + if (diffPositionX > 0) { + tabHorizontalPositionPercent = 0f; } else { - tabVerticalPositionPercent = (float) mFloatingTab.getPosition().y / screenSize.y; + tabHorizontalPositionPercent = 1f; } + } else { + tabVerticalPositionPercent = (float) mFloatingTab.getPosition().y / screenSize.y; + } - if (tabVerticalPositionPercent < MIN_TAB_VERTICAL_POSITION) { - tabVerticalPositionPercent = MIN_TAB_VERTICAL_POSITION; - } else if (tabVerticalPositionPercent > MAX_TAB_VERTICAL_POSITION - viewHeightPercent) { - tabVerticalPositionPercent = MAX_TAB_VERTICAL_POSITION - viewHeightPercent; + tabVerticalPositionPercent = computeVerticalPositionPercent(viewHeightPercent, tabVerticalPositionPercent); + + Point throwTargetPosition = new Point( + (int) (tabHorizontalPositionPercent * (float) mHoverView.getScreenSize().x), + (int) (tabVerticalPositionPercent * (float) mHoverView.getScreenSize().y)); + boolean throwOnExit = mHoverView.mScreen.getExitView().isInExitZone(throwTargetPosition, screenSize); + if (throwOnExit) { + Point closeTargetPosition = new Point( + screenSize.x / 2 - tabSize / 2, + (int) (screenSize.y * tabVerticalPositionPercent) - tabSize / 2); + closeWithThrowingAnimation(closeTargetPosition); + } else { + int sideDockHorizontalPosition = SideDock.SidePosition.RIGHT; + if (tabHorizontalPositionPercent <= 0.5) { + sideDockHorizontalPosition = SideDock.SidePosition.LEFT; } - Point throwTargetPosition = new Point( - (int) (tabHorizontalPositionPercent * (float) mHoverView.getScreenSize().x), - (int) (tabVerticalPositionPercent * (float) mHoverView.getScreenSize().y)); - boolean throwOnExit = mHoverView.mScreen.getExitView().isInExitZone(throwTargetPosition, screenSize); - if (throwOnExit) { - Point closeTargetPosition = new Point( - screenSize.x / 2 - tabSize / 2, - (int) (screenSize.y * tabVerticalPositionPercent) - tabSize / 2); - closeWithThrowingAnimation(closeTargetPosition); - } else { - int sideDockHorizontalPosition = SideDock.SidePosition.RIGHT; - if (tabHorizontalPositionPercent <= 0.5) { - sideDockHorizontalPosition = SideDock.SidePosition.LEFT; - } + Log.d(TAG, "Dropped at horizontal " + tabHorizontalPositionPercent + ", vertical " + tabVerticalPositionPercent); + SideDock.SidePosition sidePosition = new SideDock.SidePosition( + sideDockHorizontalPosition, + tabVerticalPositionPercent + ); + mHoverView.mCollapsedDock = new SideDock( + mHoverView, + tabSize, + sidePosition + ); + mHoverView.saveVisualState(); + sendToDock(); + } + } - Log.d(TAG, "Dropped at horizontal " + tabHorizontalPositionPercent + ", vertical " + tabVerticalPositionPercent); - SideDock.SidePosition sidePosition = new SideDock.SidePosition( - sideDockHorizontalPosition, - tabVerticalPositionPercent - ); - mHoverView.mCollapsedDock = new SideDock( - mHoverView, - tabSize, - sidePosition - ); - mHoverView.saveVisualState(); - sendToDock(); - } + private float computeVerticalPositionPercent(float viewHeightPercent, float tabVerticalPositionPercent) { + if (tabVerticalPositionPercent < MIN_TAB_VERTICAL_POSITION) { + tabVerticalPositionPercent = MIN_TAB_VERTICAL_POSITION; + } else if (tabVerticalPositionPercent > MAX_TAB_VERTICAL_POSITION - viewHeightPercent) { + tabVerticalPositionPercent = MAX_TAB_VERTICAL_POSITION - viewHeightPercent; } + return tabVerticalPositionPercent; } protected void onClose(final boolean userDropped) { From 836366ebc6c34e24fc605503f1650004b3a0314b Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Tue, 17 Sep 2019 16:52:45 +0900 Subject: [PATCH 076/105] Resolve TODO --- .../java/io/mattcarroll/hover/ExitView.java | 29 ++----------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/ExitView.java b/hover/src/main/java/io/mattcarroll/hover/ExitView.java index 8c19959..3ca4c67 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ExitView.java +++ b/hover/src/main/java/io/mattcarroll/hover/ExitView.java @@ -35,7 +35,6 @@ /** * Fullscreen View that provides an exit "drop zone" for users to exit the Hover Menu. */ -// TODO 2019.09.09 EXIT POP - Polish code, remove logs, check landscape mode class ExitView extends RelativeLayout { private static final String TAG = "ExitView"; @@ -99,7 +98,6 @@ private void setAnimations() { enterAnimation.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { - Log.d(TAG, "enterAnimation onAnimationStart"); mExitIcon.setScaleY(EXIT_ICON_DEFAULT_SCALE_Y); mExitIcon.setScaleX(EXIT_ICON_DEFAULT_SCALE_X); mExitIcon.setRotation(EXIT_ICON_DEFAULT_ROTATION); @@ -107,12 +105,11 @@ public void onAnimationStart(Animator animator) { @Override public void onAnimationEnd(Animator animator) { - Log.d(TAG, "enterAnimation onAnimationEnd"); + } @Override public void onAnimationCancel(Animator animator) { - Log.d(TAG, "enterAnimation onAnimationCancel"); mExitIcon.setScaleY(EXIT_ICON_DEFAULT_SCALE_Y); mExitIcon.setScaleX(EXIT_ICON_DEFAULT_SCALE_X); mExitIcon.setRotation(EXIT_ICON_DEFAULT_ROTATION); @@ -120,7 +117,7 @@ public void onAnimationCancel(Animator animator) { @Override public void onAnimationRepeat(Animator animator) { - Log.d(TAG, "enterAnimation onAnimationRepeat"); + } }); @@ -131,27 +128,6 @@ public void onAnimationRepeat(Animator animator) { exitAnimation = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, exitAnimationScaleX, exitAnimationScaleY, exitAnimationRotate, exitAnimationAlpha); exitAnimation.setDuration(ENTER_EXIT_DURATION); exitAnimation.setInterpolator(getExitViewInterpolator()); - exitAnimation.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animator) { - Log.d(TAG, "exitAnimation onAnimationStart"); - } - - @Override - public void onAnimationEnd(Animator animator) { - Log.d(TAG, "exitAnimation onAnimationEnd"); - } - - @Override - public void onAnimationCancel(Animator animator) { - Log.d(TAG, "exitAnimation onAnimationCancel"); - } - - @Override - public void onAnimationRepeat(Animator animator) { - Log.d(TAG, "exitAnimation onAnimationRepeat"); - } - }); } public boolean isInExitZone(@NonNull Point position, @NonNull Point screenSize) { @@ -228,7 +204,6 @@ public void show() { } public void resetExitButtonAnimation() { - Log.d(TAG, "resetExitButtonAnimation"); isExitAnimated = false; mExitIcon.setScaleY(EXIT_ICON_DEFAULT_SCALE_Y); mExitIcon.setScaleX(EXIT_ICON_DEFAULT_SCALE_X); From 9d1a905e05230d5a3a92af743ed519917c679c75 Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Tue, 17 Sep 2019 16:54:12 +0900 Subject: [PATCH 077/105] Add initExitIconViewStatus --- .../java/io/mattcarroll/hover/ExitView.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/ExitView.java b/hover/src/main/java/io/mattcarroll/hover/ExitView.java index 3ca4c67..6559d47 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ExitView.java +++ b/hover/src/main/java/io/mattcarroll/hover/ExitView.java @@ -98,9 +98,7 @@ private void setAnimations() { enterAnimation.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { - mExitIcon.setScaleY(EXIT_ICON_DEFAULT_SCALE_Y); - mExitIcon.setScaleX(EXIT_ICON_DEFAULT_SCALE_X); - mExitIcon.setRotation(EXIT_ICON_DEFAULT_ROTATION); + initExitIconViewStatus(); } @Override @@ -110,9 +108,7 @@ public void onAnimationEnd(Animator animator) { @Override public void onAnimationCancel(Animator animator) { - mExitIcon.setScaleY(EXIT_ICON_DEFAULT_SCALE_Y); - mExitIcon.setScaleX(EXIT_ICON_DEFAULT_SCALE_X); - mExitIcon.setRotation(EXIT_ICON_DEFAULT_ROTATION); + initExitIconViewStatus(); } @Override @@ -130,6 +126,12 @@ public void onAnimationRepeat(Animator animator) { exitAnimation.setInterpolator(getExitViewInterpolator()); } + private void initExitIconViewStatus() { + mExitIcon.setScaleY(EXIT_ICON_DEFAULT_SCALE_Y); + mExitIcon.setScaleX(EXIT_ICON_DEFAULT_SCALE_X); + mExitIcon.setRotation(EXIT_ICON_DEFAULT_ROTATION); + } + public boolean isInExitZone(@NonNull Point position, @NonNull Point screenSize) { int exitXExcludeThresholdLeft = screenSize.x / 10; int exitXExcludeThresholdRight = screenSize.x * 9 / 10; @@ -205,9 +207,7 @@ public void show() { public void resetExitButtonAnimation() { isExitAnimated = false; - mExitIcon.setScaleY(EXIT_ICON_DEFAULT_SCALE_Y); - mExitIcon.setScaleX(EXIT_ICON_DEFAULT_SCALE_X); - mExitIcon.setRotation(EXIT_ICON_DEFAULT_ROTATION); + initExitIconViewStatus(); } public void hide() { From 8db94a7fabe5e67b74d71331f788573b8042738c Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Tue, 17 Sep 2019 16:55:07 +0900 Subject: [PATCH 078/105] Remove unused import --- hover/src/main/java/io/mattcarroll/hover/ExitView.java | 1 - 1 file changed, 1 deletion(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/ExitView.java b/hover/src/main/java/io/mattcarroll/hover/ExitView.java index 6559d47..1fbb4d1 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ExitView.java +++ b/hover/src/main/java/io/mattcarroll/hover/ExitView.java @@ -25,7 +25,6 @@ import android.support.annotation.Nullable; import android.support.v4.view.animation.PathInterpolatorCompat; import android.util.AttributeSet; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; From e3f6baa6e9431ea0581d0dc111c1416ef14d7bfb Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Wed, 18 Sep 2019 09:42:11 +0900 Subject: [PATCH 079/105] Apply review --- .../java/io/mattcarroll/hover/ExitView.java | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/ExitView.java b/hover/src/main/java/io/mattcarroll/hover/ExitView.java index 1fbb4d1..465aedb 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ExitView.java +++ b/hover/src/main/java/io/mattcarroll/hover/ExitView.java @@ -57,9 +57,9 @@ class ExitView extends RelativeLayout { private View mExitIcon; private View mExitGradient; private ViewGroup mVgExit; - public ObjectAnimator enterAnimation = null; - public ObjectAnimator exitAnimation = null; - public boolean isExitAnimated = false; + private ObjectAnimator mEnterAnimation = null; + private ObjectAnimator mExitAnimation = null; + private boolean mIsShowing = false; public ExitView(@NonNull Context context) { this(context, null); @@ -91,10 +91,10 @@ private void setAnimations() { PropertyValuesHolder enterAnimationScaleY = PropertyValuesHolder.ofFloat("scaleY", EXIT_ICON_DEFAULT_SCALE_Y, EXIT_ICON_TARGET_SCALE_Y); PropertyValuesHolder enterAnimationRotate = PropertyValuesHolder.ofFloat("rotation", EXIT_ICON_DEFAULT_ROTATION, EXIT_ICON_TARGET_ROTATION); PropertyValuesHolder enterAnimationAlpha = PropertyValuesHolder.ofFloat("alpha", EXIT_ICON_DEFAULT_ALPHA, EXIT_ICON_TARGET_ALPHA); - enterAnimation = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, enterAnimationScaleX, enterAnimationScaleY, enterAnimationRotate, enterAnimationAlpha); - enterAnimation.setDuration(ENTER_EXIT_DURATION); - enterAnimation.setInterpolator(getExitViewInterpolator()); - enterAnimation.addListener(new Animator.AnimatorListener() { + mEnterAnimation = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, enterAnimationScaleX, enterAnimationScaleY, enterAnimationRotate, enterAnimationAlpha); + mEnterAnimation.setDuration(ENTER_EXIT_DURATION); + mEnterAnimation.setInterpolator(getExitViewInterpolator()); + mEnterAnimation.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { initExitIconViewStatus(); @@ -102,7 +102,6 @@ public void onAnimationStart(Animator animator) { @Override public void onAnimationEnd(Animator animator) { - } @Override @@ -112,7 +111,6 @@ public void onAnimationCancel(Animator animator) { @Override public void onAnimationRepeat(Animator animator) { - } }); @@ -120,9 +118,9 @@ public void onAnimationRepeat(Animator animator) { PropertyValuesHolder exitAnimationScaleY = PropertyValuesHolder.ofFloat("scaleY", EXIT_ICON_TARGET_SCALE_Y, EXIT_ICON_DEFAULT_SCALE_Y); PropertyValuesHolder exitAnimationRotate = PropertyValuesHolder.ofFloat("rotation", EXIT_ICON_TARGET_ROTATION, EXIT_ICON_DEFAULT_ROTATION); PropertyValuesHolder exitAnimationAlpha = PropertyValuesHolder.ofFloat("alpha", EXIT_ICON_TARGET_ALPHA, EXIT_ICON_DEFAULT_ALPHA); - exitAnimation = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, exitAnimationScaleX, exitAnimationScaleY, exitAnimationRotate, exitAnimationAlpha); - exitAnimation.setDuration(ENTER_EXIT_DURATION); - exitAnimation.setInterpolator(getExitViewInterpolator()); + mExitAnimation = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, exitAnimationScaleX, exitAnimationScaleY, exitAnimationRotate, exitAnimationAlpha); + mExitAnimation.setDuration(ENTER_EXIT_DURATION); + mExitAnimation.setInterpolator(getExitViewInterpolator()); } private void initExitIconViewStatus() { @@ -175,16 +173,16 @@ private double calculateDistance(@NonNull Point p1, @NonNull Point p2) { } public void startEnterExitAnim() { - if (enterAnimation != null && !enterAnimation.isRunning() && !isExitAnimated) { - enterAnimation.start(); - isExitAnimated = true; + if (mEnterAnimation != null && !mEnterAnimation.isRunning() && !mIsShowing) { + mEnterAnimation.start(); + mIsShowing = true; } } public void startExitExitAnim() { - if (exitAnimation != null && !exitAnimation.isRunning() && isExitAnimated) { - exitAnimation.start(); - isExitAnimated = false; + if (mExitAnimation != null && !mExitAnimation.isRunning() && mIsShowing) { + mExitAnimation.start(); + mIsShowing = false; } } @@ -205,7 +203,7 @@ public void show() { } public void resetExitButtonAnimation() { - isExitAnimated = false; + mIsShowing = false; initExitIconViewStatus(); } From 726fda26258c4440b64e437657fc981de2e9db27 Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Wed, 18 Sep 2019 11:22:08 +0900 Subject: [PATCH 080/105] Apply design review: allow setting pop icon location on left bottom and right bottom --- hover/src/main/java/io/mattcarroll/hover/ExitView.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/ExitView.java b/hover/src/main/java/io/mattcarroll/hover/ExitView.java index 465aedb..c547ba7 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ExitView.java +++ b/hover/src/main/java/io/mattcarroll/hover/ExitView.java @@ -144,14 +144,14 @@ public boolean isInExitZone(@NonNull Point position, @NonNull Point screenSize) 0 - mExitIcon.getWidth(), screenSize.y * 4 / 6, exitXExcludeThresholdLeft, - screenSize.y * 5 / 6 + screenSize.y - mExitIcon.getHeight() / 2 ); Rect excludedXExitAreaRight = new Rect( exitXExcludeThresholdRight, screenSize.y * 4 / 6, screenSize.x + mExitIcon.getWidth(), - screenSize.y * 5 / 6 + screenSize.y - mExitIcon.getHeight() / 2 ); return exitArea.contains(position.x, position.y) From 009a224c7871e861998c0c0f9560f7c5d01537c0 Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Wed, 18 Sep 2019 11:26:12 +0900 Subject: [PATCH 081/105] Polish code --- hover/src/main/java/io/mattcarroll/hover/ExitView.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/ExitView.java b/hover/src/main/java/io/mattcarroll/hover/ExitView.java index c547ba7..a91daad 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ExitView.java +++ b/hover/src/main/java/io/mattcarroll/hover/ExitView.java @@ -48,10 +48,10 @@ class ExitView extends RelativeLayout { private static final float EXIT_ICON_TARGET_ROTATION = 90f; private static final float EXIT_ICON_DEFAULT_ALPHA = 0.6f; private static final float EXIT_ICON_TARGET_ALPHA = 0.75f; + private static final float EXIT_VIEW_DEFAULT_ALPHA = 0f; private static final float EXIT_VIEW_TARGET_ALPHA = 1.0f; + private static final float EXIT_VIEW_DEFAULT_Y = 800f; private static final float EXIT_VIEW_TARGET_Y = 0f; - private static final float EXIT_VIEW_BASE_ALPHA = 0f; - private static final float EXIT_VIEW_BASE_Y = 800f; private int mExitRadiusInPx; private View mExitIcon; @@ -194,7 +194,7 @@ public void show() { exitGradientAnimator.setInterpolator(getExitViewInterpolator()); exitGradientAnimator.start(); - ObjectAnimator vgExitAnimator = ObjectAnimator.ofFloat(mVgExit, "y", EXIT_VIEW_BASE_Y, EXIT_VIEW_TARGET_Y); + ObjectAnimator vgExitAnimator = ObjectAnimator.ofFloat(mVgExit, "y", EXIT_VIEW_DEFAULT_Y, EXIT_VIEW_TARGET_Y); vgExitAnimator.setDuration(FADE_DURATION); vgExitAnimator.setInterpolator(getExitViewInterpolator()); vgExitAnimator.start(); @@ -208,12 +208,12 @@ public void resetExitButtonAnimation() { } public void hide() { - ObjectAnimator vgExitAnimator = ObjectAnimator.ofFloat(mVgExit, "y", EXIT_VIEW_TARGET_Y, EXIT_VIEW_BASE_Y); + ObjectAnimator vgExitAnimator = ObjectAnimator.ofFloat(mVgExit, "y", EXIT_VIEW_TARGET_Y, EXIT_VIEW_DEFAULT_Y); vgExitAnimator.setDuration(FADE_DURATION); vgExitAnimator.setInterpolator(getExitViewInterpolator()); vgExitAnimator.start(); - ObjectAnimator exitGradientAnimator = ObjectAnimator.ofFloat(mExitGradient, "alpha", EXIT_VIEW_BASE_ALPHA); + ObjectAnimator exitGradientAnimator = ObjectAnimator.ofFloat(mExitGradient, "alpha", EXIT_VIEW_DEFAULT_ALPHA); exitGradientAnimator.setDuration(FADE_DURATION); exitGradientAnimator.setInterpolator(getExitViewInterpolator()); exitGradientAnimator.start(); From 2fed293df700baedb812b8ed28b3cf9c668c0065 Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Wed, 18 Sep 2019 14:19:01 +0900 Subject: [PATCH 082/105] Apply review: improve readability --- .../java/io/mattcarroll/hover/ExitView.java | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/ExitView.java b/hover/src/main/java/io/mattcarroll/hover/ExitView.java index a91daad..39646de 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ExitView.java +++ b/hover/src/main/java/io/mattcarroll/hover/ExitView.java @@ -39,7 +39,7 @@ class ExitView extends RelativeLayout { private static final String TAG = "ExitView"; private static final int FADE_DURATION = 250; - private static final int ENTER_EXIT_DURATION = 250; + private static final int SHOW_HIDE_DURATION = 250; private static final float EXIT_ICON_DEFAULT_SCALE_X = 1.0f; private static final float EXIT_ICON_DEFAULT_SCALE_Y = 1.0f; private static final float EXIT_ICON_TARGET_SCALE_X = 1.2f; @@ -57,8 +57,8 @@ class ExitView extends RelativeLayout { private View mExitIcon; private View mExitGradient; private ViewGroup mVgExit; - private ObjectAnimator mEnterAnimation = null; - private ObjectAnimator mExitAnimation = null; + private ObjectAnimator mShowAnimation = null; + private ObjectAnimator mHideAnimation = null; private boolean mIsShowing = false; public ExitView(@NonNull Context context) { @@ -87,14 +87,14 @@ private Interpolator getExitViewInterpolator() { } private void setAnimations() { - PropertyValuesHolder enterAnimationScaleX = PropertyValuesHolder.ofFloat("scaleX", EXIT_ICON_DEFAULT_SCALE_X, EXIT_ICON_TARGET_SCALE_X); - PropertyValuesHolder enterAnimationScaleY = PropertyValuesHolder.ofFloat("scaleY", EXIT_ICON_DEFAULT_SCALE_Y, EXIT_ICON_TARGET_SCALE_Y); - PropertyValuesHolder enterAnimationRotate = PropertyValuesHolder.ofFloat("rotation", EXIT_ICON_DEFAULT_ROTATION, EXIT_ICON_TARGET_ROTATION); - PropertyValuesHolder enterAnimationAlpha = PropertyValuesHolder.ofFloat("alpha", EXIT_ICON_DEFAULT_ALPHA, EXIT_ICON_TARGET_ALPHA); - mEnterAnimation = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, enterAnimationScaleX, enterAnimationScaleY, enterAnimationRotate, enterAnimationAlpha); - mEnterAnimation.setDuration(ENTER_EXIT_DURATION); - mEnterAnimation.setInterpolator(getExitViewInterpolator()); - mEnterAnimation.addListener(new Animator.AnimatorListener() { + PropertyValuesHolder showAnimationScaleX = PropertyValuesHolder.ofFloat("scaleX", EXIT_ICON_DEFAULT_SCALE_X, EXIT_ICON_TARGET_SCALE_X); + PropertyValuesHolder showAnimationScaleY = PropertyValuesHolder.ofFloat("scaleY", EXIT_ICON_DEFAULT_SCALE_Y, EXIT_ICON_TARGET_SCALE_Y); + PropertyValuesHolder showAnimationRotate = PropertyValuesHolder.ofFloat("rotation", EXIT_ICON_DEFAULT_ROTATION, EXIT_ICON_TARGET_ROTATION); + PropertyValuesHolder showAnimationAlpha = PropertyValuesHolder.ofFloat("alpha", EXIT_ICON_DEFAULT_ALPHA, EXIT_ICON_TARGET_ALPHA); + mShowAnimation = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, showAnimationScaleX, showAnimationScaleY, showAnimationRotate, showAnimationAlpha); + mShowAnimation.setDuration(SHOW_HIDE_DURATION); + mShowAnimation.setInterpolator(getExitViewInterpolator()); + mShowAnimation.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { initExitIconViewStatus(); @@ -114,13 +114,13 @@ public void onAnimationRepeat(Animator animator) { } }); - PropertyValuesHolder exitAnimationScaleX = PropertyValuesHolder.ofFloat("scaleX", EXIT_ICON_TARGET_SCALE_X, EXIT_ICON_DEFAULT_SCALE_X); - PropertyValuesHolder exitAnimationScaleY = PropertyValuesHolder.ofFloat("scaleY", EXIT_ICON_TARGET_SCALE_Y, EXIT_ICON_DEFAULT_SCALE_Y); - PropertyValuesHolder exitAnimationRotate = PropertyValuesHolder.ofFloat("rotation", EXIT_ICON_TARGET_ROTATION, EXIT_ICON_DEFAULT_ROTATION); - PropertyValuesHolder exitAnimationAlpha = PropertyValuesHolder.ofFloat("alpha", EXIT_ICON_TARGET_ALPHA, EXIT_ICON_DEFAULT_ALPHA); - mExitAnimation = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, exitAnimationScaleX, exitAnimationScaleY, exitAnimationRotate, exitAnimationAlpha); - mExitAnimation.setDuration(ENTER_EXIT_DURATION); - mExitAnimation.setInterpolator(getExitViewInterpolator()); + PropertyValuesHolder hideAnimationScaleX = PropertyValuesHolder.ofFloat("scaleX", EXIT_ICON_TARGET_SCALE_X, EXIT_ICON_DEFAULT_SCALE_X); + PropertyValuesHolder hideAnimationScaleY = PropertyValuesHolder.ofFloat("scaleY", EXIT_ICON_TARGET_SCALE_Y, EXIT_ICON_DEFAULT_SCALE_Y); + PropertyValuesHolder hideAnimationRotate = PropertyValuesHolder.ofFloat("rotation", EXIT_ICON_TARGET_ROTATION, EXIT_ICON_DEFAULT_ROTATION); + PropertyValuesHolder hideAnimationAlpha = PropertyValuesHolder.ofFloat("alpha", EXIT_ICON_TARGET_ALPHA, EXIT_ICON_DEFAULT_ALPHA); + mHideAnimation = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, hideAnimationScaleX, hideAnimationScaleY, hideAnimationRotate, hideAnimationAlpha); + mHideAnimation.setDuration(SHOW_HIDE_DURATION); + mHideAnimation.setInterpolator(getExitViewInterpolator()); } private void initExitIconViewStatus() { @@ -172,16 +172,16 @@ private double calculateDistance(@NonNull Point p1, @NonNull Point p2) { ); } - public void startEnterExitAnim() { - if (mEnterAnimation != null && !mEnterAnimation.isRunning() && !mIsShowing) { - mEnterAnimation.start(); + public void startShowAnim() { + if (mShowAnimation != null && !mShowAnimation.isRunning() && !mIsShowing) { + mShowAnimation.start(); mIsShowing = true; } } - public void startExitExitAnim() { - if (mExitAnimation != null && !mExitAnimation.isRunning() && mIsShowing) { - mExitAnimation.start(); + public void startHideAnim() { + if (mHideAnimation != null && !mHideAnimation.isRunning() && mIsShowing) { + mHideAnimation.start(); mIsShowing = false; } } From 15d76634b0ff89e7060decfeca5bc445006e86ad Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Wed, 18 Sep 2019 14:20:24 +0900 Subject: [PATCH 083/105] Apply design review: adjust min MIN_TAB_VERTICAL_POSITION to fix cutting pop preview --- .../io/mattcarroll/hover/HoverViewStateCollapsed.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index f7f2294..b37e419 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -309,8 +309,8 @@ private void handleDrop(Point screenSize) { } private float computeVerticalPositionPercent(float viewHeightPercent, float tabVerticalPositionPercent) { - if (tabVerticalPositionPercent < MIN_TAB_VERTICAL_POSITION) { - tabVerticalPositionPercent = MIN_TAB_VERTICAL_POSITION; + if (tabVerticalPositionPercent < MIN_TAB_VERTICAL_POSITION + viewHeightPercent) { + tabVerticalPositionPercent = MIN_TAB_VERTICAL_POSITION + viewHeightPercent; } else if (tabVerticalPositionPercent > MAX_TAB_VERTICAL_POSITION - viewHeightPercent) { tabVerticalPositionPercent = MAX_TAB_VERTICAL_POSITION - viewHeightPercent; } @@ -409,9 +409,9 @@ protected void onDocked() { void moveFloatingTabTo(View floatingTab, @NonNull Point position) { if (mHoverView.mScreen.getExitView().isInExitZone(position, mHoverView.getScreenSize())) { - mHoverView.mScreen.getExitView().startEnterExitAnim(); + mHoverView.mScreen.getExitView().startShowAnim(); } else { - mHoverView.mScreen.getExitView().startExitExitAnim(); + mHoverView.mScreen.getExitView().startHideAnim(); } mFloatingTab.moveCenterTo(position); mPrevPoint = mCurrPoint; From 3f43375342091593dde1ae7e23d7de63f087f70b Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Wed, 18 Sep 2019 14:21:43 +0900 Subject: [PATCH 084/105] polish code --- hover/src/main/java/io/mattcarroll/hover/ExitView.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/ExitView.java b/hover/src/main/java/io/mattcarroll/hover/ExitView.java index 39646de..0c184dd 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ExitView.java +++ b/hover/src/main/java/io/mattcarroll/hover/ExitView.java @@ -172,14 +172,14 @@ private double calculateDistance(@NonNull Point p1, @NonNull Point p2) { ); } - public void startShowAnim() { + public void startShowAnimation() { if (mShowAnimation != null && !mShowAnimation.isRunning() && !mIsShowing) { mShowAnimation.start(); mIsShowing = true; } } - public void startHideAnim() { + public void startHideAnimation() { if (mHideAnimation != null && !mHideAnimation.isRunning() && mIsShowing) { mHideAnimation.start(); mIsShowing = false; From fbfdb83a6a8f11cf4613d22130eb7b0c0e3f7595 Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Wed, 18 Sep 2019 14:37:25 +0900 Subject: [PATCH 085/105] Apply review: improve readability --- .../java/io/mattcarroll/hover/ExitView.java | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/ExitView.java b/hover/src/main/java/io/mattcarroll/hover/ExitView.java index 0c184dd..714569f 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ExitView.java +++ b/hover/src/main/java/io/mattcarroll/hover/ExitView.java @@ -57,8 +57,8 @@ class ExitView extends RelativeLayout { private View mExitIcon; private View mExitGradient; private ViewGroup mVgExit; - private ObjectAnimator mShowAnimation = null; - private ObjectAnimator mHideAnimation = null; + private ObjectAnimator mShowEnterAnimation = null; + private ObjectAnimator mShowExitAnimation = null; private boolean mIsShowing = false; public ExitView(@NonNull Context context) { @@ -87,14 +87,14 @@ private Interpolator getExitViewInterpolator() { } private void setAnimations() { - PropertyValuesHolder showAnimationScaleX = PropertyValuesHolder.ofFloat("scaleX", EXIT_ICON_DEFAULT_SCALE_X, EXIT_ICON_TARGET_SCALE_X); - PropertyValuesHolder showAnimationScaleY = PropertyValuesHolder.ofFloat("scaleY", EXIT_ICON_DEFAULT_SCALE_Y, EXIT_ICON_TARGET_SCALE_Y); - PropertyValuesHolder showAnimationRotate = PropertyValuesHolder.ofFloat("rotation", EXIT_ICON_DEFAULT_ROTATION, EXIT_ICON_TARGET_ROTATION); - PropertyValuesHolder showAnimationAlpha = PropertyValuesHolder.ofFloat("alpha", EXIT_ICON_DEFAULT_ALPHA, EXIT_ICON_TARGET_ALPHA); - mShowAnimation = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, showAnimationScaleX, showAnimationScaleY, showAnimationRotate, showAnimationAlpha); - mShowAnimation.setDuration(SHOW_HIDE_DURATION); - mShowAnimation.setInterpolator(getExitViewInterpolator()); - mShowAnimation.addListener(new Animator.AnimatorListener() { + PropertyValuesHolder showEnterAnimationScaleX = PropertyValuesHolder.ofFloat("scaleX", EXIT_ICON_DEFAULT_SCALE_X, EXIT_ICON_TARGET_SCALE_X); + PropertyValuesHolder showEnterAnimationScaleY = PropertyValuesHolder.ofFloat("scaleY", EXIT_ICON_DEFAULT_SCALE_Y, EXIT_ICON_TARGET_SCALE_Y); + PropertyValuesHolder showEnterAnimationRotate = PropertyValuesHolder.ofFloat("rotation", EXIT_ICON_DEFAULT_ROTATION, EXIT_ICON_TARGET_ROTATION); + PropertyValuesHolder showEnterAnimationAlpha = PropertyValuesHolder.ofFloat("alpha", EXIT_ICON_DEFAULT_ALPHA, EXIT_ICON_TARGET_ALPHA); + mShowEnterAnimation = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, showEnterAnimationScaleX, showEnterAnimationScaleY, showEnterAnimationRotate, showEnterAnimationAlpha); + mShowEnterAnimation.setDuration(SHOW_HIDE_DURATION); + mShowEnterAnimation.setInterpolator(getExitViewInterpolator()); + mShowEnterAnimation.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { initExitIconViewStatus(); @@ -114,13 +114,13 @@ public void onAnimationRepeat(Animator animator) { } }); - PropertyValuesHolder hideAnimationScaleX = PropertyValuesHolder.ofFloat("scaleX", EXIT_ICON_TARGET_SCALE_X, EXIT_ICON_DEFAULT_SCALE_X); - PropertyValuesHolder hideAnimationScaleY = PropertyValuesHolder.ofFloat("scaleY", EXIT_ICON_TARGET_SCALE_Y, EXIT_ICON_DEFAULT_SCALE_Y); - PropertyValuesHolder hideAnimationRotate = PropertyValuesHolder.ofFloat("rotation", EXIT_ICON_TARGET_ROTATION, EXIT_ICON_DEFAULT_ROTATION); - PropertyValuesHolder hideAnimationAlpha = PropertyValuesHolder.ofFloat("alpha", EXIT_ICON_TARGET_ALPHA, EXIT_ICON_DEFAULT_ALPHA); - mHideAnimation = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, hideAnimationScaleX, hideAnimationScaleY, hideAnimationRotate, hideAnimationAlpha); - mHideAnimation.setDuration(SHOW_HIDE_DURATION); - mHideAnimation.setInterpolator(getExitViewInterpolator()); + PropertyValuesHolder showExitAnimationScaleX = PropertyValuesHolder.ofFloat("scaleX", EXIT_ICON_TARGET_SCALE_X, EXIT_ICON_DEFAULT_SCALE_X); + PropertyValuesHolder showExitAnimationScaleY = PropertyValuesHolder.ofFloat("scaleY", EXIT_ICON_TARGET_SCALE_Y, EXIT_ICON_DEFAULT_SCALE_Y); + PropertyValuesHolder showExitAnimationRotate = PropertyValuesHolder.ofFloat("rotation", EXIT_ICON_TARGET_ROTATION, EXIT_ICON_DEFAULT_ROTATION); + PropertyValuesHolder showExitAnimationAlpha = PropertyValuesHolder.ofFloat("alpha", EXIT_ICON_TARGET_ALPHA, EXIT_ICON_DEFAULT_ALPHA); + mShowExitAnimation = ObjectAnimator.ofPropertyValuesHolder(mExitIcon, showExitAnimationScaleX, showExitAnimationScaleY, showExitAnimationRotate, showExitAnimationAlpha); + mShowExitAnimation.setDuration(SHOW_HIDE_DURATION); + mShowExitAnimation.setInterpolator(getExitViewInterpolator()); } private void initExitIconViewStatus() { @@ -172,16 +172,16 @@ private double calculateDistance(@NonNull Point p1, @NonNull Point p2) { ); } - public void startShowAnimation() { - if (mShowAnimation != null && !mShowAnimation.isRunning() && !mIsShowing) { - mShowAnimation.start(); + public void showEnterAnimation() { + if (mShowEnterAnimation != null && !mShowEnterAnimation.isRunning() && !mIsShowing) { + mShowEnterAnimation.start(); mIsShowing = true; } } - public void startHideAnimation() { - if (mHideAnimation != null && !mHideAnimation.isRunning() && mIsShowing) { - mHideAnimation.start(); + public void showExitAnimation() { + if (mShowExitAnimation != null && !mShowExitAnimation.isRunning() && mIsShowing) { + mShowExitAnimation.start(); mIsShowing = false; } } From d1c69760f8d888fa697779f52c2dfb01709e8686 Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Wed, 18 Sep 2019 15:49:09 +0900 Subject: [PATCH 086/105] Add missing commits --- .../java/io/mattcarroll/hover/HoverViewStateCollapsed.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index b37e419..ec595ea 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -409,9 +409,9 @@ protected void onDocked() { void moveFloatingTabTo(View floatingTab, @NonNull Point position) { if (mHoverView.mScreen.getExitView().isInExitZone(position, mHoverView.getScreenSize())) { - mHoverView.mScreen.getExitView().startShowAnim(); + mHoverView.mScreen.getExitView().showEnterAnimation(); } else { - mHoverView.mScreen.getExitView().startHideAnim(); + mHoverView.mScreen.getExitView().showExitAnimation(); } mFloatingTab.moveCenterTo(position); mPrevPoint = mCurrPoint; From 524ac149258d6ee5ca783a19cb1bde8105a9c044 Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Wed, 18 Sep 2019 16:13:50 +0900 Subject: [PATCH 087/105] Apply review: remove unused code --- .../main/java/io/mattcarroll/hover/ExitView.java | 13 ------------- .../mattcarroll/hover/HoverViewStateCollapsed.java | 5 ----- 2 files changed, 18 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/ExitView.java b/hover/src/main/java/io/mattcarroll/hover/ExitView.java index 714569f..f49d07b 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ExitView.java +++ b/hover/src/main/java/io/mattcarroll/hover/ExitView.java @@ -159,19 +159,6 @@ public boolean isInExitZone(@NonNull Point position, @NonNull Point screenSize) && !excludedXExitAreaRight.contains(position.x, position.y); } - private Point getExitZoneCenter() { - return new Point( - (int) (mExitIcon.getX() + (mExitIcon.getWidth() / 2)), - (int) (mExitIcon.getY() + (mExitIcon.getHeight() / 2)) - ); - } - - private double calculateDistance(@NonNull Point p1, @NonNull Point p2) { - return Math.sqrt( - Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2) - ); - } - public void showEnterAnimation() { if (mShowEnterAnimation != null && !mShowEnterAnimation.isRunning() && !mIsShowing) { mShowEnterAnimation.start(); diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index ec595ea..987ad23 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -55,8 +55,6 @@ class HoverViewStateCollapsed extends BaseHoverViewState { private Handler mHandler = new Handler(); private Runnable mIdleActionRunnable; private Runnable mOnStateChanged; - private Point mStartPoint = null; - private long mDragStartMillis = -1L; private Point mPrevPoint = null; private Point mCurrPoint = new Point(0, 0); @@ -193,9 +191,6 @@ protected void onPickedUpByUser() { return; } - mStartPoint = mFloatingTab.getPosition(); - mDragStartMillis = System.currentTimeMillis(); - mHoverView.mScreen.getExitView().show(); restoreHoverViewIdleAction(); mHoverView.notifyOnDragStart(this); From c82a872325734ead879c29e2355919c045f29f94 Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Mon, 23 Sep 2019 18:17:00 +0900 Subject: [PATCH 088/105] Add GestureBlackBox to improve throw --- .../java/io/mattcarroll/hover/ExitView.java | 5 +- .../hover/HoverViewStateCollapsed.java | 181 +++++++++++++----- 2 files changed, 135 insertions(+), 51 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/ExitView.java b/hover/src/main/java/io/mattcarroll/hover/ExitView.java index f49d07b..4c713d7 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ExitView.java +++ b/hover/src/main/java/io/mattcarroll/hover/ExitView.java @@ -132,6 +132,7 @@ private void initExitIconViewStatus() { public boolean isInExitZone(@NonNull Point position, @NonNull Point screenSize) { int exitXExcludeThresholdLeft = screenSize.x / 10; int exitXExcludeThresholdRight = screenSize.x * 9 / 10; + int safeMargin = 1; // safe from the decimal point calculation Rect exitArea = new Rect( 0 - mExitIcon.getWidth(), @@ -144,14 +145,14 @@ public boolean isInExitZone(@NonNull Point position, @NonNull Point screenSize) 0 - mExitIcon.getWidth(), screenSize.y * 4 / 6, exitXExcludeThresholdLeft, - screenSize.y - mExitIcon.getHeight() / 2 + screenSize.y - (mExitIcon.getHeight() / 2 + safeMargin) ); Rect excludedXExitAreaRight = new Rect( exitXExcludeThresholdRight, screenSize.y * 4 / 6, screenSize.x + mExitIcon.getWidth(), - screenSize.y - mExitIcon.getHeight() / 2 + screenSize.y - (mExitIcon.getHeight() / 2 + safeMargin) ); return exitArea.contains(position.x, position.y) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 987ad23..370c7fb 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -43,7 +43,7 @@ class HoverViewStateCollapsed extends BaseHoverViewState { private static final float MIN_TAB_VERTICAL_POSITION = 0.0f; private static final float MAX_TAB_VERTICAL_POSITION = 1.0f; private static final long DEFAULT_IDLE_MILLIS = 5000; - private static final int POP_THROWING_THRESHOLD = 20; + private static final float POP_THROWING_SPEED_THRESHOLD = 0.3f; private static final int NEGATIVE = -1; private static final int POSITIVE = 1; @@ -55,8 +55,7 @@ class HoverViewStateCollapsed extends BaseHoverViewState { private Handler mHandler = new Handler(); private Runnable mIdleActionRunnable; private Runnable mOnStateChanged; - private Point mPrevPoint = null; - private Point mCurrPoint = new Point(0, 0); + private GestureBlackBox mGestureBlackBox = new GestureBlackBox(); @Override public void takeControl(@NonNull HoverView floatingTab, final Runnable onStateChanged) { @@ -196,52 +195,14 @@ protected void onPickedUpByUser() { mHoverView.notifyOnDragStart(this); } - private double calculateDistance(@NonNull Point point1, @NonNull Point point2) { - return Math.sqrt( - Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2) - ); - } - - /** - * Get target Y position from 2 points - * @param point1 first point - * @param point2 second point - * @return targetPoint - */ - private float getTargetYPosition(@NonNull Point point1, @NonNull Point point2) { - // STEP 1: get liner line equation from 2 points (ax + by = c) - float a = point2.y - point1.y; - float b = point1.x - point2.x; - float c = a * (point1.x) + b * (point1.y); - - // STEP 2: get x direction of the line - int xDirection = POSITIVE; - if (point1.x - point2.x >= 0) { - xDirection = NEGATIVE; - } - - // To avoid divide by zero exception - if (b == 0) { - b = 1; - } - - // STEP 3: return target Y position ( y = (c - ax) / b) - if (xDirection == NEGATIVE) { - return c / b; - } else { - return (c - a * mHoverView.getScreenSize().x) / b; - } - } - private void onDroppedByUser() { if (!hasControl()) { return; } mHoverView.mScreen.getExitView().hide(); + mGestureBlackBox.addGesturePoint(mFloatingTab.getPosition()); + - if (mPrevPoint == null) { - mPrevPoint = mFloatingTab.getPosition(); - } Point screenSize = mHoverView.getScreenSize(); boolean droppedOnExit = mHoverView.mScreen.getExitView().isInExitZone(mFloatingTab.getPosition(), screenSize); if (droppedOnExit) { @@ -249,19 +210,20 @@ private void onDroppedByUser() { } else { handleDrop(screenSize); } + mGestureBlackBox.clear(); } private void handleDrop(Point screenSize) { - float distance = (float) calculateDistance(mPrevPoint, mFloatingTab.getPosition()); int tabSize = mHoverView.getResources().getDimensionPixelSize(R.dimen.hover_tab_size); float tabHorizontalPositionPercent = (float) mFloatingTab.getPosition().x / screenSize.x; final float viewHeightPercent = mFloatingTab.getHeight() / 2f / screenSize.y; float tabVerticalPositionPercent; - if (distance > POP_THROWING_THRESHOLD) { - float positionY = getTargetYPosition(mPrevPoint, mFloatingTab.getPosition()); + + if (mGestureBlackBox.getSpeed() > POP_THROWING_SPEED_THRESHOLD) { + float positionY = mGestureBlackBox.getTargetYPosition(); tabVerticalPositionPercent = positionY / screenSize.y; - int diffPositionX = mPrevPoint.x - mFloatingTab.getPosition().x; + int diffPositionX = mGestureBlackBox.getDiffX(); if (diffPositionX > 0) { tabHorizontalPositionPercent = 0f; } else { @@ -409,8 +371,7 @@ void moveFloatingTabTo(View floatingTab, @NonNull Point position) { mHoverView.mScreen.getExitView().showExitAnimation(); } mFloatingTab.moveCenterTo(position); - mPrevPoint = mCurrPoint; - mCurrPoint = position; + mGestureBlackBox.addGesturePoint(position); } protected void activateDragger() { @@ -501,4 +462,126 @@ public void onTouchDown(FloatingTab floatingTab) { public void onTouchUp(FloatingTab floatingTab) { } } + + class GestureBlackBox { + private final long mMaxMeasureTimeGap = 100L; + private final int mMaxArraySize = 100; + GesturePoint mFirstPoint = null; + GesturePoint mSecondPoint = null; + + ArrayList mGesturePoints = new ArrayList<>(); + + private void addGesturePoint(Point point) { + if (mGesturePoints.size() >= mMaxArraySize) { + mGesturePoints.remove(0); + } + mGesturePoints.add(new GesturePoint(point, System.currentTimeMillis())); + } + + private boolean getPoints() { + if (mGesturePoints.size() < 2) { + return false; + } + + mFirstPoint = mGesturePoints.get(mGesturePoints.size() - 1); + mSecondPoint = mGesturePoints.get(mGesturePoints.size() - 2); + for (int i = mGesturePoints.size() - 2; i >= 0; i--) { + GesturePoint tempPoint = mGesturePoints.get(i); + if (mFirstPoint.mPointMillis - tempPoint.mPointMillis <= mMaxMeasureTimeGap) { + mSecondPoint = tempPoint; + } else { + break; + } + } + return true; + } + + private double getDistance() { + if (!getPoints()) { + return 0; + } + return calculateDistance(mFirstPoint.mPoint, mSecondPoint.mPoint); + } + + private int getDiffX() { + if (!getPoints()) { + return 0; + } + return mSecondPoint.mPoint.x - mFirstPoint.mPoint.x; + } + + private float getTargetYPosition() { + if (!getPoints()) { + return 0; + } + + return getTargetYPosition(mSecondPoint.mPoint, mFirstPoint.mPoint); + } + + /** + * Get target Y position from 2 points + * + * @param point1 first mPoint + * @param point2 second mPoint + * @return targetPoint + */ + private float getTargetYPosition(@NonNull Point point1, @NonNull Point point2) { + // STEP 1: get liner line equation from 2 points (ax + by = c) + float a = point2.y - point1.y; + float b = point1.x - point2.x; + float c = a * (point1.x) + b * (point1.y); + + // STEP 2: get x direction of the line + int xDirection = POSITIVE; + if (point1.x - point2.x >= 0) { + xDirection = NEGATIVE; + } + + // To avoid divide by zero exception + if (b == 0) { + b = 1; + } + + // STEP 3: return target Y position ( y = (c - ax) / b) + if (xDirection == NEGATIVE) { + return c / b; + } else { + return (c - a * mHoverView.getScreenSize().x) / b; + } + } + + private double getSpeed() { + if (!getPoints()) { + return 0; + } + return getDistance() / (mFirstPoint.mPointMillis - mSecondPoint.mPointMillis); + } + + private void clear() { + mGesturePoints.clear(); + mFirstPoint = null; + mSecondPoint = null; + } + + private double calculateDistance(@NonNull Point point1, @NonNull Point point2) { + return Math.sqrt( + Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2) + ); + } + + @Override + public String toString() { + return "" + mGesturePoints.size(); + } + + class GesturePoint { + GesturePoint(Point point, long pointMillis) { + this.mPoint = point; + this.mPointMillis = pointMillis; + } + + Point mPoint; + long mPointMillis; + } + } } From bf8a69c3d0535c195625c1a0a8f0e32a2213a451 Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Mon, 23 Sep 2019 18:21:24 +0900 Subject: [PATCH 089/105] Polish code --- .../java/io/mattcarroll/hover/HoverViewStateCollapsed.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 370c7fb..ef74a3a 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -575,13 +575,13 @@ public String toString() { } class GesturePoint { + private Point mPoint; + private long mPointMillis; + GesturePoint(Point point, long pointMillis) { this.mPoint = point; this.mPointMillis = pointMillis; } - - Point mPoint; - long mPointMillis; } } } From 7557b85e3c9b505c8353f1d3fa23fbb7c5be88ac Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Tue, 24 Sep 2019 17:14:05 +0900 Subject: [PATCH 090/105] Apply review --- .../hover/HoverViewStateCollapsed.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index ef74a3a..0b0ad56 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -478,7 +478,7 @@ private void addGesturePoint(Point point) { mGesturePoints.add(new GesturePoint(point, System.currentTimeMillis())); } - private boolean getPoints() { + private boolean updatePoints() { if (mGesturePoints.size() < 2) { return false; } @@ -497,21 +497,21 @@ private boolean getPoints() { } private double getDistance() { - if (!getPoints()) { + if (!updatePoints()) { return 0; } return calculateDistance(mFirstPoint.mPoint, mSecondPoint.mPoint); } private int getDiffX() { - if (!getPoints()) { + if (!updatePoints()) { return 0; } return mSecondPoint.mPoint.x - mFirstPoint.mPoint.x; } private float getTargetYPosition() { - if (!getPoints()) { + if (!updatePoints()) { return 0; } @@ -551,7 +551,7 @@ private float getTargetYPosition(@NonNull Point point1, @NonNull Point point2) { } private double getSpeed() { - if (!getPoints()) { + if (!updatePoints()) { return 0; } return getDistance() / (mFirstPoint.mPointMillis - mSecondPoint.mPointMillis); @@ -569,11 +569,6 @@ private double calculateDistance(@NonNull Point point1, @NonNull Point point2) { ); } - @Override - public String toString() { - return "" + mGesturePoints.size(); - } - class GesturePoint { private Point mPoint; private long mPointMillis; From 3ba84e8ed4e7553868fa7d737b8c000123cc998c Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Wed, 25 Sep 2019 16:50:49 +0900 Subject: [PATCH 091/105] Fix disappearing pop icon --- .../io/mattcarroll/hover/FloatingTab.java | 44 ++++++++++++++----- .../hover/HoverViewStateCollapsed.java | 1 + 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java index 7785207..19c6ac7 100644 --- a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java +++ b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java @@ -52,6 +52,8 @@ class FloatingTab extends HoverFrameLayout { private int mTabSize; private View mTabView; private Dock mDock; + public AnimatorSet animatorSetDisappear; + public AnimatorSet animatorSetAppear; public FloatingTab(@NonNull Context context, @NonNull String tabId) { super(context); @@ -100,15 +102,16 @@ public void enableDebugMode(boolean debugMode) { } public void appear(@Nullable final Runnable onAppeared) { - AnimatorSet animatorSet = new AnimatorSet(); + cancelAnimatorSetAppearIfNeeded(); + animatorSetAppear = new AnimatorSet(); ObjectAnimator scaleX = ObjectAnimator.ofFloat(this, "scaleX", 0.0f, 1.0f); ObjectAnimator scaleY = ObjectAnimator.ofFloat(this, "scaleY", 0.0f, 1.0f); - animatorSet.setDuration(APPEARING_ANIMATION_DURATION); - animatorSet.setInterpolator(new OvershootInterpolator()); - animatorSet.playTogether(scaleX, scaleY); - animatorSet.start(); + animatorSetAppear.setDuration(APPEARING_ANIMATION_DURATION); + animatorSetAppear.setInterpolator(new OvershootInterpolator()); + animatorSetAppear.playTogether(scaleX, scaleY); + animatorSetAppear.start(); - animatorSet.addListener(new Animator.AnimatorListener() { + animatorSetAppear.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @@ -133,18 +136,22 @@ public void onAnimationRepeat(Animator animation) { } public void appearImmediate() { + cancelAnimatorSetDisappearIfNeeded(); setVisibility(VISIBLE); + setScaleX(1.0f); + setScaleY(1.0f); } public void disappear(@Nullable final Runnable onDisappeared) { - AnimatorSet animatorSet = new AnimatorSet(); + cancelAnimatorSetDisappearIfNeeded(); + animatorSetDisappear = new AnimatorSet(); ObjectAnimator scaleX = ObjectAnimator.ofFloat(this, "scaleX", 0.0f); ObjectAnimator scaleY = ObjectAnimator.ofFloat(this, "scaleY", 0.0f); - animatorSet.setDuration(APPEARING_ANIMATION_DURATION); - animatorSet.playTogether(scaleX, scaleY); - animatorSet.start(); + animatorSetDisappear.setDuration(APPEARING_ANIMATION_DURATION); + animatorSetDisappear.playTogether(scaleX, scaleY); + animatorSetDisappear.start(); - animatorSet.addListener(new Animator.AnimatorListener() { + animatorSetDisappear.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @@ -169,9 +176,24 @@ public void onAnimationRepeat(Animator animation) { } public void disappearImmediate() { + cancelAnimatorSetAppearIfNeeded(); setVisibility(GONE); } + private void cancelAnimatorSetAppearIfNeeded() { + if (animatorSetAppear != null && animatorSetAppear.isRunning()) { + animatorSetAppear.cancel(); + animatorSetAppear = null; + } + } + + private void cancelAnimatorSetDisappearIfNeeded() { + if (animatorSetDisappear != null && animatorSetDisappear.isRunning()) { + animatorSetDisappear.cancel(); + animatorSetDisappear = null; + } + } + public void shrink() { mTabSize = getResources().getDimensionPixelSize(R.dimen.hover_tab_size_shrunk); updateSize(); diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 0b0ad56..5029a92 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -91,6 +91,7 @@ public void run() { return; } if (wasFloatingTabVisible) { + mFloatingTab.appearImmediate(); sendToDock(); } else { moveToDock(); From e1adecd36b9617ffed6ee8b19688894573392e2f Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Wed, 25 Sep 2019 16:57:05 +0900 Subject: [PATCH 092/105] change variable names --- .../io/mattcarroll/hover/FloatingTab.java | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java index 19c6ac7..9c08e08 100644 --- a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java +++ b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java @@ -52,8 +52,8 @@ class FloatingTab extends HoverFrameLayout { private int mTabSize; private View mTabView; private Dock mDock; - public AnimatorSet animatorSetDisappear; - public AnimatorSet animatorSetAppear; + private AnimatorSet mAnimatorSetDisappear; + private AnimatorSet mAnimatorSetAppear; public FloatingTab(@NonNull Context context, @NonNull String tabId) { super(context); @@ -103,15 +103,15 @@ public void enableDebugMode(boolean debugMode) { public void appear(@Nullable final Runnable onAppeared) { cancelAnimatorSetAppearIfNeeded(); - animatorSetAppear = new AnimatorSet(); + mAnimatorSetAppear = new AnimatorSet(); ObjectAnimator scaleX = ObjectAnimator.ofFloat(this, "scaleX", 0.0f, 1.0f); ObjectAnimator scaleY = ObjectAnimator.ofFloat(this, "scaleY", 0.0f, 1.0f); - animatorSetAppear.setDuration(APPEARING_ANIMATION_DURATION); - animatorSetAppear.setInterpolator(new OvershootInterpolator()); - animatorSetAppear.playTogether(scaleX, scaleY); - animatorSetAppear.start(); + mAnimatorSetAppear.setDuration(APPEARING_ANIMATION_DURATION); + mAnimatorSetAppear.setInterpolator(new OvershootInterpolator()); + mAnimatorSetAppear.playTogether(scaleX, scaleY); + mAnimatorSetAppear.start(); - animatorSetAppear.addListener(new Animator.AnimatorListener() { + mAnimatorSetAppear.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @@ -144,14 +144,14 @@ public void appearImmediate() { public void disappear(@Nullable final Runnable onDisappeared) { cancelAnimatorSetDisappearIfNeeded(); - animatorSetDisappear = new AnimatorSet(); + mAnimatorSetDisappear = new AnimatorSet(); ObjectAnimator scaleX = ObjectAnimator.ofFloat(this, "scaleX", 0.0f); ObjectAnimator scaleY = ObjectAnimator.ofFloat(this, "scaleY", 0.0f); - animatorSetDisappear.setDuration(APPEARING_ANIMATION_DURATION); - animatorSetDisappear.playTogether(scaleX, scaleY); - animatorSetDisappear.start(); + mAnimatorSetDisappear.setDuration(APPEARING_ANIMATION_DURATION); + mAnimatorSetDisappear.playTogether(scaleX, scaleY); + mAnimatorSetDisappear.start(); - animatorSetDisappear.addListener(new Animator.AnimatorListener() { + mAnimatorSetDisappear.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @@ -181,16 +181,16 @@ public void disappearImmediate() { } private void cancelAnimatorSetAppearIfNeeded() { - if (animatorSetAppear != null && animatorSetAppear.isRunning()) { - animatorSetAppear.cancel(); - animatorSetAppear = null; + if (mAnimatorSetAppear != null && mAnimatorSetAppear.isRunning()) { + mAnimatorSetAppear.cancel(); + mAnimatorSetAppear = null; } } private void cancelAnimatorSetDisappearIfNeeded() { - if (animatorSetDisappear != null && animatorSetDisappear.isRunning()) { - animatorSetDisappear.cancel(); - animatorSetDisappear = null; + if (mAnimatorSetDisappear != null && mAnimatorSetDisappear.isRunning()) { + mAnimatorSetDisappear.cancel(); + mAnimatorSetDisappear = null; } } From 4f49a5a6237845d3a9fce9692e7d29383e3a6896 Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Wed, 25 Sep 2019 17:16:47 +0900 Subject: [PATCH 093/105] Fix crash --- .../java/io/mattcarroll/hover/HoverViewStateCollapsed.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 5029a92..4215e3b 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -304,7 +304,11 @@ private void closeWithThrowingAnimation(Point targetPoint) { mFloatingTab.closeAnimation(targetPoint, new Runnable() { @Override public void run() { - activateDragger(); + try { + activateDragger(); + } catch (Exception e) { + // Do nothing. This may happen only on testing + } onClose(true); } }); From a28c20be47456a2126192e2469955b156a3cbe59 Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Wed, 25 Sep 2019 17:34:29 +0900 Subject: [PATCH 094/105] Revert "Fix crash" This reverts commit 4f49a5a6 --- .../java/io/mattcarroll/hover/HoverViewStateCollapsed.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 4215e3b..5029a92 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -304,11 +304,7 @@ private void closeWithThrowingAnimation(Point targetPoint) { mFloatingTab.closeAnimation(targetPoint, new Runnable() { @Override public void run() { - try { - activateDragger(); - } catch (Exception e) { - // Do nothing. This may happen only on testing - } + activateDragger(); onClose(true); } }); From 943672d2fcc55240fe7d1419ea02781fb562bb96 Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Wed, 25 Sep 2019 17:35:14 +0900 Subject: [PATCH 095/105] Apply review - fix crash --- .../io/mattcarroll/hover/HoverViewStatePreviewed.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index f032375..faedaa1 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -78,10 +78,12 @@ protected void onClose(final boolean userDropped) { @Override protected void activateDragger() { - ArrayList> list = new ArrayList<>(); - list.add(new Pair<>(mFloatingTab, mFloatingTabDragListener)); - list.add(new Pair<>(mMessageView, mDefaultMessageViewDragListener)); - mHoverView.mDragger.activate(list); + if (mHoverView != null && mHoverView.mDragger != null) { + ArrayList> list = new ArrayList<>(); + list.add(new Pair<>(mFloatingTab, mFloatingTabDragListener)); + list.add(new Pair<>(mMessageView, mDefaultMessageViewDragListener)); + mHoverView.mDragger.activate(list); + } } @Override From 27487363698782bafef66c527107ae09ddb26335 Mon Sep 17 00:00:00 2001 From: Bruce Kim Date: Wed, 25 Sep 2019 17:38:15 +0900 Subject: [PATCH 096/105] Fix crash --- .../io/mattcarroll/hover/HoverViewStateCollapsed.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 5029a92..6c02f35 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -376,9 +376,11 @@ void moveFloatingTabTo(View floatingTab, @NonNull Point position) { } protected void activateDragger() { - ArrayList> list = new ArrayList<>(); - list.add(new Pair<>(mFloatingTab, mFloatingTabDragListener)); - mHoverView.mDragger.activate(list); + if (mHoverView != null && mHoverView.mDragger != null) { + ArrayList> list = new ArrayList<>(); + list.add(new Pair<>(mFloatingTab, mFloatingTabDragListener)); + mHoverView.mDragger.activate(list); + } } protected void deactivateDragger() { From 3393905c6eb596186261f656087a1916089276f2 Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Mon, 30 Sep 2019 12:16:45 +0900 Subject: [PATCH 097/105] Bump version to 1.0.0 (#35) --- hover/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hover/build.gradle b/hover/build.gradle index ac8eeb2..8beff63 100644 --- a/hover/build.gradle +++ b/hover/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.library' apply plugin: 'checkstyle' project.group = 'com.buzzvil' -project.version = '1.0.0-rc.7' +project.version = '1.0.0' android { compileSdkVersion project.compileSdkVersion.toInteger() From de2113be19db516df30265549f7d3f2d06a5936c Mon Sep 17 00:00:00 2001 From: Seohyun Kwak Date: Tue, 5 Nov 2019 17:06:56 +0900 Subject: [PATCH 098/105] add public to hover view state --- hover/src/main/java/io/mattcarroll/hover/HoverViewState.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewState.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewState.java index 6a175af..e77e01c 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewState.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewState.java @@ -22,7 +22,7 @@ * A state of a {@link HoverView}. {@code HoverView} is implemented with a state pattern and this * is the interface that is implemented by all such states. */ -interface HoverViewState { +public interface HoverViewState { /** * Activates this state. * @param hoverView hoverView From 77cb8f63805afde01ac94b91210c91497fa039ae Mon Sep 17 00:00:00 2001 From: "Ethan.Yoo" Date: Thu, 7 Nov 2019 19:06:45 +0900 Subject: [PATCH 099/105] fix lint --- .../java/io/mattcarroll/hover/HoverViewStateExpanded.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java index 7472693..5d3b7e5 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java @@ -318,7 +318,7 @@ public void onBackPressed() { mHoverView.collapse(); } - private void createTabsForIndices(int ... sectionIndices) { + private void createTabsForIndices(int... sectionIndices) { for (int sectionIndex : sectionIndices) { Log.d(TAG, "Creating tab for section at index " + sectionIndex); HoverMenu.Section section = mHoverView.mMenu.getSection(sectionIndex); @@ -362,7 +362,7 @@ private void reorderSection(int fromPosition, int toPosition) { updateChainedPositions(); } - private void updateSections(int ... sectionIndices) { + private void updateSections(int... sectionIndices) { Log.d(TAG, "Tab(s) changed: " + Arrays.toString(sectionIndices)); for (int sectionIndex : sectionIndices) { updateSection(sectionIndex); @@ -386,7 +386,7 @@ private void updateSection(int sectionIndex) { } } - private void removeSections(int ... sectionIndices) { + private void removeSections(int... sectionIndices) { Log.d(TAG, "Tab(s) removed: " + Arrays.toString(sectionIndices)); // Sort the indices so that they appear from lowest to highest. Then process // in reverse order so that we don't remove sections out from under us. From ea32d8f25c7287de19adb453c743f9581dbce520 Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Mon, 11 Nov 2019 17:09:32 +0900 Subject: [PATCH 100/105] Bump version to 1.0.1 (#38) --- hover/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hover/build.gradle b/hover/build.gradle index 8beff63..1b404ac 100644 --- a/hover/build.gradle +++ b/hover/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.library' apply plugin: 'checkstyle' project.group = 'com.buzzvil' -project.version = '1.0.0' +project.version = '1.0.1' android { compileSdkVersion project.compileSdkVersion.toInteger() From 03a75e7f195d7f041e03a9ebc6232d67af5efb0c Mon Sep 17 00:00:00 2001 From: "Ethan.Yoo" Date: Tue, 12 Nov 2019 21:15:43 +0900 Subject: [PATCH 101/105] apply publish.gradle to hover --- hover/build.gradle | 10 +++++++++- hover/publisher.gradle | 36 ------------------------------------ 2 files changed, 9 insertions(+), 37 deletions(-) delete mode 100644 hover/publisher.gradle diff --git a/hover/build.gradle b/hover/build.gradle index 8beff63..d903491 100644 --- a/hover/build.gradle +++ b/hover/build.gradle @@ -49,4 +49,12 @@ project.afterEvaluate { check.dependsOn('checkstyle') } -apply from: 'publisher.gradle' +ext { + pName = 'hover' + pDescription = 'Buzzvil hover Android SDK' + pPublisherVcsUrl = rootProject.ext.buzzscreenPublisherVcsUrl + pGroup = project.group + pVersion = project.version +} + +apply from: '../../../gradle/publish.gradle' diff --git a/hover/publisher.gradle b/hover/publisher.gradle deleted file mode 100644 index e203028..0000000 --- a/hover/publisher.gradle +++ /dev/null @@ -1,36 +0,0 @@ -apply plugin: 'com.jfrog.bintray' -apply plugin: 'com.github.dcendents.android-maven' - -group = project.group -version = project.version - -Properties prop = new Properties() -String propFileName = 'local.properties' - -try { - File file = project.rootProject.file(propFileName, PathValidation.EXISTS) - prop.load(file.newDataInputStream()) -} catch (InvalidUserDataException e) { - print("File not found : " + propFileName) -} - -bintray { - user = project.hasProperty('user') ? project.user : prop.getProperty("bintray.user") - key = project.hasProperty('key') ? project.key : prop.getProperty("bintray.apikey") - configurations = ['archives'] - publish = false - - pkg { - repo = 'maven' - name = 'hover' - desc = 'Buzzvil hover Android SDK' - userOrg = 'buzzvil' - licenses = ['Apache-2.0'] - vcsUrl = 'https://github.com/Buzzvil/hover' - publicDownloadNumbers = true - version { - name = project.version - released = new Date() - } - } -} From 9a9a95ddb6395a690104573821e7cf769cd380ae Mon Sep 17 00:00:00 2001 From: "Ethan.Yoo" Date: Wed, 13 Nov 2019 11:37:14 +0900 Subject: [PATCH 102/105] change publish.gradle path to be based on root dir --- hover/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hover/build.gradle b/hover/build.gradle index 7eb4d8e..4b71ff4 100644 --- a/hover/build.gradle +++ b/hover/build.gradle @@ -57,4 +57,4 @@ ext { pVersion = project.version } -apply from: '../../../gradle/publish.gradle' +apply from: "$rootDir/gradle/publish.gradle" \ No newline at end of file From 05003d8bedadf9e7905432f3bc0ff17b3aa9effd Mon Sep 17 00:00:00 2001 From: "Ethan.Yoo" Date: Wed, 13 Nov 2019 11:50:04 +0900 Subject: [PATCH 103/105] remove unnecessary plugin import code --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index f897f9e..b607207 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,6 @@ buildscript { plugins { id "com.jfrog.bintray" version "1.8.0" - id "com.github.dcendents.android-maven" version "2.0" } allprojects { From 56c599aef307649c643964c84c62b0e02e4e7c00 Mon Sep 17 00:00:00 2001 From: Josh Yun Date: Thu, 14 Nov 2019 10:15:19 +0900 Subject: [PATCH 104/105] updated VcsUrl --- hover/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hover/build.gradle b/hover/build.gradle index 4b71ff4..00d72f7 100644 --- a/hover/build.gradle +++ b/hover/build.gradle @@ -52,7 +52,7 @@ project.afterEvaluate { ext { pName = 'hover' pDescription = 'Buzzvil hover Android SDK' - pPublisherVcsUrl = rootProject.ext.buzzscreenPublisherVcsUrl + pPublisherVcsUrl = 'https://github.com/Buzzvil/hover.git' pGroup = project.group pVersion = project.version } From ecc7d3991fd5c69dd6601545956429a780eff4e0 Mon Sep 17 00:00:00 2001 From: Jineon Kim Date: Tue, 31 Dec 2019 12:19:54 +0900 Subject: [PATCH 105/105] androidx --- hover/build.gradle | 6 +- .../mattcarroll/hover/BaseHoverViewState.java | 6 +- .../hover/BaseTouchController.java | 4 +- .../java/io/mattcarroll/hover/Content.java | 2 +- .../io/mattcarroll/hover/ContentDisplay.java | 6 +- .../main/java/io/mattcarroll/hover/Dock.java | 2 +- .../java/io/mattcarroll/hover/Dragger.java | 2 +- .../java/io/mattcarroll/hover/ExitView.java | 7 +- .../io/mattcarroll/hover/FloatingTab.java | 4 +- .../mattcarroll/hover/HoverFrameLayout.java | 4 +- .../java/io/mattcarroll/hover/HoverMenu.java | 8 +- .../java/io/mattcarroll/hover/HoverView.java | 4 +- .../io/mattcarroll/hover/HoverViewState.java | 4 +- .../hover/HoverViewStateClosed.java | 2 +- .../hover/HoverViewStateCollapsed.java | 8 +- .../hover/HoverViewStateExpanded.java | 6 +- .../hover/HoverViewStateHidden.java | 2 +- .../hover/HoverViewStatePreviewed.java | 4 +- .../io/mattcarroll/hover/PositionDock.java | 2 +- .../java/io/mattcarroll/hover/Screen.java | 4 +- .../java/io/mattcarroll/hover/ShadeView.java | 4 +- .../java/io/mattcarroll/hover/SideDock.java | 4 +- .../java/io/mattcarroll/hover/TabChain.java | 4 +- .../io/mattcarroll/hover/TabMessageView.java | 6 +- .../io/mattcarroll/hover/TabSelectorView.java | 2 +- .../mattcarroll/hover/content/Navigator.java | 2 +- .../hover/content/NavigatorContent.java | 2 +- .../content/menus/DoNothingMenuAction.java | 2 +- .../mattcarroll/hover/content/menus/Menu.java | 2 +- .../hover/content/menus/MenuAction.java | 2 +- .../hover/content/menus/MenuItem.java | 2 +- .../hover/content/menus/MenuListAdapter.java | 2 +- .../hover/content/menus/MenuListContent.java | 4 +- .../hover/content/menus/MenuListView.java | 4 +- .../content/menus/ShowSubmenuMenuAction.java | 4 +- .../serialization/MenuActionFactory.java | 2 +- .../menus/serialization/MenuDeserializer.java | 2 +- .../content/toolbar/ToolbarNavigator.java | 6 +- .../hover/overlay/OverlayPermission.java | 4 +- .../mattcarroll/hover/view/InViewDragger.java | 2 +- .../hover/window/HoverMenuService.java | 4 +- .../hover/window/InWindowDragger.java | 2 +- .../hover/window/WindowViewController.java | 2 +- .../res/layout/view_toolbar_navigator.xml | 2 +- hoverdemo-helloworld/.gitignore | 1 - hoverdemo-helloworld/README.md | 9 - hoverdemo-helloworld/build.gradle | 27 -- hoverdemo-helloworld/proguard-rules.pro | 17 - .../src/main/AndroidManifest.xml | 30 -- .../helloworld/AllStatesHoverMenuService.java | 182 ----------- .../ChangingMenusHoverMenuService.java | 159 ---------- .../hoverdemo/helloworld/HoverMenuScreen.java | 71 ----- .../hoverdemo/helloworld/MainActivity.java | 125 -------- .../MenuThenNoMenuHoverMenuService.java | 199 ------------ .../MultipleSectionsHoverMenuService.java | 124 -------- .../MutatingSectionsHoverMenuService.java | 227 ------------- .../ReorderingHoverMenuService.java | 163 ---------- .../SingleSectionHoverMenuService.java | 118 ------- ...leSectionNotificationHoverMenuService.java | 136 -------- .../res/drawable-xhdpi/tab_background.png | Bin 22401 -> 0 bytes .../drawable-xhdpi/tab_background_blue.png | Bin 23017 -> 0 bytes .../drawable-xhdpi/tab_background_pink.png | Bin 22582 -> 0 bytes .../src/main/res/layout/activity_main.xml | 114 ------- .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 3418 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 2206 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 4842 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 7718 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 10486 -> 0 bytes .../src/main/res/values-w820dp/dimens.xml | 6 - .../src/main/res/values/colors.xml | 6 - .../src/main/res/values/dimens.xml | 5 - .../src/main/res/values/strings.xml | 15 - .../src/main/res/values/styles.xml | 11 - hoverdemo-kitchensink/.gitignore | 1 - hoverdemo-kitchensink/build.gradle | 30 -- hoverdemo-kitchensink/proguard-rules.pro | 17 - .../hover/hoverdemo/ApplicationTest.java | 28 -- .../src/main/AndroidManifest.xml | 26 -- .../hover/hoverdemo/kitchensink/App.java | 58 ---- .../hover/hoverdemo/kitchensink/Bus.java | 31 -- .../hoverdemo/kitchensink/DemoHoverMenu.java | 138 -------- .../kitchensink/DemoHoverMenuActivity.java | 55 ---- .../kitchensink/DemoHoverMenuFactory.java | 78 ----- .../kitchensink/DemoHoverMenuService.java | 80 ----- .../hoverdemo/kitchensink/MainActivity.java | 75 ----- .../kitchensink/appstate/AppStateAdapter.java | 192 ----------- .../kitchensink/appstate/AppStateContent.java | 93 ------ .../kitchensink/appstate/AppStateTracker.java | 297 ------------------ .../colorselection/ColorSelectionContent.java | 159 ---------- .../HoverIntroductionContent.java | 93 ------ .../kitchensink/introduction/HoverMotion.java | 138 -------- .../placeholder/PlaceholderContent.java | 85 ----- .../kitchensink/theming/HoverTheme.java | 45 --- .../theming/HoverThemeManager.java | 61 ---- .../kitchensink/theming/HoverThemer.java | 27 -- .../hoverdemo/kitchensink/ui/DemoTabView.java | 104 ------ .../kitchensink/ui/EmptyListView.java | 43 --- .../hover_introduction_logo.png | Bin 47904 -> 0 bytes .../hover_introduction_logo_no_shadow.png | Bin 33215 -> 0 bytes .../src/main/res/drawable-xhdpi/ic_menu.png | Bin 17226 -> 0 bytes .../res/drawable-xhdpi/ic_orange_circle.png | Bin 17645 -> 0 bytes .../main/res/drawable-xhdpi/ic_paintbrush.png | Bin 17989 -> 0 bytes .../src/main/res/drawable-xhdpi/ic_pen.png | Bin 17575 -> 0 bytes .../src/main/res/drawable-xhdpi/ic_stack.png | Bin 18839 -> 0 bytes .../res/drawable-xhdpi/tab_background.png | Bin 22401 -> 0 bytes .../src/main/res/drawable/circle.xml | 8 - .../res/drawable/rounded_rect_dark_gray.xml | 9 - .../main/res/drawable/rounded_rect_green.xml | 9 - .../main/res/drawable/rounded_rect_red.xml | 9 - .../main/res/drawable/rounded_rect_yellow.xml | 9 - .../main/res/layout/activity_hover_menu.xml | 10 - .../src/main/res/layout/activity_main.xml | 36 --- .../main/res/layout/view_activity_state.xml | 13 - .../res/layout/view_app_state_content.xml | 6 - .../main/res/layout/view_app_state_header.xml | 14 - .../layout/view_color_selection_content.xml | 66 ---- .../res/layout/view_content_introduction.xml | 103 ------ .../src/main/res/layout/view_emptylist.xml | 17 - .../res/layout/view_placeholder_content.xml | 34 -- .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 3418 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 2206 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 4842 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 7718 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 10486 -> 0 bytes .../src/main/res/values-w820dp/dimens.xml | 6 - .../src/main/res/values/colors.xml | 12 - .../src/main/res/values/dimens.xml | 5 - .../src/main/res/values/strings.xml | 5 - .../src/main/res/values/styles.xml | 21 -- .../com/hover/hoverdemo/ExampleUnitTest.java | 30 -- hoverdemo-nonfullscreen/.gitignore | 1 - hoverdemo-nonfullscreen/README.md | 33 -- hoverdemo-nonfullscreen/build.gradle | 34 -- hoverdemo-nonfullscreen/proguard-rules.pro | 17 - .../ExampleInstrumentedTest.java | 26 -- .../src/main/AndroidManifest.xml | 22 -- .../nonfullscreen/DemoHoverMenu.java | 91 ------ .../nonfullscreen/DemoHoverMenuService.java | 63 ---- .../hoverdemo/nonfullscreen/DemoTabView.java | 104 ------ .../hoverdemo/nonfullscreen/MainActivity.java | 61 ---- .../nonfullscreen/NonFullscreenContent.java | 66 ---- .../res/drawable-xhdpi/ic_orange_circle.png | Bin 17645 -> 0 bytes .../res/drawable-xhdpi/tab_background.png | Bin 22401 -> 0 bytes .../src/main/res/layout/activity_main.xml | 32 -- .../res/layout/content_non_fullscreen.xml | 14 - .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 3418 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 2206 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 4842 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 7718 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 10486 -> 0 bytes .../src/main/res/values-w820dp/dimens.xml | 6 - .../src/main/res/values/colors.xml | 8 - .../src/main/res/values/dimens.xml | 5 - .../src/main/res/values/strings.xml | 3 - .../src/main/res/values/styles.xml | 11 - .../ExampleUnitTest.java | 17 - settings.gradle | 2 +- 157 files changed, 81 insertions(+), 4815 deletions(-) delete mode 100644 hoverdemo-helloworld/.gitignore delete mode 100644 hoverdemo-helloworld/README.md delete mode 100644 hoverdemo-helloworld/build.gradle delete mode 100644 hoverdemo-helloworld/proguard-rules.pro delete mode 100644 hoverdemo-helloworld/src/main/AndroidManifest.xml delete mode 100644 hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/AllStatesHoverMenuService.java delete mode 100644 hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/ChangingMenusHoverMenuService.java delete mode 100644 hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/HoverMenuScreen.java delete mode 100644 hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/MainActivity.java delete mode 100644 hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/MenuThenNoMenuHoverMenuService.java delete mode 100644 hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/MultipleSectionsHoverMenuService.java delete mode 100644 hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/MutatingSectionsHoverMenuService.java delete mode 100644 hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/ReorderingHoverMenuService.java delete mode 100644 hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/SingleSectionHoverMenuService.java delete mode 100644 hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/SingleSectionNotificationHoverMenuService.java delete mode 100644 hoverdemo-helloworld/src/main/res/drawable-xhdpi/tab_background.png delete mode 100644 hoverdemo-helloworld/src/main/res/drawable-xhdpi/tab_background_blue.png delete mode 100644 hoverdemo-helloworld/src/main/res/drawable-xhdpi/tab_background_pink.png delete mode 100644 hoverdemo-helloworld/src/main/res/layout/activity_main.xml delete mode 100644 hoverdemo-helloworld/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 hoverdemo-helloworld/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 hoverdemo-helloworld/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 hoverdemo-helloworld/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 hoverdemo-helloworld/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 hoverdemo-helloworld/src/main/res/values-w820dp/dimens.xml delete mode 100644 hoverdemo-helloworld/src/main/res/values/colors.xml delete mode 100644 hoverdemo-helloworld/src/main/res/values/dimens.xml delete mode 100644 hoverdemo-helloworld/src/main/res/values/strings.xml delete mode 100644 hoverdemo-helloworld/src/main/res/values/styles.xml delete mode 100644 hoverdemo-kitchensink/.gitignore delete mode 100644 hoverdemo-kitchensink/build.gradle delete mode 100644 hoverdemo-kitchensink/proguard-rules.pro delete mode 100644 hoverdemo-kitchensink/src/androidTest/java/io/mattcarroll/hover/hoverdemo/ApplicationTest.java delete mode 100644 hoverdemo-kitchensink/src/main/AndroidManifest.xml delete mode 100644 hoverdemo-kitchensink/src/main/java/io/mattcarroll/hover/hoverdemo/kitchensink/App.java delete mode 100644 hoverdemo-kitchensink/src/main/java/io/mattcarroll/hover/hoverdemo/kitchensink/Bus.java delete mode 100644 hoverdemo-kitchensink/src/main/java/io/mattcarroll/hover/hoverdemo/kitchensink/DemoHoverMenu.java delete mode 100644 hoverdemo-kitchensink/src/main/java/io/mattcarroll/hover/hoverdemo/kitchensink/DemoHoverMenuActivity.java delete mode 100644 hoverdemo-kitchensink/src/main/java/io/mattcarroll/hover/hoverdemo/kitchensink/DemoHoverMenuFactory.java delete mode 100755 hoverdemo-kitchensink/src/main/java/io/mattcarroll/hover/hoverdemo/kitchensink/DemoHoverMenuService.java delete mode 100644 hoverdemo-kitchensink/src/main/java/io/mattcarroll/hover/hoverdemo/kitchensink/MainActivity.java delete mode 100644 hoverdemo-kitchensink/src/main/java/io/mattcarroll/hover/hoverdemo/kitchensink/appstate/AppStateAdapter.java delete mode 100644 hoverdemo-kitchensink/src/main/java/io/mattcarroll/hover/hoverdemo/kitchensink/appstate/AppStateContent.java delete mode 100644 hoverdemo-kitchensink/src/main/java/io/mattcarroll/hover/hoverdemo/kitchensink/appstate/AppStateTracker.java delete mode 100644 hoverdemo-kitchensink/src/main/java/io/mattcarroll/hover/hoverdemo/kitchensink/colorselection/ColorSelectionContent.java delete mode 100644 hoverdemo-kitchensink/src/main/java/io/mattcarroll/hover/hoverdemo/kitchensink/introduction/HoverIntroductionContent.java delete mode 100644 hoverdemo-kitchensink/src/main/java/io/mattcarroll/hover/hoverdemo/kitchensink/introduction/HoverMotion.java delete mode 100644 hoverdemo-kitchensink/src/main/java/io/mattcarroll/hover/hoverdemo/kitchensink/placeholder/PlaceholderContent.java delete mode 100644 hoverdemo-kitchensink/src/main/java/io/mattcarroll/hover/hoverdemo/kitchensink/theming/HoverTheme.java delete mode 100644 hoverdemo-kitchensink/src/main/java/io/mattcarroll/hover/hoverdemo/kitchensink/theming/HoverThemeManager.java delete mode 100644 hoverdemo-kitchensink/src/main/java/io/mattcarroll/hover/hoverdemo/kitchensink/theming/HoverThemer.java delete mode 100644 hoverdemo-kitchensink/src/main/java/io/mattcarroll/hover/hoverdemo/kitchensink/ui/DemoTabView.java delete mode 100644 hoverdemo-kitchensink/src/main/java/io/mattcarroll/hover/hoverdemo/kitchensink/ui/EmptyListView.java delete mode 100644 hoverdemo-kitchensink/src/main/res/drawable-xhdpi/hover_introduction_logo.png delete mode 100644 hoverdemo-kitchensink/src/main/res/drawable-xhdpi/hover_introduction_logo_no_shadow.png delete mode 100644 hoverdemo-kitchensink/src/main/res/drawable-xhdpi/ic_menu.png delete mode 100644 hoverdemo-kitchensink/src/main/res/drawable-xhdpi/ic_orange_circle.png delete mode 100644 hoverdemo-kitchensink/src/main/res/drawable-xhdpi/ic_paintbrush.png delete mode 100644 hoverdemo-kitchensink/src/main/res/drawable-xhdpi/ic_pen.png delete mode 100644 hoverdemo-kitchensink/src/main/res/drawable-xhdpi/ic_stack.png delete mode 100644 hoverdemo-kitchensink/src/main/res/drawable-xhdpi/tab_background.png delete mode 100644 hoverdemo-kitchensink/src/main/res/drawable/circle.xml delete mode 100644 hoverdemo-kitchensink/src/main/res/drawable/rounded_rect_dark_gray.xml delete mode 100644 hoverdemo-kitchensink/src/main/res/drawable/rounded_rect_green.xml delete mode 100644 hoverdemo-kitchensink/src/main/res/drawable/rounded_rect_red.xml delete mode 100644 hoverdemo-kitchensink/src/main/res/drawable/rounded_rect_yellow.xml delete mode 100644 hoverdemo-kitchensink/src/main/res/layout/activity_hover_menu.xml delete mode 100644 hoverdemo-kitchensink/src/main/res/layout/activity_main.xml delete mode 100644 hoverdemo-kitchensink/src/main/res/layout/view_activity_state.xml delete mode 100644 hoverdemo-kitchensink/src/main/res/layout/view_app_state_content.xml delete mode 100644 hoverdemo-kitchensink/src/main/res/layout/view_app_state_header.xml delete mode 100644 hoverdemo-kitchensink/src/main/res/layout/view_color_selection_content.xml delete mode 100644 hoverdemo-kitchensink/src/main/res/layout/view_content_introduction.xml delete mode 100644 hoverdemo-kitchensink/src/main/res/layout/view_emptylist.xml delete mode 100644 hoverdemo-kitchensink/src/main/res/layout/view_placeholder_content.xml delete mode 100644 hoverdemo-kitchensink/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 hoverdemo-kitchensink/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 hoverdemo-kitchensink/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 hoverdemo-kitchensink/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 hoverdemo-kitchensink/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 hoverdemo-kitchensink/src/main/res/values-w820dp/dimens.xml delete mode 100644 hoverdemo-kitchensink/src/main/res/values/colors.xml delete mode 100644 hoverdemo-kitchensink/src/main/res/values/dimens.xml delete mode 100644 hoverdemo-kitchensink/src/main/res/values/strings.xml delete mode 100644 hoverdemo-kitchensink/src/main/res/values/styles.xml delete mode 100644 hoverdemo-kitchensink/src/test/java/com/hover/hoverdemo/ExampleUnitTest.java delete mode 100644 hoverdemo-nonfullscreen/.gitignore delete mode 100644 hoverdemo-nonfullscreen/README.md delete mode 100644 hoverdemo-nonfullscreen/build.gradle delete mode 100644 hoverdemo-nonfullscreen/proguard-rules.pro delete mode 100644 hoverdemo-nonfullscreen/src/androidTest/java/io/mattcarroll/hoverdemonon_fullscreen/ExampleInstrumentedTest.java delete mode 100644 hoverdemo-nonfullscreen/src/main/AndroidManifest.xml delete mode 100644 hoverdemo-nonfullscreen/src/main/java/io/mattcarroll/hoverdemo/nonfullscreen/DemoHoverMenu.java delete mode 100755 hoverdemo-nonfullscreen/src/main/java/io/mattcarroll/hoverdemo/nonfullscreen/DemoHoverMenuService.java delete mode 100644 hoverdemo-nonfullscreen/src/main/java/io/mattcarroll/hoverdemo/nonfullscreen/DemoTabView.java delete mode 100644 hoverdemo-nonfullscreen/src/main/java/io/mattcarroll/hoverdemo/nonfullscreen/MainActivity.java delete mode 100644 hoverdemo-nonfullscreen/src/main/java/io/mattcarroll/hoverdemo/nonfullscreen/NonFullscreenContent.java delete mode 100644 hoverdemo-nonfullscreen/src/main/res/drawable-xhdpi/ic_orange_circle.png delete mode 100644 hoverdemo-nonfullscreen/src/main/res/drawable-xhdpi/tab_background.png delete mode 100644 hoverdemo-nonfullscreen/src/main/res/layout/activity_main.xml delete mode 100644 hoverdemo-nonfullscreen/src/main/res/layout/content_non_fullscreen.xml delete mode 100644 hoverdemo-nonfullscreen/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 hoverdemo-nonfullscreen/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 hoverdemo-nonfullscreen/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 hoverdemo-nonfullscreen/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 hoverdemo-nonfullscreen/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 hoverdemo-nonfullscreen/src/main/res/values-w820dp/dimens.xml delete mode 100644 hoverdemo-nonfullscreen/src/main/res/values/colors.xml delete mode 100644 hoverdemo-nonfullscreen/src/main/res/values/dimens.xml delete mode 100644 hoverdemo-nonfullscreen/src/main/res/values/strings.xml delete mode 100644 hoverdemo-nonfullscreen/src/main/res/values/styles.xml delete mode 100644 hoverdemo-nonfullscreen/src/test/java/io/mattcarroll/hoverdemonon_fullscreen/ExampleUnitTest.java diff --git a/hover/build.gradle b/hover/build.gradle index 00d72f7..86b8441 100644 --- a/hover/build.gradle +++ b/hover/build.gradle @@ -22,10 +22,10 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - api "com.android.support:appcompat-v7:${supportLibVersion}" - api "com.android.support:recyclerview-v7:${supportLibVersion}" // Used to get DiffUtil + api ("androidx.appcompat:appcompat:$androidXAppcompatVersion") + api ("androidx.recyclerview:recyclerview:$androidXRecyclerviewVersion") - testImplementation 'junit:junit:4.12' + testImplementation "junit:junit:$junitVersion" } //------ Checkstyle ------- diff --git a/hover/src/main/java/io/mattcarroll/hover/BaseHoverViewState.java b/hover/src/main/java/io/mattcarroll/hover/BaseHoverViewState.java index ee8deda..625b5fc 100644 --- a/hover/src/main/java/io/mattcarroll/hover/BaseHoverViewState.java +++ b/hover/src/main/java/io/mattcarroll/hover/BaseHoverViewState.java @@ -15,9 +15,9 @@ */ package io.mattcarroll.hover; -import android.support.annotation.CallSuper; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.CallSuper; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; /** * {@link HoverViewState} that includes behavior common to all implementations. diff --git a/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java b/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java index 4e398e1..1263983 100644 --- a/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java +++ b/hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java @@ -2,8 +2,8 @@ import android.graphics.PointF; import android.graphics.Rect; -import android.support.annotation.NonNull; -import android.support.v4.util.Pair; +import androidx.annotation.NonNull; +import androidx.core.util.Pair; import android.util.Log; import android.view.MotionEvent; import android.view.View; diff --git a/hover/src/main/java/io/mattcarroll/hover/Content.java b/hover/src/main/java/io/mattcarroll/hover/Content.java index 68a2d32..d9a9836 100755 --- a/hover/src/main/java/io/mattcarroll/hover/Content.java +++ b/hover/src/main/java/io/mattcarroll/hover/Content.java @@ -15,7 +15,7 @@ */ package io.mattcarroll.hover; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import android.view.View; /** diff --git a/hover/src/main/java/io/mattcarroll/hover/ContentDisplay.java b/hover/src/main/java/io/mattcarroll/hover/ContentDisplay.java index 3f3de18..997434c 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ContentDisplay.java +++ b/hover/src/main/java/io/mattcarroll/hover/ContentDisplay.java @@ -19,9 +19,9 @@ import android.graphics.Color; import android.graphics.Point; import android.graphics.drawable.Drawable; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.content.ContextCompat; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.LayoutInflater; import android.view.View; diff --git a/hover/src/main/java/io/mattcarroll/hover/Dock.java b/hover/src/main/java/io/mattcarroll/hover/Dock.java index 24ca0bc..33ee584 100644 --- a/hover/src/main/java/io/mattcarroll/hover/Dock.java +++ b/hover/src/main/java/io/mattcarroll/hover/Dock.java @@ -16,7 +16,7 @@ package io.mattcarroll.hover; import android.graphics.Point; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; diff --git a/hover/src/main/java/io/mattcarroll/hover/Dragger.java b/hover/src/main/java/io/mattcarroll/hover/Dragger.java index 60d7394..fdabc7b 100644 --- a/hover/src/main/java/io/mattcarroll/hover/Dragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/Dragger.java @@ -17,7 +17,7 @@ import android.graphics.Point; import android.graphics.PointF; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import android.util.Log; import android.view.GestureDetector; import android.view.MotionEvent; diff --git a/hover/src/main/java/io/mattcarroll/hover/ExitView.java b/hover/src/main/java/io/mattcarroll/hover/ExitView.java index 4c713d7..5032302 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ExitView.java +++ b/hover/src/main/java/io/mattcarroll/hover/ExitView.java @@ -21,9 +21,6 @@ import android.content.Context; import android.graphics.Point; import android.graphics.Rect; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.view.animation.PathInterpolatorCompat; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; @@ -31,6 +28,10 @@ import android.view.animation.Interpolator; import android.widget.RelativeLayout; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.view.animation.PathInterpolatorCompat; + /** * Fullscreen View that provides an exit "drop zone" for users to exit the Hover Menu. */ diff --git a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java index 9c08e08..628499c 100644 --- a/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java +++ b/hover/src/main/java/io/mattcarroll/hover/FloatingTab.java @@ -23,8 +23,8 @@ import android.content.res.Configuration; import android.graphics.Color; import android.graphics.Point; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.util.Log; import android.view.View; import android.view.ViewGroup; diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverFrameLayout.java b/hover/src/main/java/io/mattcarroll/hover/HoverFrameLayout.java index 947d549..e7662ac 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverFrameLayout.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverFrameLayout.java @@ -3,8 +3,8 @@ import android.annotation.TargetApi; import android.content.Context; import android.os.Build; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.util.AttributeSet; import android.view.View; import android.widget.FrameLayout; diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverMenu.java b/hover/src/main/java/io/mattcarroll/hover/HoverMenu.java index 0e2d807..54ce906 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverMenu.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverMenu.java @@ -15,10 +15,10 @@ */ package io.mattcarroll.hover; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.util.DiffUtil; -import android.support.v7.util.ListUpdateCallback; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.DiffUtil; +import androidx.recyclerview.widget.ListUpdateCallback; import android.view.View; import java.util.ArrayList; diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverView.java b/hover/src/main/java/io/mattcarroll/hover/HoverView.java index 4ac199a..8da4957 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverView.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverView.java @@ -21,8 +21,8 @@ import android.graphics.Point; import android.os.Parcel; import android.os.Parcelable; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.util.AttributeSet; import android.util.Log; import android.view.KeyEvent; diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewState.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewState.java index e77e01c..6edbb76 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewState.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewState.java @@ -15,8 +15,8 @@ */ package io.mattcarroll.hover; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; /** * A state of a {@link HoverView}. {@code HoverView} is implemented with a state pattern and this diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java index 6c6fb36..1966d53 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateClosed.java @@ -15,7 +15,7 @@ */ package io.mattcarroll.hover; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import android.util.Log; /** diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java index 6c02f35..e982dc9 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateCollapsed.java @@ -17,10 +17,10 @@ import android.graphics.Point; import android.os.Handler; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.util.Pair; -import android.support.v7.util.ListUpdateCallback; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.util.Pair; +import androidx.recyclerview.widget.ListUpdateCallback; import android.util.Log; import android.view.View; diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java index 5d3b7e5..0c1bc38 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateExpanded.java @@ -16,9 +16,9 @@ package io.mattcarroll.hover; import android.graphics.Point; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.util.ListUpdateCallback; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.ListUpdateCallback; import android.util.Log; import android.view.View; diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateHidden.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateHidden.java index c2f7fc0..06ef01e 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStateHidden.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStateHidden.java @@ -2,7 +2,7 @@ import android.os.Handler; import android.os.Looper; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import android.util.Log; import android.view.View; diff --git a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java index faedaa1..c924ae9 100644 --- a/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java +++ b/hover/src/main/java/io/mattcarroll/hover/HoverViewStatePreviewed.java @@ -15,8 +15,8 @@ */ package io.mattcarroll.hover; -import android.support.annotation.NonNull; -import android.support.v4.util.Pair; +import androidx.annotation.NonNull; +import androidx.core.util.Pair; import android.util.Log; import java.util.ArrayList; diff --git a/hover/src/main/java/io/mattcarroll/hover/PositionDock.java b/hover/src/main/java/io/mattcarroll/hover/PositionDock.java index be789c3..e49f98a 100644 --- a/hover/src/main/java/io/mattcarroll/hover/PositionDock.java +++ b/hover/src/main/java/io/mattcarroll/hover/PositionDock.java @@ -16,7 +16,7 @@ package io.mattcarroll.hover; import android.graphics.Point; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; /** * {@link Dock} that has a static position as defined by a provided {@link Point}. A diff --git a/hover/src/main/java/io/mattcarroll/hover/Screen.java b/hover/src/main/java/io/mattcarroll/hover/Screen.java index ea6dfb4..b67c124 100644 --- a/hover/src/main/java/io/mattcarroll/hover/Screen.java +++ b/hover/src/main/java/io/mattcarroll/hover/Screen.java @@ -15,8 +15,8 @@ */ package io.mattcarroll.hover; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.util.Log; import android.view.View; import android.view.ViewGroup; diff --git a/hover/src/main/java/io/mattcarroll/hover/ShadeView.java b/hover/src/main/java/io/mattcarroll/hover/ShadeView.java index 8ba309f..89829bf 100644 --- a/hover/src/main/java/io/mattcarroll/hover/ShadeView.java +++ b/hover/src/main/java/io/mattcarroll/hover/ShadeView.java @@ -18,8 +18,8 @@ import android.animation.Animator; import android.animation.ObjectAnimator; import android.content.Context; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.util.AttributeSet; import android.view.LayoutInflater; import android.widget.FrameLayout; diff --git a/hover/src/main/java/io/mattcarroll/hover/SideDock.java b/hover/src/main/java/io/mattcarroll/hover/SideDock.java index 4b06583..770725e 100644 --- a/hover/src/main/java/io/mattcarroll/hover/SideDock.java +++ b/hover/src/main/java/io/mattcarroll/hover/SideDock.java @@ -16,8 +16,8 @@ package io.mattcarroll.hover; import android.graphics.Point; -import android.support.annotation.IntDef; -import android.support.annotation.NonNull; +import androidx.annotation.IntDef; +import androidx.annotation.NonNull; import android.util.Log; import java.lang.annotation.Retention; diff --git a/hover/src/main/java/io/mattcarroll/hover/TabChain.java b/hover/src/main/java/io/mattcarroll/hover/TabChain.java index ac5bf9e..992cc9b 100644 --- a/hover/src/main/java/io/mattcarroll/hover/TabChain.java +++ b/hover/src/main/java/io/mattcarroll/hover/TabChain.java @@ -16,8 +16,8 @@ package io.mattcarroll.hover; import android.graphics.Point; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.util.Log; import android.view.View; diff --git a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java index 6badd87..a60787b 100644 --- a/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java +++ b/hover/src/main/java/io/mattcarroll/hover/TabMessageView.java @@ -2,9 +2,9 @@ import android.content.Context; import android.graphics.Point; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.view.animation.LinearOutSlowInInterpolator; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.interpolator.view.animation.LinearOutSlowInInterpolator; import android.util.Log; import android.view.View; import android.view.animation.AlphaAnimation; diff --git a/hover/src/main/java/io/mattcarroll/hover/TabSelectorView.java b/hover/src/main/java/io/mattcarroll/hover/TabSelectorView.java index 997f5ee..f6d4fa2 100755 --- a/hover/src/main/java/io/mattcarroll/hover/TabSelectorView.java +++ b/hover/src/main/java/io/mattcarroll/hover/TabSelectorView.java @@ -19,7 +19,7 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; -import android.support.annotation.ColorInt; +import androidx.annotation.ColorInt; import android.util.AttributeSet; import android.util.TypedValue; import android.view.View; diff --git a/hover/src/main/java/io/mattcarroll/hover/content/Navigator.java b/hover/src/main/java/io/mattcarroll/hover/content/Navigator.java index 3129026..ca398b0 100644 --- a/hover/src/main/java/io/mattcarroll/hover/content/Navigator.java +++ b/hover/src/main/java/io/mattcarroll/hover/content/Navigator.java @@ -16,7 +16,7 @@ package io.mattcarroll.hover.content; import android.content.Context; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import android.util.AttributeSet; import android.view.ViewGroup; import android.widget.FrameLayout; diff --git a/hover/src/main/java/io/mattcarroll/hover/content/NavigatorContent.java b/hover/src/main/java/io/mattcarroll/hover/content/NavigatorContent.java index 87058ac..99413c6 100644 --- a/hover/src/main/java/io/mattcarroll/hover/content/NavigatorContent.java +++ b/hover/src/main/java/io/mattcarroll/hover/content/NavigatorContent.java @@ -15,7 +15,7 @@ */ package io.mattcarroll.hover.content; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import android.view.View; /** diff --git a/hover/src/main/java/io/mattcarroll/hover/content/menus/DoNothingMenuAction.java b/hover/src/main/java/io/mattcarroll/hover/content/menus/DoNothingMenuAction.java index be8cb17..c22687b 100644 --- a/hover/src/main/java/io/mattcarroll/hover/content/menus/DoNothingMenuAction.java +++ b/hover/src/main/java/io/mattcarroll/hover/content/menus/DoNothingMenuAction.java @@ -16,7 +16,7 @@ package io.mattcarroll.hover.content.menus; import android.content.Context; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import io.mattcarroll.hover.content.Navigator; diff --git a/hover/src/main/java/io/mattcarroll/hover/content/menus/Menu.java b/hover/src/main/java/io/mattcarroll/hover/content/menus/Menu.java index 7167808..50660ad 100644 --- a/hover/src/main/java/io/mattcarroll/hover/content/menus/Menu.java +++ b/hover/src/main/java/io/mattcarroll/hover/content/menus/Menu.java @@ -15,7 +15,7 @@ */ package io.mattcarroll.hover.content.menus; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import java.util.List; diff --git a/hover/src/main/java/io/mattcarroll/hover/content/menus/MenuAction.java b/hover/src/main/java/io/mattcarroll/hover/content/menus/MenuAction.java index 588173c..18e46a5 100755 --- a/hover/src/main/java/io/mattcarroll/hover/content/menus/MenuAction.java +++ b/hover/src/main/java/io/mattcarroll/hover/content/menus/MenuAction.java @@ -16,7 +16,7 @@ package io.mattcarroll.hover.content.menus; import android.content.Context; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import io.mattcarroll.hover.content.Navigator; diff --git a/hover/src/main/java/io/mattcarroll/hover/content/menus/MenuItem.java b/hover/src/main/java/io/mattcarroll/hover/content/menus/MenuItem.java index b44d061..b2930ff 100755 --- a/hover/src/main/java/io/mattcarroll/hover/content/menus/MenuItem.java +++ b/hover/src/main/java/io/mattcarroll/hover/content/menus/MenuItem.java @@ -15,7 +15,7 @@ */ package io.mattcarroll.hover.content.menus; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; /** * Represents a menu item that can act as a composite with submenu items. diff --git a/hover/src/main/java/io/mattcarroll/hover/content/menus/MenuListAdapter.java b/hover/src/main/java/io/mattcarroll/hover/content/menus/MenuListAdapter.java index 9573718..db294d9 100755 --- a/hover/src/main/java/io/mattcarroll/hover/content/menus/MenuListAdapter.java +++ b/hover/src/main/java/io/mattcarroll/hover/content/menus/MenuListAdapter.java @@ -15,7 +15,7 @@ */ package io.mattcarroll.hover.content.menus; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; diff --git a/hover/src/main/java/io/mattcarroll/hover/content/menus/MenuListContent.java b/hover/src/main/java/io/mattcarroll/hover/content/menus/MenuListContent.java index 602a798..bbeb1d3 100755 --- a/hover/src/main/java/io/mattcarroll/hover/content/menus/MenuListContent.java +++ b/hover/src/main/java/io/mattcarroll/hover/content/menus/MenuListContent.java @@ -16,8 +16,8 @@ package io.mattcarroll.hover.content.menus; import android.content.Context; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.view.View; import io.mattcarroll.hover.Content; diff --git a/hover/src/main/java/io/mattcarroll/hover/content/menus/MenuListView.java b/hover/src/main/java/io/mattcarroll/hover/content/menus/MenuListView.java index fd914e1..65fec3c 100755 --- a/hover/src/main/java/io/mattcarroll/hover/content/menus/MenuListView.java +++ b/hover/src/main/java/io/mattcarroll/hover/content/menus/MenuListView.java @@ -16,8 +16,8 @@ package io.mattcarroll.hover.content.menus; import android.content.Context; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; diff --git a/hover/src/main/java/io/mattcarroll/hover/content/menus/ShowSubmenuMenuAction.java b/hover/src/main/java/io/mattcarroll/hover/content/menus/ShowSubmenuMenuAction.java index 63bf15d..cc5c0fc 100644 --- a/hover/src/main/java/io/mattcarroll/hover/content/menus/ShowSubmenuMenuAction.java +++ b/hover/src/main/java/io/mattcarroll/hover/content/menus/ShowSubmenuMenuAction.java @@ -16,8 +16,8 @@ package io.mattcarroll.hover.content.menus; import android.content.Context; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.view.View; import io.mattcarroll.hover.content.Navigator; diff --git a/hover/src/main/java/io/mattcarroll/hover/content/menus/serialization/MenuActionFactory.java b/hover/src/main/java/io/mattcarroll/hover/content/menus/serialization/MenuActionFactory.java index 01d6243..f4aab66 100644 --- a/hover/src/main/java/io/mattcarroll/hover/content/menus/serialization/MenuActionFactory.java +++ b/hover/src/main/java/io/mattcarroll/hover/content/menus/serialization/MenuActionFactory.java @@ -15,7 +15,7 @@ */ package io.mattcarroll.hover.content.menus.serialization; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import io.mattcarroll.hover.content.menus.Menu; import io.mattcarroll.hover.content.menus.MenuAction; diff --git a/hover/src/main/java/io/mattcarroll/hover/content/menus/serialization/MenuDeserializer.java b/hover/src/main/java/io/mattcarroll/hover/content/menus/serialization/MenuDeserializer.java index 157397c..05b9b96 100644 --- a/hover/src/main/java/io/mattcarroll/hover/content/menus/serialization/MenuDeserializer.java +++ b/hover/src/main/java/io/mattcarroll/hover/content/menus/serialization/MenuDeserializer.java @@ -15,7 +15,7 @@ */ package io.mattcarroll.hover.content.menus.serialization; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import org.json.JSONArray; import org.json.JSONException; diff --git a/hover/src/main/java/io/mattcarroll/hover/content/toolbar/ToolbarNavigator.java b/hover/src/main/java/io/mattcarroll/hover/content/toolbar/ToolbarNavigator.java index 0b608e2..d78f312 100644 --- a/hover/src/main/java/io/mattcarroll/hover/content/toolbar/ToolbarNavigator.java +++ b/hover/src/main/java/io/mattcarroll/hover/content/toolbar/ToolbarNavigator.java @@ -19,9 +19,9 @@ import android.content.res.TypedArray; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; -import android.support.annotation.NonNull; -import android.support.v4.content.ContextCompat; -import android.support.v7.widget.Toolbar; +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; +import androidx.appcompat.widget.Toolbar; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; diff --git a/hover/src/main/java/io/mattcarroll/hover/overlay/OverlayPermission.java b/hover/src/main/java/io/mattcarroll/hover/overlay/OverlayPermission.java index 78b4acc..3e7653c 100644 --- a/hover/src/main/java/io/mattcarroll/hover/overlay/OverlayPermission.java +++ b/hover/src/main/java/io/mattcarroll/hover/overlay/OverlayPermission.java @@ -20,8 +20,8 @@ import android.net.Uri; import android.os.Build; import android.provider.Settings; -import android.support.annotation.NonNull; -import android.support.annotation.RequiresApi; +import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; /** * Provides queries and actions that are required for dealing with the user permission to display diff --git a/hover/src/main/java/io/mattcarroll/hover/view/InViewDragger.java b/hover/src/main/java/io/mattcarroll/hover/view/InViewDragger.java index f26f642..9deb4d5 100644 --- a/hover/src/main/java/io/mattcarroll/hover/view/InViewDragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/view/InViewDragger.java @@ -18,7 +18,7 @@ import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import android.view.View; import android.view.ViewGroup; diff --git a/hover/src/main/java/io/mattcarroll/hover/window/HoverMenuService.java b/hover/src/main/java/io/mattcarroll/hover/window/HoverMenuService.java index 92f11fb..21598ba 100755 --- a/hover/src/main/java/io/mattcarroll/hover/window/HoverMenuService.java +++ b/hover/src/main/java/io/mattcarroll/hover/window/HoverMenuService.java @@ -20,8 +20,8 @@ import android.content.Context; import android.content.Intent; import android.os.IBinder; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import android.util.Log; import android.view.WindowManager; diff --git a/hover/src/main/java/io/mattcarroll/hover/window/InWindowDragger.java b/hover/src/main/java/io/mattcarroll/hover/window/InWindowDragger.java index 213c25a..2c886c2 100755 --- a/hover/src/main/java/io/mattcarroll/hover/window/InWindowDragger.java +++ b/hover/src/main/java/io/mattcarroll/hover/window/InWindowDragger.java @@ -19,7 +19,7 @@ import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import android.view.View; import io.mattcarroll.hover.Dragger; diff --git a/hover/src/main/java/io/mattcarroll/hover/window/WindowViewController.java b/hover/src/main/java/io/mattcarroll/hover/window/WindowViewController.java index 1d76369..4ccac68 100755 --- a/hover/src/main/java/io/mattcarroll/hover/window/WindowViewController.java +++ b/hover/src/main/java/io/mattcarroll/hover/window/WindowViewController.java @@ -18,7 +18,7 @@ import android.graphics.PixelFormat; import android.graphics.Point; import android.os.Build; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import android.view.Gravity; import android.view.View; import android.view.WindowManager; diff --git a/hover/src/main/res/layout/view_toolbar_navigator.xml b/hover/src/main/res/layout/view_toolbar_navigator.xml index 54d2727..0bda395 100755 --- a/hover/src/main/res/layout/view_toolbar_navigator.xml +++ b/hover/src/main/res/layout/view_toolbar_navigator.xml @@ -6,7 +6,7 @@ android:orientation="vertical" > - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/AllStatesHoverMenuService.java b/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/AllStatesHoverMenuService.java deleted file mode 100644 index 29a5b99..0000000 --- a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/AllStatesHoverMenuService.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - *    http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.mattcarroll.hover.hoverdemo.helloworld; - -import android.content.Context; -import android.content.Intent; -import android.os.Handler; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.widget.ImageView; - -import org.codecanon.hover.hoverdemo.helloworld.R; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import io.mattcarroll.hover.Content; -import io.mattcarroll.hover.HoverMenu; -import io.mattcarroll.hover.HoverView; -import io.mattcarroll.hover.window.HoverMenuService; - -/** - * Extend {@link HoverMenuService} to get a Hover menu that displays the tabs and content - * in your custom {@link HoverMenu}. - * - * This menu presents a Hover Menu that automatically transitions through each state every few - * seconds. - */ -public class AllStatesHoverMenuService extends HoverMenuService { - - private static final String TAG = "AllStatesHoverMenuService"; - - private Handler mHandler = new Handler(); - private int mNextStateTransition = 0; - - private final List mStateTransitions = Arrays.asList( - new Runnable() { - @Override - public void run() { - getHoverView().expand(); - } - }, - new Runnable() { - @Override - public void run() { - getHoverView().collapse(); - } - }, - new Runnable() { - @Override - public void run() { - getHoverView().close(); - } - }, - new Runnable() { - @Override - public void run() { - getHoverView().collapse(); - } - }, - new Runnable() { - @Override - public void run() { - getHoverView().expand(); - } - }, - new Runnable() { - @Override - public void run() { - getHoverView().close(); - } - } - ); - - @Override - protected void onHoverMenuLaunched(@NonNull Intent intent, @NonNull HoverView hoverView) { - hoverView.setMenu(createHoverMenu()); - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - transitionToNextState(); - - mHandler.postDelayed(this, 3000); - } - }, 3000); - } - - @NonNull - private HoverMenu createHoverMenu() { - return new SingleSectionHoverMenu(getApplicationContext()); - } - - private void transitionToNextState() { - mStateTransitions.get(mNextStateTransition).run(); - mNextStateTransition = mNextStateTransition < mStateTransitions.size() - 1 - ? mNextStateTransition + 1 - : 0; - } - - @Override - protected void onHoverMenuExitingByUserRequest() { - mHandler.removeCallbacksAndMessages(null); - } - - private static class SingleSectionHoverMenu extends HoverMenu { - - private Context mContext; - private Section mSection; - - private SingleSectionHoverMenu(@NonNull Context context) { - mContext = context; - - mSection = new Section( - new SectionId("1"), - createTabView(), - createScreen() - ); - } - - private View createTabView() { - ImageView imageView = new ImageView(mContext); - imageView.setImageResource(R.drawable.tab_background); - imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); - return imageView; - } - - private Content createScreen() { - return new HoverMenuScreen(mContext, "Screen 1"); - } - - @Override - public String getId() { - return "singlesectionmenu"; - } - - @Override - public int getSectionCount() { - return 1; - } - - @Nullable - @Override - public Section getSection(int index) { - if (0 == index) { - return mSection; - } else { - return null; - } - } - - @Nullable - @Override - public Section getSection(@NonNull SectionId sectionId) { - if (sectionId.equals(mSection.getId())) { - return mSection; - } else { - return null; - } - } - - @NonNull - @Override - public List
getSections() { - return Collections.singletonList(mSection); - } - } -} diff --git a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/ChangingMenusHoverMenuService.java b/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/ChangingMenusHoverMenuService.java deleted file mode 100644 index 950ae15..0000000 --- a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/ChangingMenusHoverMenuService.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - *    http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.mattcarroll.hover.hoverdemo.helloworld; - -import android.content.Context; -import android.content.Intent; -import android.os.Handler; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.widget.ImageView; - -import org.codecanon.hover.hoverdemo.helloworld.R; - -import java.util.ArrayList; -import java.util.List; - -import io.mattcarroll.hover.Content; -import io.mattcarroll.hover.HoverMenu; -import io.mattcarroll.hover.HoverView; -import io.mattcarroll.hover.window.HoverMenuService; - -/** - * Extend {@link HoverMenuService} to get a Hover menu that displays the tabs and content - * in your custom {@link HoverMenu}. - * - * This HoverMenuService switches menus at runtime. - */ -public class ChangingMenusHoverMenuService extends HoverMenuService { - - private static final String TAG = "ChangingMenusHoverMenuService"; - - private SingleSectionHoverMenu mHoverMenu1; - private SingleSectionHoverMenu mHoverMenu2; - private boolean mShowingMenu1 = true; - private Handler mHandler = new Handler(); - - @Override - public void onCreate() { - super.onCreate(); - mHoverMenu1 = new SingleSectionHoverMenu(getApplicationContext(), "changingmenus", 1, "This is menu 1"); - mHoverMenu2 = new SingleSectionHoverMenu(getApplicationContext(), "changingmenus", 3, "This is menu 2"); - } - - @Override - protected void onHoverMenuLaunched(@NonNull Intent intent, @NonNull HoverView hoverView) { - hoverView.setMenu(createHoverMenu()); - hoverView.collapse(); - - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - switchMenus(); - - mHandler.postDelayed(this, 3000); - } - }, 3000); - } - - @NonNull - private HoverMenu createHoverMenu() { - return mHoverMenu1; - } - - private void switchMenus() { - if (mShowingMenu1) { - getHoverView().setMenu(mHoverMenu2); - } else { - getHoverView().setMenu(mHoverMenu1); - } - mShowingMenu1 = !mShowingMenu1; - } - - @Override - protected void onHoverMenuExitingByUserRequest() { - mHandler.removeCallbacksAndMessages(null); - } - - private static class SingleSectionHoverMenu extends HoverMenu { - - private final String mId; - private Context mContext; - private List
mSections; - - private SingleSectionHoverMenu(@NonNull Context context, - @NonNull String menuId, - int sectionCount, - @NonNull String content) { - mId = menuId; - mContext = context; - - mSections = new ArrayList<>(sectionCount); - for (int i = 1; i <= sectionCount; ++i) { - mSections.add(new Section( - new SectionId(Integer.toString(i)), - createTabView(), - createScreen(content) - )); - } - } - - private View createTabView() { - ImageView imageView = new ImageView(mContext); - imageView.setImageResource(R.drawable.tab_background); - imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); - return imageView; - } - - private Content createScreen(@NonNull String content) { - return new HoverMenuScreen(mContext, content); - } - - @Override - public String getId() { - return mId; - } - - @Override - public int getSectionCount() { - return mSections.size(); - } - - @Nullable - @Override - public Section getSection(int index) { - return mSections.get(index); - } - - @Nullable - @Override - public Section getSection(@NonNull SectionId sectionId) { - for (Section section : mSections) { - if (sectionId.equals(section.getId())) { - return section; - } - } - return null; - } - - @NonNull - @Override - public List
getSections() { - return new ArrayList<>(mSections); - } - } -} diff --git a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/HoverMenuScreen.java b/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/HoverMenuScreen.java deleted file mode 100644 index 066ca37..0000000 --- a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/HoverMenuScreen.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - *    http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.mattcarroll.hover.hoverdemo.helloworld; - -import android.content.Context; -import android.support.annotation.NonNull; -import android.view.Gravity; -import android.view.View; -import android.widget.TextView; - -import io.mattcarroll.hover.Content; - -/** - * A screen that is displayed in our Hello World Hover Menu. - */ -public class HoverMenuScreen implements Content { - - private final Context mContext; - private final String mPageTitle; - private final View mWholeScreen; - - public HoverMenuScreen(@NonNull Context context, @NonNull String pageTitle) { - mContext = context.getApplicationContext(); - mPageTitle = pageTitle; - mWholeScreen = createScreenView(); - } - - @NonNull - private View createScreenView() { - TextView wholeScreen = new TextView(mContext); - wholeScreen.setText("Screen: " + mPageTitle); - wholeScreen.setGravity(Gravity.CENTER); - return wholeScreen; - } - - // Make sure that this method returns the SAME View. It should NOT create a new View each time - // that it is invoked. - @NonNull - @Override - public View getView() { - return mWholeScreen; - } - - @Override - public boolean isFullscreen() { - return true; - } - - @Override - public void onShown() { - // No-op. - } - - @Override - public void onHidden() { - // No-op. - } -} diff --git a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/MainActivity.java b/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/MainActivity.java deleted file mode 100644 index 726d6e9..0000000 --- a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/MainActivity.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - *    http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.mattcarroll.hover.hoverdemo.helloworld; - -import android.content.Intent; -import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; -import android.view.View; - -import org.codecanon.hover.hoverdemo.helloworld.R; - -import io.mattcarroll.hover.overlay.OverlayPermission; - -public class MainActivity extends AppCompatActivity { - - private static final int REQUEST_CODE_HOVER_PERMISSION = 1000; - - private boolean mPermissionsRequested = false; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - - findViewById(R.id.button_launch_hover_single_section).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - Intent startHoverIntent = new Intent(MainActivity.this, SingleSectionHoverMenuService.class); - startService(startHoverIntent); - } - }); - - findViewById(R.id.button_launch_hover_multi_sections).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - Intent startHoverIntent = new Intent(MainActivity.this, MultipleSectionsHoverMenuService.class); - startService(startHoverIntent); - } - }); - - findViewById(R.id.button_launch_hover_foreground).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - Intent startHoverIntent = new Intent(MainActivity.this, SingleSectionNotificationHoverMenuService.class); - startService(startHoverIntent); - } - }); - - findViewById(R.id.button_launch_hover_changing_sections).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - Intent startHoverIntent = new Intent(MainActivity.this, MutatingSectionsHoverMenuService.class); - startService(startHoverIntent); - } - }); - - findViewById(R.id.button_launch_hover_reordering_sections).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - Intent startHoverIntent = new Intent(MainActivity.this, ReorderingHoverMenuService.class); - startService(startHoverIntent); - } - }); - - findViewById(R.id.button_launch_hover_all_states).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - Intent startHoverIntent = new Intent(MainActivity.this, AllStatesHoverMenuService.class); - startService(startHoverIntent); - } - }); - - findViewById(R.id.button_launch_hover_changing_menus).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - Intent startHoverIntent = new Intent(MainActivity.this, ChangingMenusHoverMenuService.class); - startService(startHoverIntent); - } - }); - - findViewById(R.id.button_launch_hover_menu_then_no_menu).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - Intent startHoverIntent = new Intent(MainActivity.this, MenuThenNoMenuHoverMenuService.class); - startService(startHoverIntent); - } - }); - } - - @Override - protected void onResume() { - super.onResume(); - - // On Android M and above we need to ask the user for permission to display the Hover - // menu within the "alert window" layer. Use OverlayPermission to check for the permission - // and to request it. - if (!mPermissionsRequested && !OverlayPermission.hasRuntimePermissionToDrawOverlay(this)) { - @SuppressWarnings("NewApi") - Intent myIntent = OverlayPermission.createIntentToRequestOverlayPermission(this); - startActivityForResult(myIntent, REQUEST_CODE_HOVER_PERMISSION); - } - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (REQUEST_CODE_HOVER_PERMISSION == requestCode) { - mPermissionsRequested = true; - } else { - super.onActivityResult(requestCode, resultCode, data); - } - } -} diff --git a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/MenuThenNoMenuHoverMenuService.java b/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/MenuThenNoMenuHoverMenuService.java deleted file mode 100644 index a216664..0000000 --- a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/MenuThenNoMenuHoverMenuService.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - *    http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.mattcarroll.hover.hoverdemo.helloworld; - -import android.content.Context; -import android.content.Intent; -import android.os.Handler; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.widget.ImageView; - -import org.codecanon.hover.hoverdemo.helloworld.R; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import io.mattcarroll.hover.Content; -import io.mattcarroll.hover.HoverMenu; -import io.mattcarroll.hover.HoverView; -import io.mattcarroll.hover.window.HoverMenuService; - -/** - * Extend {@link HoverMenuService} to get a Hover menu that displays the tabs and content - * in your custom {@link HoverMenu}. - * - * This menu presents a Hover Menu that automatically transitions from having a menu set, to not - * having a menu set, and does so while going through many different transitions. - */ -public class MenuThenNoMenuHoverMenuService extends HoverMenuService { - - private static final String TAG = "MenuThenNoMenuHoverMenuService"; - - private Handler mHandler = new Handler(); - private int mNextStateTransition = 0; - private HoverMenu mMenu; - - private final List mStateTransitions = Arrays.asList( - new Runnable() { - @Override - public void run() { - // Remove the menu. Should go to closed state. - getHoverView().setMenu(null); - } - }, - new Runnable() { - @Override - public void run() { - // Give the menu back. Should stay closed. - getHoverView().setMenu(mMenu); - } - }, - new Runnable() { - @Override - public void run() { - // Expand the menu from the closed state. - getHoverView().expand(); - } - }, - new Runnable() { - @Override - public void run() { - // Remove the menu. Should go to closed state. - getHoverView().setMenu(null); - } - }, - new Runnable() { - @Override - public void run() { - // Give the menu back. - getHoverView().setMenu(mMenu); - } - }, - new Runnable() { - @Override - public void run() { - // Go to collapsed state. - getHoverView().collapse(); - } - }, - new Runnable() { - @Override - public void run() { - // Expand the menu. - getHoverView().expand(); - } - } - ); - - @Override - protected void onHoverMenuLaunched(@NonNull Intent intent, @NonNull HoverView hoverView) { - hoverView.setMenu(createHoverMenu()); - hoverView.collapse(); - - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - transitionToNextState(); - - mHandler.postDelayed(this, 3000); - } - }, 3000); - } - - @NonNull - private HoverMenu createHoverMenu() { - mMenu = new SingleSectionHoverMenu(getApplicationContext()); - return mMenu; - } - - private void transitionToNextState() { - mStateTransitions.get(mNextStateTransition).run(); - mNextStateTransition = mNextStateTransition < mStateTransitions.size() - 1 - ? mNextStateTransition + 1 - : 0; - } - - @Override - protected void onHoverMenuExitingByUserRequest() { - mHandler.removeCallbacksAndMessages(null); - } - - private static class SingleSectionHoverMenu extends HoverMenu { - - private Context mContext; - private Section mSection; - - private SingleSectionHoverMenu(@NonNull Context context) { - mContext = context; - - mSection = new Section( - new SectionId("1"), - createTabView(), - createScreen() - ); - } - - private View createTabView() { - ImageView imageView = new ImageView(mContext); - imageView.setImageResource(R.drawable.tab_background); - imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); - return imageView; - } - - private Content createScreen() { - return new HoverMenuScreen(mContext, "Screen 1"); - } - - @Override - public String getId() { - return "singlesectionmenu"; - } - - @Override - public int getSectionCount() { - return 1; - } - - @Nullable - @Override - public Section getSection(int index) { - if (0 == index) { - return mSection; - } else { - return null; - } - } - - @Nullable - @Override - public Section getSection(@NonNull SectionId sectionId) { - if (sectionId.equals(mSection.getId())) { - return mSection; - } else { - return null; - } - } - - @NonNull - @Override - public List
getSections() { - return Collections.singletonList(mSection); - } - } -} diff --git a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/MultipleSectionsHoverMenuService.java b/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/MultipleSectionsHoverMenuService.java deleted file mode 100644 index ac1471c..0000000 --- a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/MultipleSectionsHoverMenuService.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - *    http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.mattcarroll.hover.hoverdemo.helloworld; - -import android.content.Context; -import android.content.Intent; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.widget.ImageView; - -import org.codecanon.hover.hoverdemo.helloworld.R; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import io.mattcarroll.hover.HoverMenu; -import io.mattcarroll.hover.HoverView; -import io.mattcarroll.hover.window.HoverMenuService; - -/** - * Extend {@link HoverMenuService} to get a Hover menu that displays the tabs and content - * in your custom {@link HoverMenu}. - * - * This demo menu displays multiple sections of content. - */ -public class MultipleSectionsHoverMenuService extends HoverMenuService { - - private static final String TAG = "MultipleSectionsHoverMenuService"; - - @Override - protected void onHoverMenuLaunched(@NonNull Intent intent, @NonNull HoverView hoverView) { - hoverView.setMenu(createHoverMenu()); - hoverView.collapse(); - } - - @NonNull - private HoverMenu createHoverMenu() { - return new MultiSectionHoverMenu(getApplicationContext()); - } - - private static class MultiSectionHoverMenu extends HoverMenu { - - private final Context mContext; - private final List
mSections; - - public MultiSectionHoverMenu(@NonNull Context context) { - mContext = context.getApplicationContext(); - - mSections = Arrays.asList( - new Section( - new SectionId("1"), - createTabView(), - new HoverMenuScreen(mContext, "Screen 1") - ), - new Section( - new SectionId("2"), - createTabView(), - new HoverMenuScreen(mContext, "Screen 2") - ), - new Section( - new SectionId("3"), - createTabView(), - new HoverMenuScreen(mContext, "Screen 3") - ) - ); - } - - private View createTabView() { - ImageView imageView = new ImageView(mContext); - imageView.setImageResource(R.drawable.tab_background); - imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); - return imageView; - } - - @Override - public String getId() { - return "multisectionmenu"; - } - - @Override - public int getSectionCount() { - return mSections.size(); - } - - @Nullable - @Override - public Section getSection(int index) { - return mSections.get(index); - } - - @Nullable - @Override - public Section getSection(@NonNull SectionId sectionId) { - for (Section section : mSections) { - if (section.getId().equals(sectionId)) { - return section; - } - } - return null; - } - - @NonNull - @Override - public List
getSections() { - return new ArrayList<>(mSections); - } - } - -} diff --git a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/MutatingSectionsHoverMenuService.java b/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/MutatingSectionsHoverMenuService.java deleted file mode 100644 index c89ea73..0000000 --- a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/MutatingSectionsHoverMenuService.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - *    http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.mattcarroll.hover.hoverdemo.helloworld; - -import android.content.Context; -import android.content.Intent; -import android.os.Handler; -import android.os.Looper; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.widget.ImageView; - -import org.codecanon.hover.hoverdemo.helloworld.R; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import io.mattcarroll.hover.HoverMenu; -import io.mattcarroll.hover.HoverView; -import io.mattcarroll.hover.window.HoverMenuService; - -/** - * Extend {@link HoverMenuService} to get a Hover menu that displays the tabs and content - * in your custom {@link HoverMenu}. - * - * This demo menu adds and removes sections at scheduled times to demonstrate how Hover deals with - * content coming and going. - */ -public class MutatingSectionsHoverMenuService extends HoverMenuService { - - private static final String TAG = "MutatingSectionsHoverMenuService"; - - @Override - protected void onHoverMenuLaunched(@NonNull Intent intent, @NonNull HoverView hoverView) { - hoverView.setMenu(createHoverMenu()); - hoverView.collapse(); - } - - @NonNull - private HoverMenu createHoverMenu() { - return new MutatingHoverMenu(getApplicationContext()); - } - - private static class MutatingHoverMenu extends HoverMenu { - - private final Context mContext; - private final List
mSections = new ArrayList<>(); - - private int mNextStep = 0; - private final List mMutationSteps = Arrays.asList( - new Runnable() { - @Override - public void run() { - insertTab(1); - } - }, - new Runnable() { - @Override - public void run() { - insertTab(1); - } - }, - new Runnable() { - @Override - public void run() { - insertTab(1); - } - }, - new Runnable() { - @Override - public void run() { - insertTab(0); - } - }, - new Runnable() { - @Override - public void run() { - insertTab(1); - } - }, - new Runnable() { - @Override - public void run() { - removeTab(3); - } - }, - new Runnable() { - @Override - public void run() { - removeTab(1); - } - }, - new Runnable() { - @Override - public void run() { - removeTab(0); - } - }, - new Runnable() { - @Override - public void run() { - changeTab(1); - } - }, - new Runnable() { - @Override - public void run() { - removeTab(1); - } - }, - new Runnable() { - @Override - public void run() { - changeTab(0); - } - } - ); - - MutatingHoverMenu(@NonNull Context context) { - mContext = context; - - insertTab(0); - - new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { - @Override - public void run() { - mMutationSteps.get(mNextStep).run(); - ++mNextStep; - - if (mNextStep < mMutationSteps.size()) { - new Handler(Looper.getMainLooper()).postDelayed(this, 1000); - } - } - }, 2000); - } - - private View createTabView() { - ImageView imageView = new ImageView(mContext); - imageView.setImageResource(R.drawable.tab_background); - imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); - return imageView; - } - - private View createDifferentTabView() { - ImageView imageView = new ImageView(mContext); - imageView.setImageResource(R.drawable.tab_background_blue); - imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); - return imageView; - } - - @Override - public String getId() { - return "mutatingmenu"; - } - - @Override - public int getSectionCount() { - return mSections.size(); - } - - @Nullable - @Override - public Section getSection(int index) { - return mSections.get(index); - } - - @Nullable - @Override - public Section getSection(@NonNull SectionId sectionId) { - for (Section section : mSections) { - if (section.getId().equals(sectionId)) { - return section; - } - } - return null; - } - - @NonNull - @Override - public List
getSections() { - return new ArrayList<>(mSections); - } - - private void insertTab(int position) { - String id = Integer.toString(mSections.size()); - mSections.add(position, new Section( - new SectionId(id), - createTabView(), - new HoverMenuScreen(mContext, "Screen " + id) - )); - notifyMenuChanged(); - } - - private void changeTab(int position) { - Section oldSection = mSections.get(position); - Section newSection = new Section( - oldSection.getId(), - createDifferentTabView(), - new HoverMenuScreen(mContext, "This is a new screen!") - ); - mSections.remove(position); - mSections.add(position, newSection); - - notifyMenuChanged(); - } - - private void removeTab(int position) { - mSections.remove(position); - notifyMenuChanged(); - } - } -} diff --git a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/ReorderingHoverMenuService.java b/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/ReorderingHoverMenuService.java deleted file mode 100644 index 178c15b..0000000 --- a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/ReorderingHoverMenuService.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - *    http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.mattcarroll.hover.hoverdemo.helloworld; - -import android.content.Context; -import android.content.Intent; -import android.os.Handler; -import android.os.Looper; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.widget.ImageView; - -import org.codecanon.hover.hoverdemo.helloworld.R; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import io.mattcarroll.hover.HoverMenu; -import io.mattcarroll.hover.HoverView; -import io.mattcarroll.hover.window.HoverMenuService; - -/** - * Extend {@link HoverMenuService} to get a Hover menu that displays the tabs and content - * in your custom {@link HoverMenu}. - * - * This demo menu re-orders the Sections of its Hover Menu at scheduled times to demonstrate how - * Hover handles re-ordering menu Sections. - */ -public class ReorderingHoverMenuService extends HoverMenuService { - - private static final String TAG = "ReorderingHoverMenuService"; - - @Override - protected void onHoverMenuLaunched(@NonNull Intent intent, @NonNull HoverView hoverView) { - hoverView.setMenu(createHoverMenu()); - hoverView.collapse(); - } - - @NonNull - private HoverMenu createHoverMenu() { - return new ReorderingSectionHoverMenu(getApplicationContext()); - } - - private static class ReorderingSectionHoverMenu extends HoverMenu { - - private final Context mContext; - private final List
mSections = new ArrayList<>(); - - private int mNextStep = 0; - private final List mMutationSteps = Arrays.asList( - new Runnable() { - @Override - public void run() { - moveTab(1, 2); - } - }, - new Runnable() { - @Override - public void run() { - moveTab(3, 1); - } - }, - new Runnable() { - @Override - public void run() { - moveTab(2, 3); - } - } - ); - - ReorderingSectionHoverMenu(@NonNull Context context) { - mContext = context; - - insertTab(0); - insertTab(1); - insertTab(2); - insertTab(3); - - new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { - @Override - public void run() { - mMutationSteps.get(mNextStep).run(); - ++mNextStep; - - if (mNextStep < mMutationSteps.size()) { - new Handler(Looper.getMainLooper()).postDelayed(this, 1000); - } - } - }, 5000); - } - - private View createTabView() { - ImageView imageView = new ImageView(mContext); - imageView.setImageResource(R.drawable.tab_background); - imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); - return imageView; - } - - @Override - public String getId() { - return "reorderingmenu"; - } - - @Override - public int getSectionCount() { - return mSections.size(); - } - - @Nullable - @Override - public Section getSection(int index) { - return mSections.get(index); - } - - @Nullable - @Override - public Section getSection(@NonNull SectionId sectionId) { - for (Section section : mSections) { - if (section.getId().equals(sectionId)) { - return section; - } - } - return null; - } - - @NonNull - @Override - public List
getSections() { - return new ArrayList<>(mSections); - } - - private void insertTab(int position) { - String id = Integer.toString(mSections.size()); - mSections.add(position, new Section( - new SectionId(id), - createTabView(), - new HoverMenuScreen(mContext, "Screen " + id) - )); - notifyMenuChanged(); - } - - private void moveTab(int startPosition, int endPosition) { - Section section = mSections.remove(startPosition); - mSections.add(endPosition, section); - notifyMenuChanged(); - } - } -} diff --git a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/SingleSectionHoverMenuService.java b/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/SingleSectionHoverMenuService.java deleted file mode 100644 index 0dd88c9..0000000 --- a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/SingleSectionHoverMenuService.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - *    http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.mattcarroll.hover.hoverdemo.helloworld; - -import android.content.Context; -import android.content.Intent; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.widget.ImageView; - -import org.codecanon.hover.hoverdemo.helloworld.R; - -import java.util.Collections; -import java.util.List; - -import io.mattcarroll.hover.Content; -import io.mattcarroll.hover.HoverMenu; -import io.mattcarroll.hover.HoverView; -import io.mattcarroll.hover.window.HoverMenuService; - -/** - * Extend {@link HoverMenuService} to get a Hover menu that displays the tabs and content - * in your custom {@link HoverMenu}. - * - * This menu presents the simplest possible Hover Menu, a menu with a single Section. - */ -public class SingleSectionHoverMenuService extends HoverMenuService { - - private static final String TAG = "SingleSectionHoverMenuService"; - - @Override - protected void onHoverMenuLaunched(@NonNull Intent intent, @NonNull HoverView hoverView) { - hoverView.setMenu(createHoverMenu()); - hoverView.collapse(); - } - - @NonNull - private HoverMenu createHoverMenu() { - return new SingleSectionHoverMenu(getApplicationContext()); - } - - private static class SingleSectionHoverMenu extends HoverMenu { - - private Context mContext; - private Section mSection; - - private SingleSectionHoverMenu(@NonNull Context context) { - mContext = context; - - mSection = new Section( - new SectionId("1"), - createTabView(), - createScreen() - ); - } - - private View createTabView() { - ImageView imageView = new ImageView(mContext); - imageView.setImageResource(R.drawable.tab_background); - imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); - return imageView; - } - - private Content createScreen() { - return new HoverMenuScreen(mContext, "Screen 1"); - } - - @Override - public String getId() { - return "singlesectionmenu"; - } - - @Override - public int getSectionCount() { - return 1; - } - - @Nullable - @Override - public Section getSection(int index) { - if (0 == index) { - return mSection; - } else { - return null; - } - } - - @Nullable - @Override - public Section getSection(@NonNull SectionId sectionId) { - if (sectionId.equals(mSection.getId())) { - return mSection; - } else { - return null; - } - } - - @NonNull - @Override - public List
getSections() { - return Collections.singletonList(mSection); - } - } -} diff --git a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/SingleSectionNotificationHoverMenuService.java b/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/SingleSectionNotificationHoverMenuService.java deleted file mode 100644 index 9542a78..0000000 --- a/hoverdemo-helloworld/src/main/java/io/mattcarroll/hover/hoverdemo/helloworld/SingleSectionNotificationHoverMenuService.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - *    http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.mattcarroll.hover.hoverdemo.helloworld; - -import android.app.Notification; -import android.content.Context; -import android.content.Intent; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.NotificationCompat; -import android.view.View; -import android.widget.ImageView; - -import org.codecanon.hover.hoverdemo.helloworld.R; - -import java.util.Collections; -import java.util.List; - -import io.mattcarroll.hover.Content; -import io.mattcarroll.hover.HoverMenu; -import io.mattcarroll.hover.HoverView; -import io.mattcarroll.hover.window.HoverMenuService; - -/** - * Extend {@link HoverMenuService} to get a Hover menu that displays the tabs and content - * in your custom {@link HoverMenu}. - * - * This menu presents the simplest possible Hover Menu, a menu with a single Section. This menu - * also runs as a foreground Service by providing a notification. - */ -public class SingleSectionNotificationHoverMenuService extends HoverMenuService { - - private static final String TAG = "SingleSectionNotificationHoverMenuService"; - - @Override - protected int getForegroundNotificationId() { - return 1000; - } - - @Nullable - @Override - protected Notification getForegroundNotification() { - return new NotificationCompat.Builder(this) - .setSmallIcon(R.drawable.tab_background) - .setContentTitle("Hover Menu") - .setContentText("Hover is running in a foreground Service.") - .build(); - } - - @Override - protected void onHoverMenuLaunched(@NonNull Intent intent, @NonNull HoverView hoverView) { - hoverView.setMenu(createHoverMenu()); - hoverView.collapse(); - } - - @NonNull - private HoverMenu createHoverMenu() { - return new SingleSectionHoverMenu(getApplicationContext()); - } - - private static class SingleSectionHoverMenu extends HoverMenu { - - private Context mContext; - private Section mSection; - - private SingleSectionHoverMenu(@NonNull Context context) { - mContext = context; - - mSection = new Section( - new SectionId("1"), - createTabView(), - createScreen() - ); - } - - private View createTabView() { - ImageView imageView = new ImageView(mContext); - imageView.setImageResource(R.drawable.tab_background); - imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); - return imageView; - } - - private Content createScreen() { - return new HoverMenuScreen(mContext, "Notice the foreground Service notification?"); - } - - @Override - public String getId() { - return "singlesectionmenu_foreground"; - } - - @Override - public int getSectionCount() { - return 1; - } - - @Nullable - @Override - public Section getSection(int index) { - if (0 == index) { - return mSection; - } else { - return null; - } - } - - @Nullable - @Override - public Section getSection(@NonNull SectionId sectionId) { - if (sectionId.equals(mSection.getId())) { - return mSection; - } else { - return null; - } - } - - @NonNull - @Override - public List
getSections() { - return Collections.singletonList(mSection); - } - } -} diff --git a/hoverdemo-helloworld/src/main/res/drawable-xhdpi/tab_background.png b/hoverdemo-helloworld/src/main/res/drawable-xhdpi/tab_background.png deleted file mode 100644 index ba00401b9b3f9064162cddbc4bc1dc0bb325931e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22401 zcmeI4c{tSH`~L?+rXp*WBF37U-8QmhjgT!N>zKth%rIjY%E%Ixr7UGhvZRGXiXzd1 zR9bD>3P~s}_I{(9^6uUH^PA82bA5il>w8@@*EQ~OUeEhJ=RD3i_v@b5ACq9YYX{G2 z@znqTfXBqxz?yDPEx)n?XF zWp8dNrB4dLOQ}FrAy~Monv@zEicnEgQ&!t5g@hwiU~m)+1&1I}8p?1DWu(-P7g&2W z{gY+@j-X*}VDzIq`hQwrPb!tH0fPkx2SbBVP*Q*g41q?YVQ?f2iGY6%zvS zqsV*@!iZylr(grT$W$+qpVV?(j5{fiss#owcl7i1V_v@GpB?#8ez2ocgoR+pFa#71 z`;!w6`_qRU7(o0sG#nO&C*pnaepCwG5AjDoI#P4eC4~_w>|ZJsWs`;HS`1U7%C}XH;F{l{=Qu;8Kald*Z;OXr4-FE zSTDcjDQ(t-{qFQ@>->s`H^5Nw+Vrih3V|aaNaSufa(Qbb)F5zm4LE#7knhUhVwls9 z5e`Ge{4ENK?yP~L2mKZ0FWTSZkZ@jvP^O~%Qm%-B!)g#n0lpZjwwEu)0}mtnd1%6Z zHLg&8+rJtneiSOk4~sW3(55#)y}WQ57=k;T07sx8a2!$F&ph`tjV=3p%MKbC>~g}>#x8GlJWdn#m)2jy`sw+@&Fk;W$sB_3@mIM2 zb05K;c)x#jP`-!yruyd~6cT|Nj0wQ&deCk|4`4viJu8D%E3DfKt^znsP&(dmUH zqtg8M3cv4zTjBnv=%oL&y!_tFAHw|VjX{0|;1wl|=FeQEp-&=`0?bJ`yf#V`_NV3* zF_*u1Y0#@$dWH2Z`Dr6GVSj7;U2nf!oe~4TRiA1|IQ<1fEdTxCy7Kbxt`7g&b>-#X zU4MDn`gu{ckw1F-t$Bsl^0&k9Fl^{gMDW_GDk>-yP1x_vzk67Eh2V+y243{#Q> zC<6I-kF!hjZZeMFB)dNv#3jhNndTPLaNCFv#Bsc`HgepD5LA?B`(^mnRokbiZMEA_ z-C9~&lqKtXsLI}V7bssp=^P24yt;p0c>{nA$Oe?AAq-R$lXXMcThc6FD(Ph0mX=J5 zTDK)2OMoWF4GxWR`^*P?unM{g8si3oa}uYY11+b&_93L$1;`!?8KoSL8%&}kRs{n? z1ZITW7X>_y3|Nyvg%afw#wP;g0zLEgw{N{%bShAMZ}F>%Un2jp4O`#3o0=SOd+i?$PK}Wnc=t_GXyey_S+rU7H@i| zB4KTT=|XgnLC&?PD+x|${>A(eTHzr#jIM^@Y?-Vb-#reuor0MiW!wdJ7`=;)H@E68 z=w!~+){Lq7pVpDhEiZ(Ws7PnUJu?##JEA{CTX>lz*uh(>!F6lsu-2>@sNihPGy0q- zqPuokXkQGo5;hZS>`>R8A#lH3J0b3*5o@kh(RH-CZUa%bV`>6UImA;AneD9>5$HJM z%#pkAdQ$X&-e8t!L1IK+iPAd5SNi+u#&{{eX-P{OIN;AM3H%c1G^f(hel8-<=+xo+ zf|gP1#UCW-1rZj%Osrie*7xqkEz;np&;(M)N)K+U3>IGY4-ABB#7XZ)*!p;gXDG4HT0T zvOVl}zfE*#72ABGfuljB;?3fV&zfGXY5qocUxe_EJ&4z7G4RGE>)MGXzx5%3O z4gqn9{1l4;>vNzUoL9-!lP#%)I$dJ{}1rG2a9DnH}S=|Jpu-8S;C-`Th(1tuhO z$B{;^(t=-dj2E@oUdkn(E5+T%*+Vn^;@17JG<-1U_)JM?!J!Bb*)*pwXOa!i6qPH{ z+V0wSLjB31WePZRrwBetj)|r-dCk?uZ=Rgef&foOiI3gM_jlsXu1*A+n$*0QF? zE~x)J=+<4iRBHMaf?x2-hMv_uiRRU>E-0?)IHAz=BJ}7>XPe5k5+CA_W%~&CGB2{@ z?%7MG8lV~^)WcVK`RpN5_NHdco-RnbpZ1}=$d@EoEZfE-@sviaa;7ha+{Bh-J^NAt zni|LCExB&vZ1=mvn_bU_wAV_wUNFvn`H2|qKEWQFBwN|uYP~HYK$Y{DiK|%2cD@{T z?Zc)zhF!#mSzDYwE?6aqITpW`miWk_VJ{F=)>ot1E0b~8wpUt=WDkO$(Qnw{|K<$m z>@K|_hfUF&M4ms+`f?_n8pAiK$2n&|cq^na4pN(c&4#|(*cqWIHsXj&N6~4OA?J@) zSH>uTsUPmbu!x=X60ud$)|)90ev-EfQPL?-B+%;Wwlk!Q{5~nY;Oc&nozcZi?Hyex5qX(s2yuROQLh0_Pwek5E(xr!- z=_516;nL&g07W179T-hZHzM6J;Msiq$X)d|iIk9Qs1aXpH6;-0%Ue`m*Dle0xqNWD z`VJCXFs9q?sOq8oYmsdt?iQi?zVfdfdBvQqM%r4GJD<4tS{&~&q#gSrNF&K@txx;V zbY;4;xP*&hTjB5V?9LM(k3P@)+@9dgHGAZn;ito2nIr7g+v^AhhTu2k!@dkTIP2f8){U6A(*`4nDscd+X*N3z{PRRVR7 zz~MqDj%XfUJ9*&49{t_>HtEjnZTzrJk+hiAHrQk+T^FjCdR?VF{7Eo-c50KvQwhC> zN2d985K4VqL$6`i#$(7v|GcXbjzXu^ZR>?8j~)O6hu5c8XboYfHY+B(ByU~>*l3t} zjZ1pVJHD2&8@g&Z@Sr>eZn}NYKf%N(R{^!@^?ANMGVIg-#DF!`5DTvhkru6!UX=Si zH;dv$avl_=&AJa5`HG|~7{TB70tq@+?^F-u%dCO#6wrH`C;Z_v0+TRj+5pk3OS%4` zuS1>o+N8hrMSGb^w!p=9#-6K*Xjy32=e8ZvI6R)x1V7uec37$L!z7=@ z$-U*G8QX;}TNotG={1yZ1?}+7z%^9mRcmA#W;CH*9-?PcGDTATVk z$kIdM7l?5kcgsMHaoj^{H)jNs9#(1IH;%}y4%61Q>f_Gb?B-kCM3dKyuXMdB-)%Cy z7%`k;IAMqCQ#mA@7V24eiLB=M!m*d_%p(!^f=Nu{2F2t^wQh5LzPnNL+nY+h0DA^U zqQ2~$+VB)WfwV`0x=SBv%QQc^`c)82zayBJ&O3*H8P~Gt+Pwb5o?t!AY6+V#zBb1M z@4iBf*L}ltdQBxBK;=kYb;oGSPI=Q5b_&Ofd1DPkj)TKq<*429HC$O4gY0KBs~gPc zwNw&t9Rl^wxlLW=;Bnk#u0@y5E4po4b0HYv{shHNa3K30QE=mApPpBr=j;eF2;Z~% z)NIr2$=gwHW877W>^c^g~yq4`nB&x$^Wq1n;8vMTk&4|R1a zGW|SjKr>Xtj;tqD3zuAc65HplE3fbIi@zgdwqOA)GPIvnYjLbq4LkF&`fjz)Hf{l~ zH6D6}0x(L7E*aAPGVYxa@T87XnO1uA+iknd#=t^XyQ}z)#ASBu1KxCuKiek+mTzt| z^Oz`bpYwbQRPNM!Vxps~oyAYCmz6d#8%cucZF&RFCp5gxi=TctE`Kbh!#*kDh5=vQ z@sc_C>w6a<<$GRMwp2Jv&~H6ZwU>h;`MX*sfp-1li#3;xJTBPpxd7aV1Q)sRU+)Jz z*_dwR0~}c7+bDZZQ#bUICw9=99C^5YQnqa*=FWmkoEh7Fp%<&l{mzzfNKONZifnPm z;}vS-xea7&fHygS!%|kC)Q{b}Fbn{_I7Z5FmIf_q$90tSeNxGK%4VuQ4^vlo3)rBr zFsEa#r^>}|A!HL`D|OC^?PmRfPzkH^GKnw7S}twdB2KFOpk6+9f_FByM3=kf$Uui( zn(86BnQR)d9Cs$%X+wX9-Try|l#{#GCzOKLd>Stm;L=6Nq`n(R^7r!&bU2nL^o1-s zRjh3-UGtL9fLfa5;ggEfyf9E`iM{zX=dQD&9QJ!-^oD94FysY;$Lu^Vo)eU?Aj>sY>&G;!EwE49_D($fG|G2l|J79$hfT2xmko-K#H zIUd0SIFW>X-2K5Ek%M;5%(p)fZ{n}KqgwDm(c~@pq0s7$wi!u0A}R2#*H9)_8m&R{ zXH=i?)#r^}KIxut$-L|H$jw(OLnbG$3ws>WlxcfH-YmdX(Wx+`W7 zdcZxA)|6MjK6Cs@tA2mb2+y^&gJ<*IXT38wJw49urv^pS%nu1}FiTfZl(#T88}EE` zNoamO`pfg;zUuQzCHDKpt3@QE-i|{;q5KA&CcATK4tnl8V^??KblROct7qW0y3ISE z!UbVl)q{mqJM+pg&uBL35AVdtk6YjTNVcL8MdrD7a|&;1Nq1bTc{v{P@?-fF_vGQz zesWv!WoK>%8IeEVUZ71AElTObI^&%w;g_p&BjB^qfZblRB!H1q#e>~McGauAJ(-G_ zV)cAWTg!^<7w}KugB(4gs@Gj+gs4}CBA_sxuzsW2wcX9Q90{v)2ji++)53VKel+Sx zO4k(uP16cdTodL?&CWa|`dG>W@0mO*Gg_K4B6?_ASgw|96HI*@-O{M`_O@Jea}BQ6 zzD=p-4pVGGHA{fIKW4`}IF0tG4mf6SK6T$4{d{Yi_Y>hQ zVee9F4ep4-2G7o+ScsbGtE1sknWn&N{FOJpUp2=2Sra; zA6U$#t?zH)>?q~*Hq>$Y&{;PZm?yz8mCAXkls>j&@#qWbOCHmGan&TaJmzos9p46}D7M7Khxz_A6vJ434PLcr2= z2+#C*(1&Olx%cOtq|l8qaK@s~^g0Caymx9CLH+WYCUFUbT0gN+z=P`zwlrwa$LFTnji7m^Ou| zigO3d_^W~HFD^H&3r?F-$Udp~OtdmL7!7)ybZm9A_<;0-ZP!GqmacReRvf%L`^>y? z)l+DqN>hw!%G9a`P*t)!54mOf-By9Uw)%AShFp?I3SYmE_oim?{=V8MheVorRZ77T zPw4vEW?4;+23oznZCYV_ zYBXhaJ1mX{2rj)Yw6CEL_UR5KWeU^JUzJr57Xr+Jxu}BJmiE3Y8kKIpS3I3E<NwMzylI%;Et1uT3NMfpZdx7enldBR&65g%?u|?936NN_ZNaQMf zJVXOTu`THNp0{VO2l%|(zUk(pGfj7MW(d zuI~NWkJ>vxXf9ruL3s+W*KL|PeE42bV{mkL*n3_299GRZ_k$!(nD19u2nl{B2-4;C zj*tm+8#3DQ;7;eq0nk+!)G$vD$hFVsh{xQN;ik{lz0VNcmY(ze??OqG$HlM(o_@X? zh-&xIl)3i{MmpL(AKxE}65H%P)^Tw_p?}*#2$CoZtXWrM{ns51HnaO;3zLzS_et?FtJ+l@6Ffsq%mbr;@Kbawd!)uf6w z@GNmnxoSLnE6^uKv&>}c88zwuWSq9KdG2OT!&@$XWENX5c~yG6L16R$45cD;@aLbS<-CrkkBSDqCYv0@S13IoWDZ!orpLNdzM6OB&o<7Q#AA8O` zTJk^6aW}h{}Uae_0GY z81bmQb9>CRe!p{roVLuu>VPMUM%y3vJ?LIoyx!V3d2st>wqx$?9<(ojp$5n3x6x{V zH2vcPk!xner=BLCo8sTFp|U|_L74sG6i##WVnyIb=Ldj3{qd#QF6$fs&$$6r<=z7qqGjTc`ne*uNkVkPlGul$1nPgzwaD=ZM@lY`8nv@ zYb{GvjuB42wJl%>Zon@{Vh1lcjQ$LC%JlN(%Yd&sfcbsy=BJ83R?wdh156Be8C=kF HJMe!1Omput diff --git a/hoverdemo-helloworld/src/main/res/drawable-xhdpi/tab_background_blue.png b/hoverdemo-helloworld/src/main/res/drawable-xhdpi/tab_background_blue.png deleted file mode 100644 index c95818225c5e8ccf98149decf2890da2d99f9ade..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23017 zcmeI4c{tSF`}oI_LJ}GhA^SFF!z{M4C2Q6c(%URdm>FX%NhL{9SxYD?m7UNgOUaTX zTJ72O$gU(>)Niy*o}T*r=KKA8e#`f|X0B_@?VS6*&pEGi&VBCl{^K3B)q1l4-#R`J z2qdt@%-D|cdtvdrf`{?u{esa z27sq{5Hx~)sSIrpNY@~k3gEm6bQuqVCyA^lJ5_#1R)&Pvlij9e1+$_W5xhudAvA)0 zh_wSQ#2bgf%NpqO=>}sN4txo8KqlDNhwP6H)|36}7t4?ri=nbIUsdSdda|1q8S^)S%Ejp>PZa1BD@=2n2+o0rB5MrUStcvcKFn zCqMic6Z~;B5|vJ(kYyJA0v?nAx}L1;VnfW&_i_1BnGKQszq4adga!jtC|m;u{hbjW z$F!ja(0smj4UdBodNaV#K zspvv~HTt=9e)=OA19XD^;?ia;Y6t@107GCkVOTf{0z+eAuq95uY5wBFim{FG03G<@ zg<-~Ugmyr{u?U7e5&}apz5Gr0S3eXyiMWR)FF!Sx_`u_^L<-FppzD)-0Z#&yO7_%+ z{w!Rg`E~tbw~+nm02xQvVyw?7&>)fUSS=i!0BGSE`yPhSglKBRa1aliCIaGtz@srp z3=ANk314woSuHjHhihXBE?{vBFC<0Pbn~1@CX#QwuiL-w+WJ4n{f+66uL}zgl?{Km~cnldB#GgjW7B`cD#F29C5dxGEJOMg`OkiLd3DnRom zEbeMO*&o}Q8RwW`Y|-Xxbie|*#ek=eTU_b{ye{-_r9ZpHwES*H`sZ}AhTxn3CFXx_ zBgl(D{#P62o2#!{e|F+eA<}~Y8ex+sV}<--7i;}}7k~5ncf(&B(1k7@5k92<15@D- z1pa#y0oU@t;XUwh2poyQK{PdSS`dsTk^mthFhm3nr-=bHfgcn7-<=38G#1G?mA^%- z|CbZ-b0y=v0J0|muMhn(wjTxmljhC?2h&7gUw+!9}*5& z45-jRGX8sB$UKK+=oFbHhvhf&OMLuaT&H*fjr3oMGD~`i`+-U3f7qD+?YIgMJzzu_ zoRMPT5!#Hsi6TNU+GrdEfx{!vNH_q;;kDU&^Z(B?k+od&zY$melz;!n;_5F~jBkGb zb#n3_I}^WUIe*VMe1}9BI$SUj7!0fTf%=WY5&%_CFZ~LPWgAQ2H#rwjhmmX{UE;t@RIaXmwC=$jVL}8 zniU04&`0V*e^@Q7Cr%AZw@E~jPZfO7yo`Y zU0VIC>GpqZy0rRN)1Q`(WD;E;@x8TQikDa|-t51@uxC8YBIs*tX(6?Ap}!XYYO$3R zOz?3wCNb`m{)=}bxHf~ySEFBRervh?kCsbnzFU6VU`w7neVx#6rHtoVj7Mrv<}LW!xv#>GUzionLj3MHlv8y6D=D*_uAE0mZzY+OtftO#setWaX=uyHX_ zup+Q=u|kQd!^Xu#!HU4f#R?^+4jUH}1uFs@7b}#QI&54_6s!nrT&z%H>acM!QLrMg zaj`;)sl&#_M8S%{#>EOHrVbky69p>*8y72-m^y4+OcbmLY+S5RV(PGQF;TE0uyL_M ziK)ZJ#YDl1z{bT2C8iD=7ZU|50vi`Al$bhfTucQ9t!;=e8iXHHQaoSOp{@-# zhKpEce1ba(H@pLxuHIj(yn2OteIA zvi6ou(X1U`Zf?1?uUrqAJ~HucqHtT;=bm~FJ> zngBV?Yp^75MOu?Fd2OSXTuLS>qD+)#`}}xZl%d*Tr}L)_jnlYv1xrC__deHM>)O{# zCvHT39)nkb6kyWsF5JX}a-7s3OmPX;Me@6IwW>>S7jD8-FoB|)}{+9YEf?p zq)hFI39yI>sF{O|d7X}_-eW$+G5vb1XrRw!&Lc7{loKECa506bD@-XNh75U|+7-&A zwVGG1Zdc0C;Lr$cb{{``?rqpi`m|OkC9R%g!D!NTDn-b)d|`jHANEqU^SDK)DKwdSYD!o3Z))hbRZD%LuBD z*w|UAsk`Rm~H+Zt07JcqKnHu5>*Xa;vt@BnM;r$vyIesm5nD zE4f~A|DJ%fEPMZJzV|{M>N~6(EVJ<1szV;6kC*N=I1tqlSv)jfTpy1t&j>sVdc6L6B!*1IKkM$)b`=4LNxj$21h?e;o3 zs^Skm6GKdm6iPMqGMz149&RmR+vb^3D0aDXN6zxpl+TvkA3sW%iYg8)r~y3 z8*>%DZZ^vrKetoBT%NodlIQnEuXWmN=(O88_JO|esZjN{%HjBY#!yh+!B<5C)I|a) zilfc0&x1^nO~#Y$ZYawj^O$QE>145oD}}_HoD|O6-reUo)a8a8C*jAVhmI9O#OB?E z0ulp0m&lg2pW;|>ZF@J6Q>Q=R7}1r_@kYOt=B?*;o&espw>E!8hvw5`-t`|#J|^$7 z!e@{l8h3jc>&a4&G|cJ+$aOzam&ccnMb;FYKdy&JilH47e&S>DhLB-cVvDpyAu`9r z?Ppidv=~L|LDe@0rYusA)D)v;aCGEEN_M-^X?ZWmKq zoA+S;Bd)hBz7b*jCA;sDzikly*5~rF_>L!*NQT?%7OUF$R^8+y>L|>(bzQydBzv(# zbtumq(v(acFBESk6Bj3&=GOA=p2>5LzKtWFjKPDmB9u&fnmW(Og4T6l#nU`*^@=R& zCKWNh`X|;~y17rg)rBuagYCD&_p~@(-$9BDaXOucA`pyEI>%JoX`3bYaUyhdlAY#we$|8{{NAJTy9e zmd#4Qs|!>6^G)y3aSgMr*OVc<4W{F(-_Mjiacc^I*xclgxmKgJSD#qcb%FZPhi`j` zNjd$YSW=30gMGneG}T5Ar`vX%7@{gR3kb~~(UP0e%9w02c^`coxBaetLHNZdxRsq` zV%+Fy?>b|0$SA7&esZ?>=mm0MPWYYT=Bcq-9!c`>exU$$Uv(hHAO?DPB3CNYp4jQ)rznI5wcMPmc$0gj~T%EVkB8 zIZ`?`PHc8)f(h^5Ct&;HuZjbn{S_pa`r^WuW_f+oa(t%S+xy!}C*TLl6cJcu*P_kf zbjh64mTdy%5|zOr?uw%>J6=acCUw#Eyj$qm7TQ*)Lv7(*CyFz=LieUN$-BSYpI6d& z6MaumvoI%?k5q!r&M&}&z`bM1Yh8CZkP<)f7 zFYW?&C3Ri?F!EZ#@nl(2(6Ir>l>1%vwEfOaK}YIDVO`x7;~hSl9C`DU-1OOm*oM># zh2WI?`}>+>0xllAjJsh^^MWf%Rjwrr-`nS{fa5)R*GyiTuwU7A zQ&(g_wC5>}Tv@r4>~fQw#<5fvCGX6~<`)K|&&#DH3?A;@Dw}#jzRx+cIV(Qwba-8m3PDLhu@V%t!WYN-jc}yYlR`wZ_VwBkIU&XGEjz;H&%d6L> z^=@SNklAGgJ-5&J>o9ymne*Gk)$QRTN(Q*-F<_(-pQzt z8naC4BSqFFJHYzV$l+Nj>8s-0K5IAi@eMBw7kEDMxY8-T0^NIEWu_bN=&G)+o$G-r z)KAS7Pfgi>&?(fuuQM{9!ibTN<|W3gjIZ`^OTwSZ^*QKWEL>(gs=EB#^;T3K-xsJ@ z*~7O5Jl2yzF!5_+!lIv&VxH~^#60rKob$33jJBiXc)x$(un!mI)p{%}McMRtQC7U4 z)59?Tg00csX>)Vn=3)NBFU`t_9+x~+yVbiXp%~}ZejgmQz4p|QTnd?(ar^w5kNySv zsO`w$^PSv(4Va&sU8{3-C%0r1-IXl0!ueTvl}qJtVf7yWilR#HORD-=^AzvZ#ShZc zphbQbHFPdhWSVD&zTEV?)TED!-aPeBKc~(*bKoWy%>-UnynoS8%AjtTkou z6sJa@J!i?`!CI%0>64Wcg{^x{k-o>X57zTMJx9)tb?X9p&PQ&=s znQ*Ss2YV;g&Z78DvN@!7s3)rlbKJxVbzR1ZQg2J#e+9@t!-@n*PiLkkT{-@8okWl{ zR=Tot-BB+mi;WzkrpfnfJR+iA)XGOR>V@9Gx%H^J#fDw&P6$jv^Z^ZLyQAT|*EXEU zeiS|67yuEp8Ojth_%NzxUa;F|n~CAUor;o4y+`D^OCRre zHl%W$lWeofv1>{DTOYpFoDNeCFzLSE&wEA1M+P^dM+QelW9&JdqV5|P?#(+7#y5XF z;GfQ4-U{y$h%z%bym3rcc<*RLW#6qNev{Wzd^_FR>@1&Kst1=lDyWu}p&!Gff~r)O zN$Ky_yYlK@OQlWyVvn_t3hhhw)bCW;QwDar9%OVS{q)}XY`d*(PrIbu1h3*M|5`Ry z7~v?n7WHg(^~QHPQbL!@U=VFLuC~03D zS9pM9b*@bJ(T_X1IKWjVJu^Agdqf-iB4h9ED~Jl~vJn!yDBFC`S`@f(%!WgZ1Xfg6 ztRD46*k%<((y-i`emjFT`St7&wxC;w$}OhOOq9x8A6{A_ZHtpLLMElv@N| zrdXuSN!!8kdF!wy#XBT;9o;{6=Z;(wJ$z(aNbqTeH7cHi9?u=3J2=FVZ?$ck0v{B~ zubiIN5WMm{!!Yl!%eOZ@%8h*EW00Q^PqZ{XJ0q|>D5*KmdOXzex{QTi->L`6gRM{B z7ZxNPR9PN`9hS&AFK%?RG>#A;pCA2nwscEbf|KA)%5vk#6fBZXBqe+=qOR+*g(+tQx$8ZZ#_arO)b zm0I3Kd_JqX1(PE@>YR`xvFS+oHCpcb#I-;tjyS>5G`ck-J z$+r5ov^f-J>Jemcf6L+LVv4|Fmr3Wgu^0)_@(=!uDy~;+rBf5LFPv2ueJJN$Ff-Wt z-bD@Udi=}%Ods@x*rVEf4go8V2)@{JGhqMOS4lRa5*l&&<0saeWrs^76`38Z zelH~0R+n>{a70*9{w!}U@?t^O=&Jy?Au;2dD`gzp0>QXVV+$?KNYl`r6NNTkJMEP= zb)Aocnhqac(9$l$Kbwki+(ptF4q6Y_&Tkg9zADF?w@ItPmV0L%^^yCwd+6c^u_hMn z+o!_E)^qi2t&1#nNX$BgYC`zLPIt7y_}8%r9wE*ew&=|t`ukLvuR&#G>J zMqSEB18!IGReM|1R)tK>fqT5G%<+T#2cvcpB^5L`0D5jE$38``jjb>msF=1;<8)F@ zjw=%4eZaThO-eX%x>`YPA&6GTJ2sJEvoXj0(B)Gtr!^9rjH@C9?5e>)kHUg{Md=qY z5n=6wqx(wN8VUVQp1R{L6Ky;3TAs6lRT zG!8y~sw=*3sOH7yP%a~wMMJazOC@0o*OUHeDW`lzG4XUwY7b(#}M!aPSU!(jfp2p#>@@i^E#LG{4h;_s*&Dco<0cg-!KT){s1q2p8MaCU>F0IVG-WOR(~r zn9n8!U(Spt6h*yyU2rZ!P_bOzM^;K#i1&_wZkkVG5hHmE-OI!4W>*toRegHId&^bY z#b;uP`-HVQzI1#UGM4vIl2GuG=~SyDEAS2Q7G84*ysuzpNFS2Fy*}kv7p_NyuD)wMk^INOD4FG>>zvYlN zu(^tBY8QBTApf0n@fD79W`Q=&{gGexYEfJpI|2_Fj(R7ro_6com$z?bhgtiw9#d?R zPZmz7G~GTwp~Fm=^Aqge5ndfJ6v)82QQA57B5_KwK<7oyJYMnukCkEA9LU`US8{PW zps#gy-e}CEnseT_@3p434rgrrYmFPiyc;B+&xbrcc%p0ln0|8!$GJFfyL%M{$bRqE zuE7Q#*H<;Rx#gsXH^60nu5Fb!Z}~i4c0jz{#^-n%>}`>s?wtyu1FqWB)driDJu)x5 z*Vt6utbdJfXUv~8)s5C@=T^t_A8cJT-DL!Boas+!~hu-wiq*!8=d zr!}eI3wf$tha*6}phD38llOux1~>bi)t;a#h*t@G#!efM@^8xD)?aZUj^o8Ep+2n$ zMGUXY@*vO^DdYR{TxI>7r72shx9~RhiNuW!2Cq3(3KB2knB>`MxZ{GJaww|v%jBk= z5k4G7pFr)KU%3njL$#M_bncb*c8x1@Gh6X^L%!8s0g}#$>0ten=9{MFiDspe?pzu? z`lhLqE|inD3mP$jJ%~7nSH384`Q6J)J*ct6M>6y%C*CQy8?_rd2X3!eY8gugWB1UqKFTd<2Lrf_}>Ix&!Hk7)91*L;B>ZmQ^h`YkFZ5iF=|i z29oZHE(}WE(oPxb3Y$4N$9c!B;*i&oInGDN-ihZ5=B&(l;(74SQPVG6fs;aB%Lf+> zpq+!SU_B8l-^E7PVM``a#=9-Ka z6sXWlcpW{zw#%>$D;SzsG(VSDb+dg#Iaokvx%R3zs6l^$ia1!*0bT$*=CO;GD4bV6 zFlbwS{N7y01sA-4j+p5D&d|4mXOn$*Zd6{D#&5}0{!!}se7Oj`FmN9seihJ9o<&=t okG|sV%c`<5yL_22|AhlIB8dmZ4V5`BzKnT`iM4T|;jZxi1+!<)l>h($ diff --git a/hoverdemo-helloworld/src/main/res/drawable-xhdpi/tab_background_pink.png b/hoverdemo-helloworld/src/main/res/drawable-xhdpi/tab_background_pink.png deleted file mode 100644 index d6fcb02c6ef6c5bef4537c00c63f4cb6e3780761..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22582 zcmeI4c|6oz+rUS-5lTrS%UGgf%!V0bjARKR*|KZQqOr_iEJKp5DCfM zG(3=C8*XKX3-`h4;1%^TE73F*%Yh#u2n(e7`I4z9nx5ikzbKZxSPWJKepU(c(Ni>7 zY!K*ZX$>@_1QLK+8rmQn6pjQUbTpt^I!KtNIuHhdYJ(vp8&QYP$|KIID&Bqt0zi7>O3{bhVTt82d-G^KXl~3j}k&!#MKtO>>zKJPt*q1o~lvFeE>$ z7Xj=~_CkZd6)w~Kynaz;WNHwWj3byCVORwkBoZE_MTBZgeRVe*Jf>hBwh;( zfZWu0Rqi7-D^w=`4-~&uR>Zh2gPyPa+6Q zAi!B;(a{89aS$R%n@G^o(ZuWM5H;Cj`GK3iHDyYovQ}Q$vK7f%m!HF(Eg|5qrC%$2 zNuR@(KQ@p`SlrcmieI-iJI=Ag*rLtn=zzlF76Tpzx46^^cr^GgrQf>6w)|p7`ulWp zhG5D6GV`Ce5xS2+{zn^S$<=4ApF5#ah(V#)K!Sl6YlZw|7i;}>7ccq!tKs(zpuvkr zgfHp8VJfKDkbi9=pjw_dyeA$Cg2HuhAWco27Dz`EP5=>MIz$)_r>TS0#D1OV|LR0& zAyIJFsk{`i{x>J$+e*gm!;-xScntXK*uED0f0{c_97GeQ1A&2bkVIA-K_Iap9Zw<= z1Vw1;An`~~ECj&{RsYH+g0qeX6nyc__k`*u{Vf4k6>e1ZQyAQ%o0L&Bk0C=Rd9-JAb6&qU60&HqAN{aOC~ zZ;PwnT``vY{^R82-*zT0WjTM%IKL*!f6q`C?>MYf-DoMcm@G!b#U$xJPe@rgCF{C~ zT9%7^y&`aW9DZm1mq_}>JL^*L^_K9@CGAU{TW0EgH~S?RwydXF1dO(p7F-Jr z{=WEo3u_XM;Ol5aV%;gJi+3ZaHjBw;qwi~eXzBD*%VjlRESEOevL{cUCv>Tl^<0bf zNDa(>rnYRZ*|)KOzwm8H|9;#Ma^BVx!716H06y zE-p3-P6RG4PAIW;xVYFTI1#wGIHAPW;o@SW;6&i!;)D`ghl`7if)jy@ixWz09WE|5 z3QhzrE>0-1b-1|LC^!+gxHzH2*5Tq}qu@l~;^Kr7TZfB_je-+_i;ELVY#lBxHVRIJ ze~4@4x3^Rf$gEdWgtFd2L5@b4v)*3;#F^Sy0s!Hg0D!1i0AS%0>-QM|5DWnTp6>+! zP}u;0BqiOW*#rPs$1pQ8u%q=&e)5Q6LV@zCwVD3rO-f~3 z&NZy%5wbjgqHbGpq>yRpu^ZdOK=RVc)?0u!if?jWMQd9M`sIt61MQ5ro>c~#nu^&e z9^M>tgE%ogAC4Z)*+1+4p?ofEVA@A+PN(wY-CtWrYe)CrUwHJU4?Ocaa~J$6tR+t0 zmRGC%`g*u$`RH*x?3$J1#O3A`r-^gTzVPhu25*%HjUyKjt}9%5T!mayp4jY_?v=V= zwpaP%gZ}7sZBZH1`-SN;{_5^hu5CgD{$nB8yIO|wA^1!y`gruj?-hQSWG;YpYlz!@b&L8Kd zkFA+eW}d^pGL$Lfzj;XTv03WrnaiUZ03AtS=B8+3ga@w(4%Oz~eb4gQbm7``w>4L$ zhZmgD?%wK$v#_;1G>LK#m{e9 zTiq!)(oFiv8pA+Do^hWm4u~L@4es9(^q-2QGY`Stm~Sir!CprAKmDnKPQ_ zt8%^5XbK5{%!1-t_+n3DV;_-YAM{HAEJ9Qm3_c1p?#Ucv;IMzGdh73zgzfs{O%GUW zO+wxx&(Jvaexks!gSP`AmU@xHCOECDdJc1H!X?gvLmRH7`mfFtz?&Wa;K|>jqIPR8j7%G`kdI!*%(%c{9-=*jB?)t+QmyDFCHeCF+M#1MR)gfq@?|JN@v5m zjv-T(cX*xk(mD}4Rz#4y4k;@2zh^#KyT!%0>=|=L4(`KjMb9RP%8$sj?B1Uv1)Iaw zc8cWaUlgC6F1V)e4edTTEV1jxDV-O|qJQQAkn0R@+C_mIku-fc5fTjdEvXe|=mk34 zI31MbWvsEudrRlO--1wmp(hS{D=-jI`_FFK({8h&@TT5rUFY_N znzV5ji6kT1MM0brJ$u63yc}C&&0*u_ZWcH?rNKfM2)EpIz_n3Y(FGhVLiGh>YZ|i4`Fvx_R}OKU76y` zhrvZ|hbW>DjTlM`qYZigRM(CRmmfL9eFwct!eq4ubCOi`yISikJBRNwuX+7i7L^?$ zLq~t=mm1y~+NyBr_C7tpfZ9&jnB>TYr;LlWTZLV8r}`mDPC6cUz$RiFD?ZgJT}$cp zIX~^@J>b1#g4g1bRfB(PU5095?k~4fnxD^&Sbu04^FI1y6!|iZ@Fwz6o8*kQvsG3G zqF|3qvc&7)klsNd%|DezA%&UfidbNwEWbZG>D}05R`1n5o(Kb2ShBj%$2jmiht?+1 z;<*O>$Rsb_gFmoX@{becMEK^SxX4 zv@42M?vEw)K4w$4VBQ9&9jFX59%6zZ>$luJcR=*;4$IDlhba#sN3rG`4k+1mO-5o! zdjK-k8+>M!B6heWA*c2)DcSP%^k4E<7)hE6&K&y&xZ?+uBA;Y zh~8|PNqF{Wf)vc7DUg1zQ!-uFtoC<qkr@O0PPFNyx0S7Sx}qg6R47G#cxo~R3h}rBq6RF z7nUofo$5p}JIIVS=p*9!%`p%oRv~pfsgv zreH-ulx&5PGMaA!5j<0sTa}REX&G|Gvtm?i42uLCrMKTc483nL8nz+3izn!6$*neP zfPlD>aF@x&kZ9S8Kk3(7PJ9UI?Shz9q_oz*(K!*M2N?5_nJ{t`Ps~?w|0vOIf6=wf z>$W1EX>iQ=8e{X}X#gBw*7S<9!JSf*Qywj}0VsGg}z8gg@dpxQ|S`2e|RO_NT zHh0RRS7;lLOoZ4bVZ;68`-j>^sF|`N+c&K~C74)Y z=?z#lTx)p3rYu;m>;T0x7h%-O zvlyyNo_?3%9zUX8yyMn*q+BSW^*S_WoM-Q5c^$RmrwWPo*sx&6Ws?e7V;NDN?j5YC z^Qu~etnI6*Y_c0Pf}<`+hXIU6!3$cX-jTB2Jp9w9!Q1XnJ!T-jCM%*w2phT^ z(~tbRX-i1`P04(k zPBZk9Rkrli60r~8i5JpA;--2S)BCyC1b;l#A`DTXm<-Xkm3$kjYYd4 z^<72kha9|P)^&Rvk;J73hQ{~ab&-t&fpQ{->LEv_=Qd>=NH?ocIGd8NIbk8eyy8t@ zc7EgPZh2spe~<=cUw2P>dm}K4CbdRY-e6=*ccuXA7;NHreBrWFbQE%-oF>I%PH}WO zq^jPqH*&zhd7aWFMs1aOV-3#E%cuYGoi*KOY2^6w;#k?5W&;zo#(X_5jqKDpTA>!vX(iGPT%Z)mzkSb^PM@#S*e&=_xU@{2nrd zvo;d1wq=wzw>=xNi<2FB@*9nZx5j!o#*90}3At`=CP3w${$Z25vvZ|dJ_Q*)?q-T) z6d_}q%b0OJG0I(O1~93k`IiSY3eLM*SFfb>CN(@(-At=Bgh|C5JyX1HbB%MFwbJ7l z2Ko{&U069IhWsX`sG4^DCc_v^57>4wZKKVZv)d|+4Qzy!lq!mZDv1Y7kv+mi_g{!o z4>JeWT!*WiKcy?$TL5ey4eFhlM>Qb>Is%Hf_MB+IMml>lT^^XKJYaOZRhm0ogA9hP zSDRKJa+#5sZ^nc?=eK`x?pR`Mc*NtaV@I0TG(?r2LgyJGwz`wsL!*!45Nm&Yyv^y($qHl42KRDV8Z~cYi$k(`b$*&_`MTFC zPR9e##-TJ;B+y$1vIPl}WXE&&K3S6ZeWf7}z7KV&GI0q=T5f8(+C#tCm)B zQGAh8(4Po3F%rq7_q5ad`LUG#udz;AU<)=tmP@OniNxM@0|I<_btMUGZtwX#|Z z7cKSqf6r*Io>fJ1&z*$PXF{ysSa)xZE4mWJ^!nVD_xye34sT3UXJz_kW+HlDZmEth z5(r;;vvFUZ_5O3=zo{0BVb0H5zuBgLZu`9K=gN|mjMdf1-N8=DZEigI9p~-N*Zsaj zDb!B2`eSOJagVV?gS|q8(PY8%0y&+HaYOtmMSgZ}w|yT^iU>A_8`@{Rw%@9Ix5V}7 zYeIEuk?`Bp=N?_ZFi6$E7R90(?>;PzV=6NxsxyjW!?SNIp;hAmp9(^3f~`-xEF@PN z%v--s*lJ%N40{!9Ah;_x*&(yY(w%wF8_0Kg&*a(XQ6Cw;LukpkRG!r0PCLJQqjA$C z_J)GYEN_JU#$cB8*PEHC#UB{e+cwkXd2{+4 zgXIXnia+Cv0}SnO(Jq>K@v==QH%4r@JIc`8r^hKs@Ul-S*m-qaBE8fn;8GDtfoHH8 z)z$1YRpB`Vz?=`+Q!04ObJ{$-;Lk->?A#Ra^83{ zrd;T~HnR$I5|sbP=nQ#QJWgztcZ7KO-cjP7{?nC{bk)ZyrP+w!O%b;BN_ms?jR(~0 zo)ZobPnvg3*VY`MQ2X-{@9l>H0XW|tdPnp4LXXw^!2WB9kNn%kZU2ZA#Y9adb!QmF ziVYhKuNUp)m5n(VKcns{&nHMtoj>VZB7$ENNLAI_i%_^lz47ACpFF=9?}*+gSYLF} z3CK6UzFdC(2xj!k{aqu}=Y0(G8Ue(-5B=ba%9lG2R7$2a%?_KS@=$=j>1UqHKjLk; zBDp1F@{TAXx?cz+19A-ah-y&6q!Ph{QIi!sF9qDAyKcYC%uATPdNqsEG#jlD$v2@i z;WCn$Sk|^<{}e7(+y)^W2iO@`OQLMc$_R0eFUXxr3fZCH+k=Q|q_^H-TnSN29HdaH zs6%bD`4#Jh;MErl=dO^lVSb_Hn>b$3U z%J|)_kfCQQ+OPTCcoz}YFx3qi&Nw`&5{?|=9TaVVIK+7<%LHGQ3PKHb_m6&P)E%5E zw5}7*0VmV6It>$6X3LAb(-nqQbTCA6%5Sg;ds zTT>>(jHTHJo0Vu^P_By6;4h5M%`BEX7@|1VbLH-OCq;{a&I?ja21eZgecs5UHOHM_ cf8qs5IoNF;tdA~Re6z2av6WHT_PsIx0gS~0=Kufz diff --git a/hoverdemo-helloworld/src/main/res/layout/activity_main.xml b/hoverdemo-helloworld/src/main/res/layout/activity_main.xml deleted file mode 100644 index 6637d91..0000000 --- a/hoverdemo-helloworld/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - - -