问题
写了个数独小游戏,现在想在显示列表中能够预览题目的内容,写了个自定义的组件,但是添加进去之后,显示不完全。不报错,在初始化列表的时候显示所有的列表中的自定义组件的对象都是同一个,然后在添加显示的数据信息之后每个列表的对象又不一样了。
下面这两次输出全部都是在一次添加数据的时候出现的(这个已经找到原因了,放在文章最后)
布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorGray81">
<com.modev.sudoku.views.CoverImage
android:id="@+id/home_item_cover"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_margin="10dp"/>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="80dp"
android:gravity="center"
android:background="@color/colorGray81">
<TextView
android:id="@+id/home_item_tv_level"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:textColor="@color/black"
android:textSize="18sp" />
<TextView
android:id="@+id/home_item_tv_diff"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="7dp"
android:textColor="@color/black"
android:textSize="18sp" />
<TextView
android:id="@+id/home_item_tv_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="7dp"
android:textColor="@color/black"
android:textSize="18sp" />
</LinearLayout>
</LinearLayout >
适配器
package com.modev.sudoku.adapter;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.modev.sudoku.R;
import com.modev.sudoku.modile.Problem;
import com.modev.sudoku.views.CoverImage;
import java.util.List;
public class HomeListViewAdapter extends ArrayAdapter<Problem> {
private int resource;
public HomeListViewAdapter(@NonNull Context context, int resource, @NonNull List<Problem> objects) {
super(context, resource, objects);
this.resource = resource;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Problem problem = getItem(position);
View view;
ViewHolder viewHolder;
if (convertView == null) {
view = LayoutInflater.from(getContext()).inflate(resource, parent, false);
viewHolder = new ViewHolder();
viewHolder.coverImage = view.findViewById(R.id.home_item_cover);
viewHolder.level = view.findViewById(R.id.home_item_tv_level);
viewHolder.diff = view.findViewById(R.id.home_item_tv_diff);
viewHolder.status = view.findViewById(R.id.home_item_tv_status);
view.setTag(viewHolder);
}else {
view = convertView;
viewHolder = (ViewHolder)view.getTag();
}
Log.d("测试", "coverImage:" + viewHolder.coverImage + "\t ProblemId:" + problem.getId());
viewHolder.coverImage.setProblem(problem);
viewHolder.level.setText("第"+(problem.getId())+"题");
viewHolder.diff.setText("难度:"+problem.getDiff());
if (problem.getStatus() == -1) {
viewHolder.status.setText("状态:未尝试");
}else if (problem.getStatus() == 0) {
viewHolder.status.setText("状态:未完成");
}else {
viewHolder.status.setText("状态:已完成");
}
return view;
}
public void setProblemsList(List<Problem> problems) {
super.clear();
super.addAll(problems);
// super.notifyDataSetChanged();
}
class ViewHolder{
CoverImage coverImage;
// ImageView cover;
TextView level;
TextView diff;
TextView status;
}
}
自定义视图组件
package com.modev.sudoku.views;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import androidx.annotation.Nullable;
import com.modev.sudoku.modile.Problem;
public class CoverImage extends View {
private int height;
private int width;
private float sideLenght;
private Problem problem;
public CoverImage(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
height = getMeasuredWidth();
width = getMeasuredWidth();
sideLenght = width / 9F;
setMeasuredDimension(width,height);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paintPanel(canvas);
if (problem != null) {
paintNumbers(canvas);
}
}
private void paintPanel(Canvas canvas) {
//浅色线条
Paint grayPaint = new Paint();
grayPaint.setColor(Color.GRAY);
//深色线条
Paint blackPaint = new Paint();
blackPaint.setStrokeWidth(5);
blackPaint.setColor(Color.BLACK);
//绘制浅色线条
for (int i = 0; i <= 9; i++) {
canvas.drawLine(i*width/9F, 0F, i*width/9F, height, grayPaint);
canvas.drawLine(0F, i*height/9F, width, i*height/9F, grayPaint);
}
//绘制四条深色线条
canvas.drawLine(width/3F, 0f, width/3F, height, blackPaint);
canvas.drawLine(2F*width/3F, 0f, 2F*width/3F, height, blackPaint);
canvas.drawLine(0, height/3F, width, height/3F, blackPaint);
canvas.drawLine(0, 2F*height/3F, width, 2F*height/3F, blackPaint);
}
private void paintNumbers(Canvas canvas) {
//数组
int[][] problemArr = problem.getDefaultProblem();
//绘制数字的黑色颜色,设置字体大小,居中,颜色
Paint blackPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
blackPaint.setColor(0xFF666666);
blackPaint.setTextSize(18);
blackPaint.setTextAlign(Paint.Align.CENTER);
//灰色蒙版的颜色,设置颜色,透明度
Paint grayPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
grayPaint.setColor(Color.GRAY);
grayPaint.setAlpha(55);
//遍历数组,然后画东西
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (problemArr[i][j] != 0) {
canvas.drawText(String.valueOf(problemArr[i][j]), j*sideLenght+sideLenght/2, i*sideLenght+3*sideLenght/4, blackPaint);
canvas.drawRect(j*sideLenght, i*sideLenght, j*sideLenght+sideLenght, i*sideLenght+sideLenght,grayPaint );
}
}
}
}
public void setProblem(Problem problem) {
this.problem = problem;
invalidate();
}
}
在界面中添加适配器的代码
private void setMethod() {
adapter = new HomeListViewAdapter(getApplicationContext(), R.layout.home_item, new ArrayList<Problem>());
problemsLv.setAdapter(adapter);
}
//因为服务在一开始并不会创建,没有数据,之后在服务类中添加数据,这个是在服务器类中的
//在服务初始化后添加数据
adapter.setProblemsList(getProblems());
解决方案
不显示的原因:
重写OnMeasure()调用父类的方法的时候,这个应该放在第一行,然后就ok了,咋回事咱也不知道,反正就这么解决了。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
关于会出现列表项两次初始化的原因已经找到了,看下面这篇文章就行了
android ListView 在初始化时多次调用getView()原因分析