package com.ql.app;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.OnGestureListener;
import android.widget.FrameLayout;
import android.widget.ImageView;
public class SnakeLayout extends FrameLayout {
private static final String LOG_TAG = "SnakeLayout";
private GestureDetector mGestureDetector;
private SnakeOnGestureListener mGestureListener;
private List<View> ViewHolder;
private int selectImg;
private int totalViewNum;
private View mContentView;
private SnakeView ScrollView;
private Context mContext;
private enum State {
ABOUT_TO_ANIMATE, ANIMATING, ANIMATE_END, READY, TRACKING
};
private State mState;
private double aniStartPos;// Value = scrollNum + percent*direction;
private double aniStopPos;// Value = scrollNum + percent*direction;
private Date aniStartTime;
private long aniTime = 1000;
private double aniSpeed = 500;
private double aniDefG = 5;
private int mContentWidth = 0;
private int mContentHeight = 0;
private int clickItem = -1;
private int direction = 0;
private int movDirection = 0;
private double percent = 0;
private int scrollNum = 0;
private PathScale myPathViews;
private List<Bitmap> BmpRecViews;
private OnSelectListener selectListener;
private OnClickListener clickListener;
private int currentIndex = 0;
public SnakeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
Log.d(LOG_TAG, "Init Snake Layout");
mContext = context;
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.SnakeLayout);
selectImg = a.getInteger(R.styleable.SnakeLayout_selectImg, -1);
a.recycle();
mGestureListener = new SnakeOnGestureListener();
mGestureDetector = new GestureDetector(mGestureListener);
mGestureDetector.setIsLongpressEnabled(false);
BmpRecViews = new ArrayList<Bitmap>();
myPathViews = new PathScale();
mState = State.READY;
}
public void Init() {
for (int i = 0; i < totalViewNum; i++) {
ImageView v = (ImageView) ViewHolder.get(i);
v.setScaleType(ImageView.ScaleType.FIT_XY);
v.setImageBitmap(BmpRecViews.get((i + currentIndex)
% BmpRecViews.size()));
}
}
public void addBitmap(Bitmap b) {
if (b != null)
BmpRecViews.add(b);
}
public void addBitmap(Bitmap b, int position) {
if (b != null)
BmpRecViews.add(position, b);
}
public void addRec(int rec) {
Bitmap b = BitmapFactory.decodeResource(this.getResources(), rec);
if (b != null)
BmpRecViews.add(b);
}
public void addRec(int rec, int position) {
Bitmap b = BitmapFactory.decodeResource(this.getResources(), rec);
if (b != null)
BmpRecViews.add(position, b);
}
private class PathScale {
private int totalNum;
List<Double> myLen;
List<Rect> myRect;
int recentScrollNum = 0;
double RecentPercent = 0;
public PathScale() {
totalNum = 0;
myLen = new ArrayList<Double>();
myRect = new ArrayList<Rect>();
}
public double getAverageLen() {
double len = 0;
if (totalNum < 2)
return len;
for (int i = 0; i < totalNum - 2; i++) {
len += myLen.get(i);
}
return len / (totalNum - 1);
}
public int size() {
return totalNum;
}
public void addPointView(int left, int top, int right, int bottom) {
totalNum++;
Log.d(LOG_TAG, "total num : " + totalNum);
Rect r = new Rect(left, top, right, bottom);
myRect.add(r);
if (totalNum > 1) {
Rect r0 = myRect.get(totalNum - 2);
int dx = r0.centerX() - r.centerX();
int dy = r0.centerY() - r.centerY();
double len = Math.sqrt(dx * dx + dy * dy);
myLen.add(len);
}
}
public int getRecentScrollNum() {
return recentScrollNum;
}
public double getPercent() {
return RecentPercent;
}
public void computeScroll(int clickNum, int dir, double len) {
double remain = len;
recentScrollNum = 0;
RecentPercent = 0;
if (dir == 1) {
for (int i = clickNum;; i++) {
if (i > totalNum - 2)
i = totalNum - 2;
if (i < 0)
i = 0;
double tmp = myLen.get(i);
if (remain >= tmp) {
recentScrollNum++;
remain -= tmp;
} else {
RecentPercent = remain / tmp;
break;
}
}
} else if (dir == -1) {
for (int i = clickNum;; i--) {
if (i - 1 > totalNum - 2)
i = totalNum - 1;
if (i - 1 < 0)
i = 1;
double tmp = myLen.get(i - 1);
if (remain >= tmp) {
recentScrollNum--;
remain -= tmp;
} else {
RecentPercent = remain / tmp;
break;
}
}
}
}
public Rect getMoveRect(int selectNum) {
if (direction == 1) {
int newIndex = selectNum + scrollNum;
if (newIndex >= totalNum - 1) {
Rect r0 = myRect.get(totalNum - 1);
Rect r1 = myRect.get(totalNum - 2);
int nx = (int) (r0.centerX() - (r1.centerX() - r0.centerX())
* percent);
int ny = (int) (r0.centerY() - (r1.centerY() - r0.centerY())
* percent);
int nw = (int) (r0.width() - (r1.width() - r0.width())
* percent);
int nh = (int) (r0.height() - (r1.height() - r0.height())
* percent);
return new Rect(nx - nw / 2, ny - nh / 2, nx + nw / 2, ny
+ nh / 2);
} else if (newIndex == -1) {
Rect r0 = myRect.get(0);
Rect r1 = myRect.get(1);
int nx = (int) (r0.centerX() - (r1.centerX() - r0.centerX())
* (1 - percent));
int ny = (int) (r0.centerY() - (r1.centerY() - r0.centerY())
* (1 - percent));
int nw = (int) (r0.width() - (r1.width() - r0.width())
* (1 - percent));
int nh = (int) (r0.height() - (r1.height() - r0.height())
* (1 - percent));
return new Rect(nx - nw / 2, ny - nh / 2, nx + nw / 2, ny
+ nh / 2);
} else if (newIndex > totalNum - 1 || newIndex < -1) {
return null;
} else {
Rect r0 = myRect.get(newIndex);
Rect r1 = myRect.get(newIndex + 1);
int nx = (int) (r0.centerX() + (r1.centerX() - r0.centerX())
* percent);
int ny = (int) (r0.centerY() + (r1.centerY() - r0.centerY())
* percent);
int nw = (int) (r0.width() + (r1.width() - r0.width())
* percent);
int nh = (int) (r0.height() + (r1.height() - r0.height())
* percent);
return new Rect(nx - nw / 2, ny - nh / 2, nx + nw / 2, ny
+ nh / 2);
}
} else if (direction == -1) {
int newIndex = selectNum + scrollNum;
if (newIndex == 0) {
Rect r0 = myRect.get(0);
Rect r1 = myRect.get(1);
int nx = (int) (r0.centerX() - (r1.centerX() - r0.centerX())
* percent);
int ny = (int) (r0.centerY() - (r1.centerY() - r0.centerY())
* percent);
int nw = (int) (r0.width() - (r1.width() - r0.width())
* percent);
int nh = (int) (r0.height() - (r1.height() - r0.height())
* percent);
return new Rect(nx - nw / 2, ny - nh / 2, nx + nw / 2, ny
+ nh / 2);
} else if (newIndex == totalNum) {
Rect r0 = myRect.get(totalNum - 1);
Rect r1 = myRect.get(totalNum - 2);
int nx = (int) (r0.centerX() - (r1.centerX() - r0.centerX())
* (1 - percent));
int ny = (int) (r0.centerY() - (r1.centerY() - r0.centerY())
* (1 - percent));
int nw = (int) (r0.width() - (r1.width() - r0.width())
* (1 - percent));
int nh = (int) (r0.height() - (r1.height() - r0.height())
* (1 - percent));
return new Rect(nx - nw / 2, ny - nh / 2, nx + nw / 2, ny
+ nh / 2);
} else if (newIndex > totalNum || newIndex < 0) {
return null;
} else {
Rect r0 = myRect.get(newIndex);
Rect r1 = myRect.get(newIndex - 1);
int nx = (int) (r0.centerX() + (r1.centerX() - r0.centerX())
* percent);
int ny = (int) (r0.centerY() + (r1.centerY() - r0.centerY())
* percent);
int nw = (int) (r0.width() + (r1.width() - r0.width())
* percent);
int nh = (int) (r0.height() + (r1.height() - r0.height())
* percent);
return new Rect(nx - nw / 2, ny - nh / 2, nx + nw / 2, ny
+ nh / 2);
}
} else {
return null;
}
}
}
public static interface OnSelectListener {
public void onSelected(int position);
}
public void setOnSelectListener(OnSelectListener l) {
selectListener = l;
}
public static interface OnClickListener {
public void onClicked(int position);
}
public void setOnClickListener(OnClickListener l) {
clickListener = l;
}
protected void onFinishInflate() {
super.onFinishInflate();
Log.d(LOG_TAG, "onFinishInflate");
ViewHolder = new ArrayList<View>();
View v = findViewById(R.id.snakeImg0);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg1);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg2);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg3);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg4);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg5);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg6);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg7);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg8);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg9);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg10);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg11);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg12);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg13);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg14);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg15);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg16);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg17);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg18);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg19);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg20);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg21);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg22);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg23);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg24);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg25);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg26);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg27);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg28);
if (v != null)
ViewHolder.add(v);
v = findViewById(R.id.snakeImg29);
if (v != null)
ViewHolder.add(v);
mContentView = findViewById(R.id.snakeContent);
totalViewNum = ViewHolder.size();
if (totalViewNum < 3) {
throw new RuntimeException(
"Please confirm that there are more than Three "
+ "ImageViews with id snakeImg* in your xml file, * is a interger");
}
if (selectImg == -1)
selectImg = totalViewNum / 2;
this.setOnTouchListener(touchListener);
this.setLongClickable(true);
}
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (mContentView != null) {
mContentWidth = mContentView.getWidth();
mContentHeight = mContentView.getHeight();
}
if (myPathViews.size() == 0) {
for (int i = 0; i < totalViewNum; i++) {
View v = ViewHolder.get(i);
int left = getLeft(v), top = getTop(v);
int right = getRight(v), bottom = getBottom(v);
myPathViews.addPointView(left, top, right, bottom);
}
}
Log.d(LOG_TAG, "onLayout mContentWidth:" + mContentWidth
+ " mContentHeight:" + mContentHeight);
}
protected void dispatchDraw(Canvas canvas) {
Log.d(LOG_TAG, "dispatchDraw");
if (ScrollView == null) {
ScrollView = new SnakeView(mContext);
ScrollView.setLayoutParams(new LayoutParams(mContentWidth,
mContentHeight));
addView(ScrollView);
}
super.dispatchDraw(canvas);
}
public void getGlobalLocation(View v, int location[]) {
int v_location[] = new int[2], p_location[] = new int[2];
v.getLocationOnScreen(v_location);
mContentView.getLocationOnScreen(p_location);
location[0] = v_location[0] - p_location[0];
location[1] = v_location[1] - p_location[1];
}
public int getLeft(View v) {
int v_location[] = new int[2], p_location[] = new int[2];
v.getLocationOnScreen(v_location);
int l = ((ImageView) v).getPaddingLeft();
mContentView.getLocationOnScreen(p_location);
return l + v_location[0] - p_location[0];
}
public int getRight(View v) {
int v_location[] = new int[2], p_location[] = new int[2];
v.getLocationOnScreen(v_location);
int r = ((ImageView) v).getPaddingRight();
mContentView.getLocationOnScreen(p_location);
return v.getWidth() - r + v_location[0] - p_location[0];
}
public int getTop(View v) {
int v_location[] = new int[2], p_location[] = new int[2];
v.getLocationOnScreen(v_location);
int t = ((ImageView) v).getPaddingTop();
mContentView.getLocationOnScreen(p_location);
return t + v_location[1] - p_location[1];
}
public int getBottom(View v) {
int v_location[] = new int[2], p_location[] = new int[2];
v.getLocationOnScreen(v_location);
int b = ((ImageView) v).getPaddingBottom();
mContentView.getLocationOnScreen(p_location);
return v.getHeight() - b + v_location[1] - p_location[1];
}
OnTouchListener touchListener = new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
Log.d(LOG_TAG, "onTouch " + " x: " + event.getX() + " y: "
+ event.getY());
int action = event.getAction();
if (action == MotionEvent.ACTION_UP) {
Log.d(LOG_TAG, "ACTION_UP " + percent);
if (mState == State.TRACKING) {
aniStartPos = 1.0 * scrollNum + direction * percent;
aniStopPos = scrollNum;
if (percent > 0.5) {
aniStopPos += direction;
}
aniTime = (long) (1000 * percent);
mState = State.ABOUT_TO_ANIMATE;
aniStartTime = new Date();
ScrollView.invalidate();
}
}
mGestureDetector.onTouchEvent(event);
return false;
}
};
public void moveView() {
Log.d(LOG_TAG, "move View");
if (direction != 0) {
if (percent > 1)
percent = 1;
if (direction == -1) {
int size = BmpRecViews.size();
for (int i = 0; i < totalViewNum + 1; i++) {
Rect r = myPathViews.getMoveRect(i - scrollNum);
if (r == null)
continue;
int bmpIndex = (i - scrollNum + currentIndex) % size;
while (bmpIndex < 0)
bmpIndex += size;
Bitmap b = BmpRecViews.get(bmpIndex);
if (b != null) {
ScrollView.addView(b, r.left, r.top, r.width(), r
.height());
}
}
} else if (direction == 1) {
int size = BmpRecViews.size();
for (int i = -1; i < totalViewNum; i++) {
Rect r = myPathViews.getMoveRect(i - scrollNum);
if (r == null)
continue;
int bmpIndex = (i - scrollNum + currentIndex) % size;
while (bmpIndex < 0)
bmpIndex += size;
Bitmap b = BmpRecViews.get(bmpIndex);
if (b != null) {
ScrollView.addView(b, r.left, r.top, r.width(), r
.height());
}
}
}
}
}
class SnakeOnGestureListener implements OnGestureListener {
int initX;
int initY;
int scrollView;
int mClickView = -1;
public boolean onDown(MotionEvent event) {
Log.d(LOG_TAG, "onDown");
initX = (int) event.getX();
initY = (int) event.getY();
if (mState == State.ANIMATING) {
mState = State.TRACKING;
} else {
direction = 0;
percent = 0;
scrollNum = 0;
aniSpeed = 0;
for (int i = 0; i < totalViewNum; i++) {
ImageView tempView = (ImageView) ViewHolder.get(i);
int local[] = new int[2];
getGlobalLocation(tempView, local);
int l = getLeft(tempView);
int t = getTop(tempView);
int w = getRight(tempView) - l;
int h = getBottom(tempView) - t;
tempView.setVisibility(View.INVISIBLE);
int newIndex = i + currentIndex;
int size = BmpRecViews.size();
while (newIndex < 0) {
newIndex += size;
}
newIndex = newIndex % size;
Bitmap b = BmpRecViews.get(newIndex);
if (b != null) {
ScrollView.addView(b, l, t, w, h);
}
}
}
return false;
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float vx,
float vy) {
aniSpeed = Math.sqrt(vx * vx + vy * vy);
double len = myPathViews.getAverageLen();
double v = aniSpeed / (2 * len);
aniTime = (long) (v * 1000 / aniDefG);
double s = v * v / (2 * aniDefG);
Log.d(LOG_TAG, "onFling,velocityX:" + vx + " velocityY:" + vy
+ " aniTime:" + aniTime + " Fling s:" + s);
aniStartPos = 1.0 * scrollNum + direction * percent;
aniStopPos = aniStartPos + direction * s;
aniStopPos = Math.round(aniStopPos);
mState = State.ABOUT_TO_ANIMATE;
aniStartTime = new Date();
ScrollView.invalidate();
return false;
}
public void onLongPress(MotionEvent e) {
Log.d(LOG_TAG, "onLongPress");
}
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
Log.d(LOG_TAG, "onScroll, distanceX:" + distanceX + "distanceY:"
+ distanceY);
mState = State.TRACKING;
scrollView = getNearClickView(initX, initY);
double dx = e2.getX() - initX;
double dy = e2.getY() - initY;
initX = (int) e2.getX();
initY = (int) e2.getY();
// compute the direction
if (scrollView != 0 && scrollView != totalViewNum - 1) {
View v0 = ViewHolder.get(scrollView);
View v1 = ViewHolder.get(scrollView - 1);
View v2 = ViewHolder.get(scrollView + 1);
double len1, len2;
double x0 = (getLeft(v0) + getRight(v0)) * 1.0 / 2;
double y0 = (getTop(v0) + getBottom(v0)) * 1.0 / 2;
double x1 = (getLeft(v1) + getRight(v1)) * 1.0 / 2;
double y1 = (getTop(v1) + getBottom(v1)) * 1.0 / 2;
double x2 = (getLeft(v2) + getRight(v2)) * 1.0 / 2;
double y2 = (getTop(v2) + getBottom(v2)) * 1.0 / 2;
double dx1 = x1 - x0, dy1 = y1 - y0;
double dx2 = x2 - x0, dy2 = y2 - y0;
len1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
len2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);
double r1 = (dx1 * dx + dy1 * dy) / len1, r2 = (dx2 * dx + dy2
* dy)
/ len2;
if (r1 > r2 && r1 > 0) {
movDirection = -1;
myPathViews.computeScroll(scrollView, movDirection, r1);
} else if (r2 > r1 && r2 > 0) {
movDirection = 1;
myPathViews.computeScroll(scrollView, movDirection, r2);
}
} else if (scrollView == 0) {
View v0 = ViewHolder.get(scrollView);
View v1 = ViewHolder.get(scrollView + 1);
double len1;
double x0 = (getLeft(v0) + getRight(v0)) * 1.0 / 2;
double y0 = (getTop(v0) + getBottom(v0)) * 1.0 / 2;
double x1 = (getLeft(v1) + getRight(v1)) * 1.0 / 2;
double y1 = (getTop(v1) + getBottom(v1)) * 1.0 / 2;
double dx1 = x1 - x0, dy1 = y1 - y0;
len1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
double r1 = (dx1 * dx + dy1 * dy) / len1;
if (r1 > 0) {
movDirection = 1;
myPathViews.computeScroll(scrollView, movDirection, r1);
} else {
movDirection = -1;
myPathViews.computeScroll(scrollView, movDirection, -r1);
}
} else if (scrollView == totalViewNum - 1) {
View v0 = ViewHolder.get(scrollView);
View v1 = ViewHolder.get(scrollView - 1);
double len1;
double x0 = (getLeft(v0) + getRight(v0)) * 1.0 / 2;
double y0 = (getTop(v0) + getBottom(v0)) * 1.0 / 2;
double x1 = (getLeft(v1) + getRight(v1)) * 1.0 / 2;
double y1 = (getTop(v1) + getBottom(v1)) * 1.0 / 2;
double dx1 = x1 - x0, dy1 = y1 - y0;
len1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
double r1 = (dx1 * dx + dy1 * dy) / len1;
if (r1 > 0) {
movDirection = -1;
myPathViews.computeScroll(scrollView, movDirection, r1);
} else {
movDirection = 1;
myPathViews.computeScroll(scrollView, movDirection, -r1);
}
}
if (direction == 0)
direction = movDirection;
double pos = scrollNum * 1.0 + percent * direction
+ myPathViews.getPercent() * movDirection
+ myPathViews.getRecentScrollNum() * 1.0;
if (pos > 0)
direction = 1;
else
direction = -1;
scrollNum = (int) pos;
percent = Math.abs(pos - 1.0 * scrollNum);
Log.d(LOG_TAG, "pos:" + pos + " scrollNum:" + scrollNum
+ " percent:" + percent + " direction = " + direction);
// move the view
ScrollView.clear();
moveView();
ScrollView.invalidate();
return false;
}
public void onShowPress(MotionEvent e) {
Log.d(LOG_TAG, "onShowPress");
}
public boolean onSingleTapUp(MotionEvent e) {
Log.d(LOG_TAG, "onSingleTapUp");
if (mState == State.ANIMATING) {
mState = State.TRACKING;
} else if (mState == State.READY) {
mClickView = getClickView((int) e.getX(), (int) e.getY());
Log.d(LOG_TAG, "View " + mClickView + " is clicked!");
clickItem = mClickView;
if (clickListener != null) {
int s = currentIndex + clickItem, size = BmpRecViews.size();
s %= size;
if (s < 0)
s += size;
clickListener.onClicked(s);
}
if (mClickView != -1) {
aniStopPos = selectImg - mClickView;
if (aniStopPos == 0)
return false;
if (aniStopPos > 0)
direction = 1;
else
direction = -1;
aniStartPos = 0;
aniTime = (long) Math.abs(500 * aniStopPos);
mState = State.ABOUT_TO_ANIMATE;
aniStartTime = new Date();
ScrollView.invalidate();
}
}
return false;
}
}
public void setSelected(int position) {
currentIndex = position - selectImg;
}
public void setSelectedWithAnimation(int position) {
int size = BmpRecViews.size();
currentIndex %= size;
if (currentIndex < 0)
currentIndex += size;
aniStopPos = position - selectImg - currentIndex;
if (aniStopPos == 0)
return;
if (aniStopPos > 0)
direction = 1;
else
direction = -1;
aniStartPos = 0;
aniTime = 1000;
mState = State.ABOUT_TO_ANIMATE;
aniStartTime = new Date();
ScrollView.invalidate();
}
private int getClickView(int x, int y) {
int cn = -1;
View v;
for (int i = 0; i < totalViewNum; i++) {
v = ViewHolder.get(i);
if (v == null)
continue;
int l = getLeft(v), r = getRight(v);
int t = getTop(v), b = getBottom(v);
if (l < x && x < r && t < y && y < b) {
cn = i;
}
}
return cn;
}
public int getNearClickView(int x, int y) {
int minLen = 10000, cn = -1;
View v;
for (int i = 0; i < totalViewNum; i++) {
v = ViewHolder.get(i);
if (v == null)
continue;
int vx = (getLeft(v) + getRight(v)) / 2;
int vy = (getTop(v) + getBottom(v)) / 2;
int len = (int) Math
.sqrt((x - vx) * (x - vx) + (y - vy) * (y - vy));
if (len < minLen) {
minLen = len;
cn = i;
}
}
return cn;
}
public boolean getAnimateData() {
long time = aniTime;
Date date = new Date();
long t = date.getTime() - aniStartTime.getTime();
if (t < 0 || t > time) {
mState = State.ANIMATE_END;
return false;
} else {
mState = State.ANIMATING;
double s = aniStopPos - aniStartPos;
double g = 2 * s / (time * time);
double mScroll = 0;
mScroll = g * time * t - g * t * t / 2;
scrollNum = (int) (mScroll + aniStartPos);
percent = Math.abs(mScroll + aniStartPos - 1.0 * scrollNum);
ScrollView.clear();
moveView();
return true;
}
}
public void handleAniEnd() {
int size = BmpRecViews.size();
currentIndex -= aniStopPos;
clickItem = -1;
for (int i = 0; i < totalViewNum; i++) {
int newIndex = i + currentIndex;
while (newIndex < 0) {
newIndex += size;
}
newIndex = newIndex % size;
ImageView myView = (ImageView) ViewHolder.get(i);
myView.setVisibility(View.VISIBLE);
myView.setImageBitmap(BmpRecViews.get(newIndex));
}
invalidate();
mState = State.READY;
if (selectListener != null) {
int s = currentIndex + selectImg;
s %= size;
if (s < 0)
s += size;
selectListener.onSelected(s);
}
}
public class SnakeView extends View {
private List<MyView> mListView;
public int test = 0;
public SnakeView(Context context) {
super(context);
mListView = new ArrayList<MyView>();
}
private class MyView {
Bitmap bitmap;
int left;
int top;
int width;
int height;
public MyView(Bitmap b, int l, int t, int w, int h) {
bitmap = b;
left = l;
top = t;
width = w;
height = h;
}
}
public void addView(Bitmap b, int left, int top, int width, int height) {
if (b != null) {
MyView v = new MyView(b, left, top, width, height);
mListView.add(v);
}
}
public void clear() {
mListView.clear();
}
protected void onDraw(Canvas canvas) {
Paint defaultPaint = new Paint();
defaultPaint.setAlpha(0);
defaultPaint.setAntiAlias(true);
int num = mListView.size();
if (num == 0)
canvas.drawRect(0, 0, mContentWidth, mContentHeight,
defaultPaint);
Log.d(LOG_TAG, "Num need to show : " + num);
if (selectImg >= 0 && selectImg < num) {
for (int i = 0; i <= selectImg; i++) {
canvas.save();
MyView v = mListView.get(i);
Matrix m = new Matrix();
int bw = v.bitmap.getWidth(), bh = v.bitmap.getHeight();
m.postScale((float) v.width / bw, (float) v.height / bh);
Bitmap dstbmp = Bitmap.createBitmap(v.bitmap, 0, 0, bw, bh,
m, true);
canvas.drawBitmap(dstbmp, v.left, v.top, null);
}
for (int i = num - 1; i > selectImg; i--) {
canvas.save();
MyView v = mListView.get(i);
Matrix m = new Matrix();
int bw = v.bitmap.getWidth(), bh = v.bitmap.getHeight();
m.postScale((float) v.width / bw, (float) v.height / bh);
Bitmap dstbmp = Bitmap.createBitmap(v.bitmap, 0, 0, bw, bh,
m, true);
canvas.drawBitmap(dstbmp, v.left, v.top, null);
}
}
if (mState == State.ABOUT_TO_ANIMATE || mState == State.ANIMATING) {
getAnimateData();
if (mState == State.ANIMATE_END) {
mListView.clear();
handleAniEnd();
}
this.invalidate();
}
}
}
}
package com.ql.app;
import android.app.Activity;
import android.os.Bundle;
public class SnakeLayoutActivity extends Activity {
/** Called when the activity is first created. */
SnakeLayout mSnake;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mSnake = (SnakeLayout)findViewById(R.id.snakeLayout);
mSnake.addRec(R.drawable.png1);
mSnake.addRec(R.drawable.png2);
mSnake.addRec(R.drawable.png3);
mSnake.addRec(R.drawable.png4);
mSnake.addRec(R.drawable.png5);
mSnake.addRec(R.drawable.png6);
mSnake.addRec(R.drawable.png7);
mSnake.addRec(R.drawable.png8);
mSnake.addRec(R.drawable.png9);
// mSnake.addRec(R.drawable.png10);
// mSnake.addRec(R.drawable.png11);
// mSnake.addRec(R.drawable.png12);
// mSnake.addRec(R.drawable.png13);
// mSnake.addRec(R.drawable.png14);
// mSnake.addRec(R.drawable.png15);
// mSnake.addRec(R.drawable.png16);
// mSnake.addRec(R.drawable.png17);
// mSnake.addRec(R.drawable.png18);
// mSnake.addRec(R.drawable.png19);
// mSnake.addRec(R.drawable.png20);
// mSnake.addRec(R.drawable.png21);
// mSnake.addRec(R.drawable.png22);
// mSnake.addRec(R.drawable.png23);
// mSnake.addRec(R.drawable.png24);
// mSnake.addRec(R.drawable.png25);
// mSnake.addRec(R.drawable.png26);
// mSnake.addRec(R.drawable.png27);
// mSnake.addRec(R.drawable.png28);
mSnake.Init();
}
}
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:snake="http://schemas.android.com/apk/res/com.ql.app" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <com.ql.app.SnakeLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/snakeLayout" android:layout_weight="1" snake:selectImg="8" > <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@id/snakeContent" android:orientation="vertical" > <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@id/snakeImg0" android:paddingLeft="0dip" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@id/snakeImg1" android:paddingLeft="25dip" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@id/snakeImg2" android:paddingLeft="50dip" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@id/snakeImg3" android:paddingLeft="75dip" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@id/snakeImg4" android:paddingLeft="100dip" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@id/snakeImg5" android:paddingLeft="125dip" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@id/snakeImg6" android:paddingLeft="150dip" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@id/snakeImg7" android:paddingLeft="175dip" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@id/snakeImg8" android:paddingLeft="200dip" /> </LinearLayout> </com.ql.app.SnakeLayout> </LinearLayout>
- TestSnakeLayout.rar (506.3 KB)
- 下载次数: 183