Android ListView与自定义自动调整Textview - 一些项目在滚动之前无法正常显示

时间:2013-07-13 20:33:55

标签: listview scroll textview android-cursoradapter autosize

我发现这里已经多次解决了类似的话题,但我无法找到解决问题的方法。

我正在使用带有自定义CursorAdapter的ListView,它从数据库中获取数据。这些行是基于自定义相对布局的XML文件创建的,它具有图像作为背景,并且应该保持图像的纵横比。相对布局的宽度设置为match_parent,然后根据图像的纵横比计算高度 在相对布局中有5个项目(实际上有6个项目,第6个是一个空视图,只是将行分成两半):1个ImageView和4个自定义文本视图,它们被修改为自动调整文本大小在TextView的高度上(文本的大小设置为百分比,此处参数heightPercentage为0.5,因此文本的大小应为TextView高度的50%)。

一切似乎都有效,但有时一些项目没有正确呈现(文本大小似乎是正确的,但TextView的宽度太短。滚动几个项目然后回来一切都很好。

以下是照片:

纠正一个(滚动后):
Correct

不正确(滚动前)
Incorrect

修改: 我试图使用互联网上发现的一些自动调整文本视图,行为或多或少相似;有时视图在滚动条形图之前没有正确呈现,或者它首先正确呈现,但是在滚动之后它被弄乱了...在我看来,在Listview行中使用的自定义视图有一些特定的规则,我这样做不明白:-(我试图把像invalidateViews(),notifyDataSetChanged()这样的方法放到不同的代码位置,有时甚至像runInIOThread(),但是没有成功,行为永远不会改变......



下面是名为RelativeLayoutKeepRatio的Custom Relative Layout的代码,名为WidthResizeTextView的自定义TextView和名为MyCWGCursorAdapter的自定义CursorAdapter。

public class RelativeLayoutKeepRatio extends RelativeLayout {
private float aspectRatio = 0; 
private ViewGroup.LayoutParams mLayoutParams = null;

public RelativeLayoutKeepRatio(Context context) {
    super(context);

}

public RelativeLayoutKeepRatio(Context context, AttributeSet attrs) {
    super(context, attrs);
    aspectRatio = getAspectRatio(context, attrs);
}

public RelativeLayoutKeepRatio(Context context, AttributeSet attrs,
        int defStyle) {
    super(context, attrs, defStyle);
    aspectRatio = getAspectRatio(context, attrs);
}

private float getAspectRatio(Context context, AttributeSet attrs)
{
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LayoutKeepRatio);
    float aspectRatio = a.getFloat(R.styleable.LayoutKeepRatio_aspectRatio, 0);
    if (aspectRatio == 0)
    {
        Drawable bg = getBackground();
        if (bg != null)
        {
            int mBgWidth = bg.getIntrinsicWidth();
            int mBgHeight = bg.getIntrinsicHeight();
            aspectRatio = (float)mBgWidth / (float)mBgHeight;
        }
    }
    return aspectRatio;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    if (mLayoutParams == null) {
        mLayoutParams = getLayoutParams();
    }

    int width = 0;
    int height = 0;

    //the width is known and we want to calculate the height
    if ((mLayoutParams.width == ViewGroup.LayoutParams.MATCH_PARENT ||
         mLayoutParams.width == 0
        ) &&
        mLayoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT)
    {
            width = MeasureSpec.getSize(widthMeasureSpec);
            height = calculateHeight(width, aspectRatio);           
    //the height is known and we want to calculate the width
    } else if ((mLayoutParams.height == ViewGroup.LayoutParams.MATCH_PARENT ||
            mLayoutParams.height == 0
            ) &&
            mLayoutParams.width == ViewGroup.LayoutParams.WRAP_CONTENT)
    {
        height = MeasureSpec.getSize(heightMeasureSpec);
        width = calculateWidth(width, aspectRatio);
    }

    else //the width and height are known, we do not need to calculate anything
    {
        width = MeasureSpec.getSize(widthMeasureSpec);
        height = MeasureSpec.getSize(heightMeasureSpec);
    }

    int mode = MeasureSpec.EXACTLY;
    super.onMeasure(MeasureSpec.makeMeasureSpec(width, mode),
            MeasureSpec.makeMeasureSpec(height, mode));
}

private int calculateWidth(int height, float aspectRatio)
{
    return (int)((float) height * aspectRatio);
}

private int calculateHeight(int width, float aspectRatio)
{
    return (int)((float) width / aspectRatio);
}
}


public class WidthResizeTextView extends TextView {
private float heightPercentage = 0; 

public WidthResizeTextView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ResizeTextView);
    heightPercentage = a.getFloat(R.styleable.ResizeTextView_HeightPercentage, 0);
}

public WidthResizeTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ResizeTextView);
    heightPercentage = a.getFloat(R.styleable.ResizeTextView_HeightPercentage, 0);
}

public WidthResizeTextView(Context context) {
    super(context);
    // TODO Auto-generated constructor stub
}

public float getHeightPercentage(){
    return heightPercentage;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    String text = getText().toString();

    int height = MeasureSpec.getSize(heightMeasureSpec);
    int mode = MeasureSpec.getMode(heightMeasureSpec);
    if (mode == MeasureSpec.EXACTLY){
        setTextSize(TypedValue.COMPLEX_UNIT_PX, (int)((float)height * heightPercentage));
        int neededWidth = (int)getPaint().measureText(text);
        super.onMeasure(MeasureSpec.makeMeasureSpec(neededWidth, mode),
                MeasureSpec.makeMeasureSpec(height, mode));
    }
    else
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}


public class MyCWGCursorAdapter extends CursorAdapter {
String path = null;
Typeface face = null;
public MyCWGCursorAdapter(Context context, Cursor c, int flags) {
    super(context, c, flags);
    path = CommonUtils.getAppPath(context);
    face = Typeface.createFromAsset(context.getAssets(), "fonts/CANDARA.TTF");
}

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    RelativeLayout row = (RelativeLayout)inflater.inflate(R.layout.row, parent, false);
    ViewWrapper wrapper = new ViewWrapper(row);
    row.setTag(wrapper);
    return (row);
}

@Override
public void bindView(View row, Context context, Cursor cursor) {
    // TODO Auto-generated method stub
    ViewWrapper wrapper = (ViewWrapper)row.getTag();
    String nick = cursor.getString(1);
    String fileName = cursor.getString(2);
    int count = cursor.getInt(3);

    Bitmap bitmap = CommonUtils.applyCircleMask(BitmapFactory.decodeFile(path + fileName));
    if (bitmap == null)
        bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.empty_cwg);
    ImageView picture = wrapper.getImageView();
    picture.setImageBitmap(bitmap);

    WidthResizeTextView nickLabel = wrapper.getNickLabel();
    nickLabel.setTypeface(face);

    WidthResizeTextView nickTextView = wrapper.getNickTextView();
    nickTextView.setText(nick);
    nickTextView.setTypeface(face);

    WidthResizeTextView countLabel = wrapper.getCountLabel();
    countLabel.setTypeface(face);

    WidthResizeTextView countTextView = wrapper.getCountTextView();
    countTextView.setText("" + count);
    countTextView.setTypeface(face);

}

class ViewWrapper {
    View base;
    ImageView imageView = null;
    WidthResizeTextView nickLabel = null;
    WidthResizeTextView nickTextView = null;
    WidthResizeTextView countLabel = null;
    WidthResizeTextView countTextView = null;

    ViewWrapper(View base){
        this.base = base;
    }
    ImageView getImageView(){
        if (imageView == null){
            imageView = (ImageView)base.findViewById(R.id.CWGView);
        }
        return imageView;
    }

    WidthResizeTextView getNickLabel(){
        if (nickLabel == null) {
            nickLabel = (WidthResizeTextView)base.findViewById(R.id.nickLabel);
        }
        return nickLabel;
    }

    WidthResizeTextView getNickTextView() {
        if (nickTextView == null) {
            nickTextView = (WidthResizeTextView)base.findViewById(R.id.nickTextView);
        }
        return nickTextView;
    }

    WidthResizeTextView getCountLabel(){
        if (countLabel == null) {
            countLabel = (WidthResizeTextView)base.findViewById(R.id.countLabel);
        }
        return countLabel;
    }

    WidthResizeTextView getCountTextView() {
        if (countTextView == null) {
            countTextView = (WidthResizeTextView)base.findViewById(R.id.countTextView);
        }
        return countTextView;
    }
}

}


<?xml version="1.0" encoding="utf-8"?>
<com.asharp.android.CWGs.RelativeLayoutKeepRatio
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res/com.asharp.android.CWGs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/cwg_mycwg_bg" >

        <ImageView
            android:id="@+id/CWGView"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_margin="5dip"
            android:adjustViewBounds="true"
            android:layout_alignParentLeft="true" 
            android:layout_alignParentTop="true"     
            android:src="@drawable/empty_cwg" />

        <com.asharp.android.CWGs.WidthResizeTextView
            android:id="@+id/nickLabel"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_above="@+id/spacer"
            android:layout_alignParentTop="true"
            android:layout_marginLeft="10dip"
            android:layout_toRightOf="@+id/CWGView"
            android:bufferType="spannable"
            android:gravity="left|center_vertical"
            android:singleLine="true"
            android:text="@string/nick"
            android:ellipsize="none"
            android:textColor="@color/MyCWG_field_names"
            custom:HeightPercentage="0.5" />

        <com.asharp.android.CWGs.WidthResizeTextView
            android:id="@+id/nickTextView"
            android:layout_toRightOf="@+id/countLabel"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_alignParentTop="true"
            android:layout_above="@+id/spacer"
            android:layout_marginLeft = "10dip"
            android:gravity="left|center_vertical"
            android:text="0"
            android:singleLine="true"
            android:ellipsize="none"
            android:bufferType="spannable"
            custom:HeightPercentage="0.5"
            android:background="#00FF00"
            android:textColor="@color/MyCWG_field_values"/>
        <View
            android:id="@+id/spacer"
            android:layout_width="match_parent"
            android:layout_toRightOf="@id/CWGView"
            android:layout_height="1px"
            android:layout_centerVertical="true"
            android:visibility="invisible"/>            
        <com.asharp.android.CWGs.WidthResizeTextView
            android:id="@+id/countLabel"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_below="@id/spacer"
            android:layout_marginLeft="10dip"
            android:gravity="left|center_vertical"
            android:layout_toRightOf="@+id/CWGView"
            android:layout_alignParentBottom="true"
            android:text="@string/count_colon"
            android:ellipsize="none"
            android:singleLine="true"
            android:textColor="@color/MyCWG_field_names"
            android:bufferType="spannable"
            custom:HeightPercentage="0.5" />
        <com.asharp.android.CWGs.WidthResizeTextView
            android:id="@+id/countTextView"
            android:layout_toRightOf="@id/countLabel"
            android:layout_alignParentBottom="true"
            android:layout_below="@id/spacer"
            android:layout_marginLeft = "10dip"
            android:gravity="left|center_vertical"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:singleLine="true"
            android:ellipsize="none"
            android:bufferType="spannable"
            custom:HeightPercentage="0.5"
            android:text="0"
            android:textColor="@color/MyCWG_field_values"/>


</com.asharp.android.CWGs.RelativeLayoutKeepRatio>


有没有人见过这样的行为?我花了几天时间试图解决这个问题,但我没有成功:-(我相信它与WidthResizeTextView有关,因为我花了很长时间才把它用于至少这样的工作。谢谢你帮助!

1 个答案:

答案 0 :(得分:0)

您可能希望使用标准视图(例如

)重新设计XML
  • 一个ConstraintLayout而不是RelativeLayout作为容器
  • Guidelines或用于定位小部件的高度/宽度百分比

查看ConstraintLayout documentation