Android平台上可以左右滑动的控件,总共3个文件,其中一个用于是Activity,详细内容请从附件下载:
图片素材:
本来是PNG的,上传后成了gif。
界面:
包括三个类:
1. SlipView用于显示
package com.diydyq.android.swipeTest;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
/**
* Slip the front part to some dock position
*
* @author diydyq
*
*/
public class SlipView extends View
{
private static final String TAG = "SlipView";
/** Listen slip on the block, no matter the event is success or fail */
private OnSlipListener onSlipListener;
/** Slip entity to set the value about backImage, frontImage position */
private SlipEntity slipEntity;
private float tmpTouchX;
private float tmpTouchGap;
public SlipView(Context context)
{
super(context);
Bitmap backImage = ((BitmapDrawable) getResources().getDrawable(R.drawable.back5)).getBitmap();
Bitmap frotImage = ((BitmapDrawable) getResources().getDrawable(R.drawable.frot1)).getBitmap();
this.slipEntity = new SlipEntity(backImage, frotImage);
}
public SlipView(Context context, AttributeSet attr)
{
super(context, attr);
Bitmap backImage = ((BitmapDrawable) getResources().getDrawable(R.drawable.back5)).getBitmap();
Bitmap frotImage = ((BitmapDrawable) getResources().getDrawable(R.drawable.frot1)).getBitmap();
this.slipEntity = new SlipEntity(backImage, frotImage);
}
public SlipView(Context context, SlipEntity slipEntity)
{
super(context);
this.slipEntity = slipEntity;
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
if (!this.slipEntity.isInit)
{
Log.v(TAG, "Init SlipEntity");
this.slipEntity.initSlipEntity(this.getWidth(), this.getHeight());
}
canvas.drawBitmap(this.slipEntity.getBackImage(), this.slipEntity.xBackStart, this.slipEntity.yBackStart, null);
canvas.drawBitmap(this.slipEntity.getFrotImage(), this.slipEntity.xFrotStart, this.slipEntity.yFrotStart, null);
}
/**
* listen touch events and notify listener
*/
@Override
public boolean onTouchEvent(MotionEvent event)
{
Log.v(TAG, "Touch Position:" + event.getX());
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
// Log.v(TAG, "Down");
if (this.slipEntity.isPointInImage(SlipEntity.FLAG_FROT, event.getX(), event.getY()))
{
this.tmpTouchX = event.getX();
this.tmpTouchGap = event.getX() - this.slipEntity.xFrotStart;
}
break;
case MotionEvent.ACTION_MOVE:
// Log.v(TAG, "Move");
this.slipEntity.isReachRight();
this.slipEntity.isReachLeft();
// if point(x,y) is not in back image, front image will not move
if (this.slipEntity.isPointInImage(SlipEntity.FLAG_BACK, event.getX(), event.getY()))
{
// Log.v(TAG, "Move2");
this.slipEntity.xFrotStart = event.getX() - this.tmpTouchGap;
}
break;
case MotionEvent.ACTION_UP:
Log.v(TAG, "Up");
int flagLR = 0;
if(event.getX() < this.tmpTouchX)
flagLR = 1;
else
flagLR = 2;
float dockPer = this.slipEntity.isDock();
if (dockPer != -1)
{
// Dock at some Position
if (this.onSlipListener != null)
this.onSlipListener.slipDock(slipEntity, event, this.slipEntity.getCurDockPer());
if (event.getX() < this.tmpTouchX)
{
// Slip: <==
if (dockPer == 0.0)
{
// Reached
if (this.onSlipListener != null)
this.onSlipListener.slipLeft(slipEntity, event, true);
}
else
{
// Not Reached
this.slipEntity.xFrotStart = this.slipEntity.getCurDockPos();
if (this.onSlipListener != null)
this.onSlipListener.slipLeft(slipEntity, event, false);
}
}
else
{
// Slip: ==>
if (dockPer == 1.0)
{
// Reached
if (this.onSlipListener != null)
this.onSlipListener.slipRight(slipEntity, event, true);
}
else
{
// Not Reached
this.slipEntity.xFrotStart = this.slipEntity.getCurDockPos();
if (this.onSlipListener != null)
this.onSlipListener.slipRight(slipEntity, event, false);
}
break;
}
}
else
{
// No dock
this.slipEntity.xFrotStart = this.slipEntity.getCurDockPos();
if(flagLR == 1)
this.onSlipListener.slipLeft(slipEntity, event, false);
else
this.onSlipListener.slipRight(slipEntity, event, false);
}
// if (event.getX() < this.tmpTouchX)
// {
//// Slip: <==
// if (this.slipEntity.isReachLeft())
// {
//// Reached
// if (this.onSlipListener != null)
// this.onSlipListener.slipLeft(slipEntity, event, true);
// }
// else
// {
//// Not Reached
// this.slipEntity.xFrotStart = this.slipEntity.getCurDockPos();
// if (this.onSlipListener != null)
// this.onSlipListener.slipLeft(slipEntity, event, false);
// }
// }
// else
// {
//// Slip: ==>
// if (this.slipEntity.isReachRight())
// {
//// Reached
// if (this.onSlipListener != null)
// this.onSlipListener.slipRight(slipEntity, event, true);
// }
// else
// {
//// Not Reached
// this.slipEntity.xFrotStart = this.slipEntity.getCurDockPos();
// if (this.onSlipListener != null)
// this.onSlipListener.slipRight(slipEntity, event, false);
// }
// break;
// }
}
this.invalidate();
return true;
}
/**
* Listener on slip event on slippery view author diydyq
*
*/
public interface OnSlipListener
{
/**
* Listen a slip after touch down and up, not including touch move
*
* @param slipEntity
* @param event
* @param isSuccess
*/
public abstract void slipLeft(SlipEntity slipEntity, MotionEvent event, boolean isSuccess);
/**
* Listen a slip after touch down and up, not including touch move
*
* @param slipEntity
* @param event
* @param isSuccess
*/
public abstract void slipRight(SlipEntity slipEntity, MotionEvent event, boolean isSuccess);
/**
* Listen some dock(more than DOCK_L,DOCK_R), normally need not implement it unless more docks are needed.
*
* @param slipEntity
* @param event
* @param dockPer
*/
public abstract void slipDock(SlipEntity slipEntity, MotionEvent event, float dockPer);
}
public OnSlipListener getOnSlipListener()
{
return onSlipListener;
}
public void setOnSlipListener(OnSlipListener onSlipListener)
{
this.onSlipListener = onSlipListener;
}
}
2. SlipEntity用于调整前景、背景图片位置等的操作。
package com.diydyq.android.swipeTest;
import java.util.HashMap;
import java.util.Map;
import android.graphics.Bitmap;
import android.util.Log;
/**
* Slip entity used to set position and maybe boundary of back and front image
*
* @author diydyq
*
*/
public class SlipEntity
{
public static final int FLAG_BACK = 1;
public static final int FLAG_FROT = 2;
public static final float DOCK_L = 0;
public static final float DOCK_M = (float)0.5;
public static final float DOCK_R = 1;
public static final float MICRO_X = 10;
/** Background image */
Bitmap backImage;
/** Front image */
Bitmap frotImage;
/** Start Position of back image */
float xBackStart;
/** Start Position of back image */
float yBackStart;
/** Start Position of front image */
float xFrotStart;
/** Start Position of front image */
float yFrotStart;
/** initial Position of front image */
float xFrotInitPos;
/** initial Position of front image */
float yFrotInitPos;
/** Margin of front and back image in X-Axis */
float xMarginLeft;
/** Margin of front and back image in Y-Axis */
float yMarginTop;
/** Containing dock position of the front image */
Map<Float, Float> dockPosList = new HashMap<Float, Float>();
/** Current dock Percentage: DOCK_L | DOCK_M | DOCK_R */
float curDockPer = DOCK_L;
/** Weather has invoked initSlipEntity() */
boolean isInit = false;
public SlipEntity()
{
}
public SlipEntity(Bitmap backImage, Bitmap frotImage)
{
this.backImage = backImage;
this.frotImage = frotImage;
}
public SlipEntity(float xBackStart, float yBackStart, float xFrotStart, float yFrotStart)
{
this.xBackStart = xBackStart;
this.yBackStart = yBackStart;
this.xFrotStart = xFrotStart;
this.yFrotStart = yFrotStart;
}
public void initSlipEntity(float viewWidth, float viewHeight)
{
this.xBackStart = (viewWidth - this.backImage.getWidth()) / 2;
this.yBackStart = (viewHeight - this.backImage.getHeight()) / 2;
this.xMarginLeft = 5;
this.yMarginTop = (this.backImage.getHeight() - this.frotImage.getHeight()) / 2;
this.xFrotInitPos = this.xBackStart + this.xMarginLeft;
this.yFrotInitPos = this.yBackStart + this.yMarginTop;
this.xFrotStart = this.xFrotInitPos;
this.yFrotStart = this.yFrotInitPos;
// Add dock position
float dockL = this.xFrotInitPos;
float dockR = this.xBackStart + this.backImage.getWidth() - this.frotImage.getWidth() - this.xMarginLeft;
this.dockPosList.put(DOCK_L, dockL);
this.dockPosList.put(DOCK_R, dockR);
for(Float dockPer : this.dockPosList.keySet())
{
if(this.dockPosList.get(dockPer) == 0)
{
float docPos = (dockR - dockL) * dockPer + this.dockPosList.get(DOCK_L);
this.dockPosList.put(dockPer, docPos);
}
}
// Dock at current position
this.xFrotStart = this.dockPosList.get(this.curDockPer);
this.isInit = true;
// For debug information
StringBuilder sb = new StringBuilder();
sb.append("BackImageW:" + this.backImage.getWidth() + "\n");
sb.append("BackImageH:" + this.backImage.getHeight() + "\n");
sb.append("FrotImageW:" + this.frotImage.getWidth() + "\n");
sb.append("FrotImageH:" + this.frotImage.getHeight() + "\n");
sb.append("xBackStart:" + xBackStart + "\n");
sb.append("yBackStart:" + yBackStart + "\n");
sb.append("xMarginLeft:"+ xMarginLeft + "\n");
sb.append("yMarginTop:" + yMarginTop + "\n");
sb.append("xFrotInitP:" + xFrotInitPos + "\n");
sb.append("yFrotInitP:" + yFrotInitPos + "\n");
sb.append("xFrotStart:" + xFrotStart + "\n");
sb.append("yFrotStart:" + yFrotStart + "\n");
Log.v("SlipEntity", sb.toString());
}
/**
* Weather the front image reaches the max right of background image, if true, set xFrotStart to max right.
* @return
*/
public boolean isReachRight()
{
if(this.xFrotStart > this.dockPosList.get(DOCK_R))
{
this.curDockPer = DOCK_R;
this.xFrotStart = this.dockPosList.get(DOCK_R);
return true;
}
else
{
return false;
}
}
/**
* Weather the front image reaches the max left of background image, if true, set xFrotStart to max left.
* @return
*/
public boolean isReachLeft()
{
if(this.xFrotStart < this.dockPosList.get(DOCK_L))
{
this.curDockPer = DOCK_L;
this.xFrotStart = this.dockPosList.get(DOCK_L);
return true;
}
else
{
return false;
}
}
/**
* Weather the point(x,y) is in the area of back or front image
* @param type FLAG_FROT(front image) | FLAG_BACK(back image)
* @param x X-coordinate of point
* @param y Y-coordinate of point
* @return weather the point is in specified area
*/
public boolean isPointInImage(int type, float x, float y)
{
float rPointX;
float rPointY;
switch(type)
{
case FLAG_FROT:
rPointX = this.xFrotStart + this.frotImage.getWidth();
rPointY = this.yFrotStart + this.frotImage.getHeight();
if (x > this.xFrotStart && y > this.yFrotStart && x < rPointX && y < rPointY)
return true;
else
return false;
case FLAG_BACK:
rPointX = this.xBackStart + this.backImage.getWidth();
rPointY = this.yBackStart + this.backImage.getHeight();
if (x > this.xBackStart && y > this.yBackStart && x < rPointX && y < rPointY)
return true;
else
return false;
default:
return false;
}
}
/**
* Is the current touch in some dock position
* @return return dockPer if in, or -1 while no match
*/
public float isDock()
{
for(float dockPer : this.dockPosList.keySet())
{
float dockPos = this.dockPosList.get(dockPer);
if(this.xFrotStart > dockPos - MICRO_X && this.xFrotStart < dockPos + MICRO_X)
{
this.curDockPer = dockPer;
return dockPer;
}
}
return -1;
}
/**
* Get the current dock percentage in x-axis
* @return
*/
public float getCurDockPer()
{
return this.curDockPer;
}
/**
* Get the current dock position in x-axis
* @return
*/
public float getCurDockPos()
{
return this.dockPosList.get(this.curDockPer);
}
/**
* Add dock position to the list
* @param dockPer dock Percent should be between (0.0,1.0)
*/
public void addDockPos(float dockPer)
{
if(dockPer > 0 && dockPer < 1)
{
this.dockPosList.put(dockPer, (float)0.0);
}
}
/**
* Return width of background image
* @return
*/
public float getBackWidth()
{
return this.backImage.getWidth();
}
/**
* Return height of background image
* @return
*/
public float getBackHeight()
{
return this.backImage.getHeight();
}
/**
* Return width of front image
* @return
*/
public float getFrotWidth()
{
return this.frotImage.getWidth();
}
/**
* Return height of front image
* @return
*/
public float getFrotHeight()
{
return this.frotImage.getWidth();
}
/**
* Dock at some position
* @param curDockPer
*/
public void setCurDockPos(float curDockPer)
{
this.curDockPer = curDockPer;
}
public Bitmap getBackImage()
{
return backImage;
}
public void setBackImage(Bitmap backImage)
{
this.backImage = backImage;
}
public Bitmap getFrotImage()
{
return frotImage;
}
public void setFrotImage(Bitmap frotImage)
{
this.frotImage = frotImage;
}
public float getxBackStart()
{
return xBackStart;
}
public void setxBackStart(float xBackStart)
{
this.xBackStart = xBackStart;
}
public float getyBackStart()
{
return yBackStart;
}
public void setyBackStart(float yBackStart)
{
this.yBackStart = yBackStart;
}
public float getxFrotStart()
{
return xFrotStart;
}
public void setxFrotStart(float xFrotStart)
{
this.xFrotStart = xFrotStart;
}
public float getyFrotStart()
{
return yFrotStart;
}
public void setyFrotStart(float yFrotStart)
{
this.yFrotStart = yFrotStart;
}
public float getxFrotInitPos()
{
return xFrotInitPos;
}
public void setxFrotInitPos(float xFrotInitPos)
{
this.xFrotInitPos = xFrotInitPos;
}
public float getyFrotInitPos()
{
return yFrotInitPos;
}
public void setyFrotInitPos(float yFrotInitPos)
{
this.yFrotInitPos = yFrotInitPos;
}
public float getxMarginLeft()
{
return xMarginLeft;
}
public void setxMarginLeft(float xMarginLeft)
{
this.xMarginLeft = xMarginLeft;
}
public float getyMarginTop()
{
return yMarginTop;
}
public void setyMarginTop(float yMarginTop)
{
this.yMarginTop = yMarginTop;
}
public Map<Float, Float> getDockPosList()
{
return dockPosList;
}
public void setDockPosList(Map<Float, Float> dockPosList)
{
this.dockPosList = dockPosList;
}
public boolean isInit()
{
return isInit;
}
public void setInit(boolean isInit)
{
this.isInit = isInit;
}
}
3. Activity显示方式
public class SwipeTestActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
SlipView view;
// 1.Code
Bitmap backImage = ((BitmapDrawable) getResources().getDrawable(R.drawable.back5)).getBitmap();
Bitmap frotImage = ((BitmapDrawable) getResources().getDrawable(R.drawable.frot1)).getBitmap();
SlipEntity entity = new SlipEntity(backImage, frotImage);
entity.setCurDockPos(SlipEntity.DOCK_R);
entity.addDockPos((float)0.5);
view = new SlipView(this, entity);
// 2.Code
// view = new SlipView(this);
// 3.XML
// view = (SlipView)this.findViewById(R.id.slipView);
setContentView(view);
view.setOnSlipListener(new OnSlipListener()
{
@Override
public void slipLeft(SlipEntity slipEntity, MotionEvent event, boolean isSuccess)
{
Log.v("Left", Boolean.toString(isSuccess));
}
@Override
public void slipRight(SlipEntity slipEntity, MotionEvent event, boolean isSuccess)
{
Log.v("Right", Boolean.toString(isSuccess));
}
@Override
public void slipDock(SlipEntity slipEntity, MotionEvent event, float dockPer)
{
Log.v("Dock", "dockPer:" + dockPer);
}
});
}
}