Android使用代码实现一个填空题

学习一些基础知识
public class SpannableStringActivity extends BaseActivity {@Bind(R.id.tv_content)TextView tvContent;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_spannable_string);ButterKnife.bind(this);initData();}private void initData() {String originContent = "你看我不仅能变颜色,还能点击。";SpannableString content = new SpannableString(originContent);// 设置颜色ForegroundColorSpan colorSpan = new ForegroundColorSpan(Color.parseColor("#4DB6AC"));content.setSpan(colorSpan, 7, 9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);// 设置点击事件MyClickableSpan myClickableSpan = new MyClickableSpan();content.setSpan(myClickableSpan, 12, 14, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);// 设置此方法后,点击事件才能生效tvContent.setMovementMethod(LinkMovementMethod.getInstance());tvContent.setText(content);}class MyClickableSpan extends ClickableSpan {@Overridepublic void onClick(View widget) {Toast.makeText(SpannableStringActivity.this, "我被点击了", Toast.LENGTH_SHORT).show();}}}

Spanned.SPAN_INCLUSIVE_INCLUSIVE:前后都包括
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE:前后都不包括
Spanned.SPAN_INCLUSIVE_EXCLUSIVE:前面包括,后面不包括
Spanned.SPAN_EXCLUSIVE_INCLUSIVE:前面不包括,后面包括
Spanned.SPAN_INCLUSIVE_EXCLUSIVE
实现
首先初始化一些数据
public class FillBlankView extends RelativeLayout {private TextView tvContent;private Context context;// 答案集合private List<String> answerList;// 答案范围集合private List<AnswerRange> rangeList;// 填空题内容private SpannableStringBuilder content;public FillBlankView(Context context) {this(context, null);}public FillBlankView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public FillBlankView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);this.context = context;initView();}private void initView() {LayoutInflater inflater = LayoutInflater.from(context);inflater.inflate(R.layout.layout_fill_blank, this);tvContent = (TextView) findViewById(R.id.tv_content);}...}
/*** 设置数据** @param originContent 源数据* @param answerRangeList 答案范围集合*/public void setData(String originContent, List<AnswerRange> answerRangeList) {if (TextUtils.isEmpty(originContent) || answerRangeList == null|| answerRangeList.isEmpty()) {return;}// 获取课文内容content = new SpannableStringBuilder(originContent);// 答案范围集合rangeList = answerRangeList;// 设置下划线颜色for (AnswerRange range : rangeList) {ForegroundColorSpan colorSpan = new ForegroundColorSpan(Color.parseColor("#4DB6AC"));content.setSpan(colorSpan, range.start, range.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);}// 答案集合answerList = new ArrayList<>();for (int i = 0; i < rangeList.size(); i++) {answerList.add("");}// 设置填空处点击事件for (int i = 0; i < rangeList.size(); i++) {AnswerRange range = rangeList.get(i);BlankClickableSpan blankClickableSpan = new BlankClickableSpan(i);content.setSpan(blankClickableSpan, range.start, range.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);}// 设置此方法后,点击事件才能生效tvContent.setMovementMethod(LinkMovementMethod.getInstance());tvContent.setText(content);}
/*** 点击事件*/class BlankClickableSpan extends ClickableSpan {private int position;public BlankClickableSpan(int position) {this.position = position;}@Overridepublic void onClick(final View widget) {View view = LayoutInflater.from(context).inflate(R.layout.layout_input, null);final EditText etInput = (EditText) view.findViewById(R.id.et_answer);Button btnFillBlank = (Button) view.findViewById(R.id.btn_fill_blank);// 显示原有答案String oldAnswer = answerList.get(position);if (!TextUtils.isEmpty(oldAnswer)) {etInput.setText(oldAnswer);etInput.setSelection(oldAnswer.length());}final PopupWindow popupWindow = new PopupWindow(view, LayoutParams.MATCH_PARENT, dp2px(40));// 获取焦点popupWindow.setFocusable(true);// 为了防止弹出菜单获取焦点之后,点击Activity的其他组件没有响应popupWindow.setBackgroundDrawable(new PaintDrawable());// 设置PopupWindow在软键盘的上方popupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);// 弹出PopupWindowpopupWindow.showAtLocation(tvContent, Gravity.BOTTOM, 0, 0);btnFillBlank.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// 填写答案String answer = etInput.getText().toString();fillAnswer(answer, position);popupWindow.dismiss();}});// 显示软键盘InputMethodManager inputMethodManager =(InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);inputMethodManager.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);}@Overridepublic void updateDrawState(TextPaint ds) {// 不显示下划线ds.setUnderlineText(false);}}
填写答案
/*** 填写答案** @param answer 当前填空处答案* @param position 填空位置*/private void fillAnswer(String answer, int position) {answer = " " + answer + " ";// 替换答案AnswerRange range = rangeList.get(position);content.replace(range.start, range.end, answer);// 更新当前的答案范围AnswerRange currentRange = new AnswerRange(range.start, range.start + answer.length());rangeList.set(position, currentRange);// 答案设置下划线content.setSpan(new UnderlineSpan(),currentRange.start, currentRange.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);// 将答案添加到集合中answerList.set(position, answer.replace(" ", ""));// 更新内容tvContent.setText(content);for (int i = 0; i < rangeList.size(); i++) {if (i > position) {// 获取下一个答案原来的范围AnswerRange oldNextRange = rangeList.get(i);int oldNextAmount = oldNextRange.end - oldNextRange.start;// 计算新旧答案字数的差值int difference = currentRange.end - range.end;// 更新下一个答案的范围AnswerRange nextRange = new AnswerRange(oldNextRange.start + difference,oldNextRange.start + difference + oldNextAmount);rangeList.set(i, nextRange);}}}
public class MainActivity extends AppCompatActivity {@BindView(R.id.fbv_content)FillBlankView fbvContent;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ButterKnife.bind(this);initData();}private void initData() {String content = "纷纷扬扬的________下了半尺多厚。天地间________的一片。我顺着________工地走了四十多公里," +"只听见各种机器的吼声,可是看不见人影,也看不见工点。一进灵官峡,我就心里发慌。";// 答案范围集合List<AnswerRange> rangeList = new ArrayList<>();rangeList.add(new AnswerRange(5, 13));rangeList.add(new AnswerRange(23, 31));rangeList.add(new AnswerRange(38, 46));fbvContent.setData(content, rangeList);}}
评论
