问题描述
我的布局中有一个带有自定义适配器的简单GridView
。
我的代码如下:
CircleActivity.java:
public class CircleActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_circle);
List<Integer> listColors = new ArrayList<>();
listColors.add(getResources().getColor(R.color.colorAccent));
listColors.add(getResources().getColor(R.color.colorPrimary));
listColors.add(getResources().getColor(R.color.colorPrimaryDark));
GridView gridView = (GridView) findViewById(R.id.grid_colors);
CircleAdapter adapter = new CircleAdapter(this,listColors);
gridView.setAdapter(adapter);
}
}
activity_circle.xml:
<?xml version="1.0" encoding="utf-8"?>
<GridView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/grid_colors"
android:layout_width="match_parent"
android:layout_height="match_parent" />
CircleAdapter.java:
public class CircleAdapter extends BaseAdapter{
private Context context;
private List<Integer> listColor;
public CircleAdapter(Context context, List<Integer> listColor) {
this.listColor = listColor;
this.context = context;
}
@Override
public int getCount() {
return listColor.size();
}
@Override
public Integer getItem(int position) {
return listColor.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView==null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.row_grid,parent,false);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
}
else{
holder = (ViewHolder) convertView.getTag();
}
holder.customCircleView.setFillColor(listColor.get(position));
holder.customCircleView.setCircleRadius(100);
return convertView;
}
static class ViewHolder{
private CustomCircleView customCircleView;
public ViewHolder(View row){
customCircleView = (CustomCircleView) row.findViewById(R.id.custom_circle_view);
}
}
}
row_grid.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:background="@color/colorAccent"
android:layout_width="match_parent"
android:gravity="center"
android:layout_height="match_parent">
<com.droidexperiments.gridexpand.CustomCircleView
android:id="@+id/custom_circle_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
custom:fill_color="@color/colorPrimary"
custom:circle_radius="50"
android:padding="25dp" />
</LinearLayout>
CircleView.java:
public class CustomCircleView extends View {
private int circleRadius = 20;
private int fillColor = Color.BLACK;
public CustomCircleView(Context context) {
super(context);
}
public CustomCircleView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public CustomCircleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public CustomCircleView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(R.styleable.CustomCircle);
circleRadius = typedArray.getInteger(R.styleable.CustomCircle_circle_radius,20);
fillColor = typedArray.getColor(R.styleable.CustomCircle_fill_color, Color.BLACK);
typedArray.recycle();
}
public int getCircleRadius() {
return circleRadius;
}
public void setCircleRadius(int circleRadius) {
this.circleRadius = circleRadius;
}
public int getFillColor() {
return fillColor;
}
public void setFillColor(int fillColor) {
this.fillColor = fillColor;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(fillColor);
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(canvas.getWidth()/2,canvas.getHeight()/2,circleRadius,paint);
}
}
attrts.xml:
<declare-styleable name="CustomCircle">
<attr name="fill_color" format="reference|color"/>
<attr name="circle_radius" format="integer"/>
</declare-styleable>
问题在于屏幕保持空白,并且在GridView中没有行被放大/显示。
我检查了一切。
GridView或网格行的布局或CustomCircleView
没有任何问题。
如果我将adapter
更改为简单的ArrayAdapter
,则可以正常工作。
因此,我的适配器一定存在问题:
我在适配器中getView()
检查了getView()
;
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView==null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.row_grid,parent,false);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
}
else{
holder = (ViewHolder) convertView.getTag();
}
holder.customCircleView.setFillColor(listColor.get(position));
holder.customCircleView.setCircleRadius(100);
return convertView;
}
但无法确定为什么显示空白。 有人可以帮我吗?
1楼
实现自定义视图时,必须实现onMeasure
。
此方法将告诉Android框架您的视图应为多大。
由于您没有为CustomCircleView
指定此参数, CustomCircleView
在布局中使用了wrap_content
,因此它的大小为零。
因此, GridView
所有元素都是不可见的,从而使适配器看起来好像不起作用。
我做了一个onMeasure
的简单示例实现,可以解决您的问题(只需在CustomCircleView
添加此方法):
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int size = View.MeasureSpec.makeMeasureSpec(2 * this.circleRadius, MeasureSpec.EXACTLY);
setMeasuredDimension(size, size);
}
该文档建议size
保持在给定参数( widthMeasureSpec
和heightMeasureSpec
)之内。
我没有在此处包括该限制,您可以确定自己在这种情况下想要做什么。
您可以在创建自定义组件的找到有关此信息的更多信息。
关于onMeasure
特定信息可以在找到。