Add TouchExpander

This commit is contained in:
Sergey Solovyev 2018-04-29 22:40:57 +02:00
parent a3c6d21a52
commit 5ce83d0314

View File

@ -0,0 +1,85 @@
package org.solovyev.android.calculator.view;
import android.graphics.Rect;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.Px;
import android.support.v4.view.ViewCompat;
import android.view.TouchDelegate;
import android.view.View;
import android.view.ViewTreeObserver;
public class TouchExpander implements ViewTreeObserver.OnGlobalLayoutListener {
@NonNull
private final View mView;
@NonNull
private final Rect mExtra;
// non-null when a TouchDelegate has been set
@Nullable
private View mParent;
private TouchExpander(@NonNull View view, @Px int extra) {
this(view, new Rect(extra, extra, extra, extra));
}
private TouchExpander(@NonNull View view, @NonNull Rect extra) {
mView = view;
mExtra = extra;
attach();
}
private static void outset(@NonNull Rect rect, @NonNull Rect diff) {
rect.left -= diff.left;
rect.top -= diff.top;
rect.right += diff.right;
rect.bottom += diff.bottom;
}
@NonNull
public static TouchExpander attach(@NonNull View view, @Px int extra) {
return new TouchExpander(view, extra);
}
@NonNull
public static TouchExpander attach(@NonNull View view, @NonNull Rect extra) {
return new TouchExpander(view, extra);
}
private void attach() {
if (ViewCompat.isLaidOut(mView)) {
onLaidOut();
return;
}
mView.getViewTreeObserver().addOnGlobalLayoutListener(this);
}
@Override
public void onGlobalLayout() {
if (!ViewCompat.isLaidOut(mView)) return;
mView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
onLaidOut();
}
private void onLaidOut() {
if (!ViewCompat.isLaidOut(mView)) {
throw new IllegalStateException("View is not laid out");
}
final Rect hitRect = new Rect();
mView.getHitRect(hitRect);
outset(hitRect, mExtra);
mParent = (View) mView.getParent();
mParent.setTouchDelegate(new TouchDelegate(hitRect, mView));
}
public void detach() {
mView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
if (mParent != null) {
mParent.setTouchDelegate(null);
mParent = null;
}
}
}