JudgeActivity.java 6.08 KB
package com.hjx.parent;

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.os.Bundle;
import android.util.Log;

import com.bumptech.glide.Glide;
import com.hjx.parent.api.JudgeRepository;
import com.hjx.parent.databinding.ActivityJudgeBinding;
import com.hjx.parent.databinding.LayoutJudgeRectBinding;
import com.hjx.parent.rx.BaseRxActivity;
import com.hjx.parent.utils.CutUtil;

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

import io.reactivex.Observable;
import io.reactivex.Single;
import top.zibin.luban.Luban;

public class JudgeActivity extends BaseRxActivity<ActivityJudgeBinding> {

    private Bitmap bitmap;

    private final List<JudgeCut> mList = new ArrayList<>();

    @SuppressLint("CheckResult")
    @Override
    public void initView(Bundle savedInstanceState) {
        binding.ivBack.setOnClickListener(v -> {
            onBackPressed();
        });
        String path = getIntent().getStringExtra("path");
        if (path == null) return;
        final ArrayList<Rect> rects = getIntent().getParcelableArrayListExtra("rects");
        if (rects == null) return;

        Single.just(path)
                .map(origin -> Luban.with(this).load(origin).ignoreBy(300).get().get(0))
                .map(file -> Glide.with(this).asBitmap().load(file).submit().get())
                .compose(transformSingle())
                .subscribe((bitmap, th) -> {
                    if (th != null) th.printStackTrace();
                    if (bitmap == null) return;
                    this.bitmap = bitmap;

                    binding.ivPic.setImageBitmap(bitmap);
                    CutUtil.onLayoutReady(binding.ivPic, v -> {
                        prepareRects(rects);
                    });
                });
        binding.btnSelectAll.setOnClickListener(v -> {
            if (mList.isEmpty()) return;
            mList.forEach(it -> it.vb.getRoot().setSelected(true));
            checkCount();
        });
    }

    private void prepareRects(List<Rect> rects) {
        mList.clear();
        binding.flRects.removeAllViews();
        float[] measuredSize = CutUtil.measureBitmap(binding.ivPic, bitmap);
        for (int i = 0; i < rects.size(); i++) {
            Rect it = rects.get(i);
            Bitmap bitmap = CutUtil.cut(this.bitmap, it.left, it.top, it.width(), it.height(), this);
            Rect rect = measureRect(it, measuredSize);
            LayoutJudgeRectBinding vb = showRect(rect);
            mList.add(new JudgeCut(i, bitmap, rect, vb));
        }

        judge();
    }

    @SuppressLint("CheckResult")
    private void judge() {
        showLoadingDialog("");
        Observable.fromIterable(mList)
                .map(it -> {
                    if (it.url != null && !it.url.isEmpty()) return it;
                    String base64 = CutUtil.bitmapToBase64(it.bitmap, true);
                    it.url = base64;
                    return it;
                })
                .flatMap(it -> JudgeRepository.singleJudge(it.url)
                        .map(result -> {
                            it.correctResult = result;
                            return it;
                        })
                        .toObservable()
                )
                .compose(transform())
                .subscribe(it -> {
                    if (it.correctResult == 1) {
                        it.vb.ivResult.setImageResource(R.drawable.png_ic_judge_correct);
                    } else if (it.correctResult == 2) {
                        it.vb.ivResult.setImageResource(R.drawable.png_ic_judge_wrong);
                    }
                    it.vb.getRoot().setSelected(it.correctResult != 1);
                    checkCount();
                }, th -> {
                    cancelLoadingDialog();
                    Log.e(getClass().getName(), "", th);
                }, this::cancelLoadingDialog)
        ;
    }

    private LayoutJudgeRectBinding showRect(Rect rect) {
        LayoutJudgeRectBinding vb = LayoutJudgeRectBinding.inflate(getLayoutInflater(), binding.flRects, false);

        vb.getRoot().setMinimumWidth(rect.width());
        vb.getRoot().setMinimumHeight(rect.height());
        vb.getRoot().setTranslationX((float) rect.left);
        vb.getRoot().setTranslationY((float) rect.top);
        vb.getRoot().setOnClickListener(v -> {
            v.setSelected(!v.isSelected());
            checkCount();
        });
        binding.flRects.addView(vb.getRoot());

        return vb;
    }

    @SuppressLint("SetTextI18n")
    private void checkCount() {
        int count = (int) mList.stream().filter(it -> it.vb.getRoot().isSelected()).count();
        if (count == 0) binding.btnAdd.setText("加入错题");
        else binding.btnAdd.setText("加入错题(" + count + ")");
        binding.btnAdd.setEnabled(count > 0);
    }

    /** bitmapRect 转换为 viewRect */
    private Rect measureRect(Rect rect, float[] measuredSize) {
        float realW = measuredSize[0];
        float realH = measuredSize[1];
        float offsetX = measuredSize[2];
        float offsetY = measuredSize[3];
        float percentX = realW / bitmap.getWidth();
        float percentY = realH / bitmap.getHeight();

        float left = rect.left * percentX + offsetX;
        float right = rect.right * percentX + offsetX;
        float top = rect.top * percentY + offsetY;
        float bottom = rect.bottom * percentY + offsetY;
        return new Rect((int) left, (int) top, (int) right, (int) bottom);
    }

    @Override
    protected ActivityJudgeBinding getViewBinding() {
        return ActivityJudgeBinding.inflate(getLayoutInflater());
    }

    static class JudgeCut {
        final int index;
        final Bitmap bitmap;
        final Rect rect;
        final LayoutJudgeRectBinding vb;

        String url;

        /** 0:未批改;1:正确;2:错误;3:未作答  */
        int correctResult = 0;

        public JudgeCut(int index, Bitmap bitmap, Rect rect, LayoutJudgeRectBinding vb) {
            this.index = index;
            this.bitmap = bitmap;
            this.rect = rect;
            this.vb = vb;
        }
    }
}