求助:这样的Layout如何实现缩放 本帖最后由 zyongsheng83 于 2011-03-07 15:19:31 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 整个表格的实现 FixedGrid.java:package com.yfmandroid.widget;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.view.animation.Animation;import android.view.animation.LayoutAnimationController;import android.view.animation.ScaleAnimation;import android.widget.HorizontalScrollView;import android.widget.LinearLayout;import android.widget.ScrollView;public abstract class FixedGrid extends LinearLayout { private static final String LOG_TAG = "FixedGrid"; protected Context mContext; private LinearLayout mGridHeaderLayout; private LinearLayout mColumnHeaderLayout; private LinearLayout mRowHeaderLayout; private LinearLayout mContentLayout; private LinearLayout mUpLayout; private LinearLayout mDownLayout; private HorizontalScrollView mColumnHeaderScroll; private ScrollView mRowHeaderScroll; private CustomScrollView mContentScroll; private FixedGridMultiPointTouchListener mOnTouchListener; private boolean mScalable; public FixedGrid(Context context) { this(context, false); } public FixedGrid(Context context, boolean scalable) { super(context); mContext = context; mScalable = scalable; initGrid(); mOnTouchListener = new FixedGridMultiPointTouchListener(); setOnTouchListener(mOnTouchListener); mContentScroll.setOnTouchListener(mOnTouchListener); } private void initGrid() { setOrientation(VERTICAL); setBackgroundColor(Color.BLACK); mUpLayout = new LinearLayout(mContext); mUpLayout.setBackgroundColor(Color.BLACK); mUpLayout.setLayoutParams(new LinearLayout.LayoutParams( LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); addView(mUpLayout); mDownLayout = new LinearLayout(mContext); mDownLayout.setBackgroundColor(Color.BLACK); mDownLayout.setLayoutParams(new LinearLayout.LayoutParams( LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT)); addView(mDownLayout); addGridHeader(); addColumnHeader(); addRowHeader(); addContent(); } private void addGridHeader() { LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); layoutParams.setMargins(1, 1, 1, 1); mGridHeaderLayout = genGridHeader(); mGridHeaderLayout.setLayoutParams(layoutParams); mUpLayout.addView(mGridHeaderLayout); } private void addColumnHeader() { LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); layoutParams.setMargins(1, 1, 1, 1); mColumnHeaderScroll = new HorizontalScrollView(mContext) { public boolean onTouchEvent(MotionEvent ev) { return false; }; }; mColumnHeaderScroll.setLayoutParams(layoutParams); mColumnHeaderScroll.setHorizontalScrollBarEnabled(false); mColumnHeaderScroll.setHorizontalFadingEdgeEnabled(false); mColumnHeaderLayout = genColumnHeader(); mColumnHeaderScroll.addView(mColumnHeaderLayout); mUpLayout.addView(mColumnHeaderScroll); } private void addRowHeader() { LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.FILL_PARENT); layoutParams.setMargins(1, 1, 1, 1); mRowHeaderScroll = new ScrollView(mContext) { public boolean onTouchEvent(MotionEvent ev) { return false; }; }; mRowHeaderScroll.setLayoutParams(layoutParams); mRowHeaderScroll.setVerticalScrollBarEnabled(false); mRowHeaderScroll.setVerticalFadingEdgeEnabled(false); mRowHeaderLayout = genRowHeader(); mRowHeaderScroll.addView(mRowHeaderLayout); mDownLayout.addView(mRowHeaderScroll); } private void addContent() { LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT); layoutParams.setMargins(1, 1, 1, 1); mContentScroll = new CustomScrollView(mContext) { public void scrollTo(int x, int y) { super.scrollTo(x, y); mRowHeaderScroll.scrollTo(0, y); mColumnHeaderScroll.scrollTo(x, 0); }; public void fling(int velocityX, int velocityY) { super.fling(velocityX, velocityY); mRowHeaderScroll.fling(velocityY); mColumnHeaderScroll.fling(velocityX); }; }; mContentScroll.setFlingEnabled(false); mContentScroll.setLayoutParams(layoutParams); mContentLayout = genContent(); mContentScroll.addView(mContentLayout); mDownLayout.addView(mContentScroll); } protected abstract LinearLayout genGridHeader(); protected abstract LinearLayout genColumnHeader(); protected abstract LinearLayout genRowHeader(); protected abstract LinearLayout genContent(); @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Log.e(LOG_TAG, "rowwidth: " + mRowHeaderScroll.getWidth()); } private class FixedGridMultiPointTouchListener extends MultiPointTouchListener{ @Override public boolean onTouch(View v, MotionEvent event) { if(!super.onTouch(v, event)){ return mContentScroll.onTouchEvent(event); } return true; } @Override protected boolean onScale(float oldScale, float lastScale, float newScale, final float clearScale, float midX, float midY){ if(!mScalable){ return false; } Log.e(LOG_TAG, "onScale: " + oldScale + ", " + lastScale + ", " + newScale + ", " + clearScale + ", " + midX + ", " + midY); ScaleAnimation animation = new ScaleAnimation(lastScale, newScale, lastScale, newScale); //Log.e(LOG_TAG, animation + " ==== scaling: " + lastScale + "==>" + newScale); animation.setAnimationListener(new ScaleAnimation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) {// printSize(FixedGrid.this, "gird");// printSize(mRowHeaderScroll, "rows");// printSize(mRowHeaderLayout, "rowl");// FixedGrid.this.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT, FrameLayout.LayoutParams.FILL_PARENT)); } private void printSize(View v, String tag){ Log.e(LOG_TAG, tag + ": " + v.getWidth() + ", " + v.getHeight()); } }); animation.setFillAfter(true); animation.setDuration(1);// startAnimation(animation); LayoutAnimationController controller = new LayoutAnimationController(animation);// if(newScale < 1){// //setLayoutParams(new LinearLayout.LayoutParams((int)(800 / newScale), (int)(535 / newScale)));// }else{// //setLayoutParams(new LinearLayout.LayoutParams(800, (int)(535 / newScale)));// } setLayoutAnimation(controller); animation.reset(); clearAnimation(); invalidate(); return true; } }} 事件监听 MultiPointTouchListener.java:package com.yfmandroid.widget;import android.graphics.PointF;import android.util.FloatMath;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.view.View.OnTouchListener;public class MultiPointTouchListener implements OnTouchListener { private static final String LOG_TAG = "MultiPointTouchListener"; private static final int NONE = 0; private static final int DRAG = 1; private static final int ZOOM = 2; private int mode = NONE; private PointF start = new PointF(); private PointF mid = new PointF(); private float oldDist = 1f; private float mLastDist; private float mOldScale = 1; private float mLastScale; @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: start.set(event.getX(), event.getY()); mode = DRAG; break; case MotionEvent.ACTION_POINTER_DOWN: oldDist = spacing(event); mLastDist = oldDist; if (oldDist > 10f) { midPoint(mid, event); mode = ZOOM; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: if (mode == ZOOM) { mOldScale = mLastScale; } mode = NONE; break; case MotionEvent.ACTION_MOVE: if (mode == DRAG) { return onMove(event.getX() - start.x, event.getY() - start.y); } else if (mode == ZOOM) {// Log.e(LOG_TAG, "zooming"); float lastDist = spacing(event);// Log.e(LOG_TAG, "oldDist: " + oldDist);// Log.e(LOG_TAG, "lastDist: " + lastDist); if (lastDist > 10f) { float lastScale = mLastScale; mLastScale = lastDist / oldDist * mOldScale;// Log.e(LOG_TAG, "lastScale: " + lastScale);// Log.e(LOG_TAG, "mLastScale: " + mLastScale); float clearScale = lastDist / mLastDist; mLastDist = lastDist;// Log.e(LOG_TAG, "scalexxx: " + (mLastScale - lastScale)); if(Math.abs(mLastScale - lastScale) > 0.001){ return onScale(mOldScale, lastScale, mLastScale, clearScale, mid.x, mid.y); } return true; } } break; } return false; } protected boolean onMove(float x, float y){ return false; } protected boolean onScale(float oldScale, float lastScale, float newScale, float clearScale, float midX, float midY){ return false; } protected void dumpEvent(MotionEvent event) { String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE", "POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?" }; StringBuilder sb = new StringBuilder(); int action = event.getAction(); int actionCode = action & MotionEvent.ACTION_MASK; sb.append("event ACTION_").append(names[actionCode]); if (actionCode == MotionEvent.ACTION_POINTER_DOWN || actionCode == MotionEvent.ACTION_POINTER_UP) { sb.append("(pid ").append( action >> MotionEvent.ACTION_POINTER_ID_SHIFT); sb.append(")"); } sb.append("["); for (int i = 0; i < event.getPointerCount(); i++) { sb.append("#").append(i); sb.append("(pid ").append(event.getPointerId(i)); sb.append(")=").append((int) event.getX(i)); sb.append(",").append((int) event.getY(i)); if (i + 1 < event.getPointerCount()) sb.append(";"); } sb.append("]"); Log.e(LOG_TAG, sb.toString()); } /** Determine the space between the first two fingers */ private float spacing(MotionEvent event) { float x = event.getX(0) - event.getX(1); float y = event.getY(0) - event.getY(1); return FloatMath.sqrt(x * x + y * y); } /** Calculate the mid point of the first two fingers */ private void midPoint(PointF point, MotionEvent event) { float x = event.getX(0) + event.getX(1); float y = event.getY(0) + event.getY(1); point.set(x / 2, y / 2); }} 我认为用Layout去 实现缩放 难以成功,,只有自定义View 重新绘画 可以,, 所有的Excel表格都是画出来的矩形,,而且容易缩放 自定义View重新绘画是什么意思?我是新手,能举个很简单很简单的例子吗? 这个用surfaceView吧。需要缩放时直接重画屏幕好了。 android播放器,点击暂停,再点暂停按钮可以继续播放,要是点播放按钮从头播放了 Android CTS4.0.3测试时到这个测试项时老是超时怎么办啊? 关于Android应用的Layout布局 Android应用中调用系统相应用汇总 关于Socket连接问题 谁能讲一下~android源码? 运行系统sample出错 iphone 的app store网址是多少啊? android图文效果 手机休眠后感应器不工作问题 需求:在自己的程序中调用联系人列表,然后选择某个联系人,返回该联系人的Uri USB调试模式_eclipse_logCat看不到日志信息
package com.yfmandroid.widget;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.LayoutAnimationController;
import android.view.animation.ScaleAnimation;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.ScrollView;public abstract class FixedGrid extends LinearLayout {
private static final String LOG_TAG = "FixedGrid";
protected Context mContext;
private LinearLayout mGridHeaderLayout;
private LinearLayout mColumnHeaderLayout;
private LinearLayout mRowHeaderLayout;
private LinearLayout mContentLayout; private LinearLayout mUpLayout; private LinearLayout mDownLayout; private HorizontalScrollView mColumnHeaderScroll; private ScrollView mRowHeaderScroll; private CustomScrollView mContentScroll;
private FixedGridMultiPointTouchListener mOnTouchListener;
private boolean mScalable;
public FixedGrid(Context context) {
this(context, false);
} public FixedGrid(Context context, boolean scalable) {
super(context);
mContext = context;
mScalable = scalable;
initGrid();
mOnTouchListener = new FixedGridMultiPointTouchListener();
setOnTouchListener(mOnTouchListener);
mContentScroll.setOnTouchListener(mOnTouchListener);
} private void initGrid() {
setOrientation(VERTICAL);
setBackgroundColor(Color.BLACK); mUpLayout = new LinearLayout(mContext);
mUpLayout.setBackgroundColor(Color.BLACK);
mUpLayout.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
addView(mUpLayout); mDownLayout = new LinearLayout(mContext);
mDownLayout.setBackgroundColor(Color.BLACK);
mDownLayout.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT));
addView(mDownLayout); addGridHeader();
addColumnHeader();
addRowHeader();
addContent();
} private void addGridHeader() {
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(1, 1, 1, 1);
mGridHeaderLayout = genGridHeader();
mGridHeaderLayout.setLayoutParams(layoutParams);
mUpLayout.addView(mGridHeaderLayout);
} private void addColumnHeader() {
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(1, 1, 1, 1);
mColumnHeaderScroll = new HorizontalScrollView(mContext) {
public boolean onTouchEvent(MotionEvent ev) {
return false;
};
};
mColumnHeaderScroll.setLayoutParams(layoutParams);
mColumnHeaderScroll.setHorizontalScrollBarEnabled(false);
mColumnHeaderScroll.setHorizontalFadingEdgeEnabled(false);
mColumnHeaderLayout = genColumnHeader();
mColumnHeaderScroll.addView(mColumnHeaderLayout);
mUpLayout.addView(mColumnHeaderScroll);
} private void addRowHeader() {
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.FILL_PARENT);
layoutParams.setMargins(1, 1, 1, 1);
mRowHeaderScroll = new ScrollView(mContext) {
public boolean onTouchEvent(MotionEvent ev) {
return false;
};
};
mRowHeaderScroll.setLayoutParams(layoutParams);
mRowHeaderScroll.setVerticalScrollBarEnabled(false);
mRowHeaderScroll.setVerticalFadingEdgeEnabled(false);
mRowHeaderLayout = genRowHeader();
mRowHeaderScroll.addView(mRowHeaderLayout);
mDownLayout.addView(mRowHeaderScroll);
} private void addContent() {
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT);
layoutParams.setMargins(1, 1, 1, 1);
mContentScroll = new CustomScrollView(mContext) {
public void scrollTo(int x, int y) {
super.scrollTo(x, y);
mRowHeaderScroll.scrollTo(0, y);
mColumnHeaderScroll.scrollTo(x, 0);
}; public void fling(int velocityX, int velocityY) {
super.fling(velocityX, velocityY);
mRowHeaderScroll.fling(velocityY);
mColumnHeaderScroll.fling(velocityX);
};
};
mContentScroll.setFlingEnabled(false);
mContentScroll.setLayoutParams(layoutParams);
mContentLayout = genContent();
mContentScroll.addView(mContentLayout);
mDownLayout.addView(mContentScroll);
} protected abstract LinearLayout genGridHeader(); protected abstract LinearLayout genColumnHeader(); protected abstract LinearLayout genRowHeader(); protected abstract LinearLayout genContent(); @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.e(LOG_TAG, "rowwidth: " + mRowHeaderScroll.getWidth());
}
private class FixedGridMultiPointTouchListener extends MultiPointTouchListener{ @Override
public boolean onTouch(View v, MotionEvent event) {
if(!super.onTouch(v, event)){
return mContentScroll.onTouchEvent(event);
}
return true;
}
@Override
protected boolean onScale(float oldScale, float lastScale, float newScale, final float clearScale, float midX, float midY){
if(!mScalable){
return false;
}
Log.e(LOG_TAG, "onScale: " + oldScale + ", " + lastScale + ", " + newScale + ", " + clearScale + ", " + midX + ", " + midY);
ScaleAnimation animation = new ScaleAnimation(lastScale, newScale, lastScale, newScale);
//Log.e(LOG_TAG, animation + " ==== scaling: " + lastScale + "==>" + newScale);
animation.setAnimationListener(new ScaleAnimation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
// printSize(FixedGrid.this, "gird");
// printSize(mRowHeaderScroll, "rows");
// printSize(mRowHeaderLayout, "rowl");
// FixedGrid.this.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT, FrameLayout.LayoutParams.FILL_PARENT));
}
private void printSize(View v, String tag){
Log.e(LOG_TAG, tag + ": " + v.getWidth() + ", " + v.getHeight());
}
});
animation.setFillAfter(true);
animation.setDuration(1);
// startAnimation(animation);
LayoutAnimationController controller = new LayoutAnimationController(animation);
// if(newScale < 1){
// //setLayoutParams(new LinearLayout.LayoutParams((int)(800 / newScale), (int)(535 / newScale)));
// }else{
// //setLayoutParams(new LinearLayout.LayoutParams(800, (int)(535 / newScale)));
// }
setLayoutAnimation(controller);
animation.reset();
clearAnimation();
invalidate();
return true;
}
}
}
package com.yfmandroid.widget;import android.graphics.PointF;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;public class MultiPointTouchListener implements OnTouchListener {
private static final String LOG_TAG = "MultiPointTouchListener"; private static final int NONE = 0;
private static final int DRAG = 1;
private static final int ZOOM = 2;
private int mode = NONE; private PointF start = new PointF();
private PointF mid = new PointF();
private float oldDist = 1f;
private float mLastDist;
private float mOldScale = 1;
private float mLastScale;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
start.set(event.getX(), event.getY());
mode = DRAG;
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
mLastDist = oldDist;
if (oldDist > 10f) {
midPoint(mid, event);
mode = ZOOM;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
if (mode == ZOOM) {
mOldScale = mLastScale;
}
mode = NONE;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
return onMove(event.getX() - start.x, event.getY() - start.y);
} else if (mode == ZOOM) {
// Log.e(LOG_TAG, "zooming");
float lastDist = spacing(event);
// Log.e(LOG_TAG, "oldDist: " + oldDist);
// Log.e(LOG_TAG, "lastDist: " + lastDist);
if (lastDist > 10f) {
float lastScale = mLastScale;
mLastScale = lastDist / oldDist * mOldScale;
// Log.e(LOG_TAG, "lastScale: " + lastScale);
// Log.e(LOG_TAG, "mLastScale: " + mLastScale);
float clearScale = lastDist / mLastDist;
mLastDist = lastDist;
// Log.e(LOG_TAG, "scalexxx: " + (mLastScale - lastScale));
if(Math.abs(mLastScale - lastScale) > 0.001){
return onScale(mOldScale, lastScale, mLastScale, clearScale, mid.x, mid.y);
}
return true;
}
}
break;
} return false;
}
protected boolean onMove(float x, float y){
return false;
}
protected boolean onScale(float oldScale, float lastScale, float newScale, float clearScale, float midX, float midY){
return false;
} protected void dumpEvent(MotionEvent event) {
String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE",
"POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?" };
StringBuilder sb = new StringBuilder();
int action = event.getAction();
int actionCode = action & MotionEvent.ACTION_MASK;
sb.append("event ACTION_").append(names[actionCode]);
if (actionCode == MotionEvent.ACTION_POINTER_DOWN
|| actionCode == MotionEvent.ACTION_POINTER_UP) {
sb.append("(pid ").append(
action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
sb.append(")");
}
sb.append("[");
for (int i = 0; i < event.getPointerCount(); i++) {
sb.append("#").append(i);
sb.append("(pid ").append(event.getPointerId(i));
sb.append(")=").append((int) event.getX(i));
sb.append(",").append((int) event.getY(i));
if (i + 1 < event.getPointerCount())
sb.append(";");
}
sb.append("]");
Log.e(LOG_TAG, sb.toString());
} /** Determine the space between the first two fingers */
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
} /** Calculate the mid point of the first two fingers */
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
}
需要缩放时直接重画屏幕好了。