《“透视”个人大数据》项目开发小记 --(三)Android APP 开发(4)自定RelativeLayout实现通用图片编辑

       在开发项目的APP中,图片是重要表现形式,对图片进行适当的编辑(裁剪,设置聚光区,添加文字及图形标记等),可以增强图片的表现力。为了便于操作使用,APP中通过自定RelativeLayout实现通用图片编辑,并计划做成一个开源项目,这里将主要的技术和代码进行分享。 这个自定RelativeLayout开始是用于在图片界面中,动态添加textView及EditText的,之后又增加了图片缩放及拖移,目前又增加了图片的编辑功能。这里介绍的内容包括自定elativeLayout,关联java类的代码及应用实例简介。
   一, 主要功能
     1),动态添加textView及EditText

 2), “缩放,拖移”查看图片

 3), 图片编辑
     A), 设置裁剪或聚光区

  B), 添加文字

 C), 添加图形标记

 D), 删除已添加的项目

 E), 拖移已添加的项目

 二,自定RelativeLayout
      这个自定RelativeLayout除了图片的“缩放,拖移”,其它的一些功能是根据需要动态设置添加的,界面中操作按钮显示符号,也是动态设置的。图片编辑参数是通过回调(Callback)在主界面完成的,并未将所有功能完全封装在自定RelativeLayout内。

package com.bi3eview.newstart60.local.doTask;
import android.os.Environment;
import android.content.Intent;
import android.graphics.Matrix;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.text.Layout.Alignment;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.media.RingtoneManager;
import android.media.MediaPlayer;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.media.SoundPool;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.provider.MediaStore;
import android.graphics.Region;
import android.os.Vibrator;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.widget.EditText;
import android.content.Context;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.Point;
import android.graphics.Canvas;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.support.annotation.NonNull;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import com.bi3eview.newstart60.local.COMCONST;
import com.bi3eview.newstart60.local.R;
import com.bi3eview.newstart60.local.SelfWidget.PathParser;
import com.bi3eview.newstart60.local.Util.buttonData;
import com.bi3eview.newstart60.local.Util.buttonDrawUtil;
import com.bi3eview.newstart60.local.Util.BitMapUtil;
import com.bi3eview.newstart60.local.Util.GraphicItemUtil;
import com.bi3eview.newstart60.local.Util.GraphicsExpItem;
import com.bi3eview.newstart60.local.constant.Constants;
import com.bi3eview.newstart60.local.pubcom.graClipTextShapeView;
import com.google.zxing.util.BitmapUtil;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.FileNotFoundException;
/**
 *  create by bs60 on 2020.01.17
 * */
public class TaskDataLLayout extends RelativeLayout {
    public static Bitmap mcur_photoBipmap = null;
    private Rect mFrameRect;
    private Context mcontext = null;
    private Paint mPaint = null;
    private Matrix matrix;
    private Point center;
    private Point bmpCenter;
    private long mButtonDownTimev = 0;
    private long mButtonUpTimev = 100;
    private long mTimeMove = 100;
    private final int LONGPRESS_TIME = 1500;
    buttonDrawUtil mButDrawMenuHandle = null;
    boolean mButtonMenuResetblv = true;
    GraphicItemUtil mgraItemHandle = null;
    private static int miViewWidth = -1;
    private static int miViewHeight = -1;
    private final int SAVEUPDATE_BUTTON = 3000;
    private long mSaveButtonPressed;
    private Bitmap mcurBbitmap;
    boolean cnewPhotoblv = false;
    boolean drawBmpLockblv = false;
    boolean bdataShowblv = false;
    boolean mLongClickblv = false;
    boolean mLongClickButtonblv = false;
    boolean mLongMoveblv = false;
    boolean mFingerNum2blv = false;
    int mlongThreadProcessCode = 0;
    float mcurScale;
    final int xoffv = 0;// 300;
    final int yoffv = 0;// 500;
    final int five=5<<24;
    /** view.setTag(int,Object)中的int值必须要左移24位才行,这样才不会报错 */
    private ViewDragHelper mViewDragHelper;
    private boolean mDragEnable = true;
    //... private Point mAutoBackOriginPos = new Point();
    private float minimal = 100.0f;
    private float miniShowWhv = 100.0f;

    private int mbuttonMoveWidth = 60;
    String mstrTraceInfo = "";
    String mdownNextInfo = "";
    String m_pkName = "";
    String m_EDITPICDIRName = "";
    String msaveEditPictureName = "";
    String mcur_TIMEFILENAME = "2022-09-28_18_36_26";
    private float screenW;//屏幕宽度
    private float screenH;//屏幕高度
    private int drawScreenW;//屏幕宽度
    private int drawScreenH;//屏幕高度

    private float miBitmapfXc = 0;
    private float miBitmapfYc = 0;

    //单指按下的坐标
    private float mFirstX = 0.0f;
    private float mFirstY = 0.0f;

    //单指离开的坐标
    private float lastMoveX =-1f;
    private float lastMoveY =-1f;

    //两指的中点坐标
    private float centPointX;
    private float centPointY;
    //是否是长按事件
    boolean isLongClick;
    //移动相关
    float downX, downY, moveX, moveY;
    //图片的绘制坐标
    private float translationX = 0.0f;
    private float translationY = 0.0f;

    //图片的原始宽高
    private float primaryW;
    private float primaryH;

    //图片当前宽高
    private float currentW;
    private float currentH;

    private float scale = 1.0f;
    private float maxScale, minScale;

    RectF mdrawClipRectF = new RectF(0f,0f,20f,20f);

    private int mLocker = 0;
    private float fingerDistance = 0.0f;

    private boolean isLoaded = false;
    private boolean isClickInImage = false;
    private boolean clickDownFirstblv = false;
    private boolean mbuttonClickblv = false;
    private boolean mPressBreak = false;
    private int mcurClipAlpha = 220;
    private byte mbClipAreaKind = buttonData.CLIPAREAKIND_OVAL;
    private int iClipColorv = Color.argb(192,128,128,128);
    private int StrokeWidth = 5;
    private Rect mCliprect = new Rect(0,0,0,0);//手动绘制矩形
    private boolean mdrawClipRectblv = false;
    private boolean mselectClipOperblv = false;
    // graphics item mark
    private float mgraItem_MarkFscale = 1.0f;
    private float mgraItem_MarkWide = 10.0f;
    private int mgraItem_Xoff = 10;
    private int mgraItem_Yoff = 10;
    // text
    private byte mbTextKind = buttonData.TEXTICONKIND_HORIZONTAL;
    private int miTextColorv = Color.GREEN;
    private int miTextSize = 26;
    private String mstrMarkname = "";
    boolean mtxtShowblv = false;
    int mtxtshowXpos = 0;
    int mtxtshowYpos = 0;

    private boolean mdrawtxtClickblv = false;
    private RectF mdrawtxt_markFRect = new RectF(0f,0f,20f,20f);
    // draw
    private byte mbDrawKind = buttonData.MARKICONKIND_LINE;
    private int miDrawColorv = Color.RED;
    private int miLinewide = 26;
    private int miTransparentValue = 80;
    private int miDrawLongMoveLen = 80;
    boolean mdrawShowblv = false;
    boolean mDrawLongMoveblv = false;
    private boolean mdrawRubberClickblv = false;
    private RectF mdrawRubber_markFRect = new RectF(0f,0f,20f,20f);
    private float mdrawFirstX = 0.0f;
    private float mdrawFirstY = 0.0f;
    private float mdrawFirstPreX = 0.0f;
    private float mdrawFirstPreY = 0.0f;
    private float mSecondX = 0.0f;
    private float mSecondY = 0.0f;
    boolean mdrawMarkSymblv = false;
    boolean mdrawDownPrimitiveblv = false;
    boolean mdrawItemDelDragClickblv = false;
    boolean mondraw_Processblv = true;
    boolean mdraw_DragMoveLockblv = false;
    private ArrayList<Point> mPolyLineList = null;
    // check item
    public static final byte CHECKITEMGRA_CLIP = 1;
    public static final byte CHECKITEMGRA_GRANUM = 2;
    //创建一个Handler
    final int PICTURERESTORE = 1000;
    final int PICTUREONDRAW = 2000;
    final int PICTURESAVEUPDATE = 3000;
    final int DOWNLONGCLICKCHECK = 3003;
    final int APPENDGRAPHICSITEM_CLIP = 3006;
    final int APPENDGRAPHICSITEM_TEXT = 3007;
    final int DRAGMOVEGRAITEM_REDRAW = 4000;
    private Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            String operCmd;
            switch (msg.what) {
                case DRAGMOVEGRAITEM_REDRAW:
                    invalidate();
                    break;
                case APPENDGRAPHICSITEM_TEXT:
                    graphics_appendItem_Text();
                    break;
                case APPENDGRAPHICSITEM_CLIP:
                    graphics_appendItem_Clip();
                    break;
                case DOWNLONGCLICKCHECK:
                    if(mlongThreadProcessCode < 9) {
                        if (!mPressBreak && mbuttonClickblv) {
                            if (!mFingerNum2blv && !mLongMoveblv) {
                                mTimeMove = System.currentTimeMillis();
                                long durationMs = mTimeMove - mButtonDownTimev;
                                if (durationMs > LONGPRESS_TIME) {
                                    mbuttonClickblv = false;
                                    isLongClick = true;
                                    MotionEvent event = null;
                                    if(!mLongClickButtonblv) {
                                        mLongClickButtonblv = true;
                                        isSelectButton(event, true);
                                    }
                                }
                            }
                        }
                    }
                    mlongThreadProcessCode = 0;
                    break;
                case PICTURESAVEUPDATE:
                    saveEditImage();
                    invalidate();
                    break;
                case PICTUREONDRAW:
                    invalidate();
                    break;
                case PICTURERESTORE:
                    cnewPhotoblv = false;
                    // mstrTraceInfo = mstrTraceInfo+">>handler";//xxxxxx
                    invalidate();
                    break;
            }
        }
    };

    public TaskDataLLayout(Context context) {
        this(context, null);
        mPaint = new Paint();
        // 需要调用下面的方法才会执行onDraw方法
        setWillNotDraw(false);
        mcontext = context;
        initset();
    }

    public TaskDataLLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        mPaint = new Paint();
        // 需要调用下面的方法才会执行onDraw方法
        setWillNotDraw(false);
        mcontext = context;
        initset();
    }

    public TaskDataLLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mPaint = new Paint();
        // 需要调用下面的方法才会执行onDraw方法
        setWillNotDraw(false);
        // setWillNotDraw(false);/**  2019.09.01 */
        mcontext = context;

        if (mDragEnable) {
            mViewDragHelper = ViewDragHelper.create(this,
                    createDrawCallback()
            );
        }
        initset();
    }

    private void initset()
    {
        mSaveButtonPressed = 0;
        mlongThreadProcessCode = 0;
        mLongClickButtonblv = false;
        cnewPhotoblv = false;
        drawBmpLockblv = false;
        bdataShowblv = true;
        mButDrawMenuHandle = new buttonDrawUtil();
        mButtonMenuResetblv = true;
        mgraItemHandle = new GraphicItemUtil();
        mdrawClipRectblv = false;
        buttonData.cActive_IDitem = buttonData.BUTTONIDNO_EMPTY;
        buttonDrawUtil.mButtonInfoblv = false;
        buttonDrawUtil.mButtonResetblv = false;
        buttonDrawUtil.mButtonRedrawblv = false;

        mbClipAreaKind = (byte)Constants.SharedPerferenceData.GetIntSharedPerference(Constants.SharedPerferenceData.SP_KEY_GRAOHICSEDIT_CLIPKIND,buttonData.CLIPAREAKIND_RECT);
        iClipColorv = Constants.SharedPerferenceData.GetIntSharedPerference(Constants.SharedPerferenceData.SP_KEY_GRAOHICSEDIT_CLIPCOLOR,Color.WHITE);
        mcurClipAlpha = Constants.SharedPerferenceData.GetIntSharedPerference(Constants.SharedPerferenceData.SP_KEY_GRAOHICSEDIT_CLIPTRANSPARENT,202);

        mbTextKind = (byte)Constants.SharedPerferenceData.GetIntSharedPerference(Constants.SharedPerferenceData.SP_KEY_GRAOHICSEDIT_TEXTKIND,buttonData.TEXTICONKIND_HORIZONTAL);
        miTextColorv = Constants.SharedPerferenceData.GetIntSharedPerference(Constants.SharedPerferenceData.SP_KEY_GRAOHICSEDIT_TEXTCOLOR,Color.GREEN);
        miTextSize = Constants.SharedPerferenceData.GetIntSharedPerference(Constants.SharedPerferenceData.SP_KEY_GRAOHICSEDIT_TEXTSIZE,26);
        mstrMarkname = Constants.SharedPerferenceData.GetStringSharedPerference(Constants.SharedPerferenceData.SP_KEY_GRAOHICSEDIT_TEXTNAME,"Welcome to Beijing!");

        mbDrawKind = (byte)Constants.SharedPerferenceData.GetIntSharedPerference(Constants.SharedPerferenceData.SP_KEY_GRAOHICSEDIT_MARKKIND,buttonData.MARKICONKIND_LINE);
        miDrawColorv = Constants.SharedPerferenceData.GetIntSharedPerference(Constants.SharedPerferenceData.SP_KEY_GRAOHICSEDIT_MARKCOLOR,Color.RED);
        miLinewide = Constants.SharedPerferenceData.GetIntSharedPerference(Constants.SharedPerferenceData.SP_KEY_GRAOHICSEDIT_MARKLINEWD,26);
        miTransparentValue = Constants.SharedPerferenceData.GetIntSharedPerference(Constants.SharedPerferenceData.SP_KEY_GRAOHICSEDIT_MARKTRANSPARENT,200);
        mPolyLineList = new ArrayList();
    }

    public static Bitmap bitMapScale(Bitmap bitmap,float scale) {
        Matrix matrix = new Matrix();
        matrix.postScale(scale,scale); //长和宽放大缩小的比例
        Bitmap resizeBmp = Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true);
        return resizeBmp;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.save();
        int iwidth = canvas.getWidth();
        int iheight = canvas.getHeight();
        miViewWidth = iwidth;
        miViewHeight = iheight;

        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(Color.GREEN);
        mPaint.setStrokeWidth(1);

        GraphicItemUtil.mcurMarkType = GraphicItemUtil.MARKTYPE_EMPTY;
        // 重置显示按钮
        if(mButtonMenuResetblv || buttonDrawUtil.mButtonResetblv){
            mButtonMenuResetblv = false;
            checkResetButtonShow();
        }
        
        if(GraphicItemUtil.miItemActiveNum > 0) {
            if (buttonData.cActive_IDitem == buttonData.BUTTONIDNO_DELETE) {
                GraphicItemUtil.mcurMarkType = GraphicItemUtil.MARKTYPE_DELETE;
            }
            if (buttonData.cActive_IDitem == buttonData.BUTTONIDNO_DRAGMOVE) {
                GraphicItemUtil.mcurMarkType = GraphicItemUtil.MARKTYPE_DRAGMOVE;
            }
        }

        if(mcur_photoBipmap != null && drawBmpLockblv == false) {
            drawBmpLockblv = true;
            if (cnewPhotoblv == false) {
                // 更新背景图后,重新设置显示参数
                cnewPhotoblv = true;
                screenW = canvas.getWidth();
                screenH = canvas.getHeight();
                drawScreenW = (int)canvas.getWidth();
                drawScreenH = (int)canvas.getHeight();
                minimal = screenW;
                if (screenH < screenW) minimal = screenH;
                miniShowWhv = minimal/4;
                setMaxMinScale();
                translationX = (screenW - mcur_photoBipmap.getWidth() * scale) / 2;
                translationY = (screenH - mcur_photoBipmap.getHeight() * scale) / 2;
            }
            if (isLoaded) {
               // 处理背景图缩放显示
                imageZoomView(canvas);
            }

            drawBmpLockblv = false;
        }
        
        if(mgraItemHandle.checkGetGraItemNum() > 0){
            // 显示图形标记项目
            GraphicItemUtil.FSCALE = scale;
            GraphicItemUtil.TRANSLATIONx = translationX;
            GraphicItemUtil.TRANSLATIONy = translationY;
            mgraItemHandle.GraphicsOnDraw(canvas);
        }

        if(mdrawClipRectblv){
            // 画当前"裁剪或聚光"项目
            draw_ClipFocusItem(canvas);
        }

        if(mtxtShowblv && buttonData.cActive_IDitem == buttonData.BUTTONIDNO_TEXT){
            // 画当前"文字"项目
            draw_TextItem(canvas);
        }

        mdrawMarkSymblv = false;
        if(mdrawShowblv && buttonData.cActive_IDitem == buttonData.BUTTONIDNO_RUBBER){
           // 画当前"标记"项目
            draw_MarkItem(canvas);
        }

        if(mButDrawMenuHandle != null && bdataShowblv != true) {
            // 绘制菜单按钮
            mButDrawMenuHandle.redrawButtonLst(canvas);
        }

        mondraw_Processblv = false;
        canvas.restore();

    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        
    }

    public void setAppPackageName(String strPkname)
    {
        m_pkName = strPkname;
        m_EDITPICDIRName = strPkname;
    }

    public void SetEditPictureFiledir(String strPicdirname) {
        m_EDITPICDIRName = strPicdirname;
    }

    public int GetCanvasWidth()
    {
        return miViewWidth;
    }

    public int GetCanvasHeight()
    {
        return miViewHeight;
    }

    private boolean handle_NewGraphicsItem(byte gkind){
        boolean bnewblv = false;
        if(gkind == buttonData.BUTTONIDNO_TEXT){
            int ixpos =  (int) ((mtxtshowXpos - translationX) / scale);
            int iypos = (int) ((mtxtshowYpos - translationY) / scale);
            mgraItemHandle.appendOrupdateTextItem(mbTextKind,miTextColorv,miTextSize,ixpos,iypos,mstrMarkname);
            bnewblv = true;
            buttonData.cActive_IDitem = buttonData.BUTTONIDNO_EMPTY;
            mButtonCallback.onButtonClick(buttonData.BUTTONIDNO_VERIFYCLIP, 0,0,true);
            mButDrawMenuHandle.clearActiveItem();
        }
        //
        if(gkind == buttonData.BUTTONIDNO_RUBBER){
            if(mbDrawKind == buttonData.MARKICONKIND_LINE){
                if(mPolyLineList.size() >= 2){
                    ArrayList<Point> cPointLst= new ArrayList<>();
                    for(int jp = 0;jp < mPolyLineList.size();jp++){
                        Point cpoint = new Point();
                        cpoint.x =  (int) ((mPolyLineList.get(jp).x - translationX) / scale);
                        cpoint.y = (int) ((mPolyLineList.get(jp).y - translationY) / scale);
                        cPointLst.add(cpoint);
                    }
                    mgraItemHandle.appendOrupdateDrawItem(mbDrawKind,miDrawColorv,miLinewide,miTransparentValue,cPointLst);
                }
            }
            if(mbDrawKind == buttonData.MARKICONKIND_OVAL || mbDrawKind == buttonData.MARKICONKIND_SOLIDOVAL){
                float fLeft = mdrawFirstPreX;
                float fRight = mSecondX;
                if(fLeft > fRight){
                    fLeft = mSecondX;
                    fRight = mdrawFirstPreX;;
                }
                float fTop = mdrawFirstPreY;
                float fBottom = mSecondY;
                if(fTop > fBottom){
                    fTop = mSecondY;
                    fBottom = mdrawFirstPreY;
                };
                ArrayList<Point> cPointLst= new ArrayList<>();
                Point cpoint = new Point();
                cpoint.x =  (int) ((fLeft - translationX) / scale);
                cpoint.y = (int) ((fTop - translationY) / scale);
                cPointLst.add(cpoint);
                Point cpoint2 = new Point();
                cpoint2.x =  (int) ((fRight - translationX) / scale);
                cpoint2.y = (int) ((fBottom - translationY) / scale);
                cPointLst.add(cpoint2);
                mgraItemHandle.appendOrupdateDrawItem(mbDrawKind,miDrawColorv,miLinewide,miTransparentValue,cPointLst);
            }
            if(mbDrawKind == buttonData.MARKICONKIND_ARROW){
                ArrayList<Point> cPointLst= new ArrayList<>();
                Point cpoint = new Point();
                cpoint.x =  (int) ((mdrawFirstPreX - translationX) / scale);
                cpoint.y = (int) ((mdrawFirstPreY - translationY) / scale);
                cPointLst.add(cpoint);
                Point cpoint2 = new Point();
                cpoint2.x =  (int) ((mSecondX - translationX) / scale);
                cpoint2.y = (int) ((mSecondY - translationY) / scale);
                cPointLst.add(cpoint2);
                mgraItemHandle.appendOrupdateDrawItem(mbDrawKind,miDrawColorv,miLinewide,miTransparentValue,cPointLst);
            }
            bnewblv = true;
            buttonData.cActive_IDitem = buttonData.BUTTONIDNO_EMPTY;
            mButtonCallback.onButtonClick(buttonData.BUTTONIDNO_VERIFYCLIP, 0,0,true);
            mButDrawMenuHandle.clearActiveItem();
        }
        //
        if(gkind == buttonData.BUTTONIDNO_CLIP){
            Rect clipRect = new Rect();
            clipRect.left = (int) ((mdrawClipRectF.left - translationX) / scale);
            clipRect.right = (int) ((mdrawClipRectF.right - translationX) / scale);
            clipRect.top = (int) ((mdrawClipRectF.top - translationY) / scale);
            clipRect.bottom = (int) ((mdrawClipRectF.bottom - translationY) / scale);
            mgraItemHandle.appendOrupdateClipItem(mbClipAreaKind,iClipColorv,clipRect);
            GraphicItemUtil.miClipAlpha = mcurClipAlpha;
            bnewblv = true;
            buttonData.cActive_IDitem = buttonData.BUTTONIDNO_EMPTY;
            mButtonCallback.onButtonClick(buttonData.BUTTONIDNO_VERIFYCLIP, 0,0,true);
            mButDrawMenuHandle.clearActiveItem();
        }
        return bnewblv;
    };

    public void updateSetClip(byte bkind,int iclipColor,int iTransparent)
    {
        mbClipAreaKind = bkind;
        iClipColorv = iclipColor;
        mcurClipAlpha = iTransparent;
    }

    public void updateSetText(byte bkind,int itxtColor,int ifntsize,String markName)
    {
        mbTextKind = bkind;
        miTextColorv = itxtColor;
        miTextSize = ifntsize;
        mstrMarkname = markName;
    }

    public void updateSetDraw(byte bkind,int iColor,int iLinewide,int iTransparent)
    {
        mbDrawKind = bkind;
        miDrawColorv = iColor;
        miLinewide = iLinewide;
        miTransparentValue = iTransparent;
    }

    public void SAVEINITRESET(String strTimeFilename)
    {
        mcur_TIMEFILENAME = strTimeFilename;
        GraphicItemUtil.mcurMarkType = GraphicItemUtil.MARKTYPE_EMPTY;
        if(mgraItemHandle != null) {
            mButDrawMenuHandle.resetActiveButton();
        }
        buttonData.cActive_IDitem = buttonData.BUTTONIDNO_EMPTY;
    }

    private void checkResetButtonShow()
    {
        if(mgraItemHandle != null) {
            mButDrawMenuHandle.checkResetButtonShow(GraphicItemUtil.miundoPosj, GraphicItemUtil.miItemActiveNum);
        }
    }

    private void imageZoomView(Canvas canvas){
        currentW = primaryW * scale;
        currentH = primaryH * scale;
        matrix.reset();
        matrix.postScale(scale, scale);//x轴y轴缩放
        peripheryJudge();
        matrix.postTranslate(translationX, translationY);//中点坐标移动
        canvas.drawBitmap(mcur_photoBipmap, matrix, null);
    }

    /**
     * 图片边界检查
     */
    private void peripheryJudge(){
        float screenWmin = screenW/2-mcur_photoBipmap.getWidth()*scale;
        float screenWmax = screenW/2;
        float screenHmin = screenH/2- mcur_photoBipmap.getHeight()*scale;
        float screenHmax = screenH/2;
        if (translationX < screenWmin){
            translationX = screenWmin;
        }
        if (translationY < screenHmin){
            translationY = screenHmin;
        }
        if (translationX > screenWmax){
            translationX = screenWmax;
        }
        if (translationY > screenHmax){
            translationY = screenHmax;
        }
    }

    public void appendEditButton(buttonData cbutData)
    {
        if(mButDrawMenuHandle != null){
            mButDrawMenuHandle.appendButtonItem(cbutData);
        };
    }
    // about measure onLayout
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //  1.measure children and  measure  self
        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);

        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);

        int width = 0;
        int height = 0;

        int lineWidth = 0;
        int lineHeight = 0;

        int childCount = getChildCount();
        int mt_Lineno = 0;
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            measureChild(child, widthMeasureSpec, heightMeasureSpec);

            MarginLayoutParams childLayoutParams = (MarginLayoutParams) child.getLayoutParams();
            int childMeasuredHeight = child.getMeasuredHeight() + childLayoutParams.bottomMargin + childLayoutParams.topMargin;
            int childMeasuredWidth = child.getMeasuredWidth() + childLayoutParams.leftMargin + childLayoutParams.rightMargin;
            int jno = (int) child.getTag(five);
            int icLino = jno/1000;
            if (mt_Lineno != icLino){// lineWidth + childMeasuredWidth > widthSpecSize) {//The line is full
                mt_Lineno = icLino;
                width = Math.max(lineWidth, childMeasuredWidth);
                height = lineHeight + height;
                lineWidth = childMeasuredWidth;
                lineHeight = childMeasuredWidth;
            } else {
                //record line info
                lineWidth = lineWidth + childMeasuredWidth;
                lineHeight = Math.max(lineHeight, childMeasuredHeight);
            }

            if (i == childCount - 1) { //The last one
                width = Math.max(width, lineWidth);
                height += lineHeight;
            }

        }
        // 2.set params
        setMeasuredDimension(widthSpecMode == MeasureSpec.EXACTLY ? widthSpecSize : width,
                heightSpecMode == MeasureSpec.EXACTLY ? heightSpecSize : height
        );

    }

    public boolean checkGetItemIfOK(byte bchkITEM) {
        boolean cbretbv = false;
        if(bchkITEM == CHECKITEMGRA_CLIP){
            if(checkGraClipItemNum() > 0) cbretbv = true;
        }
        if(bchkITEM == CHECKITEMGRA_GRANUM){
            if(checkGraItemNum() > 0) cbretbv = true;
        }

        return cbretbv;
    }

    List<Integer> eachLineHeight = new ArrayList<>();
    List<List<View>> allViews = new ArrayList<>();

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // 1. record how many views each row and   get max height of the row
        eachLineHeight.clear();
        allViews.clear();

        int childCount = getChildCount();
        int lineWidth = 0;
        int lineHeight = 0;
        List<View> lineViews = new ArrayList<>();
        int mt_Lineno = 0;
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            MarginLayoutParams layoutParams = (MarginLayoutParams) child.getLayoutParams();
            int childMeasuredHeight = child.getMeasuredHeight() + layoutParams.bottomMargin + layoutParams.topMargin;
            int childMeasuredWidth = child.getMeasuredWidth() + layoutParams.leftMargin + layoutParams.rightMargin;

            int jno = (int) child.getTag(five);
            int icLino = jno/1000;
            if (mt_Lineno != icLino){// if (lineWidth + childMeasuredWidth > getWidth()) {//The line is full
                mt_Lineno = icLino;
                lineWidth = 0;
                eachLineHeight.add(lineHeight);
                allViews.add(lineViews);
                lineViews = new ArrayList<>();
            }//The line is not full

            lineHeight = Math.max(lineHeight, childMeasuredHeight);
            lineWidth = lineWidth + childMeasuredWidth;
            lineViews.add(child);

            if (i == childCount - 1) {//The last one
                eachLineHeight.add(lineHeight);
                allViews.add(lineViews);
            }

            final int finalI = i;
            child.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mCallback != null) {// set callback
                        int jno = (int) v.getTag(five);
                        mCallback.onItemClick(finalI,jno);
                    }
                }
            });
        }

        int left = 0;
        int top = 0;

        for (int i = 0; i < allViews.size(); i++) {

            List<View> views = allViews.get(i);
            lineHeight = eachLineHeight.get(i);

            //   2. layout   row
            for (int j = 0; j < views.size(); j++) {
                View child = views.get(j);
                if (child.getVisibility() == View.GONE) {
                    continue;
                }
                MarginLayoutParams lp = (MarginLayoutParams) child
                        .getLayoutParams();
                //calc childView's left,top,right,bottom
                int lc = left + lp.leftMargin;
                int tc = top + lp.topMargin;
                int rc = lc + child.getMeasuredWidth();
                int bc = tc + child.getMeasuredHeight();
                child.layout(lc, tc, rc, bc);

                left += child.getMeasuredWidth() + lp.rightMargin
                        + lp.leftMargin;
                Point point = new Point();
                point.x = lc+xoffv;
                point.y = tc+yoffv;
                child.setTag(point);
            }
            top = top + lineHeight;
            left = 0;
        }
    }
    private float checkIfScaleOK(float forgScale,float moveScale)
    {
        float fmovScale = -1f;
        float curScale = scale * moveScale;
         if(curScale < minScale){
               fmovScale =  minScale/scale;
         }else if(curScale > maxScale){
               fmovScale = maxScale/scale;
         }else{
                fmovScale = moveScale;
        }
        return fmovScale;
    }
    /**
     *
     */
    private void setMaxMinScale(){
        float xScale, yScale;

        xScale = minimal / primaryW;
        yScale = minimal / primaryH;
        mcurScale = xScale > yScale ? xScale : yScale;
        minScale = (float)(mcurScale*0.5);
        scale = mcurScale;
        xScale = primaryW / screenW;
        yScale = primaryH / screenH;
        if (xScale > 1 || yScale > 1 ) {
            if (xScale > yScale) {
                maxScale = 1/xScale;
            }else {
                maxScale = 1/yScale;
            }
        }else {
            if (xScale > yScale) {
                maxScale = 1/xScale;
            }else {
                maxScale = 1/yScale;
            }
        }
        if(maxScale > 3) maxScale = 3;
        if(maxScale < 2f) maxScale = 2f;
        if(maxScale < minScale) maxScale = minScale*3;

    }

    private boolean graStatusCheck(MotionEvent event){
        boolean cretblv = false;
        float moveX = event.getX();
        float moveY = event.getY();
        float moveDistanceX = moveX - mFirstX;
        float moveDistanceY = moveY - mFirstY;
        if(Math.abs(moveDistanceX) > miniShowWhv || Math.abs(moveDistanceY) > miniShowWhv) {
            if (Math.abs(moveDistanceX) > Math.abs(moveDistanceY)) {
                translationX = translationX + moveDistanceX;
                cretblv = true;
            }else{
                translationY = translationY + moveDistanceY;
                cretblv = true;
            }
        }
        return cretblv;
    }

    private void isClickButtonRegion(){
        mbuttonClickblv = false;
        if(mFirstX >= buttonDrawUtil.fcLeft && mFirstX <= buttonDrawUtil.fcRight){
            if(mFirstY >= buttonDrawUtil.fcTop && mFirstY <= buttonDrawUtil.fcBottom){
                mbuttonClickblv = true;
            }
        }
    }

    private boolean isClickDrawTextRegion(float fx,float fy){
        boolean cretblv = false;
        if(fx >= mdrawtxt_markFRect.left && fx <= mdrawtxt_markFRect.right){
            if(fy >= mdrawtxt_markFRect.top && fy <= mdrawtxt_markFRect.bottom){
                cretblv = true;
            }
        }
        return cretblv;
    }

    private boolean isClickDrawRubberRegion(float fx,float fy){
        boolean cretblv = false;
        if(mdrawMarkSymblv) {
            if (fx >= mdrawRubber_markFRect.left && fx <= mdrawRubber_markFRect.right) {
                if (fy >= mdrawRubber_markFRect.top && fy <= mdrawRubber_markFRect.bottom) {
                    cretblv = true;
                }
            }
        }
        return cretblv;
    }
    /**
     * 判断手指是否点在图片内(单指)
     */
    private void isClickInImage(){
        boolean cnotButtonblv = true;
        mbuttonClickblv = false;
        if(mFirstX >= buttonDrawUtil.fcLeft && mFirstX <= buttonDrawUtil.fcRight){
            if(mFirstY >= buttonDrawUtil.fcTop && mFirstY <= buttonDrawUtil.fcBottom){
                cnotButtonblv = false;
                mbuttonClickblv = true;
            }
        }
        if(cnotButtonblv) {
            isClickInImage = true;
            if(buttonData.cActive_IDitem != buttonData.BUTTONIDNO_EMPTY){// edit picture
                isClickInImage = false;
                return;
            }
        }else {
            isClickInImage = false;
        }
    }
    /** 移动操作  */
    private void movingAction(MotionEvent event){
        float moveX = event.getX();
        float moveY = event.getY();
        if (lastMoveX == -1 || lastMoveY == -1) {
            lastMoveX = moveX;
            lastMoveY = moveY;
        }
        float moveDistanceX = moveX - lastMoveX;
        float moveDistanceY = moveY - lastMoveY;
        translationX = translationX + moveDistanceX;
        translationY = translationY + moveDistanceY;
        lastMoveX = moveX;
        lastMoveY = moveY;
        invalidate();
    }
    public void setButtonWide(int ibwide) {
        mbuttonMoveWidth = ibwide;
    }
    /**  缩放操作  */
    private void zoomAction(MotionEvent event){
        midPoint(event);
        float currentDistance = getFingerDistance(event);
        if (Math.abs(currentDistance - fingerDistance) > 1f) {
            float moveScale = currentDistance / fingerDistance;
            //... float fcurScale = scale * moveScale;
            moveScale = checkIfScaleOK(scale,moveScale);
            if(moveScale > 0f){
                scale = scale * moveScale;
                translationX = translationX * moveScale + centPointX * (1 - moveScale);
                translationY = translationY * moveScale + centPointY * (1 - moveScale);
                fingerDistance = currentDistance;
                invalidate();
            }
        }
    }

    private void operIndicateSound() {
        Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        Ringtone r = RingtoneManager.getRingtone(mcontext, notification);
        r.play();
    }

    private void touchUpOrCancel(MotionEvent event){
        mPressBreak = true;
        mdrawClipRectblv = false;
        lastMoveX = -1;
        lastMoveY = -1;
        mLocker = 0;
        boolean curButtonClickblv = false;
        if(mbuttonClickblv && !mLongMoveblv && !mFingerNum2blv) curButtonClickblv = true;
        if(curButtonClickblv) {
            if (mLongClickblv == false) {
                mButtonUpTimev = System.currentTimeMillis();
                long durationMs = mButtonUpTimev - mButtonDownTimev;
                if (durationMs > LONGPRESS_TIME) {
                    mLongClickblv = true;
                }
            }
            if(mLongClickblv == false || !mLongClickButtonblv) {
                isSelectButton(event, mLongClickblv);
            }
        }else {
            if (buttonData.cActive_IDitem == buttonData.BUTTONIDNO_DRAGMOVE) {
                if(mdrawItemDelDragClickblv && mLongMoveblv && mLongClickblv){
                    mdrawItemDelDragClickblv = false;
                    if (mgraItemHandle.confirmDragMoveItem()) {
                        ;
                    };
                };
            }
            if (buttonData.cActive_IDitem == buttonData.BUTTONIDNO_DELETE) {
                mstrTraceInfo = "DEL:"+String.valueOf(mdrawItemDelDragClickblv)+",Move:"+String.valueOf(mLongMoveblv)+",Click:"+String.valueOf(mLongClickblv);//xxxxxxxx
                if(mdrawItemDelDragClickblv && !mLongMoveblv && mLongClickblv){
                    mdrawItemDelDragClickblv = false;
                    mstrTraceInfo = mstrTraceInfo +",PASS";
                    if (mgraItemHandle.confirmDeleteSelItem()) {
                        ;
                    };
                };
            }
            if (buttonData.cActive_IDitem == buttonData.BUTTONIDNO_TEXT) {
                boolean clickYesTxtblv = false;
                if(mdrawtxtClickblv && mLongClickblv && !mLongMoveblv){
                    clickYesTxtblv = isClickDrawTextRegion(event.getX(),event.getY());
                    if(clickYesTxtblv){
                        handle_NewGraphicsItem(buttonData.BUTTONIDNO_TEXT);
                        invalidate();
                    }
                };
            }
            if (buttonData.cActive_IDitem == buttonData.BUTTONIDNO_RUBBER) {
                boolean clickYesMarkblv = false;
                if(mdrawRubberClickblv && mLongClickblv && !mLongMoveblv){
                    clickYesMarkblv = isClickDrawRubberRegion(event.getX(),event.getY());
                    if(clickYesMarkblv){
                        handle_NewGraphicsItem(buttonData.BUTTONIDNO_RUBBER);
                        invalidate();
                    }
                };
            }
            if (buttonData.cActive_IDitem == buttonData.BUTTONIDNO_CLIP) {
                if(mselectClipOperblv){
                    mselectClipOperblv = false;
                    handle_NewGraphicsItem(buttonData.BUTTONIDNO_CLIP);
                    invalidate();
                }else{
                }

            }
        };
        if (buttonData.cActive_IDitem == buttonData.BUTTONIDNO_CLIP){
            mgraItemHandle.setClipSelRunStatus(true);
        }else{
            mgraItemHandle.setClipSelRunStatus(false);
        }
        lastMoveX = -1;
        lastMoveY = -1;
    }

    private void graphicsModeMove(MotionEvent event)
    {
        // click button or draw graphics
        mTimeMove = System.currentTimeMillis();
        if (mLongClickblv == false) {
            long durationMs = mTimeMove - mButtonDownTimev;
            if (durationMs > LONGPRESS_TIME) {
                mLongClickblv = true;
            }
        }
        if (mLongMoveblv == false) {
            float fxmove = Math.abs(event.getX() - mFirstX);
            float fymove = Math.abs(event.getY() - mFirstY);
            if (fxmove >= mbuttonMoveWidth || fymove >= mbuttonMoveWidth) {
                mLongMoveblv = true;
            }
        }
        if (mbuttonClickblv) {// click button area
            mstrTraceInfo = mstrTraceInfo+"button,";//xxxxxxxx
            if (mLongMoveblv) {// long move not click button
                if (buttonData.cActive_IDitem == buttonData.BUTTONIDNO_EMPTY) {
                    float fingerNum = event.getPointerCount();
                    if (fingerNum == 1 && mLocker == 0) {
                        movingAction(event);
                    } else if (fingerNum == 2) {
                        zoomAction(event);
                        mFingerNum2blv = true;
                    }
                }
                if (buttonData.cActive_IDitem == buttonData.BUTTONIDNO_CLIP) {
                    mCliprect.right = (int) event.getX();
                    mCliprect.bottom = (int) event.getY();
                    if(Math.abs(mCliprect.right-mCliprect.right) > miniShowWhv && Math.abs(mCliprect.bottom-mCliprect.top) > miniShowWhv){
                        invalidate();
                    }
                }
                if (buttonData.cActive_IDitem == buttonData.BUTTONIDNO_TEXT) {
                    mtxtshowXpos = (int) event.getX();
                    mtxtshowYpos = (int) event.getY();
                    mtxtShowblv = true;
                }
                if (buttonData.cActive_IDitem == buttonData.BUTTONIDNO_RUBBER) {
                    if(mLongMoveblv) {
                        if(mdrawDownPrimitiveblv){
                            mdrawFirstX = mFirstX;
                            mdrawFirstY = mFirstY;
                        }
                        if(mbDrawKind == buttonData.MARKICONKIND_LINE){
                            if(mdrawDownPrimitiveblv && mPolyLineList.size() > 0){
                                mPolyLineList.clear();
                            }
                            if(mPolyLineList.size() <= 0){
                                Point firstpnt = new Point((int)mFirstX,(int)mFirstY);
                                mPolyLineList.add(firstpnt);
                                Point secondpnt = new Point((int) event.getX(),(int) event.getY());
                                mPolyLineList.add(secondpnt);
                                mdrawFirstX = event.getX();
                                mdrawFirstY = event.getY();
                                mFirstX = event.getX();
                                mFirstY = event.getY();
                                mLongMoveblv = false;
                            }else{
                                Point secondpnt = new Point((int) event.getX(),(int) event.getY());
                                if(mPolyLineList.size() < 20) {
                                    mPolyLineList.add(secondpnt);
                                    mdrawFirstX = event.getX();
                                    mdrawFirstY = event.getY();
                                    mFirstX = event.getX();
                                    mFirstY = event.getY();
                                    mLongMoveblv = false;
                                }else{
                                    int indexpj = mPolyLineList.size()-1;
                                    mPolyLineList.set(indexpj,secondpnt);
                                }
                            }
                        }else{
                            mSecondX = event.getX();
                            mSecondY = event.getY();
                        }
                        mdrawShowblv = true;
                        mdrawDownPrimitiveblv = false;
                    }
                }
            }else{
                if(mLongClickblv){// long press
                    if(!mLongClickButtonblv) {
                        mLongClickButtonblv = true;
                        isSelectButton(event, true);
                    }
                }
            }
        }else{// not click button
            float fingerNum = event.getPointerCount();
            if (fingerNum == 1 && mLocker == 0) {
                if (buttonData.cActive_IDitem == buttonData.BUTTONIDNO_CLIP) {
                    mCliprect.right = (int) event.getX();
                    mCliprect.bottom = (int) event.getY();
                    if(Math.abs(mCliprect.right-mCliprect.right) > miniShowWhv && Math.abs(mCliprect.bottom-mCliprect.top) > miniShowWhv){
                        invalidate();
                    }
                };
                if (buttonData.cActive_IDitem == buttonData.BUTTONIDNO_TEXT) {
                    boolean clickYesTxtblv = false;
                    if(mdrawtxtClickblv && mLongClickblv && !mLongMoveblv){
                        clickYesTxtblv = isClickDrawTextRegion(event.getX(),event.getY());
                        if(clickYesTxtblv){
                            //???? handler.sendEmptyMessage(APPENDGRAPHICSITEM_TEXT);
                        }
                    };
                    if(!clickYesTxtblv) {
                        if(!mdrawtxtClickblv || mLongMoveblv) {
                            mtxtshowXpos = (int) event.getX();
                            mtxtshowYpos = (int) event.getY();
                        }
                        mtxtShowblv = true;
                    }
                }
                // delete
                if (buttonData.cActive_IDitem == buttonData.BUTTONIDNO_DELETE) {
                    invalidate();//xxxxxxxxxx
                }
                // drag move
                if (buttonData.cActive_IDitem == buttonData.BUTTONIDNO_DRAGMOVE) {
                    if(mdrawItemDelDragClickblv && mLongMoveblv){//  && !mdraw_DragMoveLockblv){
                        mdraw_DragMoveLockblv = true;
                        int ixOffv = (int)((event.getX() - mFirstX)/scale);
                        int iyOffv = (int)((event.getY() - mFirstY)/scale);
                        if(mondraw_Processblv == false){// &&(ixOffv != 0 || iyOffv != 0)) {
                            if (mgraItemHandle.updateSetDragMovePara(ixOffv, iyOffv)) {
                                mondraw_Processblv = true;
                                handler.sendEmptyMessage(DRAGMOVEGRAITEM_REDRAW);
                            }
                        }
                        mdraw_DragMoveLockblv = false;
                    }else {
                    }
                }
                // rubber
                if (buttonData.cActive_IDitem == buttonData.BUTTONIDNO_RUBBER) {
                    boolean clickYesMarkblv = false;
                    if(mdrawRubberClickblv && mLongClickblv && !mLongMoveblv){
                        clickYesMarkblv = isClickDrawRubberRegion(event.getX(),event.getY());
                        if(clickYesMarkblv){
                            //???? handler.sendEmptyMessage(APPENDGRAPHICSITEM_TEXT);
                        }
                    };
                    if(!clickYesMarkblv) {
                        if(mLongMoveblv) {
                            if(mdrawDownPrimitiveblv){
                                mdrawFirstX = mFirstX;
                                mdrawFirstY = mFirstY;
                            }
                            if(mbDrawKind == buttonData.MARKICONKIND_LINE){
                                if(mdrawDownPrimitiveblv && mPolyLineList.size() > 0){
                                    mPolyLineList.clear();
                                }
                                if(mPolyLineList.size() <= 0){
                                    Point firstpnt = new Point((int)mFirstX,(int)mFirstY);
                                    mPolyLineList.add(firstpnt);
                                    Point secondpnt = new Point((int) event.getX(),(int) event.getY());
                                    mPolyLineList.add(secondpnt);
                                    mdrawFirstX = event.getX();
                                    mdrawFirstY = event.getY();
                                    mFirstX = event.getX();
                                    mFirstY = event.getY();
                                    mLongMoveblv = false;
                                }else{
                                    Point secondpnt = new Point((int) event.getX(),(int) event.getY());
                                    if(mPolyLineList.size() < 20) {
                                        mPolyLineList.add(secondpnt);
                                        mdrawFirstX = event.getX();
                                        mdrawFirstY = event.getY();
                                        mFirstX = event.getX();
                                        mFirstY = event.getY();
                                        mLongMoveblv = false;
                                    }else{
                                        int indexpj = mPolyLineList.size()-1;
                                        mPolyLineList.set(indexpj,secondpnt);
                                    }
                                }
                            }else{
                                mSecondX = event.getX();
                                mSecondY = event.getY();
                            }
                            mdrawShowblv = true;
                            mdrawDownPrimitiveblv = false;
                        }
                    }
                }
            } else if (fingerNum == 2) {
                mstrTraceInfo = mstrTraceInfo+",Zoom";//xxxxxxxx
                mFingerNum2blv = true;
                zoomAction(event);
            }
        }
    }

    private void isSelectButton(MotionEvent event,boolean isClickLongblv){
        Point fdpoint = new Point(0,0);
        boolean cButtonblv = false;
        if(clickDownFirstblv){
            fdpoint.x = (int)mFirstX;
            fdpoint.y = (int)mFirstY;
            cButtonblv = true;
        }else {
            if(event != null) {
                fdpoint.x = (int) event.getX();
                fdpoint.y = (int) event.getY();
            }else{
                fdpoint.x = (int)mFirstX;
                fdpoint.y = (int)mFirstY;
                cButtonblv = true;;
            }
        }
        if(cButtonblv){
            byte bClickKind = buttonData.BUTTONCLICK_SHORT;
            long ltimeSpace = mButtonUpTimev-mButtonDownTimev;
            if(ltimeSpace >= LONGPRESS_TIME || isClickLongblv){
                bClickKind = buttonData.BUTTONCLICK_LONG;
            }
            byte selItemID = mButDrawMenuHandle.FindClickButtonItemIDno(fdpoint,bClickKind);
            if(selItemID != buttonData.BUTTONIDNO_EMPTY) {
                int ixoff = buttonDrawUtil.cbutRect.left;
                int iyoff = buttonDrawUtil.cbutRect.top-mbuttonMoveWidth*2;
                // restore
                if (selItemID == buttonData.BUTTONIDNO_RESTORE) {
                    if (buttonDrawUtil.mButtonResetblv){// bClickKind == buttonData.BUTTONCLICK_LONG) {
                        handler.sendEmptyMessage(PICTURERESTORE);
                    } else {
                        operIndicateSound();
                        mButtonCallback.onButtonClick(selItemID, ixoff, iyoff,false);
                    }
                }else if(selItemID == buttonData.BUTTONIDNO_SAVE){
                    if (buttonDrawUtil.mButtonResetblv){
                        mButtonCallback.onButtonClick(selItemID, ixoff, iyoff,true);
                    } else {
                        operIndicateSound();
                        mButtonCallback.onButtonClick(selItemID, ixoff, iyoff,false);
                    };
                }else{
                    if(buttonDrawUtil.mButtonRedrawblv){
                        handler.sendEmptyMessage(PICTUREONDRAW);
                    }
                    if(buttonDrawUtil.mButtonResetblv){
                        mButtonCallback.onButtonClick(selItemID, ixoff, iyoff,true);
                    }else{
                        if(buttonDrawUtil.mButtonInfoblv) {
                            operIndicateSound();
                            mButtonCallback.onButtonClick(selItemID, ixoff, iyoff,false);
                        };
                    }
                }
            }
        }else{
            // mstrTraceInfo = mstrTraceInfo+">>gggg";//xxxxxx
            //... mButtonCallback.onButtonClick(buttonData.BUTTONIDNO_RESTORE,-1,-1);;
        }
        invalidate();//xxxxxxx
    }
    /**  判断手指是否点在图片内(双指)
     * 只要有一只手指在图片内就为true
     */
    private void isClickInImage(MotionEvent event){
        boolean cnotButtonblv = true;
        if(event.getX(0) >= buttonDrawUtil.fcLeft && event.getX(0) <= buttonDrawUtil.fcRight){
            if(event.getY(0) >= buttonDrawUtil.fcTop && event.getY(0) <= buttonDrawUtil.fcBottom){
                cnotButtonblv = false;
                mbuttonClickblv = true;
            }
        }
        if(cnotButtonblv){
            if(event.getX(1) >= buttonDrawUtil.fcLeft && event.getX(1) <= buttonDrawUtil.fcRight){
                if(event.getY(1) >= buttonDrawUtil.fcTop && event.getY(1) <= buttonDrawUtil.fcBottom){
                    cnotButtonblv = false;
                    mbuttonClickblv = true;
                }
            };
        }
        isClickInImage = cnotButtonblv;// true;
        if(buttonData.cActive_IDitem != buttonData.BUTTONIDNO_EMPTY){// edit picture
            isClickInImage = false;
        }
    }

    /**  获取两指间的距离  */
    private float getFingerDistance(MotionEvent event){
        float x = event.getX(1) - event.getX(0);
        float y = event.getY(1) - event.getY(0);
        return (float) Math.sqrt(x * x + y * y);
    }

    /** 获取两指间的中点坐标  */
    private void midPoint(MotionEvent event){
        centPointX = (event.getX(1) + event.getX(0))/2;
        centPointY = (event.getY(1) + event.getY(0))/2;
    }

    public int checkGraItemNum()
    {
        return mgraItemHandle.checkGetCurGraItem();
    }

    public int checkGraClipItemNum()
    {
        return mgraItemHandle.checkGetCurGraClipItem();
    }

    public String SaveEditPicture(boolean clipblv)
    {
        String curEditPicName = "";
        if(saveEditImage(clipblv)){
            mgraItemHandle.clearGraphicsItem();
            curEditPicName = msaveEditPictureName;
        }
        return curEditPicName;
    }

    public String doExeClipEditPicture()
    {
        boolean clipblv = true;
        String curEditPicName = "";
        if(clipEditPicture()){
            mgraItemHandle.clearGraphicsItem();
            curEditPicName = msaveEditPictureName;
        }
        return curEditPicName;
    }

    public String ConfirmGetEditPicture()
    {
        String curEditPicName = "";
        if(yesGetEditPicture()){
            mgraItemHandle.clearGraphicsItem();
            curEditPicName = msaveEditPictureName;
        }
        return curEditPicName;
    }

    public String doExeSaveEditPicture()
    {
        String curEditPicName = "";
        GraphicItemUtil.mcurMarkType = GraphicItemUtil.MARKTYPE_EMPTY;
        if(mgraItemHandle != null) {
            mButDrawMenuHandle.resetActiveButton();
        }
        if(saveEditImage()){
            mgraItemHandle.clearGraphicsItem();
            curEditPicName = msaveEditPictureName;
        }
        return curEditPicName;
    }

    private boolean saveEditImage() {
        boolean cretblv = false;
        //创建一个bitmap,并放入画布。
        Bitmap bitmap = Bitmap.createBitmap(mcur_photoBipmap.getWidth(), mcur_photoBipmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);// mcur_photoBipmap);
        canvas.drawBitmap(mcur_photoBipmap, 0,0, null);
        if(mgraItemHandle.miItemActiveNum > 0){
            GraphicItemUtil.FSCALE = 1;
            GraphicItemUtil.TRANSLATIONx = 0;
            GraphicItemUtil.TRANSLATIONy = 0;
            mgraItemHandle.GraphicsOnDraw(canvas);
        }
        // 保存绘制的内容
        msaveEditPictureName = Environment.getExternalStorageDirectory() + "/"+m_pkName+"/20220916img.jpg";;
        File imgFile = new File(msaveEditPictureName);
        try {
            OutputStream os = new FileOutputStream(imgFile);//创建输出流
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);//通过输出流将图片保存
            cretblv = true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return cretblv;
    }

    private boolean saveEditImage(boolean clipblv) {
        boolean cretblv = false;
        //创建一个bitmap,并放入画布。
        Bitmap bitmap = Bitmap.createBitmap(mcur_photoBipmap.getWidth(), mcur_photoBipmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);// mcur_photoBipmap);
        canvas.drawBitmap(mcur_photoBipmap, 0,0, null);
        if(mgraItemHandle.miItemActiveNum > 0){
            GraphicItemUtil.FSCALE = 1;
            GraphicItemUtil.TRANSLATIONx = 0;
            GraphicItemUtil.TRANSLATIONy = 0;
            mgraItemHandle.GraphicsOnDraw(canvas);
        }
        // 保存绘制的内容
        String FileTime = mcur_TIMEFILENAME;// "2022-09-24_13_02_26";//xxx timesdf.format(new Date()).toString();//获取系统时间
        String mpicDatefileName = "";
        msaveEditPictureName = m_EDITPICDIRName+"/eview_"+FileTime+".jpg";
        if(clipblv){
            mpicDatefileName = msaveEditPictureName;
            msaveEditPictureName = m_EDITPICDIRName+"/eview_CLIP20220922.jpg";
        }
        File imgFile = new File(msaveEditPictureName);
        try {
            OutputStream os = new FileOutputStream(imgFile);//创建输出流
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);//通过输出流将图片保存
            cretblv = true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        if(cretblv){
            Rect mclipRect = mgraItemHandle.getOndrawClipRect();
            byte clipKind = mgraItemHandle.getOndrawClipKind();
            Bitmap cbmp = null;
            if(clipKind == buttonData.CLIPAREAKIND_RECT) {
                cbmp = BitMapUtil.ImageCropWithClipRect(bitmap, mclipRect);
            }
            if(clipKind == buttonData.CLIPAREAKIND_OVAL) {
                cbmp = BitMapUtil.ImageClipWithOval(bitmap, mclipRect);
            }
            if (cbmp != null && mpicDatefileName.length() > 0) {
                msaveEditPictureName = mpicDatefileName;
                File img2File = new File(msaveEditPictureName);
                cretblv = false;
                if(clipKind == buttonData.CLIPAREAKIND_RECT) {
                    try {
                        OutputStream os = new FileOutputStream(img2File);//创建输出流
                        cbmp.compress(Bitmap.CompressFormat.JPEG, 100, os);//通过输出流将图片保存
                        cretblv = true;
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                }
                if(clipKind == buttonData.CLIPAREAKIND_OVAL) {
                    try {
                        OutputStream os = new FileOutputStream(img2File);//创建输出流
                        cbmp.compress(Bitmap.CompressFormat.PNG, 100, os);//通过输出流将图片保存
                        cretblv = true;
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return cretblv;
    }

    public String getTraceInfo()
    {
        return mstrTraceInfo;
    }

    private boolean clipEditPicture() {
        boolean cretblv = false;
        //创建一个bitmap,并放入画布。
        Bitmap bitmap = Bitmap.createBitmap(mcur_photoBipmap.getWidth(), mcur_photoBipmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);// mcur_photoBipmap);
        canvas.drawBitmap(mcur_photoBipmap, 0,0, null);
        if(mgraItemHandle.miItemActiveNum > 0){
            GraphicItemUtil.FSCALE = 1;
            GraphicItemUtil.TRANSLATIONx = 0;
            GraphicItemUtil.TRANSLATIONy = 0;
            mgraItemHandle.GraphicsOnDraw(canvas);
        }
        // 保存绘制的内容
        String FileTime = "CLIPIMAGE2022929AB";
        String mpicDatefileName = "";
        msaveEditPictureName = m_EDITPICDIRName+"/eview_"+FileTime+".jpg";
        mpicDatefileName = msaveEditPictureName;
        msaveEditPictureName = m_EDITPICDIRName+"/eview_CLIP20220922.jpg";
        File imgFile = new File(msaveEditPictureName);
        try {
            OutputStream os = new FileOutputStream(imgFile);//创建输出流
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);//通过输出流将图片保存
            cretblv = true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        if(cretblv){
            Rect mclipRect = mgraItemHandle.getOndrawClipRect();
            byte clipKind = mgraItemHandle.getOndrawClipKind();
            Bitmap cbmp = null;
            if(clipKind == buttonData.CLIPAREAKIND_RECT) {
                cbmp = BitMapUtil.ImageCropWithClipRect(bitmap, mclipRect);
            }
            if(clipKind == buttonData.CLIPAREAKIND_OVAL) {
                cbmp = BitMapUtil.ImageClipWithOval(bitmap, mclipRect);
            }
            if (cbmp != null && mpicDatefileName.length() > 0) {
                msaveEditPictureName = mpicDatefileName;
                File img2File = new File(msaveEditPictureName);
                cretblv = false;
                if(clipKind == buttonData.CLIPAREAKIND_RECT) {
                    try {
                        OutputStream os = new FileOutputStream(img2File);//创建输出流
                        cbmp.compress(Bitmap.CompressFormat.JPEG, 100, os);//通过输出流将图片保存
                        cretblv = true;
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                }
                if(clipKind == buttonData.CLIPAREAKIND_OVAL) {
                    try {
                        OutputStream os = new FileOutputStream(img2File);//创建输出流
                        cbmp.compress(Bitmap.CompressFormat.PNG, 100, os);//通过输出流将图片保存
                        cretblv = true;
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return cretblv;
    }

    private boolean yesGetEditPicture() {
        boolean cretblv = false;
        //创建一个bitmap,并放入画布。
        Bitmap bitmap = Bitmap.createBitmap(mcur_photoBipmap.getWidth(), mcur_photoBipmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);// mcur_photoBipmap);
        canvas.drawBitmap(mcur_photoBipmap, 0,0, null);
        if(mgraItemHandle.miItemActiveNum > 0){
            GraphicItemUtil.FSCALE = 1;
            GraphicItemUtil.TRANSLATIONx = 0;
            GraphicItemUtil.TRANSLATIONy = 0;
            mgraItemHandle.GraphicsOnDraw(canvas);
        }
        // 保存绘制的内容
        String FileTime = "GETIMAGE2022929AB";
         msaveEditPictureName = m_EDITPICDIRName+"/eview_"+FileTime+".jpg";
        File imgFile = new File(msaveEditPictureName);
        try {
            OutputStream os = new FileOutputStream(imgFile);//创建输出流
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);//通过输出流将图片保存
            cretblv = true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        return cretblv;
    }
    //  about callback
    Callback mCallback;
    buttonCallback mButtonCallback;

    public void setOnItemClickCallback(Callback callback) {
        mCallback = callback;
    }

    public void setOnButtonClickCallback(buttonCallback callback) {
        mButtonCallback = callback;
    }

    public void setItemContent(int position, String content) {
        if (getChildAt(position) instanceof TextView) {
            TextView tv = (TextView) getChildAt(position);
            tv.setText(content);
            tv.requestLayout();
        }
    }

    public String GetTaskParaLst()
    {
        String strTaskpar = "";
        int childCount = getChildCount();
        int icparn = 0;
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            int jno = (int) child.getTag(five);
            int icLino = jno/1000;
            int iparkind = jno % 100;
            if(iparkind == 2){// editText
                EditText edtxt = (EditText) getChildAt(i);
                if(icparn > 0){
                    strTaskpar = strTaskpar+":>";
                }
                String curTaskpar = edtxt.getText().toString();
                if(curTaskpar.length() <= 0) curTaskpar = "__";
                strTaskpar = strTaskpar+curTaskpar;
                icparn++;
            }
        }

        return strTaskpar;
    }

    public Bitmap getCurPhotoBitmap()
    {
        return mcur_photoBipmap;
    }

    public void updateSetPhotoBitmap(Bitmap cbitmap)
    {
        mcur_photoBipmap = cbitmap;
        cnewPhotoblv = false;
        isLoaded = true;
        primaryW = mcur_photoBipmap.getWidth();
        primaryH = mcur_photoBipmap.getHeight();

        GraphicItemUtil.bmpLEFT = 0;
        GraphicItemUtil.bmpTOP = 0;
        GraphicItemUtil.bmpRIGHT = (int)primaryW;
        GraphicItemUtil.bmpBOTTOM = (int)primaryH;

        miBitmapfXc = primaryW/2;
        miBitmapfYc = primaryH/2;

        matrix = new Matrix();
    }

    public void dataShowSet(boolean showblv)
    {
        int childCount = getChildCount();
        int icparn = 0;
        bdataShowblv = showblv;
        cnewPhotoblv = false;
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            if(showblv){
                child.setVisibility(View.VISIBLE);
            }else{
                child.setVisibility(View.INVISIBLE);
            }
        }
    }

    public String getItemContent(int position) {
        String content = "";
        if (getChildAt(position) instanceof TextView) {
            TextView tv = (TextView) getChildAt(position);
            content = tv.getText().toString();
        }
        return content;
    }

    public boolean removeItem(int position) {
        boolean success = false;
        if (getChildAt(position) != null) {
            removeView(getChildAt(position));
            success = true;
        }
        return success;
    }

    public interface Callback {
        void onItemClick(int position, int jno);
    }

    public interface buttonCallback {
        void onButtonClick(byte buttonIDno, int ixoff,int iyoff,boolean doOper);
    }

    // about view drag

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {

        if (mDragEnable) {
            return mViewDragHelper.shouldInterceptTouchEvent(ev);
        }

        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (isLoaded == true && bdataShowblv == false){
            switch (event.getActionMasked()){
                case MotionEvent.ACTION_DOWN:
                    lastMoveX = -1;
                    lastMoveY = -1;
                    mdrawClipRectblv = false;
                    mselectClipOperblv = false;
                    mFirstX = event.getX();
                    mFirstY = event.getY();
                    downX = event.getRawX();
                    downY = event.getRawY();
                    mButtonDownTimev = System.currentTimeMillis();
                    isClickButtonRegion();
                    mdrawItemDelDragClickblv = false;
                    if(GraphicItemUtil.mcurMarkType != GraphicItemUtil.MARKTYPE_EMPTY){
                        mdraw_DragMoveLockblv = false;
                        mdrawItemDelDragClickblv = mgraItemHandle.findMarkDrawItem(mFirstX,mFirstY);
                    }
                    clickDownFirstblv = true;
                    isLongClick = false;
                    mLongClickblv = false;
                    mLongMoveblv = false;
                    mtxtShowblv = false;
                    mdrawShowblv = false;
                    mdrawtxtClickblv = false;
                    mdrawRubberClickblv = false;
                    mdrawDownPrimitiveblv = true;
                    if(buttonData.cActive_IDitem == buttonData.BUTTONIDNO_CLIP){//  && !mbuttonClickblv) {
                        mdrawClipRectblv = true;
                        mCliprect.right+=StrokeWidth;
                        mCliprect.bottom+=StrokeWidth;
                        GraphicItemUtil.mClipSelsetRunblv = true;
                        invalidate(mCliprect);
                        mCliprect.left = (int)mFirstX;
                        mCliprect.top = (int)mFirstY;
                        mCliprect.right =mCliprect.left;
                        mCliprect.bottom = mCliprect.top;
                    }
                    if(buttonData.cActive_IDitem == buttonData.BUTTONIDNO_TEXT){
                        mdrawtxtClickblv = isClickDrawTextRegion(mFirstX,mFirstY);
                    }
                    if(buttonData.cActive_IDitem == buttonData.BUTTONIDNO_RUBBER){
                        mdrawRubberClickblv = isClickDrawRubberRegion(mFirstX,mFirstY);
                        if(!mdrawRubberClickblv && mbDrawKind == buttonData.MARKICONKIND_LINE) {
                            mPolyLineList.clear();
                        }
                        if(mdrawRubberClickblv){
                            mdrawFirstPreX = mdrawFirstX;
                            mdrawFirstPreY = mdrawFirstY;
                            mdrawShowblv = true;
                        }
                    }

                    mPressBreak = false;
                    mFingerNum2blv = false;
                    mLongClickButtonblv = false;
                    if(mlongThreadProcessCode == 0) {
                        mlongThreadProcessCode = 1;
                        LongClickCheckThread startWait = new LongClickCheckThread(handler, "12345", DOWNLONGCLICKCHECK, (int) 1600);
                        Thread thread = new Thread(startWait, "BusyWait61");
                        thread.start();
                    }else{
                        mlongThreadProcessCode = 9;
                    }
                    mLocker = 0;// new add ????
                    break;
                case MotionEvent.ACTION_POINTER_DOWN:
                     mButtonDownTimev = System.currentTimeMillis();
                    fingerDistance = getFingerDistance(event);
                     clickDownFirstblv = false;
                    mFingerNum2blv = false;
                    mLongClickButtonblv = false;
                    mLongClickblv = false;
                    mLongMoveblv = false;
                    mtxtShowblv = false;
                    mdrawShowblv = false;
                    mLocker = 0;// new add ????
                    if(buttonData.cActive_IDitem == buttonData.BUTTONIDNO_RUBBER){
                        if(!mdrawRubberClickblv) {
                            mPolyLineList.clear();
                        }
                    }
                    break;
                case MotionEvent.ACTION_MOVE:
                    if(mbuttonClickblv == false && buttonData.cActive_IDitem == buttonData.BUTTONIDNO_EMPTY){
                        float fingerNum = event.getPointerCount();
                        if (fingerNum == 1 && mLocker == 0) {
                            movingAction(event);
                        } else if (fingerNum == 2) {
                            mFingerNum2blv = true;
                            zoomAction(event);
                        };
                    }else {
                        if(mFingerNum2blv == false) {
                             graphicsModeMove(event);
                            invalidate();
                        }else{
                            float fingerNum = event.getPointerCount();
                            if (fingerNum == 2) {
                                 zoomAction(event);
                            }
                        }
                    }
                     break;
                case MotionEvent.ACTION_POINTER_UP:
                    if(GraphicItemUtil.mClipSelsetRunblv){
                        GraphicItemUtil.mClipSelsetRunblv = false;
                    }
                    mPressBreak = true;
                    mLocker = 1;// ????
                    break;
                case MotionEvent.ACTION_UP:
                    if(!mPressBreak){
                        mPressBreak = true;
                        touchUpOrCancel(event);
                    }
                    break;
                case MotionEvent.ACTION_CANCEL:
                    if(mPressBreak == false){
                        mPressBreak = true;
                        touchUpOrCancel(event);
                    }
                    break;
            }
            return true;
        }else {
            if (mDragEnable) {
                mViewDragHelper.processTouchEvent(event);
                return true;
            }
        }
        return super.onTouchEvent(event);
    }

    private void draw_TextItem(Canvas canvas)
    {
        // select confirm mark button
        mPaint.setColor(Color.WHITE);
        mPaint.setStyle(Paint.Style.FILL);
        RectF rectF = new RectF();
        rectF.left = mtxtshowXpos-mgraItem_MarkWide/2;
        rectF.right = mtxtshowXpos+mgraItem_MarkWide/2;
        rectF.top = mtxtshowYpos-mgraItem_MarkWide/2;
        rectF.bottom = mtxtshowYpos+mgraItem_MarkWide/2;
        canvas.drawOval(rectF, mPaint);
        mdrawtxt_markFRect = rectF;

        Path sympath = PathParser.doPath(COMCONST.GRAITEM_SELECTITEM);
        Matrix cmaxtrix = new Matrix();
        cmaxtrix.setScale(mgraItem_MarkFscale, mgraItem_MarkFscale);
        sympath.transform(cmaxtrix);
        sympath.offset(rectF.left+mgraItem_Xoff, rectF.top+mgraItem_Yoff);
        mPaint.setStrokeWidth(2);
        //.. paint.setStyle(Paint.Style.FILL);
        mPaint.setColor(Color.RED);
        canvas.drawPath(sympath, mPaint);
        int icfntsize = (int)(miTextSize*scale);
        //
        if(mbTextKind == buttonData.TEXTICONKIND_HORIZONTAL){
            mPaint.setColor(miTextColorv);
            mPaint.setTextSize(icfntsize);
            mPaint.setStyle(Paint.Style.FILL);
            canvas.drawText(mstrMarkname,mtxtshowXpos,mtxtshowYpos,mPaint);;
        }
        if(mbTextKind == buttonData.TEXTICONKIND_VERTICAL){
            GraphicsExpItem.drawVertical2Text(canvas,mstrMarkname,miTextColorv,icfntsize,mtxtshowXpos,mtxtshowYpos);;
        }
        if(mbTextKind == buttonData.TEXTICONKIND_ARC){
            GraphicsExpItem.drawTextOnArc(canvas,mstrMarkname,miTextColorv,icfntsize,mtxtshowXpos,mtxtshowYpos);;
        }
    }

    private void draw_MarkItem(Canvas canvas)
    {
        float fxpos = (mdrawFirstX+mSecondX)/2;
        float fypos = (mdrawFirstY+mSecondY)/2;
        int iRed = Color.red(miDrawColorv);
        int iGreen = Color.green(miDrawColorv);
        int iBlue = Color.blue(miDrawColorv);
        int curDrawColorv = Color.argb(miTransparentValue,iRed,iGreen,iBlue);
        if(mbDrawKind == buttonData.MARKICONKIND_LINE){
            if(mPolyLineList.size() >= 2){
                Path polyLinepath = new Path();
                fxpos = mPolyLineList.get(0).x;
                fypos = mPolyLineList.get(0).y;
                polyLinepath.moveTo(mPolyLineList.get(0).x,mPolyLineList.get(0).y);
                for(int jp = 1;jp < mPolyLineList.size();jp++){
                    polyLinepath.lineTo(mPolyLineList.get(jp).x,mPolyLineList.get(jp).y);
                }
                Paint paint = new Paint();
                paint.setStyle(Paint.Style.STROKE);
                paint.setAntiAlias(true); // 去锯齿
                paint.setColor(curDrawColorv);// miDrawColorv);
                paint.setStrokeWidth(miLinewide*scale);
                canvas.drawPath(polyLinepath, paint);
            }
        }
        if(mbDrawKind == buttonData.MARKICONKIND_OVAL){
            float fLeft = mdrawFirstX;
            float fRight = mSecondX;
            if(fLeft > fRight){
                fLeft = mSecondX;
                fRight = mdrawFirstX;;
            }
            float fTop = mdrawFirstY;
            float fBottom = mSecondY;
            if(fTop > fBottom){
                fTop = mSecondY;
                fBottom = mdrawFirstY;
            }
            RectF rectF = new RectF(fLeft, fTop,fRight,fBottom);
            Path drawpath = new Path();
            drawpath.addOval(rectF, Path.Direction.CCW);
            Paint paint = new Paint();
            paint.setStyle(Paint.Style.STROKE);
            paint.setAntiAlias(true); // 去锯齿
            paint.setColor(curDrawColorv);// miDrawColorv);
            paint.setStrokeWidth(miLinewide*scale);
            canvas.drawPath(drawpath, paint);
        }
        if(mbDrawKind == buttonData.MARKICONKIND_SOLIDOVAL){
            float fLeft = mdrawFirstX;
            float fRight = mSecondX;
            if(fLeft > fRight){
                fLeft = mSecondX;
                fRight = mdrawFirstX;;
            }
            float fTop = mdrawFirstY;
            float fBottom = mSecondY;
            if(fTop > fBottom){
                fTop = mSecondY;
                fBottom = mdrawFirstY;
            }
            RectF rectF = new RectF(fLeft, fTop,fRight,fBottom);
            Path drawpath = new Path();
            drawpath.addOval(rectF, Path.Direction.CCW);
            Paint paint = new Paint();
            paint.setStyle(Paint.Style.FILL);
            paint.setAntiAlias(true); // 去锯齿
            paint.setColor(curDrawColorv);// miDrawColorv);
            //... paint.setStrokeWidth(miLinewide);
            canvas.drawPath(drawpath, paint);
        }
        if(mbDrawKind == buttonData.MARKICONKIND_ARROW){
            int icLinewd = (int)(miLinewide*scale);
            GraphicsExpItem.drawARROW(canvas,(int)mdrawFirstX, (int)mdrawFirstY,(int)mSecondX,(int)mSecondY,curDrawColorv,icLinewd);
        }
        // draw select flag
        mPaint.setColor(Color.WHITE);
        mPaint.setStyle(Paint.Style.FILL);
        RectF rectF0 = new RectF();
        rectF0.left = fxpos-mgraItem_MarkWide/2;
        rectF0.right = fxpos+mgraItem_MarkWide/2;
        rectF0.top = fypos-mgraItem_MarkWide/2;
        rectF0.bottom = fypos+mgraItem_MarkWide/2;
        canvas.drawOval(rectF0, mPaint);
        mdrawRubber_markFRect = rectF0;

        Path sympath = PathParser.doPath(COMCONST.GRAITEM_SELECTITEM);
        Matrix cmaxtrix = new Matrix();
        cmaxtrix.setScale(mgraItem_MarkFscale, mgraItem_MarkFscale);
        sympath.transform(cmaxtrix);
        sympath.offset(rectF0.left+mgraItem_Xoff, rectF0.top+mgraItem_Yoff);
        mPaint.setStrokeWidth(2);
        //.. paint.setStyle(Paint.Style.FILL);
        mPaint.setColor(Color.RED);
        canvas.drawPath(sympath, mPaint);
        mdrawMarkSymblv = true;
    }

    public void setGraphicsItemMarkPara(float fscale,float fwide,int ixoff,int iyoff)
    {
        mgraItem_MarkFscale = fscale;
        mgraItem_MarkWide = fwide;
        mgraItem_Xoff = ixoff;
        mgraItem_Yoff = iyoff;
    }

    private void draw_ClipFocusItem(Canvas canvas)
    {
        RectF rectF = new RectF();
        rectF.top = mCliprect.top;
        rectF.left = mCliprect.left;
        rectF.bottom = mCliprect.bottom;
        rectF.right = mCliprect.right;
        if(mCliprect.top > mCliprect.bottom){
            rectF.bottom = mCliprect.top;
            rectF.top = mCliprect.bottom;
        }
        if(mCliprect.left > mCliprect.right){
            rectF.right = mCliprect.left;
            rectF.left = mCliprect.right;
        }
        mdrawClipRectF = rectF;
        if(mdrawClipRectF.width() >= miniShowWhv && mdrawClipRectF.height() >= miniShowWhv) {
            Path clipRectpath = new Path();
            RectF outRect = new RectF(0, 0, drawScreenW, drawScreenH);
            clipRectpath.addRect(outRect, Path.Direction.CCW);

            if (mbClipAreaKind == buttonData.CLIPAREAKIND_RECT) {
                clipRectpath.addRect(rectF, Path.Direction.CW);
            }
            if (mbClipAreaKind == buttonData.CLIPAREAKIND_OVAL) {
                clipRectpath.addOval(rectF, Path.Direction.CW);
            }
            int iRed = Color.red(iClipColorv);
            int iGreen = Color.green(iClipColorv);
            int iBlue = Color.blue(iClipColorv);
            mPaint.setColor(Color.argb(mcurClipAlpha,iRed,iGreen,iBlue));//... colorSelectorView.getColorAddAlpha(iClipColorv,192));
            mPaint.setStyle(Paint.Style.FILL);
            canvas.drawPath(clipRectpath, mPaint);
            mselectClipOperblv = true;
        }else{
            mselectClipOperblv = false;
        }
    }

    class LongClickCheckThread implements Runnable {
        Handler mTHandler;
        String waitNo;
        int iWHATval = -1;
        int iWaitMilliSecond = 1000;
        public LongClickCheckThread(Handler handler,String waitName,int iWhatv,int iWaitTimems)
        {
            this.mTHandler = handler;
            this.waitNo = waitName;
            this.iWHATval = iWhatv;
            this.iWaitMilliSecond = iWaitTimems;
            if(iWaitTimems < 120) this.iWaitMilliSecond = iWaitTimems*1000;
        }
        @Override
        public void run() {
            synchronized (waitNo) {
                try {
                    Thread.sleep(iWaitMilliSecond);// 1.5 second
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                mlongThreadProcessCode++;
                Message msg = new Message();
                msg.what = iWHATval;
                msg.obj = waitNo;
                handler.sendMessage(msg);
            }
        };
    }

    /**
     * 震动
     */
    /* private void vibrate() {
        if (!isLongClick) {
            Vibrator vibrator = (Vibrator) this.getSystemService(this.VIBRATOR_SERVICE);
            vibrator.vibrate(100);
        }
    } */

    @Override
    public void computeScroll() {
        if (mViewDragHelper.continueSettling(true)) {
            invalidate();
        }
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

    }

    @NonNull
    private ViewDragHelper.Callback createDrawCallback() {
        return new ViewDragHelper.Callback() {
            @Override
            public boolean tryCaptureView(View child, int pointerId) {
                return true;
            }

            @Override
            public int clampViewPositionHorizontal(View child, int left, int dx) {
                //range
                int leftBound = getPaddingLeft();
                int rightBound = getWidth() - child.getWidth() - getPaddingRight();
                left = Math.min(Math.max(left, leftBound), rightBound);
                return left;
            }

            @Override
            public int clampViewPositionVertical(View child, int top, int dy) {
                //range
                int topBound = getPaddingTop();
                int bottomBound = getHeight() - child.getHeight() - getPaddingBottom();
                top = Math.min(Math.max(topBound, top), bottomBound);
                return top;
            }

            @Override
            public void onViewReleased(View releasedChild, float xvel, float yvel) {
                if (releasedChild instanceof TextView) {
                    Point point = (Point) releasedChild.getTag();
                    int jno = (int) releasedChild.getTag(five);
                    if (jno != 10) {
                        mViewDragHelper.settleCapturedViewAt(point.x, point.y);
                    }
                }
                if (releasedChild instanceof ImageView) {
                    /* if (releasedChild == iv_image) {
                        mViewDragHelper.settleCapturedViewAt(mAutoBackOriginPos.x, mAutoBackOriginPos.y);;
                    } */
                }
                invalidate();
            }
            //                    solve children onclick
            public int getViewHorizontalDragRange(View child) {
                return child.getWidth();
            }

            public int getViewVerticalDragRange(View child) {
                return child.getHeight();
            }
        };
    }

    public boolean isDragEnable() {
        return mDragEnable;
    }

    public void setDragEnable(boolean dragEnable) {
        mDragEnable = dragEnable;
    }


}

 三,关联java类的代码
    在自定RelativeLayout中,专门设计了“操作按钮类”(buttonData,buttonDrawUtil)与“图形项目类”(GraphicItemUtil,GraphicsExpItem)
   1),操作按钮类

   

package com.bi3eview.newstart60.local.Util;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import java.io.Serializable;
/**
 * Created by bs60 on 2022.08.06
 */
public class buttonData  implements Serializable{
    public static int fillColor = Color.WHITE;
    public static int sideColor = Color.BLUE;
    public static int nameColor = Color.BLACK;
    public static int iconColor = Color.DKGRAY;
    public static int activeColor = Color.RED;
    public static int vecLinewd = 2;
    public static int sideWide = 2;
    public static int activeSideWide = 4;
    public static int cornRadius = 10;
    public static int buttonHeight = 46;
    public static int itxtsize;
    // click
    public final static byte BUTTONCLICK_SHORT = 1;
    public final static byte BUTTONCLICK_LONG = 2;
    // clip kind
    public final static byte CLIPAREAKIND_EMPTY = 0;
    public final static byte CLIPAREAKIND_RECT = 1;
    public final static byte CLIPAREAKIND_OVAL = 2;
    // text kind
    public final static byte COMMONKIND_EMPTY = 0;
    public final static byte TEXTICONKIND_HORIZONTAL = 21;
    public final static byte TEXTICONKIND_VERTICAL = 22;
    public final static byte TEXTICONKIND_ARC = 23;
      // mark
    public final static byte MARKICONKIND_LINE = 51;
    public final static byte MARKICONKIND_OVAL = 53;
    public final static byte MARKICONKIND_SOLIDOVAL = 63;
    public final static byte MARKICONKIND_ARROW = 54;
    // kind
    public final static byte BUTTONKIND_EMPTY = 1;
    public final static byte BUTTONKIND_RECT = 1;
    public final static byte BUTTONKIND_ROUNDRECT = 2;
    public final static byte BUTTONKIND_CIRCLE = 3;
    public final static byte BUTTONKIND_OVAL = 4;
    // status
    public final static byte BUTTONSTATUS_NORMAL = 1;
    public final static byte BUTTONSTATUS_ACTIVE = 2;
    public final static byte BUTTONSTATUS_HIDE = 3;
    // button Identify
    public final static byte BUTTONIDNO_EMPTY = 0;
    public final static byte BUTTONIDNO_REDRAW = 66;
    public final static byte BUTTONIDNO_RESTORE = 1;
    public final static byte BUTTONIDNO_RUBBER = 2;
    public final static byte BUTTONIDNO_CLIP = 3;
    public final static byte BUTTONIDNO_TEXT = 4;
    public final static byte BUTTONIDNO_PARASET = 5;
    public final static byte BUTTONIDNO_SAVE = 6;
    public final static byte BUTTONIDNO_SPOTLIGHT = 9;
    public final static byte BUTTONIDNO_DRAGMOVE = 8;
    public final static byte BUTTONIDNO_SAVE_REINFO = 67;
    public final static byte BUTTONIDNO_DELETE = 7;
    public final static byte BUTTONIDNO_UNDO = 68;
    public final static byte BUTTONIDNO_VERIFYCLIP = 101;
    // button shape
    public final static byte BUTTONSHAPE_EMPTY = 0;
    public final static byte BUTTONSHAPE_PATH = 1;
    public final static byte BUTTONSHAPE_BITMAP = 2;
    public final static byte BUTTONSHAPE_DRAW = 3;
    public static byte cActive_IDitem = BUTTONIDNO_EMPTY;
    // data
    private byte bkind,cstatus,buttonIDno,bshape;
    private int iLeft,iTop,iRight,iBottom;
    private int iXoff,iYoff,colorv;
    private String titleName;
    private String strShapePath;
    private float scale;
    // create button
    public buttonData(){
        bkind = BUTTONKIND_RECT;
        cstatus = BUTTONSTATUS_NORMAL;
        bshape = BUTTONSHAPE_EMPTY;
        titleName = "BUTTON";
        iLeft = 10;
        iTop = 10;
        iRight = 100;
        iBottom = iLeft+buttonHeight;
        strShapePath = "";
        scale = 1.0f;
        iXoff = 0;
        iYoff = 0;
        colorv = Color.RED;
    }

    public void setButtonData(byte ckindb,byte buttonID,String name,int bLeft,int bTop,int bRight,int bBottom){
        bkind = ckindb;
        buttonIDno = buttonID;
        titleName = name;
        iLeft = bLeft;
        iTop = bTop;
        iRight = bRight;
        iBottom = bBottom;
    };

    public void setButtonPath(byte ckindb,byte buttonID,String name,int bLeft,int bTop,int bRight,int bBottom,float fscale,String butShapepath,int xmoffv,int ymoffv,int icolor){
        bkind = ckindb;
        buttonIDno = buttonID;
        bshape = BUTTONSHAPE_PATH;
        titleName = name;
        iLeft = bLeft;
        iTop = bTop;
        iRight = bRight;
        iBottom = bBottom;
        strShapePath = butShapepath;
        scale = fscale;
        iXoff = xmoffv;
        iYoff = ymoffv;
        colorv = icolor;
    };

    public void updateButtonStatus(byte setStatus){ cstatus = setStatus;};
    // get
    public byte getButtonKind(){ return bkind;}
    public byte getButtonStatus(){ return cstatus;}
    public byte getButtonShape(){ return bshape;}
    public byte getButtonIDno(){ return buttonIDno;}
    public String getButtonName(){ return titleName;}
    public String getButtonPath(){ return strShapePath;}
    public float getButtonPathScale(){ return scale;}
    public int getButtonColor(){ return colorv;}
    public Point getButtonPathXYoff(){
        Point point = new Point(iXoff,iYoff);
        return point;
    }
    public Rect getButtonRect(){
        Rect rect = new Rect();
        rect.left = iLeft;
        rect.top = iTop;
        rect.right = iRight;
        rect.bottom = iBottom;
        return rect;
    }
    public RectF getButtonRectF(){
        RectF rectF = new RectF();
        rectF.left = iLeft;
        rectF.top = iTop;
        rectF.right = iRight;
        rectF.bottom = iBottom;
        return rectF;
    }
}
package com.bi3eview.newstart60.local.Util;
import android.graphics.Matrix;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Canvas;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Paint.FontMetricsInt;

import com.bi3eview.newstart60.local.SelfWidget.PathParser;

import java.util.ArrayList;
/**
 * Created by bs60 on 2022.08.06
 */
public class buttonDrawUtil {
    public static float fcLeft = 10f;
    public static float fcTop = 10f;
    public static float fcRight = 160f;
    public static float fcBottom = 60f;
    public static float CLICK_DISTANCE = 15f;
    public static Rect cbutRect = new Rect(0,0,20,20);
    public static boolean mButtonInfoblv = false;
    public static boolean mButtonResetblv = false;
    public static boolean mButtonRedrawblv = false;
    public static Bitmap mSpotLightBmp = null;
    public static Bitmap mDragMoveBmp = null;
    private int mcurActiveItemosj = -1;
    private ArrayList<buttonData> mDaItemList = null;
    Paint paint = null;
    public buttonDrawUtil(){
        mDaItemList = new ArrayList();
        paint = new Paint();
        mcurActiveItemosj = -1;
    }

    public void appendButtonItem(buttonData cbutData)
    {
        if(mDaItemList != null){
            mDaItemList.add(cbutData);
        }
    };

    public void checkResetButtonShow(int icItemposj,int igraOknum)
    {
        if(mDaItemList.size() > 0){
            for(int j = 0;j < mDaItemList.size();j++){
                // save
                if(mDaItemList.get(j).getButtonIDno() == buttonData.BUTTONIDNO_SAVE){
                    if(mDaItemList.get(j).getButtonStatus() == buttonData.BUTTONSTATUS_HIDE){
                        if(igraOknum > 0){
                            mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_NORMAL);
                        }
                    }else{
                        if(igraOknum == 0){
                            mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_HIDE);
                        };
                    }
                };
                // parameter set
                if(mDaItemList.get(j).getButtonIDno() == buttonData.BUTTONIDNO_PARASET){
                    boolean showblv = false;
                    if(buttonData.cActive_IDitem == buttonData.BUTTONIDNO_CLIP) showblv = true;
                    if(buttonData.cActive_IDitem == buttonData.BUTTONIDNO_TEXT) showblv = true;
                    if(buttonData.cActive_IDitem == buttonData.BUTTONIDNO_RUBBER) showblv = true;
                    if(showblv){// buttonData.cActive_IDitem != buttonData.BUTTONIDNO_EMPTY){
                        mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_NORMAL);
                    }else{
                        mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_HIDE);
                    }
                };
                // delete
                if(mDaItemList.get(j).getButtonIDno() == buttonData.BUTTONIDNO_DELETE){
                    if(mDaItemList.get(j).getButtonStatus() == buttonData.BUTTONSTATUS_HIDE){
                        if(igraOknum > 0){
                            mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_NORMAL);
                        }
                    }else{
                        if(igraOknum == 0){
                            mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_HIDE);
                        };
                    }
                };
                // drag move
                if(mDaItemList.get(j).getButtonIDno() == buttonData.BUTTONIDNO_DRAGMOVE){
                    if(mDaItemList.get(j).getButtonStatus() == buttonData.BUTTONSTATUS_HIDE){
                        if(igraOknum > 0){
                            mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_NORMAL);
                        }
                    }else{
                        if(igraOknum == 0){
                            mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_HIDE);
                        };
                    }
                };
                // undo
                if(mDaItemList.get(j).getButtonIDno() == buttonData.BUTTONIDNO_UNDO){
                    if(mDaItemList.get(j).getButtonStatus() == buttonData.BUTTONSTATUS_HIDE){
                        if(icItemposj >= 0){
                            mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_NORMAL);
                        }
                    }else{
                        if(icItemposj < 0){
                            mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_HIDE);
                        };
                    }
                };
            }
        }
    }

    public byte FindClickButtonItemIDno(Point fdpoint,byte bClcikCode)
    {
        byte bretItemIDcd = buttonData.BUTTONIDNO_EMPTY;
        int inewActiveposj = -1;
        mButtonInfoblv = false;
        mButtonResetblv = false;
        mButtonRedrawblv = false;
        byte EXEOPERCODE = buttonData.BUTTONCLICK_SHORT;
        if(mDaItemList.size() > 0){
            for(int j = 0;j < mDaItemList.size();j++) {
                if (mDaItemList.get(j).getButtonStatus() == buttonData.BUTTONSTATUS_HIDE) continue;
                Rect rect = mDaItemList.get(j).getButtonRect();
                if (fdpoint.x <= rect.left) continue;
                if (fdpoint.x >= rect.right) continue;
                if (fdpoint.y <= rect.top) continue;
                if (fdpoint.y >= rect.bottom) continue;
                // rubber
                if (mDaItemList.get(j).getButtonIDno() == buttonData.BUTTONIDNO_RUBBER) {
                    if (mDaItemList.get(j).getButtonStatus() == buttonData.BUTTONSTATUS_ACTIVE) {
                        if (bClcikCode == EXEOPERCODE) {
                            mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_NORMAL);
                            buttonData.cActive_IDitem = buttonData.BUTTONIDNO_EMPTY;
                            mcurActiveItemosj = -1;
                            mButtonRedrawblv = true;
                            mButtonResetblv = true;
                        } else {
                            mButtonInfoblv = true;
                        }
                    } else {
                        if (bClcikCode == EXEOPERCODE) {
                            inewActiveposj = j;
                            mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_ACTIVE);
                            buttonData.cActive_IDitem = buttonData.BUTTONIDNO_RUBBER;
                            mButtonRedrawblv = true;
                            mButtonResetblv = true;
                            mcurActiveItemosj = j;
                        }else{
                            mButtonInfoblv = true;
                        }
                    }
                    bretItemIDcd = buttonData.BUTTONIDNO_RUBBER;
                }
                // clip
                if (mDaItemList.get(j).getButtonIDno() == buttonData.BUTTONIDNO_CLIP) {
                    if (mDaItemList.get(j).getButtonStatus() == buttonData.BUTTONSTATUS_ACTIVE) {
                        if (bClcikCode == EXEOPERCODE) {
                            mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_NORMAL);
                            buttonData.cActive_IDitem = buttonData.BUTTONIDNO_EMPTY;
                            mButtonRedrawblv = true;
                            mButtonResetblv = true;
                            mcurActiveItemosj = -1;
                        }else{
                            mButtonInfoblv = true;
                        }
                    } else {
                        if (bClcikCode == EXEOPERCODE) {
                            inewActiveposj = j;
                            mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_ACTIVE);
                            buttonData.cActive_IDitem = buttonData.BUTTONIDNO_CLIP;
                            mButtonRedrawblv = true;
                            mButtonResetblv = true;
                            mcurActiveItemosj = j;
                        }else{
                            mButtonInfoblv = true;
                        }
                    }
                    bretItemIDcd = buttonData.BUTTONIDNO_CLIP;
                }
                // text
                if (mDaItemList.get(j).getButtonIDno() == buttonData.BUTTONIDNO_TEXT) {
                    if (mDaItemList.get(j).getButtonStatus() == buttonData.BUTTONSTATUS_ACTIVE) {
                        if (bClcikCode == EXEOPERCODE) {
                            mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_NORMAL);
                            buttonData.cActive_IDitem = buttonData.BUTTONIDNO_EMPTY;
                            mButtonRedrawblv = true;
                            mButtonResetblv = true;
                            mcurActiveItemosj = -1;
                        }else{
                            mButtonInfoblv = true;
                        }
                    } else {
                        if (bClcikCode == EXEOPERCODE) {
                            inewActiveposj = j;
                            mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_ACTIVE);
                            buttonData.cActive_IDitem = buttonData.BUTTONIDNO_TEXT;
                            mButtonRedrawblv = true;
                            mButtonResetblv = true;
                            mcurActiveItemosj = j;
                        }else{
                            mButtonInfoblv = true;
                        }
                    }
                    bretItemIDcd = buttonData.BUTTONIDNO_TEXT;
                }
                // save
                if (mDaItemList.get(j).getButtonIDno() == buttonData.BUTTONIDNO_SAVE) {
                    if (bClcikCode == EXEOPERCODE) {
                        mButtonResetblv = true;
                    }else{
                        mButtonInfoblv = true;
                    }
                    bretItemIDcd = buttonData.BUTTONIDNO_SAVE;
                }
                // parameter set
                if (mDaItemList.get(j).getButtonIDno() == buttonData.BUTTONIDNO_PARASET) {
                    if (bClcikCode == EXEOPERCODE) {
                        mButtonResetblv = true;
                    }else{
                        mButtonInfoblv = true;
                    }
                    bretItemIDcd = buttonData.BUTTONIDNO_PARASET;
                }
                // delete
                if (mDaItemList.get(j).getButtonIDno() == buttonData.BUTTONIDNO_DELETE) {
                    if (mDaItemList.get(j).getButtonStatus() == buttonData.BUTTONSTATUS_ACTIVE) {
                        if (bClcikCode == EXEOPERCODE) {
                            mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_NORMAL);
                            buttonData.cActive_IDitem = buttonData.BUTTONIDNO_EMPTY;
                            mButtonRedrawblv = true;
                            mButtonResetblv = true;
                            mcurActiveItemosj = -1;
                        }else{
                            mButtonInfoblv = true;
                        }
                    } else {
                        if (bClcikCode == EXEOPERCODE) {
                            inewActiveposj = j;
                            mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_ACTIVE);
                            buttonData.cActive_IDitem = buttonData.BUTTONIDNO_DELETE;
                            mButtonRedrawblv = true;
                            mButtonResetblv = true;
                            mcurActiveItemosj = j;
                        }else{
                            mButtonInfoblv = true;
                        }
                    }
                    bretItemIDcd = buttonData.BUTTONIDNO_DELETE;
                }
                // drag move
                if (mDaItemList.get(j).getButtonIDno() == buttonData.BUTTONIDNO_DRAGMOVE) {
                    if (mDaItemList.get(j).getButtonStatus() == buttonData.BUTTONSTATUS_ACTIVE) {
                        if (bClcikCode == EXEOPERCODE) {
                            mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_NORMAL);
                            buttonData.cActive_IDitem = buttonData.BUTTONIDNO_EMPTY;
                            mButtonRedrawblv = true;
                            mButtonResetblv = true;
                            mcurActiveItemosj = -1;
                        }else{
                            mButtonInfoblv = true;
                        }
                    } else {
                        if (bClcikCode == EXEOPERCODE) {
                            inewActiveposj = j;
                            mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_ACTIVE);
                            buttonData.cActive_IDitem = buttonData.BUTTONIDNO_DRAGMOVE;
                            mButtonRedrawblv = true;
                            mButtonResetblv = true;
                            mcurActiveItemosj = j;
                        }else{
                            mButtonInfoblv = true;
                        }
                    }
                    bretItemIDcd = buttonData.BUTTONIDNO_DRAGMOVE;
                }
                // undo
                if (mDaItemList.get(j).getButtonIDno() == buttonData.BUTTONIDNO_UNDO) {
                    if (bClcikCode == EXEOPERCODE) {
                        mButtonResetblv = true;
                    }else{
                        mButtonInfoblv = true;
                    }
                    bretItemIDcd = buttonData.BUTTONIDNO_UNDO;
                }
                // restore
                if (mDaItemList.get(j).getButtonIDno() == buttonData.BUTTONIDNO_RESTORE) {
                    if (bClcikCode == EXEOPERCODE) {
                        mButtonResetblv = true;
                    }else{
                        mButtonInfoblv = true;
                    }
                    bretItemIDcd = buttonData.BUTTONIDNO_RESTORE;
                }
                if(bretItemIDcd != buttonData.BUTTONIDNO_EMPTY){
                    cbutRect = rect;
                    break;
                }
            }
        }
        if(inewActiveposj >= 0) {
            // remove other active item
            for (int j = 0; j < mDaItemList.size(); j++) {
                if (mDaItemList.get(j).getButtonStatus() != buttonData.BUTTONSTATUS_ACTIVE) continue;
                if (j == inewActiveposj) continue;
                mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_NORMAL);
            }
        };
        return bretItemIDcd;
    }

    public void clearActiveItem()
    {
         if(mcurActiveItemosj >= 0 && mcurActiveItemosj < mDaItemList.size()){
             mDaItemList.get(mcurActiveItemosj).updateButtonStatus(buttonData.BUTTONSTATUS_NORMAL);
             mcurActiveItemosj = -1;
         }
    }

    public void resetActiveButton()
    {
        if(mDaItemList.size() > 0) {
            for (int j = 0; j < mDaItemList.size(); j++) {
                if (mDaItemList.get(j).getButtonStatus() == buttonData.BUTTONSTATUS_ACTIVE){
                    mDaItemList.get(j).updateButtonStatus(buttonData.BUTTONSTATUS_NORMAL);
                }
            }
        }
    }

    public void redrawButtonLst(Canvas canvas)
    {
        if(mDaItemList.size() > 0){
            boolean cstartblv = true;
            for(int j = 0;j < mDaItemList.size();j++){
                if(mDaItemList.get(j).getButtonStatus() == buttonData.BUTTONSTATUS_HIDE) continue;
                RectF rectF = mDaItemList.get(j).getButtonRectF();
                if(cstartblv){
                    cstartblv = false;
                    fcLeft = rectF.left;
                    fcTop = rectF.top;
                    fcRight = rectF.right;
                    fcBottom = rectF.bottom;
                }else{
                    if(rectF.left < fcLeft) fcLeft = rectF.left;
                    if(rectF.top < fcTop) fcTop = rectF.top;
                    if(rectF.right > fcRight) fcRight = rectF.right;
                    if(rectF.bottom > fcBottom) fcBottom = rectF.bottom;
                }
                if(mDaItemList.get(j).getButtonShape() == buttonData.BUTTONSHAPE_PATH){
                    boolean mdrawImgblv = false;
                    if(mDaItemList.get(j).getButtonIDno() == buttonData.BUTTONIDNO_CLIP){
                        mdrawImgblv = true;
                        drawImageButton(canvas, mDaItemList.get(j),mSpotLightBmp);
                    }
                    if(mDaItemList.get(j).getButtonIDno() == buttonData.BUTTONIDNO_DRAGMOVE){
                        mdrawImgblv = true;
                        drawImageButton(canvas, mDaItemList.get(j),mDragMoveBmp);
                    }
                    if(!mdrawImgblv) {
                        drawPathButton(canvas, mDaItemList.get(j));
                    }
                }else {
                    if (mDaItemList.get(j).getButtonKind() == buttonData.BUTTONKIND_RECT) {
                        drawRectButton(canvas, mDaItemList.get(j));
                    }
                }
            }
        }
    }

    private void paintButtonShape_Rect(Canvas canvas,buttonData cbutdata)
    {
        paint.setColor(buttonData.fillColor);
        paint.setStyle(Paint.Style.FILL);
        Rect rect = cbutdata.getButtonRect();
        canvas.drawRect(rect, paint);

        paint.setColor(buttonData.sideColor);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(buttonData.sideWide);
        canvas.drawRect(rect, paint);
    }

    private void paintButtonShape_RoundRect(Canvas canvas,buttonData cbutdata)
    {
        paint.setColor(buttonData.fillColor);
        paint.setStyle(Paint.Style.FILL);
        RectF rectF = cbutdata.getButtonRectF();
        canvas.drawRoundRect(rectF, buttonData.cornRadius,buttonData.cornRadius,paint);

        paint.setColor(buttonData.sideColor);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(buttonData.sideWide);
        canvas.drawRoundRect(rectF, buttonData.cornRadius,buttonData.cornRadius,paint);;

    }

    private void paintButtonShape_Oval(Canvas canvas,buttonData cbutdata)
    {
        paint.setColor(buttonData.fillColor);
        paint.setStyle(Paint.Style.FILL);
        RectF rectF = cbutdata.getButtonRectF();
        RectF exprectF = new RectF();
        exprectF.left = rectF.left-buttonData.sideWide*2;
        exprectF.top = rectF.top-buttonData.sideWide*2;
        exprectF.right = rectF.right+buttonData.sideWide*2;
        exprectF.bottom = rectF.bottom+buttonData.sideWide*2;
        canvas.drawOval(exprectF, paint);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(buttonData.sideWide);
        paint.setColor(buttonData.sideColor);
        if(cbutdata.getButtonStatus() == buttonData.BUTTONSTATUS_ACTIVE){
            paint.setStrokeWidth(buttonData.activeSideWide);
            paint.setColor(buttonData.activeColor);
        }
        canvas.drawOval(rectF, paint);
    }

    private void drawPathButton(Canvas canvas,buttonData cbutdata) {
        if(cbutdata.getButtonKind() != buttonData.BUTTONKIND_EMPTY){
            if(cbutdata.getButtonKind() == buttonData.BUTTONKIND_RECT){
                paintButtonShape_Rect(canvas,cbutdata);
            };
            if(cbutdata.getButtonKind() == buttonData.BUTTONKIND_ROUNDRECT){
                paintButtonShape_RoundRect(canvas,cbutdata);
            };
            if(cbutdata.getButtonKind() == buttonData.BUTTONKIND_OVAL){
                paintButtonShape_Oval(canvas,cbutdata);
            };
        }
        Rect rect = cbutdata.getButtonRect();
        Path sympath = PathParser.doPath(cbutdata.getButtonPath());
        Matrix cmaxtrix = new Matrix();
        float fscale = cbutdata.getButtonPathScale();
        Point point = cbutdata.getButtonPathXYoff();
        cmaxtrix.setScale(fscale, fscale);
        sympath.transform(cmaxtrix);
        sympath.offset(rect.left+point.x, rect.top+point.y);
        paint.setStrokeWidth(buttonData.vecLinewd);
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(cbutdata.getButtonColor());
        canvas.drawPath(sympath, paint);
    }

    private void drawImageButton(Canvas canvas,buttonData cbutdata,Bitmap cbutBmp) {
        if(cbutdata.getButtonKind() != buttonData.BUTTONKIND_EMPTY){
            if(cbutdata.getButtonKind() == buttonData.BUTTONKIND_RECT){
                paintButtonShape_Rect(canvas,cbutdata);
            };
            if(cbutdata.getButtonKind() == buttonData.BUTTONKIND_ROUNDRECT){
                paintButtonShape_RoundRect(canvas,cbutdata);
            };
            if(cbutdata.getButtonKind() == buttonData.BUTTONKIND_OVAL){
                paintButtonShape_Oval(canvas,cbutdata);
            };
        }
        Rect dstRect = cbutdata.getButtonRect();
        int ioffv = dstRect.width()/4;
        dstRect.inset(ioffv,ioffv);
        Rect srcRect = new Rect(0, 0, cbutBmp.getWidth(), cbutBmp.getHeight());
        canvas.drawBitmap(cbutBmp, srcRect, dstRect, paint);
    }

}

2),图形项目类

package com.bi3eview.newstart60.local.Util;
import android.graphics.Matrix;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Canvas;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Paint.FontMetricsInt;
import android.text.Layout.Alignment;
import android.text.StaticLayout;
import android.text.TextPaint;
/**
 * Created by bs60 on 2022.08.24
 */
public class GraphicsExpItem {

    public static void drawTextOnArc(Canvas canvas, String textString,int textColor,int fontSize,int ixpos,int iypos){
        Paint paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);

        paint.setColor(Color.RED);
        paint.setTextSize(fontSize);
        paint.setStyle(Paint.Style.STROKE);
        float measuredWidth = paint.measureText(textString);
        float bxfa = 3.5f;
        float b = (float)((measuredWidth*2/(2*3.14159+4*bxfa-4))*1.1);
        float a = b*bxfa;
        RectF rectF2 = new RectF(ixpos-a,iypos,ixpos+a,iypos+b*2);
        Path path = new Path();
        path.addArc(rectF2, 180,360);
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(textColor);
        float voffset = 0;// 50
        canvas.drawTextOnPath(textString, path, 0, voffset, paint);

    }

    private static boolean isChineseByBlock(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
        if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C//jdk1.7
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D//jdk1.7
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT) {
            return true;
        }
        return false;
    }

    private static boolean isChinesePuctuation(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
        if (ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_FORMS
                || ub == Character.UnicodeBlock.VERTICAL_FORMS) { //jdk1.7
            return true;
        }
        return false;
    }
    public static boolean isChinese(char str) {
        int charASCII = Integer.valueOf(str);
        if(charASCII >= 1 && charASCII <= 126){
            return false;
        }
        if(charASCII < 0 || charASCII > 126) return true;
        String charStr = Character.toString(str);
  
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(str);
        if (ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_FORMS
                || ub == Character.UnicodeBlock.VERTICAL_FORMS) { //jdk1.7
            return true;
        }
        return false;
    }

    public static void drawVertical2Text(Canvas canvas, String textString,int textColor,int fontSize,int ixpos,int iypos) {
        Paint paint = new Paint();
        paint.setColor(textColor);
        paint.setTextSize(fontSize);
        paint.setStyle(Paint.Style.FILL);
        float a = paint.measureText("正正", 0, 1);
        float left = ixpos;// canvas.getWidth()/2-a/2;
        float w;
        final int len = textString.length();
        float py = iypos;// 0 ;
        Path path = new Path();
        path.moveTo(ixpos,py);
        path.lineTo(0,500);
        String strChar = "";
        float fstYpos = 0;
        float fedYpos = 0;
        for(int i=0; i<len; i ++){
            char c = textString.charAt(i);
            w = paint.measureText(textString, i, i+1);//获取字符宽度
            //... Log.d(TAG,"tongfei ---w= "+w);
            StringBuffer b = new StringBuffer();
            b.append(c);
            if(py > canvas.getHeight()){//定义字的范围
                return;
            }
            if(isChinese(c)){
                if(strChar.length() > 0){
                    Path path1 = new Path();
                    path1.moveTo(left,fstYpos);
                    path1.lineTo(left,fedYpos);
                    canvas.drawTextOnPath(strChar, path1, 0, 0, paint);
                    strChar = "";
                }
                py += w;
                if(py > canvas.getHeight()){
                    return;
                }
                canvas.drawText(b.toString(), left, py, paint); //中文处理方法
            }else {
                if(strChar.length() <= 0){
                    fstYpos = py;
                    fedYpos = py;
                    strChar = b.toString();
                }else{
                    fedYpos = py;
                    strChar = strChar+b.toString();
                }
                py += w;
            }
        }
        if(strChar.length() > 0){
            Path path1 = new Path();
            path1.moveTo(left,fstYpos);
            path1.lineTo(left,fedYpos);
            canvas.drawTextOnPath(strChar, path1, 0, 0, paint);
            strChar = "";
        }
    }

    public static void drawVerticalText(Canvas canvas, Paint paint,String textString,int textColor,int fontSize) {
        TextPaint textPaint=new TextPaint();
        textPaint.setColor(textColor);
        textPaint.setTextSize(fontSize);
        float[] widths = new float[1];
        paint.getTextWidths("正", widths);//获取单个汉字的宽度
        int LineWidth = (int) Math.ceil(widths[0] * 1.01);//  + 2);
        StaticLayout staticLayout=new StaticLayout(textString, textPaint, LineWidth,
                Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
        //绘制的位置
        canvas.translate(285, 220);
        staticLayout.draw(canvas);
    }

    public static void drawARROW(Canvas canvas,int sx, int sy, int ex, int ey,int curColorv,int icLinewd)
    {
        int ixoff = ex-sx;
        int iyoff = ey-sy;
        double arraow_Linelen = Math.sqrt(ixoff * ixoff + iyoff * iyoff);
        double H = arraow_Linelen/4;// mdrawLinewide;//xxx 8; // 箭头高度
        double L = H*0.45;// 3.5; // 底边的一半
        int x3 = 0;
        int y3 = 0;
        int x4 = 0;
        int y4 = 0;
        double awrad = Math.atan(L / H); // 箭头角度
        double arraow_len = Math.sqrt(L * L + H * H); // 箭头的长度
        double[] arrXY_1 = rotateVec(ex - sx, ey - sy, awrad, true, arraow_len);
        double[] arrXY_2 = rotateVec(ex - sx, ey - sy, -awrad, true, arraow_len);
        double x_3 = ex - arrXY_1[0]; // (x3,y3)是第一端点
        double y_3 = ey - arrXY_1[1];
        double x_4 = ex - arrXY_2[0]; // (x4,y4)是第二端点
        double y_4 = ey - arrXY_2[1];
        Double X3 = new Double(x_3);
        x3 = X3.intValue();
        Double Y3 = new Double(y_3);
        y3 = Y3.intValue();
        Double X4 = new Double(x_4);
        x4 = X4.intValue();
        Double Y4 = new Double(y_4);
        y4 = Y4.intValue();

        if(icLinewd < 1) icLinewd = 1;
        Paint paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setAntiAlias(true); // 去锯齿
        paint.setColor(curColorv);
        paint.setStrokeWidth(icLinewd);
        // 画线
        canvas.drawLine(sx, sy, ex, ey,paint);
        canvas.drawLine(x3, y3, ex, ey,paint);

        canvas.drawLine(x4, y4, ex, ey,paint);
    }
    // 计算
    private static double[] rotateVec(int px, int py, double ang, boolean isChLen, double newLen)
    {
        double mathstr[] = new double[2];
        // 矢量旋转函数,参数含义分别是x分量、y分量、旋转角、是否改变长度、新长度
        double vx = px * Math.cos(ang) - py * Math.sin(ang);
        double vy = px * Math.sin(ang) + py * Math.cos(ang);
        if (isChLen) {
            double d = Math.sqrt(vx * vx + vy * vy);
            vx = vx / d * newLen;
            vy = vy / d * newLen;
            mathstr[0] = vx;
            mathstr[1] = vy;
        }
        return mathstr;
    }
}
package com.bi3eview.newstart60.local.Util;
import android.graphics.Matrix;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Canvas;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Paint.FontMetricsInt;

import com.bi3eview.newstart60.local.COMCONST;
import com.bi3eview.newstart60.local.SelfWidget.PathParser;

import java.io.Serializable;
import java.util.ArrayList;
/**
 * Created by bs60 on 2022.08.07
 */
public class GraphicItemUtil {
    public static int miokGraItemNum = 0;
    public static int miItemActiveNum = 0;
    public static int miundoPosj = -1;
    public static boolean mClipSelsetRunblv = false;
    public static int miClipAlpha = 92;
    public static int mbutWide = 30;
    public static float FSCALE,TRANSLATIONx,TRANSLATIONy;
    public static int bmpLEFT,bmpTOP,bmpRIGHT,bmpBOTTOM;
    public static final byte MARKTYPE_EMPTY = 0;
    public static final byte MARKTYPE_DELETE = 1;
    public static final byte MARKTYPE_DRAGMOVE = 2;
    public static byte mcurMarkType = MARKTYPE_EMPTY;
    public static float mgraItem_MarkFscale = 1.0f;
    public static int mgraItem_Xoff = 10;
    public static int mgraItem_Yoff = 10;
    final byte STATUS_EMPTY = 0;
    final byte STATUS_USE = 2;
    final byte STATUS_DELETE = 3;

    private ArrayList<GraItemData> mGraItemList = null;
    private ArrayList<TextData> mTextDataList = null;
    private ArrayList<ClipData> mClipDataList = null;
    private ArrayList<PolyLineData> mPolyLineDataList = null;
    private ArrayList<UndoData> mUndoDataList = null;
    private ArrayList<graMarkItem> mgraMarkList = null;
    private int MARKLIST_MAXNUM = 26;
    private int mcurMarkItemNum = 0;
    private int mfindMarkItemjno = -1;
    //
    final byte KIND_TEXT = 1;
        int curTxtIDno = 1;
        int curFntsize = 13;
        int curTxtColor = Color.RED;
        String curStrTxt = "ABC123";
        final byte COMMONKIND_EMPTY = 0;
        final byte TEXTICONKIND_HORIZONTAL = 21;
        final byte TEXTICONKIND_VERTICAL = 22;
        final byte TEXTICONKIND_ARC = 23;
        //... public final byte STATUS_EMPTY = 1;
        //... public final byte STATUS_NORMAL = 2;
    final byte KIND_CLIP = 2;
        final byte KINDCLIP_RECT = 1;
        final byte KINDCLIP_OVAL = 2;
        int clipColor = Color.argb(64,255,255,255);

    final byte KIND_POLYLINE = 3;
        int curPolyIDno = 1;
        int polyColor = Color.argb(255,0,255,0);
        int curLinewd = 6;
        int curTransparent = 200;

        final byte KIND_OPEN = 1;
        final byte KIND_CLOSE = 2;
        final byte STATUS_NORMAL = 1;
        final byte MARKICONKIND_LINE = 51;
        final byte MARKICONKIND_OVAL = 53;
        final byte MARKICONKIND_SOLIDOVAL = 63;
        final byte MARKICONKIND_ARROW = 54;

    final byte KIND_EMPTY = 0;

    int mdrawGraItempj = -1;
    int miItemIDno = 1;
    // drag move
    boolean mdrawDragMoveblv = false;
    int mdrawDragMove_Clipposj = -1;
    int mdrawDragMove_Textposj = -1;
    int mdrawDragMove_Markposj = -1;
    int mdrawDrag_MoveXoff = 0;
    int mdrawDrag_MoveYoff = 0;
    // clip
    int miItemSpaceNum = 0;
    int miClipNum = 0;
    int miGraClipItemposj = -1;
    int miClipItemposj = -1;
    int miClipItemIDno = -1;
    int miUndoClipGraItempj = -1;
    int mondrawClipLstpj = -1;

    int miSelgraItemposj = -1;
    int miGraItemposj = -1;
    // text
    int miSelTextItemposj = -1;
    // draw
    int miSelDrawItemposj = -1;
    // check trace
    String mTraceInfo = "";
    //
    public GraphicItemUtil()
    {
        FSCALE = 1;
        TRANSLATIONx = 0;
        TRANSLATIONy = 0;
        mGraItemList = new ArrayList<>();
        miItemIDno = 1;
        miItemActiveNum = 0;
        miItemSpaceNum = 0;
        miClipNum = 0;
        miGraClipItemposj = -1;
        miClipItemposj = -1;
        miClipItemIDno = -1;
        miUndoClipGraItempj = -1;

        miSelgraItemposj = -1;
        miGraItemposj = -1;
        miSelTextItemposj = -1;

        mTextDataList = new ArrayList<>();
        mClipDataList = new ArrayList<>();
        mPolyLineDataList = new ArrayList<>();
        mUndoDataList = new ArrayList<>();

        mcurMarkItemNum = 0;
        mgraMarkList = new ArrayList<>();
        for(int jm = 0;jm < MARKLIST_MAXNUM;jm++){
            graMarkItem gmark = new graMarkItem();
            mgraMarkList.add(gmark);
        }

    }

    private void initResetBasicPara()
    {
        FSCALE = 1;
        TRANSLATIONx = 0;
        TRANSLATIONy = 0;
        miItemIDno = 1;
        miItemActiveNum = 0;
        miItemSpaceNum = 0;
        miundoPosj = -1;
        miClipNum = 0;
        miGraClipItemposj = -1;
        miClipItemposj = -1;
        miClipItemIDno = -1;
        miUndoClipGraItempj = -1;

        miSelgraItemposj = -1;
        miGraItemposj = -1;
        miSelTextItemposj = -1;
        mcurMarkItemNum = 0;
    }

    public String GetTraceInfo(){
        return mTraceInfo;
    }

    public boolean appendOrupdateClipItem(byte ckind,int iColor,Rect crect)
    {
        boolean cretblv = true;
        mTraceInfo = "11:"+String.valueOf(miClipItemIDno)+","+String.valueOf(miClipItemposj)+",Gra:"+String.valueOf(miGraClipItemposj);//xxxxxxxx
        if(miClipItemIDno > 0 || miClipItemposj >= 0){// update
            if(miClipItemposj >= 0 && miGraClipItemposj >= 0){
                if(miGraClipItemposj >= 0 && miGraClipItemposj < mGraItemList.size()){
                    mTraceInfo = mTraceInfo +":>>USE";//xxxxxxxxxxx
                    mGraItemList.get(miGraClipItemposj).status = STATUS_USE;
                }
                mClipDataList.get(miClipItemposj).kind = ckind;
                mClipDataList.get(miClipItemposj).caColor = iColor;
                mClipDataList.get(miClipItemposj).crect = crect;
                //... mGraItemList.get(miClipItemposj).status = STATUS_USE;
                if(miGraClipItemposj >= 0) {
                    UndoData undoData = new UndoData(KIND_CLIP, STATUS_USE, miGraClipItemposj);
                    if(miUndoClipGraItempj >= 0 && miUndoClipGraItempj < mUndoDataList.size()){
                        mUndoDataList.remove(miUndoClipGraItempj);
                    }
                    miUndoClipGraItempj = mUndoDataList.size();
                    mUndoDataList.add(undoData);
                }
            }else{
                cretblv = false;
            }
        }else {// append
            miGraClipItemposj = mGraItemList.size();
            GraItemData gItem = new GraItemData();
            gItem.kind = KIND_CLIP;
            gItem.IDno = miItemIDno;
            gItem.posj = mClipDataList.size();
            gItem.status = STATUS_USE;
            ClipData clipdata = new ClipData(ckind, iColor, crect, miItemIDno);
            mGraItemList.add(gItem);
            mClipDataList.add(clipdata);
            miClipItemIDno = miItemIDno;
            miItemIDno++;
            miItemActiveNum++;
            miItemSpaceNum++;
            UndoData undoData = new UndoData(KIND_CLIP, STATUS_USE, miGraClipItemposj);
            miUndoClipGraItempj = mUndoDataList.size();
            mUndoDataList.add(undoData);
        }
        mClipSelsetRunblv = false;
        miundoPosj = mUndoDataList.size();
        return cretblv;
    }

    public boolean appendOrupdateTextItem(byte ckind,int iColor,int ifntsize,int ixpos,int iypos,String strTxt)
    {
        boolean cretblv = true;
        if(miSelTextItemposj >= 0){// update
            //... mTextDataList.get(miSelTextItemposj).mkind = ckind;
            //... mTextDataList.get(miClipItemposj).color = iColor;
            mTextDataList.get(miSelTextItemposj).point.x = ixpos;
            mTextDataList.get(miSelTextItemposj).point.y = iypos;
            cretblv = false;
        }else {// append
            miGraItemposj = mGraItemList.size();
            GraItemData gItem = new GraItemData();
            gItem.kind = KIND_TEXT;
            gItem.IDno = miItemIDno;
            gItem.posj = mTextDataList.size();
            gItem.status = STATUS_USE;
            mGraItemList.add(gItem);
            //
            TextData txtdata = new TextData();// ckind, iColor, crect, miGraItemposj);
            txtdata.color = iColor;
            txtdata.mkind = ckind;
            txtdata.fntsize = ifntsize;
            txtdata.point.x = ixpos;
            txtdata.point.y = iypos;
            txtdata.strTxt = strTxt;
            mTextDataList.add(txtdata);
            miItemIDno++;
            miItemActiveNum++;
            miItemSpaceNum++;
            UndoData undoData = new UndoData(KIND_TEXT, STATUS_USE, miGraItemposj);
            miUndoClipGraItempj = mUndoDataList.size();
            mUndoDataList.add(undoData);
        }
        mClipSelsetRunblv = false;
        miundoPosj = mUndoDataList.size();
        return cretblv;
    }

    public boolean appendOrupdateDrawItem(byte ckind,int iColor,int iLinewide,int iTransparent,ArrayList<Point> pointLst)
    {
        boolean cretblv = true;
        if(miSelDrawItemposj >= 0){// update
            if(pointLst.size() > 0) {
                int ixoffv = pointLst.get(0).x;
                int iyoffv = pointLst.get(0).y;
                if(mPolyLineDataList.get(miSelDrawItemposj).points.size() > 0) {
                    for(int jp = 0;jp < mPolyLineDataList.get(miSelDrawItemposj).points.size();jp++) {
                        mPolyLineDataList.get(miSelDrawItemposj).points.get(jp).x = mPolyLineDataList.get(miSelDrawItemposj).points.get(jp).x+ixoffv;
                        mPolyLineDataList.get(miSelDrawItemposj).points.get(jp).y = mPolyLineDataList.get(miSelDrawItemposj).points.get(jp).y+iyoffv;
                    }
                }
            }
            cretblv = false;
        }else {// append
            miGraItemposj = mGraItemList.size();
            GraItemData gItem = new GraItemData();
            gItem.kind = KIND_POLYLINE;
            gItem.IDno = miItemIDno;
            gItem.posj = mPolyLineDataList.size();
            gItem.status = STATUS_USE;
            mGraItemList.add(gItem);
            //
            PolyLineData drawdata = new PolyLineData();// ckind, iColor, crect, miGraItemposj);
            drawdata.gkind = ckind;
            drawdata.iColor = iColor;
            drawdata.icLwd = iLinewide;
            drawdata.iTransparentv = iTransparent;
            for(int jp = 0;jp < pointLst.size();jp++) {
                drawdata.points.add(pointLst.get(jp));
            }
            mPolyLineDataList.add(drawdata);
            miItemIDno++;
            miItemActiveNum++;
            miItemSpaceNum++;
            UndoData undoData = new UndoData(KIND_TEXT, STATUS_USE, miGraItemposj);
            miUndoClipGraItempj = mUndoDataList.size();
            mUndoDataList.add(undoData);
        }
        mClipSelsetRunblv = false;
        miundoPosj = mUndoDataList.size();
        return cretblv;
    }

    public void setClipSelRunStatus(boolean setblv)
    {
        mClipSelsetRunblv = setblv;
    }

    public void clearGraphicsItem()
    {
        miItemActiveNum = 0;
        mTextDataList.clear();
        mPolyLineDataList.clear();
        mGraItemList.clear();
        mUndoDataList.clear();
        initResetBasicPara();
    }

    public int checkGetGraItemNum()
    {
        int iretnum = 0;
        if(mGraItemList.size() > 0) {
            for (int j = 0; j < mGraItemList.size(); j++) {
                if (mGraItemList.get(j).status != STATUS_USE) continue;
                iretnum++;
            }
        }
        return iretnum;
    }

    public int checkGetCurGraItem()
    {
        int itemNum = 0;
        if(mGraItemList.size() > 0){
            for(int j = 0;j < mGraItemList.size();j++) {
                if (mGraItemList.get(j).status != STATUS_USE) continue;
                itemNum++;
            };
        };
        return itemNum;
    }

    public int checkGetCurGraClipItem()
    {
        int itemNum = 0;
        if(mGraItemList.size() > 0){
            for(int j = 0;j < mGraItemList.size();j++) {
                if (mGraItemList.get(j).status != STATUS_USE) continue;
                if(mGraItemList.get(j).kind == KIND_CLIP) {
                    itemNum++;
                }
            };
        };
        return itemNum;
    }

    public void GraphicsOnDraw(Canvas canvas)
    {
        mondrawClipLstpj = -1;
        if(miItemActiveNum <= 0){
            miItemActiveNum = 0;
            if(mGraItemList.size() > 0){
                for(int j = 0;j < mGraItemList.size();j++) {
                    if (mGraItemList.get(j).status != STATUS_USE) continue;
                    miItemActiveNum++;
                };
            };
        }
        if(miItemActiveNum <= 0) return;
        int idrawClipItemposj = -1;
        int idrawClipItemIDno = -1;
        int igraItemposj = -1;
        int icurActiveNum = 0;
        mcurMarkItemNum = 0;
        for(int j = 0;j < mGraItemList.size();j++) {
            if (mGraItemList.get(j).status != STATUS_USE) continue;
            if (mGraItemList.get(j).kind == KIND_CLIP) {
                idrawClipItemposj = mGraItemList.get(j).posj;
                idrawClipItemIDno = mGraItemList.get(j).IDno;
                igraItemposj = j;
                miGraClipItemposj = j;
                icurActiveNum++;
                if (idrawClipItemposj >= 0 || idrawClipItemIDno > 0) {
                    if (!mClipSelsetRunblv) {
                        int iretItempj = drawClipItem(canvas, idrawClipItemposj, idrawClipItemIDno);
                        if (idrawClipItemposj < 0 && iretItempj >= 0) {
                            mGraItemList.get(igraItemposj).setGraItemDataPosj(iretItempj);
                            idrawClipItemposj = iretItempj;
                        }
                        mondrawClipLstpj = iretItempj;
                        miClipItemposj = idrawClipItemposj;
                    }
                }
                continue;
            }
        }
        for(int j = 0;j < mGraItemList.size();j++){
            if(mGraItemList.get(j).status != STATUS_USE) continue;
            if(mGraItemList.get(j).kind == KIND_CLIP){
                continue;

            }
            mdrawGraItempj = j;
            if(mGraItemList.get(j).kind == KIND_TEXT){
                int iTextposj = mGraItemList.get(j).posj;
                if(iTextposj >= 0 && iTextposj < mTextDataList.size()){
                    drawTextItem(canvas,iTextposj);
                    icurActiveNum++;
                }
            }
            if(mGraItemList.get(j).kind == KIND_POLYLINE){
                int iDrawposj = mGraItemList.get(j).posj;
                if(iDrawposj >= 0 && iDrawposj < mPolyLineDataList.size()){
                    drawMarkItem(canvas,iDrawposj);
                    icurActiveNum++;
                }
            }
        }
        miItemActiveNum = icurActiveNum;
        if(mcurMarkItemNum > 0){
            Paint paint = new Paint();
            for(int jm = 0;jm < mcurMarkItemNum;jm++){
                paint.setColor(mgraMarkList.get(jm).iColorv);
                paint.setStyle(Paint.Style.FILL);
                canvas.drawOval(mgraMarkList.get(jm).markRectf, paint);

                RectF rectf = new RectF(mgraMarkList.get(jm).markRectf);
                rectf.inset(1,1);
                paint.setStyle(Paint.Style.STROKE);
                paint.setStrokeWidth(1);
                paint.setColor(Color.BLACK);
                canvas.drawOval(rectf, paint);
                rectf.inset(1,1);
                paint.setStyle(Paint.Style.STROKE);
                paint.setStrokeWidth(1);
                paint.setColor(Color.WHITE);
                canvas.drawOval(rectf, paint);

                int ivColor = 0xFFFFFFff-mgraMarkList.get(jm).iColorv+0xFF000000;
                Path sympath = PathParser.doPath(COMCONST.EDITBUTTON_DELETE);
                if(mcurMarkType == MARKTYPE_DRAGMOVE){
                    sympath = PathParser.doPath(COMCONST.GRAITEM_DRAGMOVE);
                }
                Matrix cmaxtrix = new Matrix();
                cmaxtrix.setScale(mgraItem_MarkFscale, mgraItem_MarkFscale);
                sympath.transform(cmaxtrix);
                sympath.offset(mgraMarkList.get(jm).markRectf.left+mgraItem_Xoff, mgraMarkList.get(jm).markRectf.top+mgraItem_Yoff);
                paint.setStrokeWidth(2);
                paint.setColor(ivColor);
                canvas.drawPath(sympath, paint);
            }
        }
    }

    public boolean updateSetDragMovePara(int ixmove,int iymove)
    {
        mdrawDragMoveblv = true;
        mdrawDrag_MoveXoff = ixmove;
        mdrawDrag_MoveYoff = iymove;
        return true;
    }

    public boolean confirmDeleteSelItem() {
        boolean cretblv = false;
        if (mfindMarkItemjno >= 0 && mfindMarkItemjno < mcurMarkItemNum) {
            int igraposj = mgraMarkList.get(mfindMarkItemjno).igraPosj;
            byte cmkind = mgraMarkList.get(mfindMarkItemjno).kind;
            if(cmkind == KIND_CLIP){

            }
            int itemposj = mgraMarkList.get(mfindMarkItemjno).itemposj;
            if (igraposj >= 0 && igraposj < mGraItemList.size()) {
                mGraItemList.get(igraposj).status = STATUS_DELETE;
                cretblv = true;
            }
        }
        return cretblv;
    }

    public boolean confirmDragMoveItem()
    {
        boolean cretblv = false;
        if(mdrawDragMoveblv) {
            if (mfindMarkItemjno >= 0 && mfindMarkItemjno < mcurMarkItemNum) {
                int igraposj = mgraMarkList.get(mfindMarkItemjno).igraPosj;
                byte cmkind = mgraMarkList.get(mfindMarkItemjno).kind;
                int itemposj = mgraMarkList.get(mfindMarkItemjno).itemposj;
                if (cmkind == KIND_CLIP) {
                    if (itemposj >= 0 && itemposj < mClipDataList.size()) {
                        mClipDataList.get(itemposj).crect.left = (int) (mClipDataList.get(itemposj).crect.left + mdrawDrag_MoveXoff);
                        mClipDataList.get(itemposj).crect.right = (int) (mClipDataList.get(itemposj).crect.right + mdrawDrag_MoveXoff);
                        mClipDataList.get(itemposj).crect.top = (int) (mClipDataList.get(itemposj).crect.top + mdrawDrag_MoveYoff);
                        mClipDataList.get(itemposj).crect.bottom = (int) (mClipDataList.get(itemposj).crect.bottom + mdrawDrag_MoveYoff);
                        cretblv = true;
                    }
                }
                if (cmkind == KIND_TEXT) {
                    if (itemposj >= 0 && itemposj < mTextDataList.size()) {
                        mTextDataList.get(itemposj).point.x = mTextDataList.get(itemposj).point.x + mdrawDrag_MoveXoff;
                        mTextDataList.get(itemposj).point.y = mTextDataList.get(itemposj).point.y + mdrawDrag_MoveYoff;
                        cretblv = true;
                    }
                }
                if (cmkind == KIND_POLYLINE) {
                    if (itemposj >= 0 && itemposj < mPolyLineDataList.size()) {
                        byte gkind = mPolyLineDataList.get(itemposj).gkind;
                        if(gkind == MARKICONKIND_LINE){
                            for(int jp = 0;jp < mPolyLineDataList.get(itemposj).points.size();jp++){
                                mPolyLineDataList.get(itemposj).points.get(jp).x = mPolyLineDataList.get(itemposj).points.get(jp).x+mdrawDrag_MoveXoff;
                                mPolyLineDataList.get(itemposj).points.get(jp).y = mPolyLineDataList.get(itemposj).points.get(jp).y+mdrawDrag_MoveYoff;
                            }
                            cretblv = true;
                        }
                        if(gkind == MARKICONKIND_OVAL || gkind == MARKICONKIND_SOLIDOVAL || gkind == MARKICONKIND_ARROW){
                            mPolyLineDataList.get(itemposj).points.get(0).x = mPolyLineDataList.get(itemposj).points.get(0).x+mdrawDrag_MoveXoff;
                            mPolyLineDataList.get(itemposj).points.get(0).y = mPolyLineDataList.get(itemposj).points.get(0).y+mdrawDrag_MoveYoff;
                            mPolyLineDataList.get(itemposj).points.get(1).x = mPolyLineDataList.get(itemposj).points.get(1).x+mdrawDrag_MoveXoff;
                            mPolyLineDataList.get(itemposj).points.get(1).y = mPolyLineDataList.get(itemposj).points.get(1).y+mdrawDrag_MoveYoff;
                            cretblv = true;
                        }
                    }
                }
            }
        }
        mdrawDragMoveblv = false;
        mdrawDrag_MoveXoff = 0;
        mdrawDrag_MoveYoff = 0;
        mdrawDragMove_Clipposj = -1;
        mdrawDragMove_Textposj = -1;
        mdrawDragMove_Markposj = -1;
        return cretblv;
    }

    public boolean findMarkDrawItem(float fx,float fy)
    {
        boolean cretblv = false;
        mdrawDragMoveblv = false;
        mdrawDragMove_Clipposj = -1;
        mdrawDragMove_Textposj = -1;
        mdrawDragMove_Markposj = -1;
        mdrawDrag_MoveXoff = 0;
        mdrawDrag_MoveYoff = 0;
        mfindMarkItemjno = -1;
        if(mcurMarkItemNum > 0){
            for(int jm = 0;jm < mcurMarkItemNum;jm++){
                if(fx <= mgraMarkList.get(jm).markRectf.left) continue;
                if(fx >= mgraMarkList.get(jm).markRectf.right) continue;
                if(fy <= mgraMarkList.get(jm).markRectf.top) continue;
                if(fy >= mgraMarkList.get(jm).markRectf.bottom) continue;
                mfindMarkItemjno = jm;
                byte cmkind = mgraMarkList.get(jm).kind;
                int itemposj = mgraMarkList.get(jm).itemposj;
                if(cmkind == KIND_CLIP) {
                    if (itemposj >= 0 && itemposj < mClipDataList.size()) {
                        mdrawDragMove_Clipposj = itemposj;
                    }
                }
                if(cmkind == KIND_TEXT) {
                    if (itemposj >= 0 && itemposj < mTextDataList.size()) {
                        mdrawDragMove_Textposj = itemposj;
                    }
                }
                if(cmkind == KIND_POLYLINE){
                    if(itemposj >= 0 && itemposj < mPolyLineDataList.size()){
                        mdrawDragMove_Markposj = itemposj;
                    }
                }
                cretblv = true;
                break;
            }
        }
        return cretblv;
    }
    private void drawTextItem(Canvas canvas,int iTextposj)
    {
        if(iTextposj >= 0 && iTextposj < mTextDataList.size()) {
            int iColorv = mTextDataList.get(iTextposj).color;
            int ifntsize = (int)(mTextDataList.get(iTextposj).fntsize*FSCALE);
            byte mkind = mTextDataList.get(iTextposj).mkind;
            String strTxt = mTextDataList.get(iTextposj).strTxt;
            Paint paint = new Paint();
            int ixpos = (int)(mTextDataList.get(iTextposj).point.x*FSCALE+TRANSLATIONx);
            int iypos = (int)(mTextDataList.get(iTextposj).point.y*FSCALE+TRANSLATIONy);
            if(mdrawDragMoveblv && mdrawDragMove_Textposj == iTextposj){
                ixpos = (int)((mTextDataList.get(iTextposj).point.x+mdrawDrag_MoveXoff)*FSCALE+TRANSLATIONx);
                iypos = (int)((mTextDataList.get(iTextposj).point.y+mdrawDrag_MoveYoff)*FSCALE+TRANSLATIONy);;
            }
            if(mkind == TEXTICONKIND_HORIZONTAL){
                paint.setColor(iColorv);
                paint.setTextSize(ifntsize);
                paint.setStyle(Paint.Style.FILL);
                canvas.drawText(strTxt,ixpos,iypos,paint);
                if(mcurMarkType != MARKTYPE_EMPTY) {
                    appendNewMarkItem(KIND_TEXT,mdrawGraItempj,iTextposj,iColorv,ixpos,iypos);
                }
            }
            if(mkind == TEXTICONKIND_VERTICAL){
                GraphicsExpItem.drawVertical2Text(canvas,strTxt,iColorv,ifntsize,ixpos,iypos);
                if(mcurMarkType != MARKTYPE_EMPTY) {
                    appendNewMarkItem(KIND_TEXT,mdrawGraItempj,iTextposj,iColorv,ixpos,iypos);
                }
            }
            if(mkind == TEXTICONKIND_ARC){
                GraphicsExpItem.drawTextOnArc(canvas,strTxt,iColorv,ifntsize,ixpos,iypos);
                if(mcurMarkType != MARKTYPE_EMPTY) {
                    appendNewMarkItem(KIND_TEXT,mdrawGraItempj,iTextposj,iColorv,ixpos,iypos);
                }
            }
        }

    }

    private void drawMarkItem(Canvas canvas,int iDrawposj)
    {
        if(iDrawposj >= 0 && iDrawposj < mPolyLineDataList.size()) {
            int iColorv = mPolyLineDataList.get(iDrawposj).iColor;
            int iLinewd = (int)(mPolyLineDataList.get(iDrawposj).icLwd*FSCALE);
            byte gkind = mPolyLineDataList.get(iDrawposj).gkind;
            int iTransparentv = mPolyLineDataList.get(iDrawposj).iTransparentv;
            int iRed = Color.red(iColorv);
            int iGreen = Color.green(iColorv);
            int iBlue = Color.blue(iColorv);
            int curDrawColorv = Color.argb(iTransparentv,iRed,iGreen,iBlue);

            Paint paint = new Paint();
            if(gkind == MARKICONKIND_LINE){
                Path polyLinepath = new Path();
                //... fxpos = mPolyLineList.get(0).x;
                //... fypos = mPolyLineList.get(0).y;
                int ixpos = (int)(mPolyLineDataList.get(iDrawposj).points.get(0).x*FSCALE+TRANSLATIONx);
                int iypos = (int)(mPolyLineDataList.get(iDrawposj).points.get(0).y*FSCALE+TRANSLATIONy);
                if(mdrawDragMoveblv && mdrawDragMove_Markposj == iDrawposj){
                    ixpos = (int)((mPolyLineDataList.get(iDrawposj).points.get(0).x+mdrawDrag_MoveXoff)*FSCALE+TRANSLATIONx);
                    iypos = (int)((mPolyLineDataList.get(iDrawposj).points.get(0).y+mdrawDrag_MoveYoff)*FSCALE+TRANSLATIONy);
                }
                polyLinepath.moveTo(ixpos,iypos);
                if(mcurMarkType != MARKTYPE_EMPTY) {
                    appendNewMarkItem(KIND_POLYLINE, mdrawGraItempj, iDrawposj, iColorv, ixpos, iypos);
                }
                for(int jp = 1;jp < mPolyLineDataList.get(iDrawposj).points.size();jp++){
                    ixpos = (int)(mPolyLineDataList.get(iDrawposj).points.get(jp).x*FSCALE+TRANSLATIONx);
                    iypos = (int)(mPolyLineDataList.get(iDrawposj).points.get(jp).y*FSCALE+TRANSLATIONy);
                    if(mdrawDragMoveblv && mdrawDragMove_Markposj == iDrawposj){
                        ixpos = (int)((mPolyLineDataList.get(iDrawposj).points.get(jp).x+mdrawDrag_MoveXoff)*FSCALE+TRANSLATIONx);
                        iypos = (int)((mPolyLineDataList.get(iDrawposj).points.get(jp).y+mdrawDrag_MoveYoff)*FSCALE+TRANSLATIONy);
                    }
                    polyLinepath.lineTo(ixpos,iypos);
                }
                paint.setStyle(Paint.Style.STROKE);
                paint.setAntiAlias(true); // 去锯齿
                paint.setColor(curDrawColorv);// miDrawColorv);
                paint.setStrokeWidth(iLinewd);
                canvas.drawPath(polyLinepath, paint);
            }
            if(gkind == MARKICONKIND_OVAL){
                float fLeft = (float)(mPolyLineDataList.get(iDrawposj).points.get(0).x*FSCALE+TRANSLATIONx);
                float fRight = (float)(mPolyLineDataList.get(iDrawposj).points.get(1).x*FSCALE+TRANSLATIONx);
                float fTop = (float)(mPolyLineDataList.get(iDrawposj).points.get(0).y*FSCALE+TRANSLATIONy);
                float fBottom = (float)(mPolyLineDataList.get(iDrawposj).points.get(1).y*FSCALE+TRANSLATIONy);
                if(mdrawDragMoveblv && mdrawDragMove_Markposj == iDrawposj){
                    fLeft = (float)((mPolyLineDataList.get(iDrawposj).points.get(0).x+mdrawDrag_MoveXoff)*FSCALE+TRANSLATIONx);
                    fRight = (float)((mPolyLineDataList.get(iDrawposj).points.get(1).x+mdrawDrag_MoveXoff)*FSCALE+TRANSLATIONx);
                    fTop = (float)((mPolyLineDataList.get(iDrawposj).points.get(0).y+mdrawDrag_MoveYoff)*FSCALE+TRANSLATIONy);
                    fBottom = (float)((mPolyLineDataList.get(iDrawposj).points.get(1).y+mdrawDrag_MoveYoff)*FSCALE+TRANSLATIONy);
                }
                RectF rectF = new RectF(fLeft, fTop,fRight,fBottom);
                Path drawpath = new Path();
                drawpath.addOval(rectF, Path.Direction.CCW);
                paint.setStyle(Paint.Style.STROKE);
                paint.setAntiAlias(true); // 去锯齿
                paint.setColor(curDrawColorv);// miDrawColorv);
                paint.setStrokeWidth(iLinewd);
                canvas.drawPath(drawpath, paint);
                if(mcurMarkType != MARKTYPE_EMPTY) {
                    appendNewMarkItem(KIND_POLYLINE, mdrawGraItempj, iDrawposj, iColorv, (int) ((fLeft + fRight) / 2), (int) ((fTop + fBottom) / 2));
                }
            }
            if(gkind == MARKICONKIND_SOLIDOVAL){
                float fLeft = (float)(mPolyLineDataList.get(iDrawposj).points.get(0).x*FSCALE+TRANSLATIONx);
                float fRight = (float)(mPolyLineDataList.get(iDrawposj).points.get(1).x*FSCALE+TRANSLATIONx);
                float fTop = (float)(mPolyLineDataList.get(iDrawposj).points.get(0).y*FSCALE+TRANSLATIONy);
                float fBottom = (float)(mPolyLineDataList.get(iDrawposj).points.get(1).y*FSCALE+TRANSLATIONy);
                if(mdrawDragMoveblv && mdrawDragMove_Markposj == iDrawposj){
                    fLeft = (float)((mPolyLineDataList.get(iDrawposj).points.get(0).x+mdrawDrag_MoveXoff)*FSCALE+TRANSLATIONx);
                    fRight = (float)((mPolyLineDataList.get(iDrawposj).points.get(1).x+mdrawDrag_MoveXoff)*FSCALE+TRANSLATIONx);
                    fTop = (float)((mPolyLineDataList.get(iDrawposj).points.get(0).y+mdrawDrag_MoveYoff)*FSCALE+TRANSLATIONy);
                    fBottom = (float)((mPolyLineDataList.get(iDrawposj).points.get(1).y+mdrawDrag_MoveYoff)*FSCALE+TRANSLATIONy);
                }
                RectF rectF = new RectF(fLeft, fTop,fRight,fBottom);
                Path drawpath = new Path();
                drawpath.addOval(rectF, Path.Direction.CCW);
                paint.setStyle(Paint.Style.FILL);
                paint.setAntiAlias(true); // 去锯齿
                paint.setColor(curDrawColorv);// miDrawColorv);
                //... paint.setStrokeWidth(miLinewide);
                canvas.drawPath(drawpath, paint);
                if(mcurMarkType != MARKTYPE_EMPTY) {
                    appendNewMarkItem(KIND_POLYLINE, mdrawGraItempj, iDrawposj, iColorv, (int) ((fLeft + fRight) / 2), (int) ((fTop + fBottom) / 2));
                }
            }
            if(gkind == MARKICONKIND_ARROW){
                float fLeft = (float)(mPolyLineDataList.get(iDrawposj).points.get(0).x*FSCALE+TRANSLATIONx);
                float fRight = (float)(mPolyLineDataList.get(iDrawposj).points.get(1).x*FSCALE+TRANSLATIONx);
                float fTop = (float)(mPolyLineDataList.get(iDrawposj).points.get(0).y*FSCALE+TRANSLATIONy);
                float fBottom = (float)(mPolyLineDataList.get(iDrawposj).points.get(1).y*FSCALE+TRANSLATIONy);
                if(mdrawDragMoveblv && mdrawDragMove_Markposj == iDrawposj){
                    fLeft = (float)((mPolyLineDataList.get(iDrawposj).points.get(0).x+mdrawDrag_MoveXoff)*FSCALE+TRANSLATIONx);
                    fRight = (float)((mPolyLineDataList.get(iDrawposj).points.get(1).x+mdrawDrag_MoveXoff)*FSCALE+TRANSLATIONx);
                    fTop = (float)((mPolyLineDataList.get(iDrawposj).points.get(0).y+mdrawDrag_MoveYoff)*FSCALE+TRANSLATIONy);
                    fBottom = (float)((mPolyLineDataList.get(iDrawposj).points.get(1).y+mdrawDrag_MoveYoff)*FSCALE+TRANSLATIONy);
                }
                GraphicsExpItem.drawARROW(canvas,(int)fLeft, (int)fTop,(int)fRight,(int)fBottom,curDrawColorv,iLinewd);
                if(mcurMarkType != MARKTYPE_EMPTY) {
                    appendNewMarkItem(KIND_POLYLINE, mdrawGraItempj, iDrawposj, iColorv, (int) ((fLeft + fRight) / 2), (int) ((fTop + fBottom) / 2));
                }
            }
        }

    }

    private int drawClipItem(Canvas canvas,int iClipItemposj,int iClipItemIDno)
    {
        int itemposj = iClipItemposj;
        if(iClipItemposj < 0 && iClipItemIDno > 0){
            for(int ic = 0;ic < mClipDataList.size();ic++){
                if(mClipDataList.get(ic).itemIDno != iClipItemIDno) continue;
                itemposj = ic;
                break;
            }
        }
        if(itemposj >= 0){
            Paint paint = new Paint();
            RectF outrectF = new RectF();
            outrectF.left = bmpLEFT*FSCALE+TRANSLATIONx;
            outrectF.top = bmpTOP*FSCALE+TRANSLATIONy;
            outrectF.right = bmpRIGHT*FSCALE+TRANSLATIONx;
            outrectF.bottom = bmpBOTTOM*FSCALE+TRANSLATIONy;
            Path clipRectpath = new Path();
            clipRectpath.addRect(outrectF, Path.Direction.CCW);
            int iClipColorv = mClipDataList.get(itemposj).caColor;
            Rect rect = new Rect();
            rect.left = mClipDataList.get(itemposj).crect.left;
            rect.right = mClipDataList.get(itemposj).crect.right;
            rect.top = mClipDataList.get(itemposj).crect.top;
            rect.bottom = mClipDataList.get(itemposj).crect.bottom;
            if(mdrawDragMoveblv && mdrawDragMove_Clipposj == itemposj){
                rect.left = rect.left+mdrawDrag_MoveXoff;
                rect.right = rect.right+mdrawDrag_MoveXoff;
                rect.top = rect.top+mdrawDrag_MoveYoff;
                rect.bottom = rect.bottom+mdrawDrag_MoveYoff;
            }
            RectF cliprectF= new RectF();
            cliprectF.left = rect.left*FSCALE+TRANSLATIONx;
            cliprectF.top = rect.top*FSCALE+TRANSLATIONy;
            cliprectF.right = rect.right*FSCALE+TRANSLATIONx;
            cliprectF.bottom = rect.bottom*FSCALE+TRANSLATIONy;
            if(mClipDataList.get(itemposj).kind == KINDCLIP_RECT){
                clipRectpath.addRect(cliprectF, Path.Direction.CW);
                if(mcurMarkType != MARKTYPE_EMPTY) {
                    appendNewMarkItem(KIND_CLIP, miGraClipItemposj, itemposj, iClipColorv, (int) ((cliprectF.left + cliprectF.right) / 2), (int) ((cliprectF.top + cliprectF.bottom) / 2));
                }
            }
            if(mClipDataList.get(itemposj).kind == KINDCLIP_OVAL){
                clipRectpath.addOval(cliprectF, Path.Direction.CW);
                int ixpos = (int)((cliprectF.left+cliprectF.right)/2);
                int iypos = (int)((cliprectF.top+cliprectF.bottom)/2);
                if(mcurMarkType != MARKTYPE_EMPTY) {
                    appendNewMarkItem(KIND_CLIP, miGraClipItemposj, itemposj, iClipColorv, ixpos, iypos);
                }
            }
            int iRed = Color.red(iClipColorv);
            int iGreen = Color.green(iClipColorv);
            int iBlue = Color.blue(iClipColorv);
            paint.setColor(Color.argb(miClipAlpha,iRed,iGreen,iBlue));
            paint.setStyle(Paint.Style.FILL);
            canvas.drawPath(clipRectpath, paint);
        }
        return itemposj;
    }

    public Rect getOndrawClipRect() {
        Rect rect = new Rect(0,1,0,1);
        if(mondrawClipLstpj >= 0 && mondrawClipLstpj < mClipDataList.size()){
            rect = mClipDataList.get(mondrawClipLstpj).crect;
        };
        return rect;
    }

    public byte getOndrawClipKind() {
        byte ckind = 0;
        if(mondrawClipLstpj >= 0 && mondrawClipLstpj < mClipDataList.size()){
            ckind = mClipDataList.get(mondrawClipLstpj).kind;
        };
        return ckind;
    }

    private void appendNewMarkItem(byte ckind,int igraposj,int itemposj,int cColorv,int ixpos,int iypos)
    {
        if(mcurMarkItemNum >=0 && mcurMarkItemNum < mgraMarkList.size()) {
            mgraMarkList.get(mcurMarkItemNum).updateResetPara(ckind, igraposj, itemposj, cColorv, ixpos, iypos, mbutWide/2);
            mcurMarkItemNum++;
        }
    }
    //
    class graMarkItem implements Serializable {
        private byte kind;
        private int igraPosj,itemposj;
        private int iColorv;
        RectF markRectf;
        public graMarkItem()
        {
            kind = 0;
            igraPosj = -1;
            itemposj = -1;
            iColorv = Color.RED;
            markRectf = new RectF();
            markRectf.left = 0;
            markRectf.right = 60;
            markRectf.top = 0;
            markRectf.bottom = 60;
        }

        public graMarkItem(byte ckind,int igposj,int itposj,int cColor,int ixpos,int iypos,int butwide)
        {
            kind = ckind;
            igraPosj = igposj;
            itemposj = itposj;
            iColorv = cColor;
            markRectf = new RectF();
            markRectf.left = ixpos-butwide;
            markRectf.right = ixpos+butwide;
            markRectf.top = iypos-butwide;
            markRectf.bottom = iypos+butwide;
        }

        public void updateResetPara(byte ckind,int igposj,int itposj,int cColor,int ixpos,int iypos,int butwide)
        {
            kind = ckind;
            igraPosj = igposj;
            itemposj = itposj;
            iColorv = cColor;
            markRectf.left = ixpos-butwide;
            markRectf.right = ixpos+butwide;
            markRectf.top = iypos-butwide;
            markRectf.bottom = iypos+butwide;
        }
    }
    //
    class GraItemData  implements Serializable {

        private byte kind,status;
        private int IDno,posj;
        public GraItemData()
        {
            kind = KIND_TEXT;
            status = STATUS_NORMAL;
            IDno = 0;
            posj = -1;
        }
        // set
        public void setData(byte ckind,byte cstatus,int iIDno,int iposj)
        {
            kind = ckind;
            status = cstatus;
            IDno = iIDno;
            posj = iposj;
        }
        // set
        public void setGraItemDataPosj(int iposj){
            posj = iposj;
        }
        // get
        public byte getKind(){ return kind;}
        public byte getStatus(){ return status;}
    }
    //
    class ClipData  implements Serializable {
        private Rect crect;
        private byte kind;
        private int caColor;
        private int itemIDno;
        public ClipData()
        {
            kind = KINDCLIP_RECT;
            caColor = clipColor;
            itemIDno = -1;
            crect = new Rect(100,100,600,900);
        }

        public ClipData(byte ckind,int icolor,Rect cSrect,int itemCIDno)
        {
            kind = ckind;
            caColor = icolor;
            itemIDno = itemCIDno;
            crect = cSrect;
        }
    }
    //...
    class TextData  implements Serializable {
        private byte status;
        private byte mkind;
        private String strTxt;
        private int color;
        private int fntsize;
        private int txIDno;
        private Point point;
        public TextData()
        {
            status = STATUS_EMPTY;
            strTxt = curStrTxt;
            color = curTxtColor;
            fntsize = curFntsize;
            txIDno = curTxtIDno;
            point = new Point(100,160);
        }
    }
    //
    class PolyLineData  implements Serializable {
        //... private byte status;
        private byte gkind;
        //... private int ipolyIDno;
        private int iColor;
        private int icLwd;
        private int iTransparentv;
        private ArrayList<Point> points = null;
        public PolyLineData(){
            //... status = STATUS_EMPTY;
            gkind = MARKICONKIND_LINE;
            iTransparentv = curTransparent;
            iColor = polyColor;
            icLwd = curLinewd;
            points = new ArrayList<>();
        }
        // set
        public void SetParaItem(byte cgkind,int icColor,int icLinewide,int icTranspaent,ArrayList<Point> cpointLst){
            gkind = cgkind;
            iColor = icColor;
            icLwd = icLinewide;
            iTransparentv = icTranspaent;
            if(cpointLst.size() > 0){
                for(int jpt = 0;jpt < cpointLst.size();jpt++){
                    points.add(cpointLst.get(jpt));
                };
            }
        }
    }
    //
    class UndoData implements Serializable {
        byte gkind,status;
        private int igraItempos;
        public UndoData()
        {
            gkind = KIND_EMPTY;
            status = STATUS_EMPTY;
            igraItempos = -1;
        }
        public UndoData(byte kind,byte Status,int igraposj)
        {
            gkind = kind;
            status = Status;
            igraItempos = igraposj;
        }
    }
}

   四,应用实例简介
      这是一个应用自定 RelativeLayout 实现的专用图片编辑界面(Fragment_PictureEdit)。通过这个界面可以选择相册中的图片进行编辑。这里重点是展示如何设置自定RelativeLayout的操作菜单(buildPictureEditButton()),如何通过回调(Callback)设置控制参数(标记形状,颜色等)。

 1),Layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/maintimeask_LLayout"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/timetaskColor_mainbg"
    android:weightSum="100"
    tools:context="com.bi3eview.newstart60.local.PictureEdit.Fragment_PictureEdit">
    <!-- Information ............................................................................-->
    <LinearLayout
        android:id="@+id/taskInfo_LAYOUT"
        android:layout_weight="4"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:background="@color/doTaskColor_infobg"
        >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="3dp"
            android:gravity="left"
            android:textColor="@color/fragPictureEditColor_infoTitle"
            android:textSize="@dimen/fragPictureEditSize_infoTitle"
            android:text="@string/fragpictureedit_infoTitle"
            />
        <TextView
            android:id="@+id/operMsg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="left"
            android:textColor="@color/fragPictureEditColor_operInfo"
            android:textSize="@dimen/fragPictureEditSize_operInfo"
            android:text=""
            />
    </LinearLayout>
    <!-- head ..................................................................................-->
    <LinearLayout
        android:gravity="center"
        android:id="@+id/eventtask_topview"
        android:layout_weight="9"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginLeft="3dp"
        android:layout_marginRight="3dp"
        android:orientation="horizontal"
        android:weightSum="100">
        <LinearLayout
            android:id="@+id/Layoutbut_Album"
            android:layout_width="0dp"
            android:layout_height="36dp"
            android:gravity="center"
            android:layout_weight="20"
            android:background="@drawable/combutton_layoutbg"
            android:orientation="horizontal">
            <ImageView
                android:id="@+id/imgbut_Album"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="right"
                android:tint="@color/blue"
                android:src="@drawable/comvec_album"
                />
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="left"
                android:textColor="@color/tableheadColor1_topvtxt"
                android:text="@string/cyberTaskbut_ALBUM"
                android:textSize="@dimen/timetaskbut_text"
                />
        </LinearLayout>
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="36dp"
            android:gravity="center"
            android:layout_weight="2"
            android:orientation="horizontal">
        </LinearLayout>
        <LinearLayout
            android:id="@+id/Layoutbut_EMPTY"
            android:layout_width="0dp"
            android:layout_height="28dp"
            android:gravity="center"
            android:layout_weight="13"
            android:background="@drawable/combutton_layoutside"
            android:orientation="horizontal">
            <TextView
                android:id="@+id/edtpic_EMPTY"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:layout_weight="20"
                android:textColor="@color/doTaskColor_botbutxt"
                android:text=""
                android:textSize="@dimen/finishTask_bottomfbtsize"
                />
        </LinearLayout>
        <LinearLayout
            android:id="@+id/Layoutbut_SAVE"
            android:layout_width="0dp"
            android:layout_height="36dp"
            android:gravity="center"
            android:layout_weight="20"
            android:background="@drawable/combutton_layoutbg"
            android:orientation="horizontal">
            <ImageView
                android:id="@+id/imgbut_mparYES"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="15"
                android:gravity="right"
                android:tint="@color/yellow"
                android:src="@drawable/comvec_savedata"
                />
            <TextView
                android:id="@+id/txtyes_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="left"
                android:layout_weight="15"
                android:textColor="@color/tableheadColor1_topvtxt"
                android:text="@string/fragpictureedit_saveEdit"
                android:textSize="@dimen/timetaskbut_text"
                />
        </LinearLayout>
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="36dp"
            android:gravity="center"
            android:layout_weight="2"
            android:orientation="horizontal">
        </LinearLayout>
        <LinearLayout
            android:id="@+id/Layoutbut_CLIPYES"
            android:layout_marginTop="3dp"
            android:layout_width="0dp"
            android:layout_height="46dp"
            android:gravity="center"
            android:layout_weight="29"
            android:orientation="vertical">
            <CheckBox
                android:id="@+id/chk_clipyes"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="@dimen/finishTask_botpritxt"
                android:saveEnabled="false"
                android:textColor="@color/doTaskColor_botchkubkg"
                android:text="@string/fragpictureedit_pictureClip" />
        </LinearLayout>
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="36dp"
            android:gravity="center"
            android:layout_weight="2"
            android:orientation="horizontal">
        </LinearLayout>
        <LinearLayout
            android:id="@+id/Layoutbut_PICNUM"
            android:layout_width="0dp"
            android:layout_height="28dp"
            android:gravity="center"
            android:layout_weight="10"
            android:background="@drawable/combutton_layoutside"
            android:orientation="horizontal">
            <TextView
                android:id="@+id/edtpic_num"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:layout_weight="20"
                android:textColor="@color/fragPictureEditColor_picNum"
                android:text=""
                android:textSize="@dimen/fragPictureEditSize_picnum"
                />
        </LinearLayout>
    </LinearLayout>
    <!-- 自定RelativeLayout ..........-->
    <com.bi3eview.newstart60.local.doTask.TaskDataLLayout
        android:id="@+id/Layout_taskDataLst"
        android:layout_weight="86"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="@color/darkWhite"
        android:orientation="vertical">
    </com.bi3eview.newstart60.local.doTask.TaskDataLLayout>
    <!-- bottom line ............................................................................-->
    <LinearLayout
        android:id="@+id/bottom_LLayout"
        android:gravity="center"
        android:layout_weight="1"
        android:layout_width="fill_parent"
        android:layout_marginLeft="3dp"
        android:layout_marginRight="3dp"
        android:orientation="horizontal"
        android:weightSum="100"
        android:layout_height="0dp" >
</LinearLayout>
</LinearLayout>

2), Fragment 代码

package com.bi3eview.newstart60.local.PictureEdit;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import static android.app.Activity.RESULT_OK;

import com.bi3eview.newstart60.local.COMCONST;
import com.bi3eview.newstart60.local.JavaLoadCppLib.ActEventDataClass;
import com.bi3eview.newstart60.local.R;
import com.bi3eview.newstart60.local.SelfWidget.ComboxItem;
import com.bi3eview.newstart60.local.SelfWidget.PopupWindowCombox;
import com.bi3eview.newstart60.local.SelfWidget.PopupWindowDlg;
import com.bi3eview.newstart60.local.Util.GraphicItemUtil;
import com.bi3eview.newstart60.local.Util.buttonData;
import com.bi3eview.newstart60.local.Util.buttonDrawUtil;
import com.bi3eview.newstart60.local.constant.Constants;
import com.bi3eview.newstart60.local.doTask.TaskDataLLayout;
import com.bi3eview.newstart60.local.fragmentSimple.ICallBack;
import com.bi3eview.newstart60.local.pubcom.GraphicsSetDlgClip;
import com.bi3eview.newstart60.local.pubcom.GraphicsSetDlgMark;
import com.bi3eview.newstart60.local.pubcom.GraphicsSetDlgText;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by bs60 on 2022.09.21
 */
public class Fragment_PictureEdit  extends Fragment {
    Context mContext = null;
    private View mView;
    Bundle bundle = null;
    ICallBack callback;
    //
    private int mphoto_EDITPICMODE = 0;
    //
    private TaskDataLLayout mTaskDataLayout = null;
    LinearLayout mtop_LLayoutButAlbum;
    LinearLayout mtop_LLayoutButEmpty;
    LinearLayout mtop_LLayoutButSave;
    LinearLayout mtop_LLayoutButPicNum;
    CheckBox mchk_clipPicture;
    TextView medtpic_num;
    TextView m_operInfo;

    private String muri_strPhotoname = null;
    private String mapp_uriTasktmpPhotoname = null;
    boolean mcapture_photoblv = false;
    boolean msave_ProcessLockblv = false;
    int mcurEdtPicNum = 0;
    Bitmap mphoto_bipmap;
    // graphics parameter kind
    final int GRAPHICSPARASET_CLIP = 1;
    final int GRAPHICSPARASET_TEXT = 2;
    final int GRAPHICSPARASET_DRAW = 3;

    final int EDITPICTURE_GETSUBDIR = 100;
    final int EDITPICTURE_GETTIMENAME = 101;
    final int EDITPICTURE_GETFILENUM = 102;
    final int EDITPICTURE_DELETEFILE = 104;
    //
    private final int  REQUESTCODE_ALBUM = 3;

    // handler
    final int RESETPHOTOVIEW = 1000;
    final int BUILDPICTUREBUTTON  = 1006;
    final int GRAPHICSPARASETDLG = 1007;
    final int BUTTONOPERINFO = 2000;
    final int COMMONTOASTINFO = 2001;
    final int PICTURESAVEEDIT = 2002;
    final int EDITPICTUREDIRFILE = 2003;
    final int DOEXEDELEDITPICTURE = 2004;
    private Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            String strInfoj;
            switch (msg.what) {
                case DOEXEDELEDITPICTURE:
                    doexeDELEditPic();
                    break;
                case EDITPICTUREDIRFILE:
                    EditPictureDelete();
                    break;
                case PICTURESAVEEDIT:
                    SaveEditPicture();
                    break;
                case COMMONTOASTINFO:
                    strInfoj = (String) msg.obj;
                    COMCONST.ToastCenterImage(mContext,strInfoj,R.drawable.comvec_err, Toast.LENGTH_LONG,Color.RED);
                    break;
                case BUTTONOPERINFO:
                    strInfoj = (String) msg.obj;
                    m_operInfo.setText(strInfoj);
                    break;
                case GRAPHICSPARASETDLG:
                    int igraKind = (int)msg.obj;
                    graEditSetPara(igraKind);
                    break;
                case BUILDPICTUREBUTTON:
                    buildPictureEditButton();
                    mTaskDataLayout.dataShowSet(false);
                    mTaskDataLayout.invalidate();
                    break;
                case RESETPHOTOVIEW:
                    if(mTaskDataLayout != null && muri_strPhotoname.length() > 1){
                        mphoto_bipmap = BitmapFactory.decodeFile(muri_strPhotoname);// BitmapFactory.decodeStream(fis);
                        int iwidthv = mphoto_bipmap.getWidth();
                        int iheightv = mphoto_bipmap.getHeight();
                        mTaskDataLayout.updateSetPhotoBitmap(mphoto_bipmap);
                        mTaskDataLayout.invalidate();
                        mtop_LLayoutButSave.setVisibility(View.VISIBLE);
                    }
                    break;
            }
        }
    };
    //
    public Fragment_PictureEdit() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {

        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        mView = inflater.inflate(R.layout.fragment_picture_edit, container, false);
        mtop_LLayoutButAlbum = (LinearLayout) mView.findViewById(R.id.Layoutbut_Album);
        mtop_LLayoutButEmpty = (LinearLayout) mView.findViewById(R.id.Layoutbut_EMPTY);
        mtop_LLayoutButEmpty.setVisibility(View.INVISIBLE);
        mtop_LLayoutButSave = (LinearLayout) mView.findViewById(R.id.Layoutbut_SAVE);
        mtop_LLayoutButPicNum = (LinearLayout) mView.findViewById(R.id.Layoutbut_PICNUM);
        mTaskDataLayout = (TaskDataLLayout) mView.findViewById(R.id.Layout_taskDataLst);
        medtpic_num = (TextView) mView.findViewById(R.id.edtpic_num);
        m_operInfo = (TextView) mView.findViewById(R.id.operMsg);
        m_operInfo.setText("...");// Welcome To Beijing!");
        mchk_clipPicture = (CheckBox) mView.findViewById(R.id.chk_clipyes);
        mTaskDataLayout.setOnItemClickCallback(new TaskDataLLayout.Callback() {
            @Override
            public void onItemClick(int position, int jno) {

            }
        });

        mTaskDataLayout.setOnButtonClickCallback(new TaskDataLLayout.buttonCallback() {
            @Override
            public void onButtonClick(byte buttonIDno, int ixoff,int iyoff,boolean doOper) {
                String strInfo = "";
                if(buttonIDno == buttonData.BUTTONIDNO_RESTORE){
                    strInfo = getResources().getString(R.string.pictureEditButton_Restore);
                }
               // 
                if(doOper){// do operation
                    if (buttonIDno == buttonData.BUTTONIDNO_PARASET) {
                        // 回调处理参数设置
                        if(buttonData.cActive_IDitem == buttonData.BUTTONIDNO_CLIP){
                            Message mcMsg = new Message();
                            mcMsg.obj = GRAPHICSPARASET_CLIP;
                            mcMsg.what = GRAPHICSPARASETDLG;
                            handler.sendMessage(mcMsg);
                        }
                        if(buttonData.cActive_IDitem == buttonData.BUTTONIDNO_TEXT){
                            Message mcMsg = new Message();
                            mcMsg.obj = GRAPHICSPARASET_TEXT;
                            mcMsg.what = GRAPHICSPARASETDLG;
                            handler.sendMessage(mcMsg);
                        }
                        if(buttonData.cActive_IDitem == buttonData.BUTTONIDNO_RUBBER){
                            Message mcMsg = new Message();
                            mcMsg.obj = GRAPHICSPARASET_DRAW;
                            mcMsg.what = GRAPHICSPARASETDLG;
                            handler.sendMessage(mcMsg);
                        }
                    }
                    if (buttonIDno == buttonData.BUTTONIDNO_SAVE) {
                        //... handler.sendEmptyMessage(SAVEEDITIMAGEOPER);
                    }
                }else {// help information
                    if (buttonIDno == buttonData.BUTTONIDNO_CLIP) {
                        strInfo = getResources().getString(R.string.pictureEditButton_Clip);
                    }
                    if (buttonIDno == buttonData.BUTTONIDNO_RUBBER) {
                        strInfo = getResources().getString(R.string.pictureEditButton_Rubber);
                    }
                    if (buttonIDno == buttonData.BUTTONIDNO_TEXT) {
                        strInfo = getResources().getString(R.string.pictureEditButton_Text);
                    }
                    if (buttonIDno == buttonData.BUTTONIDNO_DELETE) {
                        strInfo = getResources().getString(R.string.pictureEditButton_Delete);
                    }
                    if (buttonIDno == buttonData.BUTTONIDNO_DRAGMOVE) {
                        strInfo = getResources().getString(R.string.pictureEditButton_DragMove);
                    }
                    if (buttonIDno == buttonData.BUTTONIDNO_SAVE) {
                        strInfo = getResources().getString(R.string.pictureEditButton_Save);
                    }
                    if (buttonIDno == buttonData.BUTTONIDNO_SAVE_REINFO) {
                        //... strInfo = getResources().getString(R.string.pictureEditButton_SaveReinfo);
                    }
                    if (buttonIDno == buttonData.BUTTONIDNO_PARASET) {
                        strInfo = getResources().getString(R.string.pictureEditButton_Paraset);
                    }
                }
                if(strInfo.length() > 0){
                    //... mShowOffvPoint.x = ixoff;
                    //... mShowOffvPoint.y = iyoff;
                    Message msg = new Message();
                    msg.obj = strInfo;
                    msg.what = BUTTONOPERINFO;
                    handler.sendMessage(msg);
                }
            }
        });
        mcapture_photoblv = false;
        msave_ProcessLockblv = false;

        getDotaskFilePathName();
        setClickListenar();

        commonBusyWaitThread waitThread = new commonBusyWaitThread(handler,"12345" ,BUILDPICTUREBUTTON,1);
        Thread thread = new Thread(waitThread, "BusyWait61");
        thread.start();

        return mView;
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mContext = context;
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mContext = null;
    }

    private void setClickListenar() {
        mchk_clipPicture.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

            }
        });

        mtop_LLayoutButPicNum.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                handler.sendEmptyMessage(EDITPICTUREDIRFILE);
                return true;
            }
        });

        mtop_LLayoutButAlbum.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent cintent = new Intent(
                        Intent.ACTION_PICK,
                        android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                // 设定结果返回
                startActivityForResult(cintent, REQUESTCODE_ALBUM);
            }
        });

        mtop_LLayoutButSave.setVisibility(View.INVISIBLE);
        mtop_LLayoutButSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mTaskDataLayout.checkGraItemNum() <= 0){
                    Message msg = new Message();
                    msg.what = COMMONTOASTINFO;
                    msg.obj = getResources().getString(R.string.fragpictureedit_notEditItem);
                    handler.sendMessage(msg);
                }else{
                    boolean passblv = true;
                    if(mchk_clipPicture.isChecked()){
                        if(mTaskDataLayout.checkGraClipItemNum() <= 0){
                            passblv = false;
                            Message msg = new Message();
                            msg.what = COMMONTOASTINFO;
                            msg.obj = getResources().getString(R.string.fragpictureedit_notClipArea);
                            handler.sendMessage(msg);;
                        }
                    }
                    if(!msave_ProcessLockblv && passblv){
                        msave_ProcessLockblv = true;
                        handler.sendEmptyMessage(PICTURESAVEEDIT);
                    }
                }
            }
        });
    }

   // 设置自定RelativeLayout的操作菜单
    private void buildPictureEditButton()
    {
        String pkName = "";
        mcurEdtPicNum = 0;
        if(mTaskDataLayout != null){
            int iLayoutWidth = mTaskDataLayout.GetCanvasWidth();
            int iLayoutHeight = mTaskDataLayout.GetCanvasHeight();
            buttonData cbutData = new buttonData();
            String bName = "";
            int iButtonNum = 6;// 8+1+2;
            int buttonWide = 60;
            int buttonSpace = 30;
            int iwide = iLayoutWidth/iButtonNum;
            buttonSpace = iwide/3;
            buttonWide = buttonSpace*2;
            int iLeft = buttonWide/2;// 20;
            int iTop = buttonWide/2;
            float fcurScale = buttonWide/60f;
            float fscale = 1.7f*fcurScale;
            int ixoffv = (int)(8*fcurScale);
            int iyoffv = (int)(8*fcurScale);
            int iRight = iLeft+buttonWide;
            int iBottom = iTop+buttonWide;
            GraphicItemUtil.mbutWide = buttonWide;
            mTaskDataLayout.setButtonWide(buttonWide);
            mTaskDataLayout.setGraphicsItemMarkPara(fscale,(float)buttonWide,ixoffv,iyoffv);
            GraphicItemUtil.mgraItem_MarkFscale = fscale;
            GraphicItemUtil.mgraItem_Xoff = ixoffv;
            GraphicItemUtil.mgraItem_Yoff = iyoffv;
            // restore 1
            String strButPath = COMCONST.EDITBUTTON_RESTORE;
            cbutData.setButtonPath(buttonData.BUTTONKIND_OVAL,buttonData.BUTTONIDNO_RESTORE,
                    bName,iLeft,iTop,iRight,iBottom,fscale,strButPath,ixoffv,iyoffv,Color.BLUE);
            mTaskDataLayout.appendEditButton(cbutData);
            // clip 2
            int picItemColor = Color.argb(255,11,128,11);
            iLeft = iRight+buttonSpace;
            iRight = iLeft+buttonWide;
            strButPath = COMCONST.EDITBUTTON_CLIP;
            buttonDrawUtil.mSpotLightBmp = BitmapFactory.decodeResource(getResources(), R.drawable.grabutton_spotlightclip);
            buttonDrawUtil.mDragMoveBmp = BitmapFactory.decodeResource(getResources(), R.drawable.grabutton_dragmove);
            buttonData cbutData1 = new buttonData();
            cbutData1.setButtonPath(buttonData.BUTTONKIND_OVAL,buttonData.BUTTONIDNO_CLIP,
                    bName,iLeft,iTop,iRight,iBottom,fscale,strButPath,ixoffv,iyoffv,picItemColor);
            mTaskDataLayout.appendEditButton(cbutData1);
            // text 3
            iLeft = iRight+buttonSpace;
            iRight = iLeft+buttonWide;
            strButPath = COMCONST.EDITBUTTON_TEXT;
            buttonData cbutData2 = new buttonData();
            cbutData2.setButtonPath(buttonData.BUTTONKIND_OVAL,buttonData.BUTTONIDNO_TEXT,
                    bName,iLeft,iTop,iRight,iBottom,fscale,strButPath,ixoffv,iyoffv,picItemColor);
            mTaskDataLayout.appendEditButton(cbutData2);
            // rubber 4
            iLeft = iRight+buttonSpace;
            iRight = iLeft+buttonWide;
            strButPath = COMCONST.EDITBUTTON_RUBBER;
            buttonData cbutData3 = new buttonData();
            cbutData3.setButtonPath(buttonData.BUTTONKIND_OVAL,buttonData.BUTTONIDNO_RUBBER,
                    bName,iLeft,iTop,iRight,iBottom,fscale,strButPath,ixoffv,iyoffv,picItemColor);
            mTaskDataLayout.appendEditButton(cbutData3);
            // parameter set 5
            int paraSetColor = Color.argb(255,128,128,11);
            iLeft = iRight+buttonSpace;
            iRight = iLeft+buttonWide;
            strButPath = COMCONST.EDITBUTTON_PARASET;
            buttonData cbutData3b = new buttonData();
            cbutData3b.setButtonPath(buttonData.BUTTONKIND_OVAL,buttonData.BUTTONIDNO_PARASET,
                    bName,iLeft,iTop,iRight,iBottom,fscale,strButPath,ixoffv,iyoffv,paraSetColor);
            mTaskDataLayout.appendEditButton(cbutData3b);
            // 换行 ------------------------------------
            iLeft = buttonWide/2;
            iRight = iLeft+buttonWide;
            iTop = iBottom+buttonSpace;
            iBottom = iTop+buttonWide;
            // delete 6
            strButPath = COMCONST.EDITBUTTON_DELETE;
            buttonData cbutData4 = new buttonData();
            cbutData4.setButtonPath(buttonData.BUTTONKIND_OVAL,buttonData.BUTTONIDNO_DELETE,
                    bName,iLeft,iTop,iRight,iBottom,fscale,strButPath,ixoffv,iyoffv,Color.RED);
            mTaskDataLayout.appendEditButton(cbutData4);
            // draw move
            iLeft = iRight+buttonSpace;
            iRight = iLeft+buttonWide;
            strButPath = COMCONST.EDITBUTTON_UNDO;
            buttonData cbutData5 = new buttonData();
            cbutData5.setButtonPath(buttonData.BUTTONKIND_OVAL,buttonData.BUTTONIDNO_DRAGMOVE,
                    bName,iLeft,iTop,iRight,iBottom,fscale,strButPath,ixoffv,iyoffv,Color.BLACK);
            mTaskDataLayout.appendEditButton(cbutData5);

            buttonDrawUtil.mButtonResetblv = true;
            try {
                //包名
                pkName = mContext.getPackageName();
                mTaskDataLayout.setAppPackageName(pkName);
            } catch (Exception e) {
            }

        }
        //
        int[] daparv = new int[18];
        byte[] tmpRbyteArr = new byte[266];
        int iretcn = ActEventDataClass.JavaJNIgetSetEditPictureData_onSharebook(EDITPICTURE_GETSUBDIR, daparv, -1, tmpRbyteArr, 260);
        if(iretcn > 0){
            String strEdtDir =  new String(tmpRbyteArr, 0, iretcn);
            mTaskDataLayout.SetEditPictureFiledir(strEdtDir);
        }
        //
        iretcn = ActEventDataClass.JavaJNIgetSetEditPictureData_onSharebook(EDITPICTURE_GETFILENUM, daparv, -1, tmpRbyteArr, 260);
        if(iretcn > 0) {
            mcurEdtPicNum = iretcn;
            String strPicNum = String.valueOf(iretcn);
            medtpic_num.setText(strPicNum);

        }
        if (mcurEdtPicNum <= 0) {
            mtop_LLayoutButPicNum.setVisibility(View.INVISIBLE);
        }
        if(mTaskDataLayout != null){
            mphoto_bipmap = BitmapFactory.decodeResource(getResources(), R.drawable.drawplate);
            mTaskDataLayout.updateSetPhotoBitmap(mphoto_bipmap);
            mTaskDataLayout.invalidate();
            mtop_LLayoutButSave.setVisibility(View.VISIBLE);
        }
    }

    private void doexeDELEditPic()
    {
        int[] daparv = new int[18];
        byte[] tmpRbyteArr = new byte[266];
        int iretcn = ActEventDataClass.JavaJNIgetSetEditPictureData_onSharebook(EDITPICTURE_DELETEFILE, daparv, -1, tmpRbyteArr, 260);
        if(iretcn > 0){
            mtop_LLayoutButPicNum.setVisibility(View.INVISIBLE);
        };
    }

    private void EditPictureDelete()
    {
        if(mcurEdtPicNum > 0) {
            String strTitle = mContext.getResources().getString(R.string.fragpictureedit_deletePic) + "(" + String.valueOf(mcurEdtPicNum) + ")?";
            PopupWindowDlg curDlg = new PopupWindowDlg((Activity) mContext, strTitle);
            curDlg.setOnWinButtonClickListener(new PopupWindowDlg.OnWinButtonClickListener() {
                @Override
                public void onWindButtonClick(int butcd, String menuName) {
                    if (butcd == 9) {
                        handler.sendEmptyMessage(DOEXEDELEDITPICTURE);
                    }
                }
            });
            curDlg.showAtScreen(mtop_LLayoutButSave, COMCONST.LocationType.PARENT_CENTER);
        }else{
            mtop_LLayoutButPicNum.setVisibility(View.INVISIBLE);
        }
    }

    private void SaveEditPicture()
    {
        mtop_LLayoutButSave.setVisibility(View.INVISIBLE);
        boolean clipblv = mchk_clipPicture.isChecked();

        String strTimeFilename = "20220626_280818";
        int[] daparv = new int[18];
        byte[] tmpRbyteArr = new byte[266];
        int iretcn = ActEventDataClass.JavaJNIgetSetEditPictureData_onSharebook(EDITPICTURE_GETTIMENAME, daparv, -1, tmpRbyteArr, 260);
        if(iretcn > 0){
            strTimeFilename = new String(tmpRbyteArr, 0, iretcn);
        }
        mTaskDataLayout.SAVEINITRESET(strTimeFilename);
        String newPicname = mTaskDataLayout.SaveEditPicture(clipblv);
        if(newPicname.length() > 0){
            mphoto_bipmap = BitmapFactory.decodeFile(newPicname);
            mTaskDataLayout.updateSetPhotoBitmap(mphoto_bipmap);
            mTaskDataLayout.invalidate();
        }
        msave_ProcessLockblv = false;
        //... mtop_LLayoutButSave.setVisibility(View.VISIBLE);
    }

    private void graEditSetPara(int igraKind)
    {
        Activity activity = (Activity) mContext;
        if(igraKind == GRAPHICSPARASET_CLIP) {
            GraphicsSetDlgClip clipParaSetDlg = new GraphicsSetDlgClip(activity, "");
            clipParaSetDlg.setOnWinButtonClickListener(new GraphicsSetDlgClip.OnWinButtonClickListener() {
                @Override
                public void onWindButtonClick(int butcd, byte bkind, int iColor,int iTransparent) {
                    if (butcd == 9) {
                        mTaskDataLayout.updateSetClip(bkind, iColor,iTransparent);
                    }
                }
            });
            clipParaSetDlg.showAtScreen(mtop_LLayoutButAlbum, COMCONST.LocationType.LEFT_BOTTOM);
        }
        if(igraKind == GRAPHICSPARASET_TEXT) {
            GraphicsSetDlgText textParaSetDlg = new GraphicsSetDlgText(activity, "");
            textParaSetDlg.setOnWinButtonClickListener(new GraphicsSetDlgText.OnWinButtonClickListener() {
                @Override
                public void onWindButtonClick(int butcd, byte bkind, int iColor,int ifntsize,String markName) {
                    if (butcd == 9) {
                        mTaskDataLayout.updateSetText(bkind, iColor,ifntsize,markName);
                    }
                }
            });
            textParaSetDlg.showAtScreen(mtop_LLayoutButAlbum, COMCONST.LocationType.LEFT_BOTTOM);
        }
        if(igraKind == GRAPHICSPARASET_DRAW) {
            GraphicsSetDlgMark markParaSetDlg = new GraphicsSetDlgMark(activity, "");
            markParaSetDlg.setOnWinButtonClickListener(new GraphicsSetDlgMark.OnWinButtonClickListener() {
                @Override
                public void onWindButtonClick(int butcd, byte bkind, int iColor,int iLinewide,int iTransparentv) {
                    if (butcd == 9) {
                        mTaskDataLayout.updateSetDraw(bkind, iColor,iLinewide,iTransparentv);
                    }
                }
            });
            markParaSetDlg.showAtScreen(mtop_LLayoutButAlbum, COMCONST.LocationType.LEFT_BOTTOM);
        }
    }

    private String getDotaskFilePathName()
    {
        String taskPath = "";
        byte[] tmpRbyteArr = new byte[266];
        int[] daparv = new int[9];
        int iretcn = ActEventDataClass.JavaJNIgetOnTimeTaskParaInfo(20200128, daparv, -1, tmpRbyteArr, 262);
        if(iretcn > 0){
            String strDirpath = new String(tmpRbyteArr, 0, iretcn);
            taskPath = strDirpath;// +"/taskphototmp.jpg";
            muri_strPhotoname = taskPath;
            mapp_uriTasktmpPhotoname = taskPath;
            //... mdo_CameraAlibumPicName = taskPath;
        }
        return taskPath;
    }

    private void updateSetCameraPhotoQuality(String qualityName)
    {
        int icQualityVal = -1;
        int icModeVal = -1;
        String cqualityName = getResources().getString(R.string.cameraphoto_quality100);
        if(qualityName.equals(cqualityName)) icQualityVal = 100;
        if(icQualityVal < 0){
            cqualityName = getResources().getString(R.string.cameraphoto_quality200);
            if(qualityName.equals(cqualityName)) icQualityVal = 200;
        }
        if(icQualityVal < 0){
            cqualityName = getResources().getString(R.string.cameraphoto_quality300);
            if(qualityName.equals(cqualityName)) icQualityVal = 300;
        }
        if(icQualityVal < 0){
            cqualityName = getResources().getString(R.string.cameraphoto_quality000);
            if(qualityName.equals(cqualityName)) icQualityVal = 0;
        }
        if(icQualityVal >= 0 && icQualityVal != COMCONST.mc_cameraPhotoQuality){//  && COMCONST.mcom_SharedPreferences != null) {
            Constants.SharedPerferenceData.updateSetIntSharedPerference(Constants.SharedPerferenceData.SP_KEY_CAMERAPHOTOQUALITY, icQualityVal);
            COMCONST.mc_cameraPhotoQuality = icQualityVal;
        }
        // capture mode
        if(icQualityVal < 0){
            String cModeName = getResources().getString(R.string.cameraphoto_REDATA);
            if(qualityName.equals(cModeName)) icModeVal = COMCONST.CAPTURE_PHOTO_MODE_RETDATA;
            if(icModeVal < 0){
                cModeName = getResources().getString(R.string.cameraphoto_MOBILE);
                if(qualityName.equals(cModeName)) icModeVal = COMCONST.CAPTURE_PHOTO_MODE_RESOLVER;
            }
            if(icModeVal < 0){
                cModeName = getResources().getString(R.string.cameraphoto_APPCAPTUE);
                if(qualityName.equals(cModeName)) icModeVal = COMCONST.CAPTURE_PHOTO_MODE_HOMEGROWN ;
            }
            if(icModeVal > 0 && icModeVal != COMCONST.mcamera_PHOTOMODE && COMCONST.mcom_SharedPreferences != null){
                SharedPreferences.Editor editor = COMCONST.mcom_SharedPreferences.edit();
                editor.putInt(Constants.SharedPerferenceData.SP_KEY_EDITPICSIZEMODE, icModeVal);
                COMCONST.mcamera_PHOTOMODE = icModeVal;
                mphoto_EDITPICMODE = COMCONST.mcamera_PHOTOMODE;
                editor.commit();
            }
        }
    }

    private boolean savePhotoImage(Bitmap image) {
        boolean blretv = false;
        ByteArrayOutputStream bmpByteStream = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, bmpByteStream);
        byte[] bmpBytes = bmpByteStream.toByteArray();
        int[] daparv = new int[8];
        int iretv = ActEventDataClass.JavaJNIgetOnTimeTaskParaInfo(20200603, daparv, -1, bmpBytes, bmpBytes.length);
        if(iretv > 0) blretv = true;

        return blretv;
    }

    class commonBusyWaitThread implements Runnable {
        Handler mTHandler;
        String waitNo;
        int iWHATval = -1;
        int iWaitMilliSecond = 1000;
        public commonBusyWaitThread(Handler handler,String waitName,int iWhatv,int iWaitTimems)
        {
            this.mTHandler = handler;
            this.waitNo = waitName;
            this.iWHATval = iWhatv;
            this.iWaitMilliSecond = iWaitTimems;
            if(iWaitTimems < 120) this.iWaitMilliSecond = iWaitTimems*1000;
        }
        @Override
        public void run() {
            synchronized (waitNo) {
                try {
                    Thread.sleep(iWaitMilliSecond);// 1.5 second
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Message msg = new Message();
                msg.what = iWHATval;
                msg.obj = waitNo;
                handler.sendMessage(msg);
            }
        };
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        mcapture_photoblv = false;
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUESTCODE_ALBUM && resultCode == RESULT_OK) {// select photo alibum
            if (data != null) {
                Uri uri = data.getData();
                try {
                    Bitmap bitmap = BitmapFactory.decodeStream(mContext.getContentResolver().openInputStream(uri));
                    if (savePhotoImage(bitmap)) {
                        mcapture_photoblv = true;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    /* Message msgErr = new Message();
                    msgErr.obj = getResources().getString(R.string.finishTaskInfo_alibumErr);
                    msgErr.what = COMMONTOASTSHOW;
                    handler.sendMessage(msgErr); */
                }
            }
        }
        // final
        if(mcapture_photoblv == true) {
            if (muri_strPhotoname.length() > 1) {
                Message msg = new Message();
                msg.what = RESETPHOTOVIEW;
                msg.obj = "data";
                handler.sendMessage(msg);
            }
        }
    }
    // 设置 接口回调 方法
    public void sendMessage(ICallBack callBack){
        this.callback = callBack;

    }

    // Receive message - activity to fragment
    public void receiveMsg(int msgcd,String msg) {
        if (msgcd == 210830) {

        }
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

newstart60

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值