Android安卓开发大作业---模拟电影票小程序APP

小程序 0

完整项目结构:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
登录注册UI设计:

在这里插入图片描述
在这里插入图片描述
登录成功跳转个人信息界面:
在这里插入图片描述
签到功能:
在这里插入图片描述
电影主页:(上下图片可以左右滑动查看热映电影)
在这里插入图片描述
查看所有热映电影:(可以上下滑动)
在这里插入图片描述

选择一部电影查看详细信息:
在这里插入图片描述
点击购票:
在这里插入图片描述

选位置:(左上角会出现一个定位预览界面,高度还原小程序UI界面)
在这里插入图片描述

点击购买并且完成付款:
在这里插入图片描述

付款成功自动跳转到消息页面,里面会显示购买好的电影票:

*在这里插入图片描述

源代码:
Mainactivity.java

package com.example.myapplication;import android.content.Context;import android.content.res.TypedArray;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.Path;import android.graphics.RectF;import android.os.Handler;import android.os.Message;import android.util.AttributeSet;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.ScaleGestureDetector;import android.view.View;import android.widget.Toast;import java.util.ArrayList;public class MainActivity extends View {    private static final String TAG = MainActivity.class.getName();    boolean isDebug;    Paint paint = new Paint();    Matrix matrix = new Matrix();    int spacing = 6;    int verSpacing = 10;    int numberWidth = 20;    int row = 0;    int column = 0;    Bitmap seatBitmap;    Bitmap checkedSeatBitmap;    Bitmap seatSoldBitmap;    Bitmap overviewBitmap;    Bitmap seat;    int lastX;    int lastY;    int seatBitmapWidth;    int seatBitmapHeight;    boolean isNeedDrawSeatBitmap = true;    float rectSize = 10;    float rectWidth = 10;    float overviewSpacing = 5;    float overviewVerSpacing = 5;    float overviewScale = 4.8f;    float screenHeight;    float screenWidthScale = 0.5f;    int defaultScreenWidth;    boolean isScaling;    float scaleX, scaleY;    boolean firstScale = true;    public void setMaxSelected(int maxSelected) {        this.maxSelected = maxSelected;    }    int maxSelected=Integer.MAX_VALUE;    public void setSeatChecker(SeatChecker seatChecker) {        this.seatChecker = seatChecker;        invalidate();    }    private SeatChecker seatChecker;    public void setScreenName(String screenName) {        this.screenName = screenName;    }    private String screenName = "";    ScaleGestureDetector scaleGestureDetector = new ScaleGestureDetector(getContext(), new ScaleGestureDetector.OnScaleGestureListener() {        @Override        public boolean onScale(ScaleGestureDetector detector) {            isScaling = true;            float scaleFactor = detector.getScaleFactor();            if (getMatrixScaleY() * scaleFactor > 3) {                scaleFactor = 3 / getMatrixScaleY();            }            if (firstScale) {                scaleX = detector.getCurrentSpanX();                scaleY = detector.getCurrentSpanY();                firstScale = false;            }            if (getMatrixScaleY() * scaleFactor < 0.5) {                scaleFactor = 0.5f / getMatrixScaleY();            }            matrix.postScale(scaleFactor, scaleFactor, scaleX, scaleY);            invalidate();            return true;        }        @Override        public boolean onScaleBegin(ScaleGestureDetector detector) {            return true;        }        @Override        public void onScaleEnd(ScaleGestureDetector detector) {            isScaling = false;            firstScale = true;        }    });    boolean isOnClick;    GestureDetector gestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {        @Override        public boolean onSingleTapConfirmed(MotionEvent e) {            isOnClick = true;            int x = (int) e.getX();            int y = (int) e.getY();            for (int i = 0; i < row; i++) {                for (int j = 0; j < column; j++) {                    int tempX = (int) ((j * seatBitmap.getWidth() + j * spacing) * getMatrixScaleX() + getTranslateX());                    int maxTemX = (int) (tempX + seatBitmap.getWidth() * getMatrixScaleX());                    int tempY = (int) ((i * seatBitmap.getHeight() + i * verSpacing) * getMatrixScaleY() + getTranslateY());                    int maxTempY = (int) (tempY + seatBitmap.getHeight() * getMatrixScaleY());                    if (seatChecker != null && seatChecker.isValidSeat(i, j) && !seatChecker.isSold(i, j)) {                        if (x >= tempX && x <= maxTemX && y >= tempY && y <= maxTempY) {                            String seat = i + "," + j;                            if (isHave(seat)) {                                remove(seat);                                if (seatChecker != null) {                                    seatChecker.unCheck(i, j);                                }                            } else {                                if(selects.size()>=maxSelected){                                    Toast.makeText(getContext(),"最多只能选择"+maxSelected+"个",Toast.LENGTH_SHORT).show();                                    return super.onSingleTapConfirmed(e);                                }else {                                    selects.add(seat);                                    if (seatChecker != null) {                                        seatChecker.checked(i, j);                                    }                                }                            }                            isNeedDrawSeatBitmap = true;                            isDrawOverviewBitmap = true;                            float currentScaleY = getMatrixScaleY();                            if (currentScaleY < 1.7) {                                postDelayed(new AnimationScaleRunnable(x, y, 1.9f), SCALE_TIME);                            }                            invalidate();                            break;                        }                    }                }            }            return super.onSingleTapConfirmed(e);        }    });    public MainActivity(Context context) {        super(context);    }    int overview_checked;    int overview_sold;    int seatCheckedResID;    int seatSoldResID;    int seatAvailableResID;    public MainActivity(Context context, AttributeSet attrs) {        super(context, attrs);        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SeatTableView);        overview_checked = typedArray.getColor(R.styleable.SeatTableView_overview_checked, Color.parseColor("#5A9E64"));        overview_sold = typedArray.getColor(R.styleable.SeatTableView_overview_sold, Color.RED);        seatCheckedResID = typedArray.getResourceId(R.styleable.SeatTableView_seat_checked, R.drawable.seat1);        seatSoldResID = typedArray.getResourceId(R.styleable.SeatTableView_overview_sold, R.drawable.seat2);        seatAvailableResID = typedArray.getResourceId(R.styleable.SeatTableView_seat_available, R.drawable.seat);        init();    }    public MainActivity(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);    }    private void init() {        spacing = (int) dip2Px(5);        verSpacing = (int) dip2Px(10);        defaultScreenWidth = (int) dip2Px(80);        seatBitmap = BitmapFactory.decodeResource(getResources(), seatAvailableResID);        checkedSeatBitmap = BitmapFactory.decodeResource(getResources(), seatCheckedResID);        seatSoldBitmap = BitmapFactory.decodeResource(getResources(), seatSoldResID);        seatBitmapWidth = column * seatBitmap.getWidth() + (column - 1) * spacing;        seatBitmapHeight = row * seatBitmap.getHeight() + (row - 1) * verSpacing;        paint.setColor(Color.RED);        numberWidth = (int) dip2Px(20);        screenHeight = dip2Px(20);        headHeight = dip2Px(30);        if (seatBitmapWidth > 0 && seatBitmapHeight > 0) {            seat = Bitmap.createBitmap(seatBitmapWidth, seatBitmapHeight, Bitmap.Config.ARGB_4444);            seatCanvas = new Canvas(seat);        }        headPaint = new Paint();        headPaint.setStyle(Paint.Style.FILL);        headPaint.setTextSize(24);        headPaint.setColor(Color.WHITE);        headPaint.setAntiAlias(true);        pathPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        pathPaint.setStyle(Paint.Style.FILL);        pathPaint.setColor(Color.parseColor("#e2e2e2"));        redBorderPaint = new Paint();        redBorderPaint.setAntiAlias(true);        redBorderPaint.setColor(Color.RED);        redBorderPaint.setStyle(Paint.Style.STROKE);        redBorderPaint.setStrokeWidth(getResources().getDisplayMetrics().density * 1);        rectF = new RectF();        rectSize = seatBitmap.getHeight() / overviewScale;        rectWidth = seatBitmap.getWidth() / overviewScale;        overviewSpacing = spacing / overviewScale;        overviewVerSpacing = verSpacing / overviewScale;        rectW = column * rectWidth + (column - 1) * overviewSpacing + overviewSpacing * 2;        rectH = row * rectSize + (row - 1) * overviewVerSpacing + overviewVerSpacing * 2;        overviewBitmap = Bitmap.createBitmap((int) rectW, (int) rectH, Bitmap.Config.ARGB_4444);    }    float rectW;    float rectH;    Paint headPaint;    Bitmap headBitmap;    boolean isFirstDraw = true;    boolean isDrawOverview = false;    boolean isDrawOverviewBitmap = true;    @Override    protected void onDraw(Canvas canvas) {        if (row <= 0 || column == 0) {            return;        }        if (isNeedDrawSeatBitmap) {            drawSeat();        }        if (isFirstDraw) {            isFirstDraw = false;            matrix.postTranslate(getWidth() / 2 - seatBitmapWidth / 2, headHeight + screenHeight + borderHeight + verSpacing);        }        canvas.drawBitmap(seat, matrix, paint);        drawNumber(canvas);        if (headBitmap == null) {            headBitmap = drawHeadInfo();        }        canvas.drawBitmap(headBitmap, 0, 0, null);        drawScreen(canvas);        if (isDrawOverview) {            if (isDrawOverviewBitmap) {                drawOverview();            }            canvas.drawBitmap(overviewBitmap, 0, 0, null);            drawOverview(canvas);        }    }    private int downX, downY;    private boolean pointer;    @Override    public boolean onTouchEvent(MotionEvent event) {        int y = (int) event.getY();        int x = (int) event.getX();        super.onTouchEvent(event);        scaleGestureDetector.onTouchEvent(event);        gestureDetector.onTouchEvent(event);        int pointerCount = event.getPointerCount();        if (pointerCount > 1) {            pointer = true;        }        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                pointer = false;                downX = x;                downY = y;                isDrawOverview = true;                handler.removeCallbacks(hideOverviewRunnable);                invalidate();                break;            case MotionEvent.ACTION_MOVE:                if (!isScaling && !isOnClick) {                    int downDX = Math.abs(x - downX);                    int downDY = Math.abs(y - downY);                    if ((downDX > 10 || downDY > 10) && !pointer) {                        int dx = x - lastX;                        int dy = y - lastY;                        matrix.postTranslate(dx, dy);                        invalidate();                    }                }                break;            case MotionEvent.ACTION_UP:                handler.postDelayed(hideOverviewRunnable, 1500);                autoScale();                int downDX = Math.abs(x - downX);                int downDY = Math.abs(y - downY);                if ((downDX > 10 || downDY > 10) && !pointer) {                    autoScroll();                }                break;        }        isOnClick = false;        lastY = y;        lastX = x;        return true;    }    private Runnable hideOverviewRunnable = new Runnable() {        @Override        public void run() {            isDrawOverview = false;            invalidate();        }    };    float headHeight;    int borderHeight = 1;    Bitmap drawHeadInfo() {        String txt = "已售";        float txtY = getBaseLine(headPaint, 0, headHeight);        int txtWidth = (int) headPaint.measureText(txt);        float spacing = dip2Px(10);        float spacing1 = dip2Px(5);        float y = (headHeight - seatBitmap.getHeight()) / 2;        float width = seatBitmap.getWidth() + spacing1 + txtWidth + spacing + seatSoldBitmap.getWidth() + txtWidth + spacing1 + spacing + checkedSeatBitmap.getHeight() + spacing1 + txtWidth;        Bitmap bitmap = Bitmap.createBitmap(getWidth(), (int) headHeight, Bitmap.Config.ARGB_8888);        Canvas canvas = new Canvas(bitmap);        //绘制背景        canvas.drawRect(0, 0, getWidth(), headHeight, headPaint);        headPaint.setColor(Color.BLACK);        float startX = (getWidth() - width) / 2;        canvas.drawBitmap(seatBitmap, startX, (headHeight - seatBitmap.getHeight()) / 2, headPaint);        canvas.drawText("可选", startX + seatBitmap.getWidth() + spacing1, txtY, headPaint);        float soldSeatBitmapY = startX + seatBitmap.getWidth() + spacing1 + txtWidth + spacing;        canvas.drawBitmap(seatSoldBitmap, soldSeatBitmapY, (headHeight - seatBitmap.getHeight()) / 2, headPaint);        canvas.drawText("已售", soldSeatBitmapY + seatSoldBitmap.getWidth() + spacing1, txtY, headPaint);        float checkedSeatBitmapX = soldSeatBitmapY + seatSoldBitmap.getWidth() + spacing1 + txtWidth + spacing;        canvas.drawBitmap(checkedSeatBitmap, checkedSeatBitmapX, y, headPaint);        canvas.drawText("已选", checkedSeatBitmapX + spacing1 + checkedSeatBitmap.getWidth(), txtY, headPaint);        //绘制分割线        headPaint.setStrokeWidth(1);        headPaint.setColor(Color.GRAY);        canvas.drawLine(0, headHeight, getWidth(), headHeight, headPaint);        return bitmap;    }    Paint pathPaint;    /**     * 绘制中间屏幕     */    void drawScreen(Canvas canvas) {        pathPaint.setStyle(Paint.Style.FILL);        pathPaint.setColor(Color.parseColor("#e2e2e2"));        float startY = headHeight + borderHeight;        float centerX = seatBitmapWidth * getMatrixScaleX() / 2 + getTranslateX();        float screenWidth = seatBitmapWidth * screenWidthScale * getMatrixScaleX();        if (screenWidth < defaultScreenWidth) {            screenWidth = defaultScreenWidth;        }        Path path = new Path();        path.moveTo(centerX, startY);        path.lineTo(centerX - screenWidth / 2, startY);        path.lineTo(centerX - screenWidth / 2 + 20, screenHeight * getMatrixScaleY() + startY);        path.lineTo(centerX + screenWidth / 2 - 20, screenHeight * getMatrixScaleY() + startY);        path.lineTo(centerX + screenWidth / 2, startY);        canvas.drawPath(path, pathPaint);        pathPaint.setColor(Color.BLACK);        pathPaint.setTextSize(20 * getMatrixScaleX());        canvas.drawText(screenName, centerX - pathPaint.measureText(screenName) / 2, getBaseLine(pathPaint, startY, startY + screenHeight * getMatrixScaleY()), pathPaint);    }    private static final int SEAT_TYPE_SOLD = 1;    private static final int SEAT_TYPE_SELECTED = 2;    private static final int SEAT_TYPE_AVAILABLE = 3;    private static final int SEAT_TYPE_NOT_AVAILABLE = 4;    Canvas seatCanvas;    void drawSeat() {        for (int i = 0; i < row; i++) {            for (int j = 0; j < column; j++) {                int left = j * seatBitmap.getWidth() + j * spacing;                int top = i * seatBitmap.getHeight() + i * verSpacing;                int seatType = getSeatType(i, j);                switch (seatType) {                    case SEAT_TYPE_AVAILABLE:                        seatCanvas.drawBitmap(seatBitmap, left, top, paint);                        break;                    case SEAT_TYPE_NOT_AVAILABLE:                        break;                    case SEAT_TYPE_SELECTED:                        seatCanvas.drawBitmap(checkedSeatBitmap, left, top, paint);                        break;                    case SEAT_TYPE_SOLD:                        seatCanvas.drawBitmap(seatSoldBitmap, left, top, paint);                        break;                }            }        }        isNeedDrawSeatBitmap = false;    }    private int getSeatType(int row, int column) {        String seat = row + "," + column;        int seatType = SEAT_TYPE_AVAILABLE;        if (seatChecker != null) {            if (!seatChecker.isValidSeat(row, column)) {                seatType = SEAT_TYPE_NOT_AVAILABLE;            } else if (seatChecker.isSold(row, column)) {                seatType = SEAT_TYPE_SOLD;            }        }        if (isHave(seat)) {            seatType = SEAT_TYPE_SELECTED;        }        return seatType;    }    RectF rectF;    /**     * 绘制行号     */    void drawNumber(Canvas canvas) {        paint.setColor(Color.parseColor("#7e000000"));        paint.setTextSize(getResources().getDisplayMetrics().density * 16);        paint.setAntiAlias(true);        int translateY = (int) getTranslateY();        float scaleY = getMatrixScaleY();        rectF.top = translateY - paint.measureText("4") / 2;        rectF.bottom = translateY + (seatBitmapHeight * scaleY) + paint.measureText("4") / 2;        rectF.left = 0;        rectF.right = numberWidth;        canvas.drawRoundRect(rectF, numberWidth / 2, numberWidth / 2, paint);        Paint.FontMetrics fontMetrics = paint.getFontMetrics();        paint.setColor(Color.WHITE);        paint.setTextAlign(Paint.Align.CENTER);        for (int i = 0; i < row; i++) {            int top = (int) ((i * seatBitmap.getHeight() + i * verSpacing) * scaleY) + translateY;            int bottom = (int) ((i * seatBitmap.getHeight() + i * verSpacing + seatBitmap.getHeight()) * scaleY) + translateY;            int baseline = (int) ((bottom + top - fontMetrics.bottom - fontMetrics.top) / 2);            canvas.drawText((i + 1) + "", numberWidth / 2, baseline, paint);        }    }    Paint redBorderPaint;    /**     * 绘制概览图     */    void drawOverview(Canvas canvas) {        //绘制红色框        int left = (int) -getTranslateX();        if (left < 0) {            left = 0;        }        left /= overviewScale;        left /= getMatrixScaleX();        int currentWidth = (int) (getTranslateX() + (column * seatBitmap.getWidth() + spacing * (column - 1)) * getMatrixScaleX());        if (currentWidth > getWidth()) {            currentWidth = currentWidth - getWidth();        } else {            currentWidth = 0;        }        int right = (int) (rectW - currentWidth / overviewScale / getMatrixScaleX());        float top = -getTranslateY()+headHeight;        if (top < 0) {            top = 0;        }        top /= overviewScale;        top /= getMatrixScaleY();        if (top > 0) {            top += overviewVerSpacing;        }        int currentHeight = (int) (getTranslateY() + (row * seatBitmap.getHeight() + verSpacing * (row - 1)) * getMatrixScaleY());        if (currentHeight > getHeight()) {            currentHeight = currentHeight - getHeight();        } else {            currentHeight = 0;        }        int bottom = (int) (rectH - currentHeight / overviewScale / getMatrixScaleY());        canvas.drawRect(left, top, right, bottom, redBorderPaint);    }    Bitmap drawOverview() {        isDrawOverviewBitmap = false;        int bac = Color.parseColor("#7e000000");        paint.setColor(bac);        paint.setAntiAlias(true);        paint.setStyle(Paint.Style.FILL);        Canvas canvas = new Canvas(overviewBitmap);        //绘制透明灰色背景        canvas.drawRect(0, 0, rectW, rectH, paint);        paint.setColor(Color.WHITE);        for (int i = 0; i < row; i++) {            float top = i * rectSize + i * overviewVerSpacing + overviewVerSpacing;            for (int j = 0; j < column; j++) {                int seatType = getSeatType(i, j);                switch (seatType) {                    case SEAT_TYPE_AVAILABLE:                        paint.setColor(Color.WHITE);                        break;                    case SEAT_TYPE_NOT_AVAILABLE:                        continue;                    case SEAT_TYPE_SELECTED:                        paint.setColor(overview_checked);                        break;                    case SEAT_TYPE_SOLD:                        paint.setColor(overview_sold);                        break;                }                float left;                left = j * rectWidth + j * overviewSpacing + overviewSpacing;                canvas.drawRect(left, top, left + rectWidth, top + rectSize, paint);            }        }        return overviewBitmap;    }    /**     * 自动回弹     * 整个大小不超过控件大小的时候:     * 往左边滑动,自动回弹到行号右边     * 往右边滑动,自动回弹到右边     * 往上,下滑动,自动回弹到顶部     * <p>     * 整个大小超过控件大小的时候:     * 往左侧滑动,回弹到最右边,往右侧滑回弹到最左边     * 往上滑动,回弹到底部,往下滑动回弹到顶部     */    private void autoScroll() {        float currentSeatBitmapWidth = seatBitmapWidth * getMatrixScaleX();        float currentSeatBitmapHeight = seatBitmapHeight * getMatrixScaleY();        float moveYLength = 0;        float moveXLength = 0;        //处理左右滑动的情况        if (currentSeatBitmapWidth < getWidth()) {            if (getTranslateX() < 0 || getMatrixScaleX() < numberWidth + spacing) {                //计算要移动的距离                if (getTranslateX() < 0) {                    moveXLength = (-getTranslateX()) + numberWidth + spacing;                } else {                    moveXLength = numberWidth + spacing - getTranslateX();                }            }        } else {            if (getTranslateX() < 0 && getTranslateX() + currentSeatBitmapWidth > getWidth()) {            } else {                //往左侧滑动                if (getTranslateX() + currentSeatBitmapWidth < getWidth()) {                    moveXLength = getWidth() - (getTranslateX() + currentSeatBitmapWidth);                } else {                    //右侧滑动                    moveXLength = -getTranslateX() + numberWidth + spacing;                }            }        }        float startYPosition = screenHeight * getMatrixScaleY() + verSpacing * getMatrixScaleY() + headHeight + borderHeight;        //处理上下滑动        if (currentSeatBitmapHeight < getHeight()) {            if (getTranslateY() < startYPosition) {                moveYLength = startYPosition - getTranslateY();            } else {                moveYLength = -(getTranslateY() - (startYPosition));            }        } else {            if (getTranslateY() < 0 && getTranslateY() + currentSeatBitmapHeight > getHeight()) {            } else {                //往上滑动                if (getTranslateY() + currentSeatBitmapHeight < getHeight()) {                    moveYLength = getHeight() - (getTranslateY() + currentSeatBitmapHeight);                } else {                    moveYLength = -(getTranslateY() - (startYPosition));                }            }        }        Message message = Message.obtain();        MoveInfo moveInfo = new MoveInfo();        moveInfo.moveXLength = moveXLength;        moveInfo.moveYLength = moveYLength;        message.obj = moveInfo;        handler.sendMessageDelayed(message, time);    }    class MoveInfo {        public float moveXLength;        public float moveYLength;    }    private void autoScale() {        if (getMatrixScaleX() > 2.2) {            postDelayed(new AnimationScaleRunnable(scaleX, scaleY, 2.0f), SCALE_TIME);        } else if (getMatrixScaleX() < 0.98) {            postDelayed(new AnimationScaleRunnable(scaleX, scaleY, 1.0f), SCALE_TIME);        }    }    int FRAME_COUNT = 10;    int time = 15;    int count;    int SCALE_TIME = 15;    Handler handler = new Handler(new Handler.Callback() {        @Override        public boolean handleMessage(Message msg) {            if (count < FRAME_COUNT) {                count++;                MoveInfo moveInfo = (MoveInfo) msg.obj;                float moveXLength = moveInfo.moveXLength;                float moveYLength = moveInfo.moveYLength;                float xValue = moveXLength / FRAME_COUNT;                float yValue = moveYLength / FRAME_COUNT;                matrix.postTranslate(xValue, yValue);                invalidate();                Message message = Message.obtain();                message.obj = msg.obj;                handler.sendMessageDelayed(message, time);            } else {                count = 0;            }            return true;        }    });    ArrayList<String> selects = new ArrayList<>();    public ArrayList<String> getSelectedSeats() {        return selects;    }    private boolean isHave(String seat) {        for (String item : selects) {            if (seat.equals(item)) {                return true;            }        }        return false;    }    private void remove(String seat) {        for (int i = 0; i < selects.size(); i++) {            String item = selects.get(i);            if (seat.equals(item)) {                selects.remove(i);                break;            }        }    }    float[] m = new float[9];    private float getTranslateX() {        matrix.getValues(m);        return m[2];    }    private float getTranslateY() {        float[] m = new float[9];        matrix.getValues(m);        return m[5];    }    private float getMatrixScaleY() {        matrix.getValues(m);        return m[4];    }    private float getMatrixScaleX() {        matrix.getValues(m);        return m[0];    }    private float dip2Px(float value) {        return getResources().getDisplayMetrics().density * value;    }    private float getBaseLine(Paint p, float top, float bottom) {        Paint.FontMetrics fontMetrics = p.getFontMetrics();        int baseline = (int) ((bottom + top - fontMetrics.bottom - fontMetrics.top) / 2);        return baseline;    }    public class AnimationScaleRunnable implements Runnable {        private float x, y;//缩放的中心点        private float targetScale;        private float tempScale;        public AnimationScaleRunnable(float x, float y, float targetScale) {            float currentScale = getMatrixScaleX();            this.x = x;            this.y = y;            this.targetScale = targetScale;            if (currentScale < targetScale) {                tempScale = 1.06f;            } else {                tempScale = 0.95f;            }        }        @Override        public void run() {            matrix.postScale(tempScale, tempScale, x, y);            invalidate();            float currentScale = getMatrixScaleX();            if (tempScale > 1 && currentScale < targetScale) {                postDelayed(this, SCALE_TIME);            } else if (tempScale < 1 && currentScale > targetScale) {                postDelayed(this, SCALE_TIME);            }        }    }    public void setData(int row, int column) {        this.row = row;        this.column = column;        init();        invalidate();    }    public interface SeatChecker {        /**         * 是否可用座位         *         * @param row         * @param column         * @return         */        boolean isValidSeat(int row, int column);        /**         * 是否已售         *         * @param row         * @param column         * @return         */        boolean isSold(int row, int column);        void checked(int row, int column);        void unCheck(int row, int column);    }}

也许您对下面的内容还感兴趣: