我正在创建一个简单的国际象棋时钟型计时器应用程序。我试图在ListView
中显示玩家和他们留下的时间。我正在使用为这些行扩展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;
}
}
播放器类setTimerView函数:
public void setTimerView(GameTimerView timer) {
this.timerView = timer;
this.timerView.setName(this.name);
this.timerView.setTime(this.totalCountDown);
this.timerView.setInactive();
}
在活动的onCreate方法中
playerArrayAdapter playersAdapter = new playerArrayAdapter(
getApplicationContext(),
game.getPlayers()
);
ListView playersView = (ListView) findViewById(R.id.playerList);
playersView.setAdapter(playersAdapter);
首先,这似乎有效,并且所需的玩家名称和时间正确地呈现在列表中。但是,如果我稍后以编程方式调用示例Player.timerView.setActive()
,则不会发生任何事情。
看过ListViews的几十个自定义适配器的例子后,似乎没有人这样使用它 - 视图总是直接在Apdater.getView()
中膨胀。我想要扩展视图类的灵活性,但显然我做错了。
那么,为ListView
行使用自定义视图类的正确方法是什么?
答案 0 :(得分:1)
首先,在对GameTimerView
进行充气时,您在另一个内部有RelativeLayout
。
其次,要回答这个问题:最好不要在每次调用ArrayAdapter.getView()
时重新创建视图,而是通过添加如下缓存来修改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;
}
如果这成功纠正了您的问题,则意味着之前,当将播放器设置为活动时,ListView
会再次获取所有视图以进行渲染,重新创建它们,并删除之前的任何状态。
答案 1 :(得分:1)
根据getView()
的{{1}}方法,它会创建一个可能导致您发出问题的新视图。
如果您确实要实施Adapter
,请参阅自定义视图here的这个良好实现。希望这会帮助你开始。