本帖最后由 zyongsheng83 于 2011-03-07 15:19:31 编辑

解决方案 »

  1.   

    整个表格的实现 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;
    }
    }
    }
      

  2.   

    事件监听 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);
    }
    }
      

  3.   

    我认为用Layout去 实现缩放 难以成功,,只有自定义View 重新绘画 可以,, 所有的Excel表格都是画出来的矩形,,而且容易缩放 
      

  4.   

    自定义View重新绘画是什么意思?我是新手,能举个很简单很简单的例子吗?
      

  5.   

    这个用surfaceView吧。
    需要缩放时直接重画屏幕好了。