读书人

位子雷达

发布时间: 2013-08-13 16:43:28 作者: rapoo

座位雷达
<div 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>

读书人网 >移动开发

热点推荐