Android project initiated

This commit is contained in:
serso
2011-06-24 01:09:13 +04:00
commit eb16062296
61 changed files with 1164 additions and 0 deletions

View 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, "&nbsp;") + "</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, "&nbsp;"));
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;
}
}
}

View File

@@ -0,0 +1,7 @@
package org.solovyev.android.view;
public enum DragDirection {
up,
down;
}

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

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

View 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");
}
}