我正在创建一个简单的国际象棋时钟类型计时器应用程序。我试图在 ListView
中以行形式显示玩家及其剩余时间。我正在使用一个自定义 View ,该 View 为这些行扩展了 RelativeLayout
,这样我就可以为其提供依次突出显示播放器的方法,例如。
行布局类:
public class GameTimerView extends RelativeLayout {
private TextView nameView;
private TextView timerView;
public GameTimerView(Context context) {
super(context);
LayoutInflater inflater = LayoutInflater.from(context);
inflater.inflate(R.layout.timer_view, this);
loadViews();
}
...
private void loadViews() {
nameView = (TextView)findViewById(R.id.nameView);
timerView = (TextView)findViewById(R.id.timerView);
}
public void setName(String name) {
nameView.setText(name);
}
public void setTime(long timeInMillis) {
timerView.setText(String.format("%02d:%02d",
TimeUnit.MILLISECONDS.toMinutes(timeInMillis),
TimeUnit.MILLISECONDS.toSeconds(timeInMillis) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(timeInMillis))
));
}
public void setActive() {
this.nameView.setTextColor(Color.GREEN);
}
public void setInactive() {
nameView.setTextColor(Color.BLACK);
}
}
行布局 XML (timer_view.xml):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/nameView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@+id/timerView"
android:text="@string/player_default_name" />
<TextView
android:id="@+id/timerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="@string/zero_time" />
</RelativeLayout>
适配器:
public class playerArrayAdapter extends ArrayAdapter<Player> {
private final Context context;
private final ArrayList<Player> players;
public playerArrayAdapter(Context context, ArrayList<Player> values) {
super(context, R.layout.timer_view, values);
this.context = context;
this.players = values;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
GameTimerView playerView = new GameTimerView(context);
players.get(position).setTimerView(playerView);
return playerView;
}
}
Player类setTimerView函数:
public void setTimerView(GameTimerView timer) {
this.timerView = timer;
this.timerView.setName(this.name);
this.timerView.setTime(this.totalCountDown);
this.timerView.setInactive();
}
在 Activity 的 onCreate 方法中:
playerArrayAdapter playersAdapter = new playerArrayAdapter(
getApplicationContext(),
game.getPlayers()
);
ListView playersView = (ListView) findViewById(R.id.playerList);
playersView.setAdapter(playersAdapter);
起初这似乎有效,并且所需的玩家姓名和时间已正确呈现到列表中。但是,如果我稍后以编程方式调用 Player.timerView.setActive()
,则不会发生任何情况。
查看了数十个 ListView 自定义适配器的示例后,似乎没有一个以这种方式使用它 - View 始终直接在 Apdater.getView()
中膨胀。然而,我想要扩展 View 类的灵 active ,但显然我做错了。
那么,为 ListView
行使用自定义 View 类的正确方法是什么?
最佳答案
首先,当扩展您的 GameTimerView
时,您会在另一个组件中获得一个 RelativeLayout
。
其次,回答这个问题:最好不要在每次调用 ArrayAdapter.getView()
时重新创建 View ,而是修改 playerArrayAdapter
添加这样的缓存:
private List<View> views;
public playerArrayAdapter(Context context, ArrayList<Player> values) {
super(context, R.layout.timer_view, values);
views = new ArrayList<View>(values.length);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View playerView;
if (position < views.size()) {
playerView = views.get(position);
if (playerView != null)
return playerView;
} else {
while (views.size() < position)
views.add(null);
}
playerView = new GameTimerView(context);
views.add(position, playerView);
players.get(position).setTimerView(playerView);
return playerView;
}
如果这成功地解决了您的问题,则意味着之前在将播放器设置为 Activity 状态时,ListView
会再次获取所有 View 进行渲染、重新创建它们,并清除所有以前的状态。
关于java - Android:如何使用扩展布局类作为ListView行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25162458/