`
lesterlester
  • 浏览: 3429 次
社区版块
存档分类
最新评论
阅读更多
<div class="iteye-blog-content-contain" style="font-size: 14px">

       由于涉及到工作内容保密的问题,所以无法提供源码,只能提供涉及该项功能的实现,本着开源和互相学习以及以后相同功能的重复利用的目的。

GridView虽然也支持横向滚动,但是并不支持代码控制,所以还是用到一个横向滚动来代替这个功能
<HorizontalScrollView
            android:id="@+id/hs_gridview"
            android:layout_width="610dp"
            android:layout_height="750dp"
            android:layout_weight="1"
            android:fillViewport="true"
            android:scrollbars="horizontal" >

            <LinearLayout
                android:layout_width="610dp"
                android:layout_height="490dp" >

                <cn.com.bcl.infoissuingsys.common.CommonGridView
                    android:id="@+id/gridView"
                    android:layout_width="1200dp"
                    android:layout_height="490dp"
                    android:layout_margin="0dp"
                    android:horizontalSpacing="20dp"
                    android:listSelector="@android:color/transparent"
                    android:numColumns="20"
                    android:scrollbarStyle="outsideInset"
                    android:scrollbarThumbVertical="@drawable/scrollbar_vertical_thumb"
                    android:scrollbarTrackVertical="@drawable/scrollbar_vertical_track"
                    android:scrollbars="vertical"
                    android:stretchMode="columnWidth"
                    android:verticalSpacing="5dp" />
            </LinearLayout>
        </HorizontalScrollView>


每个gridview的Item布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <cn.com.bcl.infoissuingsys.common.CommonImageView 
        android:id="@+id/zuoweiimage"
        android:layout_width="40dp"
        android:layout_height="35dp"
        android:scaleType="fitXY"
        android:src="@drawable/keyixuan"/>
    <cn.com.bcl.infoissuingsys.common.CommonTextView 
        android:id="@+id/zuoweihao"
        android:layout_width="40dp"
        android:layout_height="35dp"
        android:textColor="#000000"
        android:textSize="15dp"
        android:text="01"
        android:gravity="center"/>
</RelativeLayout>


绘制背景图片
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff.Mode;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.LinearLayout.LayoutParams;

public class RadarBgView extends SurfaceView implements SurfaceHolder.Callback {
    
    private String TAG  = "RadarView";
    private SurfaceHolder mHolder;
    
    private Context mCnxt;
    
    private int mSeatWidth = 410;
    
    private int mSeatHeight = 220;
    
    private int mStartSeatTop = 40;
    
    private int mLine = 0;
    
    private int mColumn=0;
    
    private int mLineNoWidth = 20;

    public RadarBgView(Context context) {
        super(context);
    }
    
    public RadarBgView(Context context,int line,int column) {
        super(context);
        this.mLine = line;
        this.mColumn = column;
        mCnxt = context;
        mHolder=this.getHolder();
        mHolder.addCallback(this);
        setZOrderOnTop(true);
        mHolder.setFormat(PixelFormat.TRANSLUCENT);
        setFocusable(false);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        drawBg(mLine,mColumn);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }
    
    /** change background */
    public void notifyBgChange(){
        
    }
    
    /**draw background by seat */
    public void drawBg(int line,int column){
        Paint paint=new Paint();
//        paint.setColor(Color.BLACK);
        paint.setAntiAlias(true);
        paint.setFilterBitmap(true);
        paint.setDither(true);
        
        int divider = 1;
        /** onriginal 图片 */
        Bitmap originalSeatBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.small);
        int originalWidth = originalSeatBitmap.getWidth();
        int originalHeight = originalSeatBitmap.getHeight();
        /** 新的高度和宽度 */
        float newWidth = (mSeatWidth-mLineNoWidth-divider*(column-1))/column;
        float newHeight = (mSeatHeight-divider*(line-1))/line;
        /** 计算缩放比例 */
        float scaleWidth = newWidth/originalWidth;
        float scaleHeight = newHeight/originalHeight;
        /**取得要缩放的参数 */
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);
        /** 生成新图片 */
        Bitmap newBm = Bitmap.createBitmap(originalSeatBitmap, 0, 0, originalWidth, originalHeight,matrix,true);
        originalSeatBitmap.recycle();
        originalSeatBitmap = null;
        

        Paint testP=new Paint();
//      paint.setColor(Color.BLACK);
        testP.setAntiAlias(true);
        testP.setTextSize(5);
        
        Canvas canvas = null;
        try {
            canvas = mHolder.lockCanvas();
            synchronized (mHolder) {
                int offsetY = mStartSeatTop;
                for (int i = 0; i < line; i++) {
                    canvas.drawText(String.valueOf(i+1), 6, offsetY+newBm.getHeight(), testP);
                    int offsetX = mLineNoWidth;
                    for (int j = 0; j < column; j++) {
                        canvas.drawBitmap(newBm, offsetX, offsetY, paint);
                        offsetX+=(newBm.getWidth()+divider);
                    }
                    offsetX=0;
                    offsetY+=(newBm.getHeight()+divider);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (canvas != null) {
                mHolder.unlockCanvasAndPost(canvas);
            }
        }
    }
}


绘制雷达区域的座位表和选择区域,实现点击事件,同步实际ScrollView和GridView的同步
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class RadarAreaView extends SurfaceView implements
        SurfaceHolder.Callback {

    private String TAG = "RadarAreaView";
    private SurfaceHolder mHolder;
    private Handler mHandler;
    /** gridView 的 显示区域宽高 */
    private int mDisplayWidth = 630;
    private int mDisplayHeight = 490;
    /** gridView real 高宽 */
    private int mWholeWidth;
    private int mWholeHeight;
    /** 雷达座位区域长宽 */
    private int mRadarSeatWidth = 410;
    private int mRadarSeatHeight = 260;
    /** 显示区域偏移量 */
    private int mOffsetX = 0;
    private int mOffsetY = 40;
    /** 座位行列数 */
    private int mLineNum = 0;
    private int mColumnNum = 0;
    /** radar和gridView的长高缩放比例 */
    private float mScaleX;
    private float mScaleY;
    
    private int mLineNoWidth = 20;
    
    private int mStartSeatTop = 40;

    Bitmap mAreaBm = null;
    

    public RadarAreaView(Context context) {
        super(context);
    }

    public RadarAreaView(Context context, int line, int column,Handler handler) {
        super(context);
        mHolder = this.getHolder();
        mHolder.addCallback(this);
        setZOrderOnTop(true);
        mHolder.setFormat(PixelFormat.TRANSLUCENT);
        this.mLineNum = line;
        this.mColumnNum = column;
        this.mHandler = handler;
        setFocusable(false);
        /** 初始化可视区域的图片大小 */
        initAreaBm();
        /** 雷达View与实际 View 的长宽比例 */
        mScaleX = ((float)(mRadarSeatWidth-mLineNoWidth))/mWholeWidth;
        mScaleY = ((float)(mRadarSeatHeight-mStartSeatTop)/mWholeHeight);
    }

    /**
     * 根据实际比例初始化选择区域框的的图片大小
     */
    private void initAreaBm() {
        Bitmap originalBm = BitmapFactory.decodeResource(getResources(),
                R.drawable.area);
        int originalWidth = originalBm.getWidth();
        int originalHeight = originalBm.getHeight();

        int dividerX = 20;
        int dividerY = 5;
        /** original 图片 */
        mWholeWidth = 40 * mColumnNum + dividerX * (mColumnNum - 1);
        mWholeHeight = 35 * mLineNum + dividerY * (mLineNum - 1);
        /** 计算缩放比例 */
        float scaleWidth = ((float)mDisplayWidth) / mWholeWidth;
        float scaleHeight = ((float)mDisplayHeight) / mWholeHeight;
        /** 计算Area宽缩放后的长宽 */
        float newAreaWidth = (mRadarSeatWidth-mLineNoWidth)*scaleWidth;
        float newAreaHeight = (mRadarSeatHeight-mStartSeatTop)*scaleHeight;
        /** 计算缩放比例 */
        float newScaleWidth = newAreaWidth/originalWidth;
        float newScaleHeight = newAreaHeight/originalHeight;
        /**取得要缩放的参数 */
        Matrix matrix = new Matrix();
        matrix.postScale(newScaleWidth, newScaleHeight);
        /** 生成新图片 */
        mAreaBm = Bitmap.createBitmap(originalBm, 0, 0, originalWidth,
                originalHeight, matrix, true);
        originalBm.recycle();
        originalBm = null;
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
            drawArea();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }

    /** clear && refresh Area by offsetX & offset Y */
    public void drawArea() {
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setFilterBitmap(true);
        paint.setDither(true);
        
        Paint clearP = new Paint();
        clearP.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

        Canvas canvas = null;
        try {
            canvas = mHolder.lockCanvas();
            synchronized (mHolder) {
                canvas.drawPaint(clearP);
                canvas.drawBitmap(mAreaBm, mOffsetX, mOffsetY, null);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (canvas != null) {
                mHolder.unlockCanvasAndPost(canvas);
            }
        }
    }
    
    /** 点击雷达区域时,同步GridView显示的位置 */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        final float x = event.getX();
        final float y = event.getY();
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            /**caculate scroll */
            /**雷达区域每个item的宽高 */
            float xItemSize = (mRadarSeatWidth-mLineNoWidth)/mColumnNum;
            float yItemSize = (mRadarSeatHeight-mStartSeatTop)/mLineNum;
            int cornerX = 0;
            int cornerY = 0;
            /** 图像是左上角开始画的,所以为了让方框居于点击位置的中心,进行了偏移计算 */
            cornerX=(int) (x-mAreaBm.getWidth()/2);
            cornerY=(int) (y-mAreaBm.getHeight()/2);
            int offsetX = 0;
            int offsetY = 0;
            /** 对于超出座位图的点击事件进行处理 */
            if (cornerX<=mLineNoWidth) {
                offsetX = 0;
            } else if(cornerX>=(mRadarSeatWidth-mAreaBm.getWidth())){
                offsetX = (int) ((mRadarSeatWidth-mLineNoWidth-mAreaBm.getWidth()));
            }else{
                offsetX = (int) ((cornerX-mLineNoWidth));
            }
            if (cornerY<=mStartSeatTop) {
                offsetY = 0;
            } else if(cornerY>=(mRadarSeatHeight-mAreaBm.getHeight())){
                offsetY = (int) ((mRadarSeatHeight-mStartSeatTop-mAreaBm.getHeight()));
            }else{
                offsetY = (int) ((cornerY-mStartSeatTop));
            }
            int scrollX = (int) (offsetX/mScaleX);
            int position =(int) ((int)(offsetY/yItemSize)*mColumnNum+(int)(offsetX/xItemSize));
            /** scroll seat gridView */
            /** 从View发消息给Activity同步实际View的滚动 */
            Message msg = new Message();
            Bundle bundle = new Bundle();
            bundle.putInt("scrollX", scrollX);
            bundle.putInt("position", position);
            bundle.putInt("linePosition", (int)(offsetY/yItemSize));
            msg.setData(bundle);
            mHandler.sendMessage(msg); 
            /**caculate and draw Area */
            /** 根据点击位置和计算的左上角位置重绘选择区域 */
            if (cornerX<=mLineNoWidth) {
                mOffsetX = mLineNoWidth;
            } else if(cornerX>=(mRadarSeatWidth-mAreaBm.getWidth())){
                mOffsetX = (int) ((mRadarSeatWidth-mAreaBm.getWidth()));
            }else{
                mOffsetX =(int) cornerX;
            }
            if (cornerY<=mStartSeatTop) {
                mOffsetY = mStartSeatTop;
            } else if(cornerY>=(mRadarSeatHeight-mAreaBm.getHeight())){
                mOffsetY = (int) ((mRadarSeatHeight-mAreaBm.getHeight()));
            }else{
                mOffsetY = (int) cornerY;
            }
            drawArea();
            break;

        default:
            break;
        }
        return true;
    }
    
    /**GridView滚动时传入当前第一个可见的position 控制雷达的垂直方向的滚动同步 */
    public void scrollVertical(int position){
        float yItemSize = (mRadarSeatHeight-mStartSeatTop)/mLineNum;
        mOffsetY= (int) ((position/mColumnNum) * yItemSize)+mStartSeatTop;
        drawArea();
    }
    
    /** 通过传入的HorizantalScrollView的move offset来控制雷达的水平方向的滚动同步 */
    public void scrollHorizontal(int originalX){
        mOffsetX =mLineNoWidth + (int)(originalX*mScaleX);
        drawArea();
    }
}


Fragment或者Activity中局部代码
    /**
     * GridView
     */
    private GridView mGridView;
    /**
     * HorizontalScrollView
     */
    private HorizontalScrollView mHsGridView;  
    private RelativeLayout mRelativeLayout_radar;
    private RadarAreaView mRav;
    private RadarBgView mRbv;


mRbv = new RadarBgView(mContext,mNumLine,mNumColumns);
        mRav = new RadarAreaView(mContext,mNumLine,mNumColumns,radarHandler);
        mRelativeLayout_radar.addView(mRbv);
        mRelativeLayout_radar.addView(mRav);
 /** 控制垂直滚动 */
 mGridView.setOnScrollListener(new OnScrollListener() {
            
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                
            }
            
            @Override
            public void onScroll(final AbsListView view, int firstVisibleItem,
                    int visibleItemCount, int totalItemCount) {
                    View v = view.getChildAt(view.getFirstVisiblePosition()/mNumColumns);
                    int[] location = new int[2];
                    if(null!=v){
                        v.getLocationOnScreen(location);
                        if (mIsInitDefault) {
                            mDefaultLocation = location[1];
                            mIsInitDefault = false;
                        }
                        mRav.scrollVertical(view.getFirstVisiblePosition());
                    }
            }
        });
/** HorizontalScrollView控制横向滚动同步 */
 mHsGridView.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    break;
                case MotionEvent.ACTION_MOVE:
                    int offsetX = mHsGridView.getScrollX();
                    mRav.scrollHorizontal(offsetX);
                    break;

                default:
                    break;
                }
                return false;
            }
        });

从雷达区域来的消息处理,同步实际GridView的滚动
private Handler radarHandler = new Handler(){
        public void handleMessage(Message msg) {
            Bundle bundle = msg.getData();
            final int position = bundle.getInt("position");
            final int linePosition = bundle.getInt("linePosition");
            final int scrollX = bundle.getInt("scrollX");
            mGridView.post(new Runnable() {
                
                @Override
                public void run() {
                    mHsGridView.scrollTo(scrollX, (int) mGridView.getY());
                    mGridView.setSelection(position);
                }
            });
        };
    };


给自己mark一下

</div>
0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics