Skip to content
This repository was archived by the owner on Feb 9, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 55 additions & 14 deletions hover/src/main/java/io/mattcarroll/hover/BaseTouchController.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, View> mTouchViewMap = new HashMap<>();
protected TouchListener mTouchListener;
protected boolean mIsActivated;
private boolean mIsDebugMode;
private List<View> mViewList;

private View.OnTouchListener mDragTouchListener = new View.OnTouchListener() {
@Override
Expand All @@ -33,32 +38,66 @@ 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<View> 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();
}
}

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;
}
}

Expand All @@ -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);
}
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion hover/src/main/java/io/mattcarroll/hover/ContentDisplay.java
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
27 changes: 14 additions & 13 deletions hover/src/main/java/io/mattcarroll/hover/Dragger.java
Original file line number Diff line number Diff line change
Expand Up @@ -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}.
*/
Expand All @@ -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();
Expand All @@ -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);
}
}
Expand Down Expand Up @@ -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<View> 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) {
Expand All @@ -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)
);
}

Expand Down
43 changes: 6 additions & 37 deletions hover/src/main/java/io/mattcarroll/hover/FloatingTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -54,12 +51,11 @@ class FloatingTab extends FrameLayout {
private int mTabSize;
private View mTabView;
private Dock mDock;
private final Set<OnPositionChangeListener> 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);
}
};

Expand Down Expand Up @@ -229,7 +225,7 @@ public Point getDockPosition() {

public void setDock(@NonNull Dock dock) {
mDock = dock;
notifyListenersOfDockChange();
notifyListenersOfDockChange(mDock);
}

public void dock() {
Expand Down Expand Up @@ -259,7 +255,7 @@ public void onAnimationEnd(Animator animation) {
if (null != onDocked) {
onDocked.run();
}
notifyListenersOfPositionChange();
notifyListenersOfPositionChange(FloatingTab.this);
}

@Override
Expand All @@ -272,7 +268,7 @@ public void onAnimationRepeat(Animator animation) { }
xAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
notifyListenersOfPositionChange();
notifyListenersOfPositionChange(FloatingTab.this);
}
});
}
Expand All @@ -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) {
Expand All @@ -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);
}
}
61 changes: 61 additions & 0 deletions hover/src/main/java/io/mattcarroll/hover/HoverFrameLayout.java
Original file line number Diff line number Diff line change
@@ -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<OnPositionChangeListener> 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);
}
}
7 changes: 7 additions & 0 deletions hover/src/main/java/io/mattcarroll/hover/HoverView.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down
Loading