Android仿學習強國填空題考試界面

很久不寫博客了,應爲一直真的都很忙,沒時間寫,正好今天有時間寫一下O(∩_∩)O哈哈~。

起因:最近工作中遇到一個需求,使用手機進行填空題考試。

分析:因爲涉及到判分,需要答案與文字一一對應,剛開始在網上找一些方案在TextView修改文字樣式然後處理事件,感覺樣式不是太好控制操作繁瑣,然後又注意到學習強國的填空題真的很符合需求,所以就拿來模仿了。

截圖如下:左邊我,右邊學習強國

效果就是這個樣子的。

總體思路:RecyclerView 實現數據的裝載,使用TextView和Edittext展示內容與填空處,監聽焦點,軟件盤退格,並設置焦點,根據屏幕寬度設置一行展示的文字個數。

  • 佈局文件:佈局文件就不多說了,根據自己需求寫,但是要同時包含TextView、EditText
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="27dp"
    android:layout_height="27dp"
    android:layout_marginLeft="1.5dp"
    android:layout_marginTop="2dp"
    android:layout_marginRight="1.5dp"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:textColor="#D9000000"
        android:textSize="16sp"
        android:textStyle="bold"
        android:visibility="gone" />

    <EditText
        android:id="@+id/et_text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/bg_edit_selecter"
        android:cursorVisible="false"
        android:gravity="center"
        android:maxLength="1"
        android:textColor="#FF16AFF3"
        android:visibility="gone" />

</LinearLayout>
  • 計算一行展示的文字個數

這塊註釋寫的很清楚了,需要去除內外邊距計算 ,其實最後得出的numInLine還可以進行減一操作,爲了安全起見,但是也可以不用(int類型除法本來就會丟失精度的)。

//獲取屏幕寬度
int screenWidth = getScreenWidth();
//去除padding寬度
int contentWidth = screenWidth - DensityUtils.dp2px(context, Constant.EXAM_PADDING_DP);
//計算出一行字數
int numInLine = contentWidth / DensityUtils.dp2px(context, Constant.EXAM_LETTER_DP);
//設置一行個數
rv_list.setLayoutManager(new GridLayoutManager(context, numInLine));

/**
 * 獲取屏幕寬度
 */
public int getScreenWidth() {
    DisplayMetrics dm2 = getResources().getDisplayMetrics();
    return dm2.widthPixels;
}
  • 數據源

數據源很簡單,每個對象代表一個字,標明是否是填空處

public class BlankTextBean {

    /**
     * 文字
     */
    private String text;
    /**
     * 是否是填空
     */
    private boolean blank;

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public boolean isBlank() {
        return blank;
    }

    public void setBlank(boolean blank) {
        this.blank = blank;
    }
}
  •  適配器(用心去感受。。。)

這塊主要需求爲

1.無論點擊哪個填空處,焦點總是在第一個沒有字的格子上。

2. 點擊退格鍵,如果當前框有字則刪除,否則像錢移動一個格子。

3.填空時,如果填了字,並且後面還有格子焦點自動向後移動一個格子。

PS:在適當時機調用clearList();注意保存並設置臨時填空數據;

    class TextAdapter extends BaseQuickAdapter<BlankTextBean, BaseViewHolder> {

        private List<EditText> editTextList = new ArrayList<>();
        private boolean isDelete = false;

        public TextAdapter(@Nullable List<BlankTextBean> data) {
            super(R.layout.item_blank_text, data);
        }

        public void clearList() {
            editTextList.clear();
        }

        /**
         * 獲取首個焦點位置
         *
         * @return
         */
        private int getFirstFocusPosition() {
            for (int i = 0; i < editTextList.size(); i++) {
                if (!editTextList.get(i).getText().toString().isEmpty()) {
                    if (i == (editTextList.size() - 1)) {
                        return i;
                    }
                } else {
                    return i;
                }
            }
            return 0;
        }

        /**
         * 獲取點擊的edittext在集合的位置
         *
         * @param editText
         * @return
         */
        private int getEdittextPosition(EditText editText) {
            for (int i = 0; i < editTextList.size(); i++) {
                if (editText.hashCode() == editTextList.get(i).hashCode()) {
                    return i;
                }
            }
            return 0;
        }


        @Override
        protected void convert(BaseViewHolder helper, BlankTextBean item) {
            TextView tv_text = helper.getView(R.id.tv_text);
            EditText et_text = helper.getView(R.id.et_text);
            tv_text.setText(item.getText());
            if (item.isBlank()) {
                editTextList.add(et_text);
                //設置答案文字
                if (ExamBlankView.this.questionBean != null && ExamBlankView.this.questionBean.getUserAnswer() != null) {
                    if (editTextList.size() <= ExamBlankView.this.questionBean.getUserAnswer().length()) {
                        editTextList.get(editTextList.size() - 1).setText(String.valueOf(ExamBlankView.this.questionBean.getUserAnswer().charAt(editTextList.size() - 1)));
                    }
                }
                tv_text.setVisibility(View.GONE);
                et_text.setVisibility(View.VISIBLE);
            } else {
                tv_text.setVisibility(View.VISIBLE);
                et_text.setVisibility(View.GONE);
            }
            /**
             * 設置獲取焦點事件,使得焦點在第一個沒字的edittext上,如果都有字停留在最後一個格子處
             */
            et_text.setOnFocusChangeListener((v, hasFocus) -> {
                if (hasFocus && !isDelete) {
                    editTextList.get(getFirstFocusPosition()).requestFocus();
                }
            });

            /**
             * 焦點的轉移
             */
            et_text.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {

                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {

                }

                @Override
                public void afterTextChanged(Editable s) {
                    int edittextPosition = getEdittextPosition(et_text);//當前點擊的edittext在幾何中的位置
                    if (s.toString().length() >= 1 && (edittextPosition + 1) < editTextList.size()) {//增加
                        editTextList.get(edittextPosition + 1).requestFocus();
                    } else if (s.toString().length() < 1 && (edittextPosition - 1) >= 0) {//刪除
                        isDelete = true;
                        editTextList.get(edittextPosition - 1).requestFocus();
                        isDelete = false;
                    }
                }
            });

            /**
             * 退格鍵刪除空時的操作
             */
            et_text.setOnKeyListener((v, keyCode, event) -> {
                int edittextPosition = getEdittextPosition(et_text);
                if (keyCode == KeyEvent.KEYCODE_DEL && event.getAction() == KeyEvent.ACTION_DOWN) {
                    if (et_text.getText().toString().isEmpty()) {//當前文字爲空
                        isDelete = true;
                        if (edittextPosition - 1 >= 0) {
                            editTextList.get(edittextPosition - 1).requestFocus();
                        } else {
                            editTextList.get(edittextPosition).requestFocus();
                        }
                        isDelete = false;
                        return true;
                    } else if (!et_text.getText().toString().isEmpty()) {//當前文字不爲空
                        isDelete = true;
                        et_text.setText("");
                        if (edittextPosition - 1 >= 0) {
                            editTextList.get(edittextPosition - 1).requestFocus();
                        } else {
                            editTextList.get(edittextPosition).requestFocus();
                        }
                        isDelete = false;
                        return true;
                    }
                    return false;
                }
                return false;
            });
        }
    }

 

Demo代碼轉送門

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章