Explorar o código

1.添加获取mmse试题库UI跳转

王鹏鹏 %!s(int64=2) %!d(string=hai) anos
pai
achega
619edc19fa

+ 17 - 0
baselib/src/main/java/com/yingyangfly/baselib/utils/ImageUtil.kt

@@ -1,5 +1,7 @@
 package com.yingyangfly.baselib.utils
 
+import android.content.Context
+import android.graphics.Bitmap
 import android.graphics.drawable.Drawable
 import android.widget.ImageView
 import androidx.annotation.DrawableRes
@@ -180,4 +182,19 @@ object ImageUtil {
             load.into(this)
         }
     }
+
+    /**
+     * 加载网络图片
+     */
+    fun loadUrl(
+        content: Context,
+        bitmap: Drawable,
+        imageView: ImageView
+    ) {
+        Glide.with(content)
+            .load(bitmap)
+            .placeholder(R.mipmap.icon_place_holder)
+            .error(R.mipmap.icon_place_holder)
+            .into(imageView)
+    }
 }

+ 1 - 1
mmse/src/main/java/com/yingyangfly/mmse/fragment/DrawDesignsFragment.kt

@@ -44,7 +44,7 @@ class DrawDesignsFragment : BaseFragment<FragmentDrawDesignsBinding>() {
             btnNext.setOnSingleClickListener {
                 val bundle = Bundle()
                 bundle.putInt("questionId", 30)
-                val bitmap: Bitmap = signatureView.drawingCache
+                val bitmap: Bitmap = signatureView.getCachebBitmaps()
                 bundle.putParcelable("bitmap", bitmap)
                 val controller = Navigation.findNavController(it)
                 controller.navigate(

+ 23 - 3
mmse/src/main/java/com/yingyangfly/mmse/fragment/RecognitionImageFragment.kt

@@ -1,5 +1,8 @@
 package com.yingyangfly.mmse.fragment
 
+import android.graphics.Bitmap
+import android.graphics.drawable.BitmapDrawable
+import android.graphics.drawable.Drawable
 import android.os.Bundle
 import androidx.core.os.bundleOf
 import androidx.navigation.Navigation
@@ -8,8 +11,10 @@ import com.yingyang.mmse.databinding.FragmentRecognitionImageBinding
 import com.yingyangfly.baselib.base.BaseFragment
 import com.yingyangfly.baselib.db.QuestionsBean
 import com.yingyangfly.baselib.ext.setOnSingleClickListener
+import com.yingyangfly.baselib.utils.ImageUtil
 import com.yingyangfly.mmse.adapter.ChoiceAdapter
 
+
 /**
  * 识图功能
  */
@@ -22,9 +27,11 @@ class RecognitionImageFragment : BaseFragment<FragmentRecognitionImageBinding>()
 
     private val choiceItemList = mutableListOf<QuestionsBean>()
     private val adapter by lazy { ChoiceAdapter() }
+    private var bitmap: Bitmap? = null
 
     override fun onCreate(savedInstanceState: Bundle?) {
         questionId = arguments?.getInt("questionId") ?: 22
+        bitmap = arguments?.getParcelable("bitmap")
         super.onCreate(savedInstanceState)
     }
 
@@ -45,7 +52,10 @@ class RecognitionImageFragment : BaseFragment<FragmentRecognitionImageBinding>()
                 if (questionId == 30) {
                     val bundle = bundleOf("questionId" to questionId)
                     val controller = Navigation.findNavController(it)
-                    controller.navigate(R.id.action_recognitionImageFragment_to_drawDesignsFragment, bundle)
+                    controller.navigate(
+                        R.id.action_recognitionImageFragment_to_drawDesignsFragment,
+                        bundle
+                    )
                 } else {
                     val bundle = bundleOf("questionId" to 21)
                     val controller = Navigation.findNavController(it)
@@ -60,7 +70,10 @@ class RecognitionImageFragment : BaseFragment<FragmentRecognitionImageBinding>()
                 if (questionId == 30) {
                     val bundle = bundleOf("questionId" to 19)
                     val controller = Navigation.findNavController(it)
-                    controller.navigate(R.id.action_recognitionImageFragment_to_memoryWordsFragment, bundle)
+                    controller.navigate(
+                        R.id.action_recognitionImageFragment_to_memoryWordsFragment,
+                        bundle
+                    )
                 } else {
                     val bundle = bundleOf("questionId" to 24)
                     val controller = Navigation.findNavController(it)
@@ -96,7 +109,14 @@ class RecognitionImageFragment : BaseFragment<FragmentRecognitionImageBinding>()
             val secondQuestionId = questionId + 1
             val secondQuestion = dao?.getQuestion(secondQuestionId)
             if (secondQuestion != null) {
-                binding.secondData = secondQuestion
+                if (questionId == 22) {
+                    binding.secondData = secondQuestion
+                } else {
+                    if (bitmap != null) {
+                        val drawable: Drawable = BitmapDrawable(bitmap)
+                        ImageUtil.loadUrl(mContext, drawable, binding.rightImage)
+                    }
+                }
                 choiceItemList.add(secondQuestion)
             }
         }

+ 357 - 0
mmse/src/main/java/com/yingyangfly/mmse/widget/LinePathView.kt

@@ -0,0 +1,357 @@
+package com.yingyangfly.mmse.widget
+
+import android.content.Context
+import android.graphics.*
+import android.util.AttributeSet
+import android.view.MotionEvent
+import android.view.View
+import androidx.annotation.ColorInt
+import java.io.*
+import kotlin.math.max
+import kotlin.math.min
+
+class LinePathView : View {
+    private var mContext: Context? = null
+
+    /**
+     * 笔画X坐标起点
+     */
+    private var mX = 0f
+
+    /**
+     * 笔画Y坐标起点
+     */
+    private var mY = 0f
+
+    /**
+     * 手写画笔
+     */
+    private val mGesturePaint = Paint()
+
+    /**
+     * 路径
+     */
+    private val mPath = Path()
+
+    /**
+     * 签名画笔
+     */
+    private var cacheCanvas: Canvas? = null
+
+    /**
+     * 签名画布
+     */
+    var cachebBitmap: Bitmap? = null
+
+    /**
+     * 是否有签名
+     *
+     * @return
+     */
+    /**
+     * 是否已经签名
+     */
+    var touched = false
+        private set
+
+    /**
+     * 画笔宽度 px;
+     */
+    private var mPaintWidth = 10
+
+    /**
+     * 前景色
+     */
+    private var mPenColor = Color.BLACK
+
+    /**
+     * 背景色(指最终签名结果文件的背景颜色,默认为透明色)
+     */
+    private var mBackColor = Color.TRANSPARENT
+
+    //签名开始与结束
+    var touch: Touch? = null
+
+    constructor(context: Context?) : super(context) {
+        init(context)
+    }
+
+    constructor(context: Context?, attrs: AttributeSet?) : super(
+        context,
+        attrs
+    ) {
+        init(context)
+    }
+
+    constructor(
+        context: Context?,
+        attrs: AttributeSet?,
+        defStyleAttr: Int
+    ) : super(context, attrs, defStyleAttr) {
+        init(context)
+    }
+
+    private fun init(context: Context?) {
+        mContext = context
+        //设置抗锯齿
+        mGesturePaint.isAntiAlias = true
+        //设置签名笔画样式
+        mGesturePaint.style = Paint.Style.STROKE
+        //设置笔画宽度
+        mGesturePaint.strokeWidth = mPaintWidth.toFloat()
+        //设置签名颜色
+        mGesturePaint.color = mPenColor
+    }
+
+    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
+        super.onSizeChanged(w, h, oldw, oldh)
+        //创建跟view一样大的bitmap,用来保存签名
+        cachebBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
+        cacheCanvas = Canvas(cachebBitmap!!)
+        cacheCanvas!!.drawColor(mBackColor)
+        touched = false
+    }
+
+    override fun onTouchEvent(event: MotionEvent): Boolean {
+        if (touch != null) touch!!.OnTouch(true)
+        when (event.action) {
+            MotionEvent.ACTION_DOWN -> touchDown(event)
+            MotionEvent.ACTION_MOVE -> {
+                touched = true
+                if (touch != null) touch!!.OnTouch(false)
+                touchMove(event)
+            }
+            MotionEvent.ACTION_UP -> {
+                //将路径画到bitmap中,即一次笔画完成才去更新bitmap,而手势轨迹是实时显示在画板上的。
+                cacheCanvas!!.drawPath(mPath, mGesturePaint)
+                mPath.reset()
+            }
+        }
+        // 更新绘制
+        invalidate()
+        return true
+    }
+
+    override fun onDraw(canvas: Canvas) {
+        super.onDraw(canvas)
+        //画此次笔画之前的签名
+        canvas.drawBitmap(cachebBitmap!!, 0f, 0f, mGesturePaint)
+        // 通过画布绘制多点形成的图形
+        canvas.drawPath(mPath, mGesturePaint)
+    }
+
+    // 手指点下屏幕时调用
+    private fun touchDown(event: MotionEvent) {
+        // 重置绘制路线
+        mPath.reset()
+        val x = event.x
+        val y = event.y
+        mX = x
+        mY = y
+        // mPath绘制的绘制起点
+        mPath.moveTo(x, y)
+    }
+
+    // 手指在屏幕上滑动时调用
+    private fun touchMove(event: MotionEvent) {
+        val x = event.x
+        val y = event.y
+        val previousX = mX
+        val previousY = mY
+        val dx = Math.abs(x - previousX)
+        val dy = Math.abs(y - previousY)
+        // 两点之间的距离大于等于3时,生成贝塞尔绘制曲线
+        if (dx >= 3 || dy >= 3) {
+            // 设置贝塞尔曲线的操作点为起点和终点的一半
+            val cX = (x + previousX) / 2
+            val cY = (y + previousY) / 2
+            // 二次贝塞尔,实现平滑曲线;previousX, previousY为操作点,cX, cY为终点
+            mPath.quadTo(previousX, previousY, cX, cY)
+            // 第二次执行时,第一次结束调用的坐标值将作为第二次调用的初始坐标值
+            mX = x
+            mY = y
+        }
+    }
+
+    /**
+     * 清除画板
+     */
+    fun clear() {
+        if (cacheCanvas != null) {
+            touched = false
+            //更新画板信息
+            mGesturePaint.color = mPenColor
+            cacheCanvas!!.drawColor(mBackColor, PorterDuff.Mode.CLEAR)
+            mGesturePaint.color = mPenColor
+            invalidate()
+        }
+    }
+
+    interface Touch {
+        fun OnTouch(isTouch: Boolean)
+    }
+
+    /**
+     * 保存画板
+     *
+     * @param path 保存到路径
+     */
+    @JvmOverloads
+    @Throws(IOException::class)
+    fun save(
+        path: String?,
+        clearBlank: Boolean = false,
+        blank: Int = 0
+    ) {
+        var bitmap = cachebBitmap
+        if (clearBlank) {
+            bitmap = clearBlank(bitmap, blank)
+        }
+        val bos = ByteArrayOutputStream()
+        bitmap!!.compress(Bitmap.CompressFormat.PNG, 100, bos)
+        val buffer = bos.toByteArray()
+        val file = File(path)
+        if (file.exists()) {
+            file.delete()
+        }
+        val outputStream: OutputStream = FileOutputStream(file)
+        outputStream.write(buffer)
+        outputStream.close()
+    }
+
+    fun getCachebBitmaps(): Bitmap {
+        var bitmap = cachebBitmap
+//        if (clearBlank) {
+//            bitmap = clearBlank(bitmap, blank)
+//        }
+        val bos = ByteArrayOutputStream()
+        bitmap!!.compress(Bitmap.CompressFormat.PNG, 100, bos)
+        return bitmap
+    }
+
+    /**
+     * 获取画板的bitmap
+     *
+     * @return
+     */
+    val bitMap: Bitmap
+        get() {
+            isDrawingCacheEnabled = true
+            buildDrawingCache()
+            val bitmap = drawingCache
+            isDrawingCacheEnabled = false
+            return bitmap
+        }
+
+    /**
+     * 逐行扫描 清楚边界空白。
+     *
+     * @param bp
+     * @param blank 边距留多少个像素
+     * @return
+     */
+    private fun clearBlank(bp: Bitmap?, blank: Int): Bitmap {
+        var blank = blank
+        val HEIGHT = bp!!.height
+        val WIDTH = bp.width
+        var top = 0
+        var left = 0
+        var right = 0
+        var bottom = 0
+        var pixs = IntArray(WIDTH)
+        var isStop: Boolean
+        //扫描上边距不等于背景颜色的第一个点
+        for (y in 0 until HEIGHT) {
+            bp.getPixels(pixs, 0, WIDTH, 0, y, WIDTH, 1)
+            isStop = false
+            for (pix in pixs) {
+                if (pix != mBackColor) {
+                    top = y
+                    isStop = true
+                    break
+                }
+            }
+            if (isStop) {
+                break
+            }
+        }
+        //扫描下边距不等于背景颜色的第一个点
+        for (y in HEIGHT - 1 downTo 0) {
+            bp.getPixels(pixs, 0, WIDTH, 0, y, WIDTH, 1)
+            isStop = false
+            for (pix in pixs) {
+                if (pix != mBackColor) {
+                    bottom = y
+                    isStop = true
+                    break
+                }
+            }
+            if (isStop) {
+                break
+            }
+        }
+        pixs = IntArray(HEIGHT)
+        //扫描左边距不等于背景颜色的第一个点
+        for (x in 0 until WIDTH) {
+            bp.getPixels(pixs, 0, 1, x, 0, 1, HEIGHT)
+            isStop = false
+            for (pix in pixs) {
+                if (pix != mBackColor) {
+                    left = x
+                    isStop = true
+                    break
+                }
+            }
+            if (isStop) {
+                break
+            }
+        }
+        //扫描右边距不等于背景颜色的第一个点
+        for (x in WIDTH - 1 downTo 1) {
+            bp.getPixels(pixs, 0, 1, x, 0, 1, HEIGHT)
+            isStop = false
+            for (pix in pixs) {
+                if (pix != mBackColor) {
+                    right = x
+                    isStop = true
+                    break
+                }
+            }
+            if (isStop) {
+                break
+            }
+        }
+        if (blank < 0) {
+            blank = 0
+        }
+        //计算加上保留空白距离之后的图像大小
+        left = max(left - blank, 0)
+        top = max(top - blank, 0)
+        right = min(right + blank, WIDTH - 1)
+        bottom = min(bottom + blank, HEIGHT - 1)
+        return Bitmap.createBitmap(bp, left, top, right - left, bottom - top)
+    }
+
+    /**
+     * 设置画笔宽度 默认宽度为10px
+     *
+     * @param mPaintWidth
+     */
+    fun setPaintWidth(mPaintWidth: Int) {
+        mGesturePaint.strokeWidth = (if (mPaintWidth > 0) mPaintWidth else 10).toFloat()
+    }
+
+    fun setBackColor(@ColorInt backColor: Int) {
+        mBackColor = backColor
+    }
+
+    /**
+     * 设置画笔颜色
+     *
+     * @param mPenColor
+     */
+    fun setPenColor(mPenColor: Int) {
+        mGesturePaint.color = mPenColor
+    }
+
+}

+ 1 - 1
mmse/src/main/res/layout/fragment_draw_designs.xml

@@ -70,7 +70,7 @@
             app:strokeColor="@color/color_FF979797"
             app:strokeWidth="@dimen/divider_1px">
 
-            <com.yingyangfly.mmse.widget.SignatureView
+            <com.yingyangfly.mmse.widget.LinePathView
                 android:id="@+id/signatureView"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent" />