Skip to content

Instantly share code, notes, and snippets.

@samuel22gj
Last active September 28, 2018 06:55
Show Gist options
  • Select an option

  • Save samuel22gj/e816b0a6047b8405adc5a89de00e6c23 to your computer and use it in GitHub Desktop.

Select an option

Save samuel22gj/e816b0a6047b8405adc5a89de00e6c23 to your computer and use it in GitHub Desktop.
Class intended to support multiple click areas for a View.
/**
* Class intended to support multiple click areas for a {@link View}.
*/
public abstract class ClickAreaHelper implements View.OnTouchListener, View.OnClickListener, View.OnLongClickListener {
private OnClickAreaListener mOnClickAreaListener;
private OnLongClickAreaListener mOnLongClickAreaListener;
private View mView;
private float mClickX;
private float mClickY;
private float mLongClickX;
private float mLongClickY;
public void setOnClickAreaListener(OnClickAreaListener listener) {
mOnClickAreaListener = listener;
}
public void setOnLongClickAreaListener(OnLongClickAreaListener listener) {
mOnLongClickAreaListener = listener;
}
public void attachToView(@Nullable View view) {
if (mView == view) {
return;
}
if (mView != null) {
// Clear callbacks of previous view
destroyCallbacks();
}
mView = view;
if (view == null) {
return;
}
setupCallbacks();
}
private void setupCallbacks() {
mView.setOnTouchListener(this);
mView.setOnClickListener(this);
mView.setOnLongClickListener(this);
}
private void destroyCallbacks() {
mView.setOnTouchListener(null);
mView.setOnClickListener(null);
mView.setOnLongClickListener(null);
}
abstract int calculateAreaIndex(int width, int height, float x, float y);
///////////////////////////////////////////////////////////////////////////
// View.OnTouchListener
///////////////////////////////////////////////////////////////////////////
@Override
public boolean onTouch(View v, MotionEvent event) {
final float x = event.getX();
final float y = event.getY();
final int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_UP:
// Record click coordinate
mClickX = x;
mClickY = y;
break;
case MotionEvent.ACTION_DOWN:
// Record long click coordinate
mLongClickX = x;
mLongClickY = y;
break;
default:
break;
}
return false;
}
///////////////////////////////////////////////////////////////////////////
// View.OnClickListener
///////////////////////////////////////////////////////////////////////////
@Override
public void onClick(View v) {
if (mOnClickAreaListener != null) {
int index = calculateAreaIndex(v.getMeasuredWidth(), v.getMeasuredHeight(), mClickX, mClickY);
mOnClickAreaListener.onClick(v, index);
}
}
///////////////////////////////////////////////////////////////////////////
// View.OnLongClickListener
///////////////////////////////////////////////////////////////////////////
@Override
public boolean onLongClick(View v) {
if (mOnLongClickAreaListener != null) {
int index = calculateAreaIndex(v.getMeasuredWidth(), v.getMeasuredHeight(), mLongClickX, mLongClickY);
return mOnLongClickAreaListener.onLongClick(v, index);
}
return false;
}
}
/**
* Implementation of the {@link ClickAreaHelper} supporting arranges click areas evenly
* in either vertical or horizontal orientation.
* <p>
* The following are sample illustration:
* <pre>
* areaCount = 3
* orientation = HORIZONTAL
* | 0 | 1 | 2 |
*
* areaCount = 2
* orientation = VERTICAL
* ---
* 0
* ---
* 1
* ---
* 2
* ---
* </pre>
*/
public class LinearClickAreaHelper extends ClickAreaHelper {
@IntDef({HORIZONTAL, VERTICAL})
@Retention(RetentionPolicy.SOURCE)
public @interface Orientation {}
public static final int HORIZONTAL = 0;
public static final int VERTICAL = 1;
private int mAreaCount;
private int mOrientation;
public LinearClickAreaHelper(@IntRange(from = 1) int areaCount, @Orientation int orientation) {
mAreaCount = areaCount;
mOrientation = orientation;
}
@Override
int calculateAreaIndex(int width, int height, float x, float y) {
if (mAreaCount <= 1) {
return 0;
}
final int length = mOrientation == HORIZONTAL ? width : height;
final float position = mOrientation == HORIZONTAL ? x : y;
final int areaLength = length / mAreaCount;
return (int) (position / areaLength);
}
}
public interface OnClickAreaListener {
void onClick(@NonNull View view, int index);
}
public interface OnLongClickAreaListener {
boolean onLongClick(@NonNull View view, int index);
}
/**
* Implementation of the {@link ClickAreaHelper} supporting divide click areas into four regions.
* <p>
* The following are the illustration of click area:
* <pre>
* ---------
* | 1 | 0 |
* ---------
* | 2 | 3 |
* ---------
* </pre>
*/
public class QuadrantClickAreaHelper extends ClickAreaHelper {
@Override
int calculateAreaIndex(int width, int height, float x, float y) {
final int centerX = width / 2;
final int centerY = height / 2;
if (x >= centerX && y <= centerY) {
return 0;
} else if (x < centerX && y < centerY) {
return 1;
} else if (x <= centerX && y >= centerY) {
return 2;
} else {
return 3;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment