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



 转自:http://2660311.blog.51cto.com/2650311/600521