public class PuzzleLayout extends RelativeLayout {
public PuzzleLayout(Context context) {
super(context);
}
public PuzzleLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PuzzleLayout(Context context, AttributeSet attrs, int defStyleAttr) {
}
}
/** * Factory method to create a new ViewDragHelper. * * @param forParent Parent view to monitor * @param sensitivity Multiplier for how sensitive the helper * should be about detecting the start of a drag. * Larger values are more sensitive. 1.0f is normal. * @param cb Callback to provide information and receive events * @return a new ViewDragHelper instance */ public static ViewDragHelper create(ViewGroup forParent, float sensitivity, Callback cb)
public abstract boolean tryCaptureView(View child, int pointerId)
public int clampViewPositionHorizontal(View child, int left, int dx)
public int clampViewPositionVertical(View child, int top, int dy)
public void onViewReleased(View releasedChild, float xvel, float yvel)
public class PuzzleLayout extends RelativeLayout {
private ViewDragHelper viewDragHelper;
public PuzzleLayout(Context context) {
super(context);
init();
}
public PuzzleLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public PuzzleLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
mHeight = getHeight();
mWidth = getWidth();
getViewTreeObserver().removeOnPreDrawListener(this);
if(mDrawableId != 0 && mSquareRootNum != 0){
createChildren();
}
return false;
}
});
viewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(View child, int pointerId) {
return true;
}
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
return left;
}
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return top;
}
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
}
});
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event){
return viewDragHelper.shouldInterceptTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
viewDragHelper.processTouchEvent(event);
return true;
}
}
/**
* 将子View index与mHelper中models的index一一对应,
* 每次在交换子View位置的时候model同步更新currentPosition。
*/
private void createChildren(){
mHelper.setSquareRootNum(mSquareRootNum);
DisplayMetrics dm = getResources().getDisplayMetrics();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inDensity = dm.densityDpi;
Bitmap resource = BitmapFactory.decodeResource(getResources(), mDrawableId, options);
Bitmap bitmap = BitmapUtil.zoomImg(resource, mWidth, mHeight);
resource.recycle();
mItemWidth = mWidth / mSquareRootNum;
mItemHeight = mHeight / mSquareRootNum;
for (int i = 0; i < mSquareRootNum; i++){
for (int j = 0; j < mSquareRootNum; j++){
Log.d(TAG, "mItemWidth * x " + (mItemWidth * i));
Log.d(TAG, "mItemWidth * y " + (mItemWidth * j));
ImageView iv = new ImageView(getContext());
iv.setScaleType(ImageView.ScaleType.FIT_XY);
LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lp.leftMargin = j * mItemWidth;
lp.topMargin = i * mItemHeight;
iv.setLayoutParams(lp);
Bitmap b = Bitmap.createBitmap(bitmap, lp.leftMargin, lp.topMargin, mItemWidth, mItemHeight);
iv.setImageBitmap(b);
addView(iv);
}
}
}
public class Block {
public Block(int position, int vPosition, int hPosition){
this.position = position;
this.vPosition = vPosition;
this.hPosition = hPosition;
}
public int position;
public int vPosition;
public int hPosition;
}
class DataHelper {
static final int N = -1;
static final int L = 0;
static final int T = 1;
static final int R = 2;
static final int B = 3;
private static final String TAG = DataHelper.class.getSimpleName();
private int squareRootNum;
private List<Block> models;
DataHelper(){
models = new ArrayList<>();
}
private void reset() {
models.clear();
int position = 0;
for (int i = 0; i< squareRootNum; i++){
for (int j = 0; j < squareRootNum; j++){
models.add(new Block(position, i, j));
position ++;
}
}
}
void setSquareRootNum(int squareRootNum){
this.squareRootNum = squareRootNum;
reset();
}
}
public boolean tryCaptureView(View child, int pointerId) {
int index = indexOfChild(child);
return mHelper.getScrollDirection(index) != DataHelper.N;
}
/**
* 获取索引处model的可移动方向,不能移动返回 -1。
*/
int getScrollDirection(int index){
Block model = models.get(index);
int position = model.position;
//获取当前view所在位置的坐标 x y
/*
* * * * *
* * o * *
* * * * *
* * * * *
*/
int x = position % squareRootNum;
int y = position / squareRootNum;
int invisibleModelPosition = models.get(0).position;
/*
* 判断当前位置是否可以移动,如果可以移动就return可移动的方向。
*/
if(x != 0 && invisibleModelPosition == position - 1)
return L;
if(x != squareRootNum - 1 && invisibleModelPosition == position + 1)
return R;
if(y != 0 && invisibleModelPosition == position - squareRootNum)
return T;
if(y != squareRootNum - 1 && invisibleModelPosition == position + squareRootNum)
return B;
return N;
}
public int clampViewPositionHorizontal(View child, int left, int dx) {
int index = indexOfChild(child);
int position = mHelper.getModel(index).position;
int selfLeft = (position % mSquareRootNum) * mItemWidth;
int leftEdge = selfLeft - mItemWidth;
int rightEdge = selfLeft + mItemWidth;
int direction = mHelper.getScrollDirection(index);
//Log.d(TAG, "left " + left + " index" + index + " dx " + dx + " direction " + direction);
switch (direction){
case DataHelper.L:
if(left <= leftEdge)
return leftEdge;
else if(left >= selfLeft)
return selfLeft;
else
return left;
case DataHelper.R:
if(left >= rightEdge)
return rightEdge;
else if (left <= selfLeft)
return selfLeft;
else
return left;
default:
return selfLeft;
}
}
public int clampViewPositionVertical(View child, int top, int dy) {
int index = indexOfChild(child);
Block model = mHelper.getModel(index);
int position = model.position;
int selfTop = (position / mSquareRootNum) * mItemHeight;
int topEdge = selfTop - mItemHeight;
int bottomEdge = selfTop + mItemHeight;
int direction = mHelper.getScrollDirection(index);
//Log.d(TAG, "top " + top + " index " + index + " direction " + direction);
switch (direction){
case DataHelper.T:
if(top <= topEdge)
return topEdge;
else if (top >= selfTop)
return selfTop;
else
return top;
case DataHelper.B:
if(top >= bottomEdge)
return bottomEdge;
else if (top <= selfTop)
return selfTop;
else
return top;
default:
return selfTop;
}
}
public void onViewReleased(View releasedChild, float xvel, float yvel) {
Log.d(TAG, "xvel " + xvel + " yvel " + yvel);
int index = indexOfChild(releasedChild);
boolean isCompleted = mHelper.swapValueWithInvisibleModel(index);
Block item = mHelper.getModel(index);
viewDragHelper.settleCapturedViewAt(item.hPosition * mItemWidth, item.vPosition * mItemHeight);
View invisibleView = getChildAt(0);
ViewGroup.LayoutParams layoutParams = invisibleView.getLayoutParams();
invisibleView.setLayoutParams(releasedChild.getLayoutParams());
releasedChild.setLayoutParams(layoutParams);
invalidate();
if(isCompleted){
invisibleView.setVisibility(VISIBLE);
mOnCompleteCallback.onComplete();
}
}
@Override
public void computeScroll() {
if(viewDragHelper.continueSettling(true)) {
invalidate();
}
}
/**
* 将索引出的model的值与不可见
* model的值互换。
*/
boolean swapValueWithInvisibleModel(int index){
Block formModel = models.get(index);
Block invisibleModel = models.get(0);
swapValue(formModel, invisibleModel);
return isCompleted();
}
/**
* 交换两个model的值
*/
private void swapValue(Block formModel, Block invisibleModel) {
int position = formModel.position;
int hPosition = formModel.hPosition;
int vPosition = formModel.vPosition;
formModel.position = invisibleModel.position;
formModel.hPosition = invisibleModel.hPosition;
formModel.vPosition = invisibleModel.vPosition;
invisibleModel.position = position;
invisibleModel.hPosition = hPosition;
invisibleModel.vPosition = vPosition;
}
/**
* 判断是否拼图完成。
*/
private boolean isCompleted(){
int num = squareRootNum * squareRootNum;
for (int i = 0; i < num; i++){
Block model = models.get(i);
if(model.position != i){
return false;
}
}
return true;
}
public void randomOrder(){
int num = mSquareRootNum * mSquareRootNum * 8;
View invisibleView = getChildAt(0);
View neighbor;
for (int i = 0; i < num; i ++){
int neighborPosition = mHelper.findNeighborIndexOfInvisibleModel();
ViewGroup.LayoutParams invisibleLp = invisibleView.getLayoutParams();
neighbor = getChildAt(neighborPosition);
invisibleView.setLayoutParams(neighbor.getLayoutParams());
neighbor.setLayoutParams(invisibleLp);
mHelper.swapValueWithInvisibleModel(neighborPosition);
}
invisibleView.setVisibility(INVISIBLE);
}
/**
* 随机查询出不可见
* 位置周围的一个model的索引。
*/
public int findNeighborIndexOfInvisibleModel() {
Block invisibleModel = models.get(0);
int position = invisibleModel.position;
int x = position % squareRootNum;
int y = position / squareRootNum;
int direction = new Random(System.nanoTime()).nextInt(4);
Log.d(TAG, "direction " + direction);
switch (direction){
case L:
if(x != 0)
return getIndexByCurrentPosition(position - 1);
case T:
if(y != 0)
return getIndexByCurrentPosition(position - squareRootNum);
case R:
if(x != squareRootNum - 1)
return getIndexByCurrentPosition(position + 1);
case B:
if(y != squareRootNum - 1)
return getIndexByCurrentPosition(position + squareRootNum);
}
return findNeighborIndexOfInvisibleModel();
}
/**
* 通过给定的位置获取model的索引
*/
private int getIndexByCurrentPosition(int currentPosition){
int num = squareRootNum * squareRootNum;
for (int i = 0; i < num; i++) {
if(models.get(i).position == currentPosition)
return i;
}
return -1;
}
机械节能产品生产企业官网模板...
大气智能家居家具装修装饰类企业通用网站模板...
礼品公司网站模板
宽屏简约大气婚纱摄影影楼模板...
蓝白WAP手机综合医院类整站源码(独立后台)...苏ICP备2024110244号-2 苏公网安备32050702011978号 增值电信业务经营许可证编号:苏B2-20251499 | Copyright 2018 - 2025 源码网商城 (www.ymwmall.com) 版权所有