Android project initiated
This commit is contained in:
168
src/org/solovyev/android/view/DragButton.java
Normal file
168
src/org/solovyev/android/view/DragButton.java
Normal file
@@ -0,0 +1,168 @@
|
||||
package org.solovyev.android.view;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.util.StringUtils;
|
||||
import org.solovyev.util.math.MathUtils;
|
||||
import org.solovyev.util.math.Point2d;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.text.Html;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
|
||||
public class DragButton extends Button {
|
||||
|
||||
// max time in ms to register drag event
|
||||
private long maxTime = 700;
|
||||
|
||||
@Nullable
|
||||
private Point2d startPoint = null;
|
||||
|
||||
@Nullable
|
||||
private OnDragListener onDragListener;
|
||||
|
||||
private final OnTouchListener onTouchListener = new OnTouchListenerImpl();
|
||||
|
||||
@Nullable
|
||||
private String textUp;
|
||||
|
||||
@Nullable
|
||||
private String textDown;
|
||||
|
||||
@Nullable
|
||||
private String textMiddle;
|
||||
|
||||
public DragButton(Context context, @NotNull AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
public DragButton(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
private void init(@NotNull Context context, @NotNull AttributeSet attrs) {
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DragButton);
|
||||
|
||||
final int N = a.getIndexCount();
|
||||
for (int i = 0; i < N; i++) {
|
||||
int attr = a.getIndex(i);
|
||||
switch (attr) {
|
||||
case R.styleable.DragButton_textUp:
|
||||
this.textUp = a.getString(attr);
|
||||
break;
|
||||
case R.styleable.DragButton_textDown:
|
||||
this.textDown = a.getString(attr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// backup text
|
||||
this.textMiddle = String.valueOf(getText());
|
||||
|
||||
setText(Html.fromHtml(getStyledUpDownText(this.textUp) + "<br><b>" + StringUtils.getNotEmpty(this.textMiddle, " ") + "</b><br>" + getStyledUpDownText(this.textDown)));
|
||||
|
||||
// change top padding in order to show all text
|
||||
setPadding(getPaddingLeft(), -7, getPaddingRight(), getPaddingBottom());
|
||||
|
||||
setOnTouchListener(this.onTouchListener);
|
||||
}
|
||||
|
||||
private String getStyledUpDownText(@Nullable String text) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append("<font color='#585858'><small><small>");
|
||||
sb.append(StringUtils.getNotEmpty(text, " "));
|
||||
sb.append("</small></small></font>");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void setOnDragListener(@Nullable OnDragListener onDragListener) {
|
||||
this.onDragListener = onDragListener;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public OnDragListener getOnDragListener() {
|
||||
return onDragListener;
|
||||
}
|
||||
|
||||
public void setTextUp(String textUp) {
|
||||
this.textUp = textUp;
|
||||
}
|
||||
|
||||
public String getTextUp() {
|
||||
return textUp;
|
||||
}
|
||||
|
||||
public void setTextDown(String textDown) {
|
||||
this.textDown = textDown;
|
||||
}
|
||||
|
||||
public String getTextDown() {
|
||||
return textDown;
|
||||
}
|
||||
|
||||
public void setTextMiddle(String textMiddle) {
|
||||
this.textMiddle = textMiddle;
|
||||
}
|
||||
|
||||
public String getTextMiddle() {
|
||||
return textMiddle;
|
||||
}
|
||||
|
||||
/**
|
||||
* OnTouchListener implementation that fires onDrag()
|
||||
*
|
||||
* @author serso
|
||||
*
|
||||
*/
|
||||
private final class OnTouchListenerImpl implements OnTouchListener {
|
||||
|
||||
@Override
|
||||
public boolean onTouch(@NotNull View v, @NotNull MotionEvent event) {
|
||||
// processing on touch event
|
||||
|
||||
if (onDragListener != null) {
|
||||
// only if onDrag() listener specified
|
||||
|
||||
Log.d(String.valueOf(getId()), "onTouch() for: " + getId() + " . Motion event: " + event);
|
||||
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
// start tracking: set start point
|
||||
startPoint = new Point2d(event.getX(), event.getY());
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (event.getEventTime() - event.getDownTime() > maxTime) {
|
||||
// do not allow very long touch movements
|
||||
startPoint = null;
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_UP:
|
||||
// stop tracking
|
||||
|
||||
if (onDragListener.onDrag(DragButton.this, new DragEvent(startPoint, event))) {
|
||||
if (onDragListener.isSuppressOnClickEvent()) {
|
||||
// prevent on click action
|
||||
setPressed(false);
|
||||
}
|
||||
}
|
||||
|
||||
startPoint = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
7
src/org/solovyev/android/view/DragDirection.java
Normal file
7
src/org/solovyev/android/view/DragDirection.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package org.solovyev.android.view;
|
||||
|
||||
public enum DragDirection {
|
||||
|
||||
up,
|
||||
down;
|
||||
}
|
33
src/org/solovyev/android/view/DragEvent.java
Normal file
33
src/org/solovyev/android/view/DragEvent.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package org.solovyev.android.view;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.util.math.Point2d;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public class DragEvent {
|
||||
|
||||
@NotNull
|
||||
private final Point2d startPoint;
|
||||
|
||||
@NotNull
|
||||
private final MotionEvent motionEvent;
|
||||
|
||||
public DragEvent(@NotNull Point2d startPoint, @NotNull MotionEvent motionEvent) {
|
||||
this.startPoint = startPoint;
|
||||
this.motionEvent = motionEvent;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public MotionEvent getMotionEvent() {
|
||||
return motionEvent;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Point2d getStartPoint() {
|
||||
return startPoint;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
22
src/org/solovyev/android/view/OnDragListener.java
Normal file
22
src/org/solovyev/android/view/OnDragListener.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package org.solovyev.android.view;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
public interface OnDragListener {
|
||||
|
||||
/**
|
||||
*
|
||||
* @return 'true': if drag event has taken place (i.e. onDrag() method returned true) then click action will be suppresed
|
||||
*/
|
||||
boolean isSuppressOnClickEvent();
|
||||
|
||||
/**
|
||||
* @param dragButton drag button object for which onDrag listener was set
|
||||
* @param event drag event
|
||||
*
|
||||
* @return 'true' if drag event occurred, 'false' otherwise
|
||||
*/
|
||||
boolean onDrag(@NotNull DragButton dragButton, @NotNull DragEvent event);
|
||||
|
||||
}
|
93
src/org/solovyev/android/view/SimpleOnDragListener.java
Normal file
93
src/org/solovyev/android/view/SimpleOnDragListener.java
Normal file
@@ -0,0 +1,93 @@
|
||||
package org.solovyev.android.view;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.util.StringUtils;
|
||||
import org.solovyev.util.math.MathUtils;
|
||||
import org.solovyev.util.math.Point2d;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public class SimpleOnDragListener implements OnDragListener {
|
||||
|
||||
@NotNull
|
||||
private final Point2d axis = new Point2d(0, 1);
|
||||
|
||||
private float minDragDist = 20f;
|
||||
|
||||
private float maxDragDist = 80f;
|
||||
|
||||
// max angle (in degrees!) between start and end point vector and axis
|
||||
// vector to register drag event
|
||||
private double maxAngle = 30;
|
||||
|
||||
@Override
|
||||
public boolean onDrag(@NotNull DragButton dragButton, @NotNull DragEvent event) {
|
||||
logDragEvent(dragButton, event);
|
||||
|
||||
processButtonAction(dragButton, getActionText(dragButton, event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuppressOnClickEvent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method creates drag event in case if all conditions are satisfied
|
||||
*
|
||||
* @param event
|
||||
* motion event
|
||||
*
|
||||
* @return filled drag event object only if drag event is possible, null
|
||||
* otherwise
|
||||
*/
|
||||
@Nullable
|
||||
protected DragEvent getDragEvent(@NotNull MotionEvent event) {
|
||||
DragEvent result = null;
|
||||
|
||||
if (startPoint != null) {
|
||||
final Point2d endPoint = new Point2d(event.getX(), event.getY());
|
||||
float distance = MathUtils.getDistance(startPoint, endPoint);
|
||||
|
||||
if (minDragDist < distance && distance < maxDragDist) {
|
||||
double angle = Math.toDegrees(MathUtils.getAngle(startPoint, MathUtils.sum(startPoint, axis), endPoint));
|
||||
|
||||
final DragDirection direction;
|
||||
if (angle < maxAngle) {
|
||||
direction = DragDirection.down;
|
||||
} else if (180 - angle < maxAngle) {
|
||||
direction = DragDirection.up;
|
||||
} else {
|
||||
direction = null;
|
||||
}
|
||||
|
||||
if (direction != null) {
|
||||
if ( direction == DragDirection.up && StringUtils.isEmpty(textUp) ) {
|
||||
// no action if text is empty
|
||||
} else if (direction == DragDirection.down && StringUtils.isEmpty(textDown)) {
|
||||
// no action if text is empty
|
||||
} else {
|
||||
result = new DragEvent(direction);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void logDragEvent(@NotNull DragButton dragButton, @NotNull DragEvent event) {
|
||||
final Point2d startPoint = event.getStartPoint();
|
||||
final MotionEvent motionEvent = event.getMotionEvent();
|
||||
final Point2d endPoint = new Point2d(motionEvent.getX(), motionEvent.getY());
|
||||
|
||||
Log.d(String.valueOf(dragButton.getId()), "Start point: " + startPoint + ", End point: " + endPoint);
|
||||
Log.d(String.valueOf(dragButton.getId()), "Distance: " + MathUtils.getDistance(startPoint, endPoint));
|
||||
Log.d(String.valueOf(dragButton.getId()), "Angle: " + Math.toDegrees(MathUtils.getAngle(startPoint, MathUtils.sum(startPoint, axis), endPoint)));
|
||||
Log.d(String.valueOf(dragButton.getId()), "Axis: " + axis + " Vector: " + MathUtils.subtract(endPoint, startPoint));
|
||||
Log.d(String.valueOf(dragButton.getId()), "Total time: " + (motionEvent.getEventTime() - motionEvent.getDownTime()) + " ms");
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user