我有一个ListView
,其中将有垂直对齐的数据列,并且必须在添加新项目时进行更新。 LinearLayout
上方ListView
TextView
,ListView
作为标题,还需要更改宽度以保持对齐。
添加项目时EditText
会正确更新,但标题不会更新。
当屏幕键盘被拉入或推出视图时,标题似乎只会更新,方法是点击TextView
窗口小部件或点击后退按钮。
我为Log
创建了一个包装类,其中一些函数在super.whatever()
之前和之后调用ListView
类,以确定调用的内容和时间。
由此我可以看到,当某个项目添加到setWidth()
时,需要更改宽度时,只会调用onDraw()
和ArrayAdapter
。
在getView()
TextView
内部,我尝试调用invalidate()
,postInvalidate()
和LinearLayout
之类的标题childDrawableStateChanged()
{1}}保留标题setLayoutParams()
之类的其他内容。我尝试使用setWidth()
代替TextView
。无论有没有这些功能,应用程序都会执行相同的操作。
如何告诉getView
在绘制之前读取新的宽度,但是在ArrayAddapter
的{{1}}内?
示例代码是显示带有2个简单文本项的ListView
,其中添加Button
会将EditText
中的文本插入第1列,将“b”插入第2列。设置Button
用于测试onPause
和onResume
的效果。
package testing;
import java.util.ArrayList;
import com.testing.R;
import android.app.Activity;
import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MainActivity extends ListActivity implements OnClickListener {
TestArrayAdapter testAA;
private MyTextView headerA, headerB;
private LinearLayout headerLine;
private EditText inputEditText;
private Button addButton, settingsButton;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.main_layout);
// get views and setup custom headers
inputEditText = (EditText) this.findViewById(R.id.inputEditText);
addButton = (Button) this.findViewById(R.id.addButton);
settingsButton = (Button) this.findViewById(R.id.settingsButton);
headerLine = (LinearLayout) this.findViewById(R.id.headerLineLayout);
headerA = (MyTextView) new MyTextView(this);
headerA.setText("H1");
headerB = (MyTextView) new MyTextView(this);
headerB.setText("H2");
headerLine.addView(headerA);
headerLine.addView(headerB);
// get initial header width to set as max width
int headerWidthA = (int) headerA.getPaint().measureText((String) headerA.getText());
int headerWidthB = (int) headerB.getPaint().measureText((String) headerB.getText());
// most likely redundant
headerA.setWidth(headerWidthA);
headerB.setWidth(headerWidthB);
// setup listeners and adapter
testAA = new TestArrayAdapter(this, R.layout.main_layout_line, new StringList());
addButton.setOnClickListener(this);
settingsButton.setOnClickListener(this);
this.setListAdapter(testAA);
// set header widths as initial max width
testAA.strList.maxWidthA = headerWidthA;
testAA.strList.maxWidthB = headerWidthB;
Log.i("main", "onCreate");
}
@Override
public void onResume() {
super.onResume();
Log.i("main", "onResume");
}
@Override
public void onClick(View view) {
if (view == this.findViewById(R.id.addButton))
testAA.add(new StringLine(inputEditText.getText().toString()));
if (view == this.findViewById(R.id.settingsButton))
this.startActivity(new Intent(this, SettingsActivity.class));
}
class TestArrayAdapter extends ArrayAdapter<StringLine> {
private StringList strList;
public TestArrayAdapter(Context context, int res, StringList strList) {
super(context, res, strList.items);
this.strList = strList;
}
@Override
public View getView(int pos, View convertView, ViewGroup parent) {
Log.i("testAA", "getView start");
// inflate row view
LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.main_layout_line, parent, false);
// get items and set their text
TextView itemA = (TextView) rowView.findViewById(R.id.itemText1);
TextView itemB = (TextView) rowView.findViewById(R.id.itemText2);
itemA.setText(strList.items.get(pos).a);
itemB.setText(strList.items.get(pos).b);
// determine the width of the text and if the header needs to be updated
int itemWidthA = (int) itemA.getPaint().measureText((String) itemA.getText());
if (itemWidthA <= strList.maxWidthA) {
itemWidthA = strList.maxWidthA;
} else {
Log.i("testAA", "header changed");
strList.maxWidthA = itemWidthA;
headerA.setWidth(itemWidthA);
// TELL HEADER TO REDRAW HERE
headerA.invalidate();
headerA.postInvalidate();
headerLine.invalidate();
headerLine.postInvalidate();
headerLine.childDrawableStateChanged(headerA);
testAA.notifyDataSetChanged();
}
itemA.setWidth(itemWidthA);
Log.i("testAA", "getView end");
return rowView;
}
}
// list of for the array adapter
class StringList {
ArrayList<StringLine> items = new ArrayList<StringLine>();
int maxWidthA, maxWidthB;
}
// line item for array adapter list
class StringLine {
public StringLine(String stringA) {
a = stringA;
b = "b";
}
String a, b;
}
// wrapper class
class MyTextView extends TextView {
public MyTextView(Context context) {
super(context);
}
@Override
public void onDraw(Canvas canvas) {
Log.i("header", "onDraw start " + this.getText() + " width - " + this.getWidth());
super.onDraw(canvas);
Log.i("header", "onDraw end " + this.getText() + " width - " + this.getWidth());
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.i("header", "onMeasure start " + this.getText() + " width - " + this.getWidth());
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Log.i("header", "onMeasure end " + this.getText() + " width - " + this.getWidth());
}
@Override
public void layout(int l, int t, int r, int b) {
Log.i("header", "layout start " + this.getText() + " width - " + this.getWidth());
super.layout(l, t, r, b);
Log.i("header", "layout end " + this.getText() + " width - " + this.getWidth());
}
@Override
public void setWidth(int width) {
Log.i("header", "setWidth start " + this.getText() + " width - " + this.getWidth());
super.setWidth(width);
Log.i("header", "setWidth end " + this.getText() + " width - " + this.getWidth());
}
}
}
main_layout.xml
<?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:orientation="vertical" >
<Button
android:id="@+id/settingsButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Settings" />
<EditText
android:id="@+id/inputEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" />
<Button
android:id="@+id/addButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add" />
<LinearLayout
android:id="@+id/headerLineLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
</LinearLayout>
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
main_layout_line.xml
<?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:orientation="horizontal" >
<TextView
android:id="@+id/itemText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
<TextView
android:id="@+id/itemText2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
Logcat(项目添加到ListView
后H1的宽度必须为60)
application started
04-28 17:53:54.614: E/Trace(2780): error opening trace file: No such file or directory (2)
04-28 17:53:55.394: D/dalvikvm(2780): GC_FOR_ALLOC freed 72K, 7% free 2677K/2872K, paused 24ms, total 26ms
04-28 17:53:55.394: I/dalvikvm-heap(2780): Grow heap (frag case) to 3.336MB for 635812-byte allocation
04-28 17:53:55.424: D/dalvikvm(2780): GC_FOR_ALLOC freed 4K, 6% free 3294K/3496K, paused 31ms, total 31ms
04-28 17:53:55.464: D/dalvikvm(2780): GC_CONCURRENT freed <1K, 6% free 3305K/3496K, paused 4ms+3ms, total 36ms
04-28 17:53:55.484: I/header(2780): setWidth start H1 width - 0
04-28 17:53:55.484: I/header(2780): setWidth end H1 width - 0
04-28 17:53:55.484: I/header(2780): setWidth start H2 width - 0
04-28 17:53:55.484: I/header(2780): setWidth end H2 width - 0
04-28 17:53:55.494: I/main(2780): onCreate
04-28 17:53:55.494: I/main(2780): onResume
04-28 17:53:55.564: I/header(2780): onMeasure start H1 width - 0
04-28 17:53:55.574: I/header(2780): onMeasure end H1 width - 0
04-28 17:53:55.574: I/header(2780): onMeasure start H2 width - 0
04-28 17:53:55.574: I/header(2780): onMeasure end H2 width - 0
04-28 17:53:55.614: I/header(2780): layout start H1 width - 0
04-28 17:53:55.614: I/header(2780): layout end H1 width - 27
04-28 17:53:55.614: I/header(2780): layout start H2 width - 0
04-28 17:53:55.614: I/header(2780): layout end H2 width - 27
04-28 17:53:55.654: D/gralloc_goldfish(2780): Emulator without GPU emulation detected.
04-28 17:53:55.684: I/header(2780): onDraw start H1 width - 27
04-28 17:53:55.684: I/header(2780): onDraw end H1 width - 27
04-28 17:53:55.694: I/header(2780): onDraw start H2 width - 27
04-28 17:53:55.694: I/header(2780): onDraw end H2 width - 27
04-28 17:53:55.904: I/header(2780): onMeasure start H1 width - 27
04-28 17:53:55.904: I/header(2780): onMeasure end H1 width - 27
04-28 17:53:55.904: I/header(2780): onMeasure start H2 width - 27
04-28 17:53:55.954: I/header(2780): onMeasure end H2 width - 27
04-28 17:53:55.954: I/header(2780): layout start H1 width - 27
04-28 17:53:55.954: I/header(2780): layout end H1 width - 27
04-28 17:53:55.954: I/header(2780): layout start H2 width - 27
04-28 17:53:55.954: I/header(2780): layout end H2 width - 27
04-28 17:53:56.254: I/header(2780): onMeasure start H1 width - 27
04-28 17:53:56.254: I/header(2780): onMeasure end H1 width - 27
04-28 17:53:56.254: I/header(2780): onMeasure start H2 width - 27
04-28 17:53:56.264: I/header(2780): onMeasure end H2 width - 27
04-28 17:53:56.304: I/header(2780): onMeasure start H1 width - 27
04-28 17:53:56.304: I/header(2780): onMeasure end H1 width - 27
04-28 17:53:56.304: I/header(2780): onMeasure start H2 width - 27
04-28 17:53:56.304: I/header(2780): onMeasure end H2 width - 27
04-28 17:53:56.314: I/header(2780): layout start H1 width - 27
04-28 17:53:56.314: I/header(2780): layout end H1 width - 27
04-28 17:53:56.314: I/header(2780): layout start H2 width - 27
04-28 17:53:56.314: I/header(2780): layout end H2 width - 27
04-28 17:53:56.364: I/header(2780): onDraw start H1 width - 27
04-28 17:53:56.364: I/header(2780): onDraw end H1 width - 27
04-28 17:53:56.364: I/header(2780): onDraw start H2 width - 27
04-28 17:53:56.374: I/header(2780): onDraw end H2 width - 27
04-28 17:53:56.624: I/header(2780): onMeasure start H1 width - 27
04-28 17:53:56.624: I/header(2780): onMeasure end H1 width - 27
04-28 17:53:56.634: I/header(2780): onMeasure start H2 width - 27
04-28 17:53:56.634: I/header(2780): onMeasure end H2 width - 27
04-28 17:53:56.654: I/header(2780): onMeasure start H1 width - 27
04-28 17:53:56.654: I/header(2780): onMeasure end H1 width - 27
04-28 17:53:56.654: I/header(2780): onMeasure start H2 width - 27
04-28 17:53:56.664: I/header(2780): onMeasure end H2 width - 27
04-28 17:53:56.685: I/header(2780): layout start H1 width - 27
04-28 17:53:56.685: I/header(2780): layout end H1 width - 27
04-28 17:53:56.704: I/header(2780): layout start H2 width - 27
04-28 17:53:56.704: I/header(2780): layout end H2 width - 27
04-28 17:53:56.754: I/header(2780): onDraw start H1 width - 27
04-28 17:53:56.754: I/header(2780): onDraw end H1 width - 27
04-28 17:53:56.764: I/header(2780): onDraw start H2 width - 27
04-28 17:53:56.764: I/header(2780): onDraw end H2 width - 27
04-28 17:53:56.794: I/header(2780): onMeasure start H1 width - 27
04-28 17:53:56.794: I/header(2780): onMeasure end H1 width - 27
04-28 17:53:56.794: I/header(2780): onMeasure start H2 width - 27
04-28 17:53:56.794: I/header(2780): onMeasure end H2 width - 27
04-28 17:53:56.844: I/header(2780): onMeasure start H1 width - 27
04-28 17:53:56.844: I/header(2780): onMeasure end H1 width - 27
04-28 17:53:56.844: I/header(2780): onMeasure start H2 width - 27
04-28 17:53:56.844: I/header(2780): onMeasure end H2 width - 27
04-28 17:53:56.844: I/header(2780): layout start H1 width - 27
04-28 17:53:56.855: I/header(2780): layout end H1 width - 27
04-28 17:53:56.855: I/header(2780): layout start H2 width - 27
04-28 17:53:56.855: I/header(2780): layout end H2 width - 27
04-28 17:53:56.884: I/header(2780): onDraw start H1 width - 27
04-28 17:53:56.884: I/header(2780): onDraw end H1 width - 27
04-28 17:53:56.894: I/header(2780): onDraw start H2 width - 27
04-28 17:53:56.894: I/header(2780): onDraw end H2 width - 27
text entered and clicked add
04-28 17:54:29.965: I/testAA(2780): getView start
04-28 17:54:29.975: I/testAA(2780): header changed
04-28 17:54:29.975: I/header(2780): setWidth start H1 width - 27
04-28 17:54:29.975: I/header(2780): setWidth end H1 width - 27
04-28 17:54:29.975: I/testAA(2780): getView end
04-28 17:54:29.985: I/testAA(2780): getView start
04-28 17:54:29.995: I/testAA(2780): getView end
04-28 17:54:30.005: I/header(2780): onDraw start H1 width - 27
04-28 17:54:30.005: I/header(2780): onDraw end H1 width - 27
04-28 17:54:30.005: I/header(2780): onDraw start H2 width - 27
04-28 17:54:30.005: I/header(2780): onDraw end H2 width - 27
04-28 17:54:30.035: I/header(2780): onDraw start H1 width - 27
04-28 17:54:30.045: I/header(2780): onDraw end H1 width - 27
04-28 17:54:30.045: I/header(2780): onDraw start H2 width - 27
04-28 17:54:30.045: I/header(2780): onDraw end H2 width - 27
clicked Back Button to lower keyboard
04-28 17:54:56.755: I/header(2780): onMeasure start H1 width - 27
04-28 17:54:56.755: I/header(2780): onMeasure end H1 width - 27
04-28 17:54:56.765: I/header(2780): onMeasure start H2 width - 27
04-28 17:54:56.765: I/header(2780): onMeasure end H2 width - 27
04-28 17:54:56.765: I/testAA(2780): getView start
04-28 17:54:56.795: I/testAA(2780): getView end
04-28 17:54:56.865: I/header(2780): onMeasure start H1 width - 27
04-28 17:54:56.875: I/header(2780): onMeasure end H1 width - 27
04-28 17:54:56.875: I/header(2780): onMeasure start H2 width - 27
04-28 17:54:56.875: I/header(2780): onMeasure end H2 width - 27
04-28 17:54:56.875: I/testAA(2780): getView start
04-28 17:54:56.885: I/testAA(2780): getView end
04-28 17:54:56.895: I/header(2780): layout start H1 width - 27
04-28 17:54:56.925: I/header(2780): layout end H1 width - 60
04-28 17:54:56.925: I/header(2780): layout start H2 width - 27
04-28 17:54:56.925: I/header(2780): layout end H2 width - 27
04-28 17:54:56.985: I/header(2780): onDraw start H1 width - 60
04-28 17:54:56.985: I/header(2780): onDraw end H1 width - 60
04-28 17:54:56.985: I/header(2780): onDraw start H2 width - 27
04-28 17:54:56.995: I/header(2780): onDraw end H2 width - 27
header updated