Android使用代码实现一个填空题
学习一些基础知识
public class SpannableStringActivity extends BaseActivity {
@Bind(R.id.tv_content)
TextView tvContent;
@Override
protected 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 {
@Override
public 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;
}
@Override
public 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);
// 弹出PopupWindow
popupWindow.showAtLocation(tvContent, Gravity.BOTTOM, 0, 0);
btnFillBlank.setOnClickListener(new OnClickListener() {
@Override
public 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);
}
@Override
public 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;
@Override
protected 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);
}
}
评论