单击按钮更改 ListView 的适配器 - GUI 故障
Changing the adapter of a ListView with Button click - GUI glitch
我有一个 ListView 和它上面的两个按钮。 ListView 的内容根据单击哪个按钮而变化。为此,我有两个 BaseAdapter。 ListView.SetAdapter() 在用户单击按钮时调用。更换适配器时出现 GUI 故障;附件是问题的屏幕截图。
@Bondax 在 post: Is it okay to change a ListView's adapter dynamically? 中简要提到了这个问题。但我没有找到解决办法。为包含 ListView 和两个适配器的片段的 onCreate 附加的代码。此外,如果相关,列表视图中的每个不同行都是 ConstraintLayout。任何和所有帮助将不胜感激! :)
录制曲目按钮 第一次加载正常。
然后我点击所有时间按钮,设置新的适配器。此处出现 GUI 故障。
然后我再次单击 Recorded tracks,它也出现错误。
代码:
onCreate 包含列表视图的片段
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_stats, container, false);
trackStatsListView = (ListView) view.findViewById(R.id.listOfTracksListView);
trackStatsListView.setBackgroundColor(Color.WHITE);
ImageButton recordedTracksButton = (ImageButton) view.findViewById(R.id.recordedTracksButton);
ImageButton allTimeBestButton = (ImageButton) view.findViewById(R.id.allTimeBestButton);
//All Time stats clicked
allTimeBestButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
recordedTracksClicked = false;
trackStatsListView.setAdapter(null);
final allTimeBestAdapter allTimeBestAdapter = new allTimeBestAdapter(getActivity());
trackStatsListView.setAdapter(allTimeBestAdapter);
}
});
//Recorded Tracks clicked (click by default when Fragment loads up)
recordedTracksButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
recordedTracksClicked = true;
SkiCompanionDatabase db = new SkiCompanionDatabase(getActivity());
PopulateTrack populateTrack;
//TODO: add in location awareness
//populating data for each track
listOfTracks = new ArrayList<>();
Cursor trackIDPosition = db.getAllTrackIDs();
trackIDPosition.moveToFirst();
for (int i = 0; i < db.numberOfTracks(); i++) {
currentID = trackIDPosition.getLong(trackIDPosition.getColumnIndex(Constants.COL_TRACK_DESC_ID));
populateTrack = new PopulateTrack(getActivity(), currentID);
listOfTracks.add(new TrackDescription(currentID, db.getNameFromTrackID(currentID), db.getDateFromTrackID(currentID), "Whistler", populateTrack.totalDuration(), populateTrack.totalDistance()));
trackIDPosition.moveToNext();
}
trackStatsListView.setAdapter(null);
final StatsAdapter statsAdapter = new StatsAdapter(getActivity(), listOfTracks);
//setting an adapter to put list data into the ListView
trackStatsListView.setAdapter(statsAdapter);
//setting the onClick for each element in the list - will replace current fragment with new fragment
trackStatsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
if (recordedTracksClicked) {
//getting the ID of the track selected
Bundle itemClicked = new Bundle();
itemClicked.putLong("trackID", listOfTracks.get(listOfTracks.size() - 1 - i).getId());
//adding the id as an extra (argument) for the next fragment
Fragment trackStatsFragment = new TrackStatsFragment();
trackStatsFragment.setArguments(itemClicked);
android.app.FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
//replacing fragment, we push to backStack so that StatsFragment is still navigable with the back button
transaction.replace(R.id.fragmentContainer, trackStatsFragment);
transaction.addToBackStack(null);
transaction.commit();
}
}
});
}
});
recordedTracksButton.callOnClick();
return view;
}
AllTimeAdapter 和 RecordedTrackAdapter:
//helper class to populate ListView
class StatsAdapter extends BaseAdapter {
private ArrayList<TrackDescription> listOfTracks;
private Context context;
//Constructor
StatsAdapter(Context context, ArrayList<TrackDescription> listOfTracks) {
this.context = context;
this.listOfTracks = listOfTracks;
}
//total number elements in list
@Override
public int getCount() {
return listOfTracks.size();
}
//returns the object of an item at index i in ListView
@Override
public Object getItem(int i) {
return listOfTracks.get(i);
}
//used for returning index of Database element
@Override
public long getItemId(int i) {
return i;
}
//method which populates ListView. The Row design is specified in list_of_tracks_row.xml
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//ViewHolder is a kind of cache and is a public helper class. When an object is scrolled outside of view
//(into recycler), its data is store in ViewHolder, so that it can be quickly loaded when the user scrolls over it again.
ViewHolder viewHolder;
if (view == null) {
//inflating layout list_of_tracks_row.XML on each iteration
view = layoutInflater.inflate(R.layout.list_of_tracks_row, viewGroup, false);
//populating ViewHolder object
viewHolder = new ViewHolder();
viewHolder.tv1 = (TextView) view.findViewById(R.id.trackName);
viewHolder.tv2 = (TextView) view.findViewById(R.id.trackDate);
viewHolder.tv3 = (TextView) view.findViewById(R.id.trackLocation);
viewHolder.tv4 = (TextView) view.findViewById(R.id.trackDuration);
viewHolder.tv5 = (TextView) view.findViewById(R.id.trackDistance);
//associating current view with the relevant ViewHolder
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
//setting the text of the TextViews in the row
//newest to oldest
viewHolder.tv1.setText(listOfTracks.get(listOfTracks.size() - 1 - i).getName());
viewHolder.tv2.setText(listOfTracks.get(listOfTracks.size() - 1 - i).getDate());
viewHolder.tv3.setText(listOfTracks.get(listOfTracks.size() - 1 - i).getLocation());
viewHolder.tv4.setText(millisToHMS(listOfTracks.get(listOfTracks.size() - 1 - i).getDuration()));
viewHolder.tv5.setText(String.valueOf((int) listOfTracks.get(listOfTracks.size() - 1 - i).getDistance()) + "m");
//TODO: to speed up fragment load time, use distance and duration stored in database.
// viewHolder.tv5.setText(String.valueOf((int) skiCompanionDatabase.getDistanceFromTrackID(30)) + "m");
return view;
}
}
class allTimeBestAdapter extends BaseAdapter {
private Context context;
private AppPreferences appPreferences;
public allTimeBestAdapter(Context context) {
this.context = context;
this.appPreferences = new AppPreferences(context);
}
@Override
public int getItemViewType(int position) {
return position;
}
//number of different types in list, ie. speed, altitude...
@Override
public int getViewTypeCount() {
return 8;
}
@Override
public int getCount() {
return 6;
}
@Override
public Object getItem(int i) {
return null;
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//ViewHolder is a kind of cache and is a public helper class. When an object is scrolled outside of view
//(into recycler), its data is store in ViewHolder, so that it can be quickly loaded when the user scrolls over it again.
final ViewHolder viewHolder;
//i is the current row number. Switch statement determines the layout to be inflated depending on the row number
//row 0: speed: track_list_row_speed , row 1: altitude: track_list_row_altitude , etc...
switch (i) {
/* DURATION */
case 0:
if (view == null) {
//inflating layout specific to the row 1, ie. track_list_row_speed
view = layoutInflater.inflate(R.layout.track_list_row_duration, viewGroup, false);
//populating ViewHolder object
viewHolder = new ViewHolder();
viewHolder.tv1 = (TextView) view.findViewById(R.id.statsListTotalDuration);
viewHolder.tv2 = (TextView) view.findViewById(R.id.statsListAscentDuration);
viewHolder.tv3 = (TextView) view.findViewById(R.id.statsListDescentDuration);
//associating current view with the relevant ViewHolder
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.tv1.setText(millisToHMS(appPreferences.getAllTimeTotalDuration()));
viewHolder.tv2.setText(millisToHMS(appPreferences.getAllTimeAscentDuration()));
viewHolder.tv3.setText(millisToHMS(appPreferences.getAllTimeDescentDuration()));
// viewHolder.tv1.setText(millisToHMS(track.getTotalDuration()));
// viewHolder.tv2.setText(millisToHMS(track.getAscentDuration()));
// viewHolder.tv3.setText(millisToHMS(track.getDescentDuration()));
break;
/* DISTANCE */
case 1:
if (view == null) {
//inflating layout specific to the row 1, ie. track_list_row_speed
view = layoutInflater.inflate(R.layout.track_list_row_distance, viewGroup, false);
//populating ViewHolder object
viewHolder = new ViewHolder();
viewHolder.tv1 = (TextView) view.findViewById(R.id.statsListTotalDistance);
viewHolder.tv2 = (TextView) view.findViewById(R.id.statsListAscentDistance);
viewHolder.tv3 = (TextView) view.findViewById(R.id.statsListDescentDistance);
//associating current view with the relevant ViewHolder
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.tv1.setText(String.valueOf((int) appPreferences.getAllTimeTotalDistance()) + 'm');
viewHolder.tv2.setText(String.valueOf((int) appPreferences.getAllTimeAscentDistance()) + 'm');
viewHolder.tv3.setText(String.valueOf((int) appPreferences.getAllTimeDescentDistance()) + 'm');
break;
/* SPEED */
case 2:
if (view == null) {
//inflating layout specific to the row 1, ie. track_list_row_speed
view = layoutInflater.inflate(R.layout.track_list_row_speed, viewGroup, false);
//populating ViewHolder object
viewHolder = new ViewHolder();
viewHolder.tv1 = (TextView) view.findViewById(R.id.statsListTopSpeed);
viewHolder.tv2 = (TextView) view.findViewById(R.id.statsListAvgSpeed);
//associating current view with the relevant ViewHolder
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
//multiplying by 18/5 converts m/s to km/h
viewHolder.tv1.setText(String.valueOf(appPreferences.getAllTimeTopSpeed() * (18 / 5)).substring(0, String.valueOf(appPreferences.getAllTimeTopSpeed() * (18 / 5)).indexOf('.') + 2) + "km/h");
viewHolder.tv2.setText(String.valueOf(appPreferences.getAllTimeAvgSpeed() * (18 / 5)).substring(0, String.valueOf(appPreferences.getAllTimeAvgSpeed() * (18 / 5)).indexOf('.') + 2) + "km/h");
break;
/* PACE */
case 3:
if (view == null) {
//inflating layout specific to the row 1, ie. track_list_row_speed
view = layoutInflater.inflate(R.layout.track_list_row_pace, viewGroup, false);
//populating ViewHolder object
viewHolder = new ViewHolder();
viewHolder.tv1 = (TextView) view.findViewById(R.id.statsListBestPace);
viewHolder.tv2 = (TextView) view.findViewById(R.id.statsListAvgPace);
//associating current view with the relevant ViewHolder
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
//multiplying by 18/5 converts m/s to km/h
viewHolder.tv1.setText(secondsToMS(appPreferences.getAllTimeBestPace()));
viewHolder.tv2.setText(secondsToMS(appPreferences.getAllTimeAvgPace()));
break;
/* ALTITUDE */
case 4:
if (view == null) {
view = layoutInflater.inflate(R.layout.track_list_row_altitude, viewGroup, false);
viewHolder = new ViewHolder();
viewHolder.tv1 = (TextView) view.findViewById(R.id.statsListMinAltitude);
viewHolder.tv2 = (TextView) view.findViewById(R.id.statsListMaxAltitude);
viewHolder.tv3 = (TextView) view.findViewById(R.id.statsListGainAltitude);
viewHolder.tv4 = (TextView) view.findViewById(R.id.statsListLossAltitude);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
//setting the text of the TextViews in the row
viewHolder.tv1.setText(String.valueOf((int) appPreferences.getAllTimeMinAltitude()) + 'm');
viewHolder.tv2.setText(String.valueOf((int) appPreferences.getAllTimeMaxAltitude()) + 'm');
viewHolder.tv3.setText(String.valueOf((int) appPreferences.getAllTimeGainAltitude()) + 'm');
viewHolder.tv4.setText(String.valueOf((int) appPreferences.getAllTimeLossAltitude()) + 'm');
break;
/* GRADIENT */
case 5:
if (view == null) {
view = layoutInflater.inflate(R.layout.track_list_row_gradient, viewGroup, false);
viewHolder = new ViewHolder();
viewHolder.tv1 = (TextView) view.findViewById(R.id.statsListMaxGradient);
viewHolder.tv2 = (TextView) view.findViewById(R.id.statsListGainGradient);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.tv1.setText(String.valueOf((int) appPreferences.getAllTimeMaxGradient()) + '\u00B0');
viewHolder.tv2.setText(String.valueOf((int) appPreferences.getAllTimeAvgGradient()) + '\u00B0');
}
return view;
}
}
更新:XML代码:
list_of_track_row:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_height="match_parent">
<TextView
android:id="@+id/trackName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:text="Track name"
android:textColor="@color/colorStatsListTitle"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/trackDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignEnd="@+id/trackName"
android:layout_alignLeft="@+id/trackName"
android:layout_alignRight="@+id/trackName"
android:layout_alignStart="@+id/trackName"
android:layout_below="@+id/trackName"
android:text="Date"
android:textSize="12sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/trackName" />
<TextView
android:id="@+id/trackLocation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignEnd="@+id/trackDate"
android:layout_alignLeft="@+id/trackDate"
android:layout_alignRight="@+id/trackDate"
android:layout_alignStart="@+id/trackDate"
android:layout_below="@+id/trackDate"
android:text="Location"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/trackDate" />
<ImageView
android:id="@+id/imageView"
android:layout_width="29dp"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/trackLocation"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignTop="@+id/trackName"
app:layout_constraintBottom_toBottomOf="@+id/trackLocation"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@mipmap/ic_chevron_right" />
<TextView
android:id="@+id/trackDistance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/trackDistanceDescription"
android:layout_alignEnd="@+id/trackDistanceDescription"
android:layout_alignLeft="@+id/trackDistanceDescription"
android:layout_alignRight="@+id/trackDistanceDescription"
android:layout_alignStart="@+id/trackDistanceDescription"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="0.0 km"
android:textAlignment="center"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@+id/imageView"
app:layout_constraintEnd_toEndOf="@+id/trackDuration"
app:layout_constraintStart_toStartOf="@+id/trackDuration"
app:layout_constraintTop_toBottomOf="@+id/trackDuration" />
<TextView
android:id="@+id/trackDuration"
android:layout_width="wrap_content"
android:layout_height="16dp"
android:layout_above="@+id/trackDurationDescription"
android:layout_alignEnd="@+id/trackDurationDescription"
android:layout_alignLeft="@+id/trackDurationDescription"
android:layout_alignRight="@+id/trackDurationDescription"
android:layout_alignStart="@+id/trackDurationDescription"
android:layout_marginEnd="24dp"
android:layout_marginTop="8dp"
android:text="00:00:00"
android:textAlignment="center"
android:textSize="12sp"
app:layout_constraintEnd_toStartOf="@+id/imageView"
app:layout_constraintTop_toTopOf="@+id/imageView" />
</android.support.constraint.ConstraintLayout>
对于以后遇到此问题的任何人:2017 年发布的新开发的 ConstraintLayout 有一个 bug/glitch。我已在我的自定义 ListView 行中切换到 RelativeLayout,世界再次正常。
我有一个 ListView 和它上面的两个按钮。 ListView 的内容根据单击哪个按钮而变化。为此,我有两个 BaseAdapter。 ListView.SetAdapter() 在用户单击按钮时调用。更换适配器时出现 GUI 故障;附件是问题的屏幕截图。
@Bondax 在 post: Is it okay to change a ListView's adapter dynamically? 中简要提到了这个问题。但我没有找到解决办法。为包含 ListView 和两个适配器的片段的 onCreate 附加的代码。此外,如果相关,列表视图中的每个不同行都是 ConstraintLayout。任何和所有帮助将不胜感激! :)
录制曲目按钮 第一次加载正常。
然后我点击所有时间按钮,设置新的适配器。此处出现 GUI 故障。
然后我再次单击 Recorded tracks,它也出现错误。
代码: onCreate 包含列表视图的片段
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_stats, container, false);
trackStatsListView = (ListView) view.findViewById(R.id.listOfTracksListView);
trackStatsListView.setBackgroundColor(Color.WHITE);
ImageButton recordedTracksButton = (ImageButton) view.findViewById(R.id.recordedTracksButton);
ImageButton allTimeBestButton = (ImageButton) view.findViewById(R.id.allTimeBestButton);
//All Time stats clicked
allTimeBestButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
recordedTracksClicked = false;
trackStatsListView.setAdapter(null);
final allTimeBestAdapter allTimeBestAdapter = new allTimeBestAdapter(getActivity());
trackStatsListView.setAdapter(allTimeBestAdapter);
}
});
//Recorded Tracks clicked (click by default when Fragment loads up)
recordedTracksButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
recordedTracksClicked = true;
SkiCompanionDatabase db = new SkiCompanionDatabase(getActivity());
PopulateTrack populateTrack;
//TODO: add in location awareness
//populating data for each track
listOfTracks = new ArrayList<>();
Cursor trackIDPosition = db.getAllTrackIDs();
trackIDPosition.moveToFirst();
for (int i = 0; i < db.numberOfTracks(); i++) {
currentID = trackIDPosition.getLong(trackIDPosition.getColumnIndex(Constants.COL_TRACK_DESC_ID));
populateTrack = new PopulateTrack(getActivity(), currentID);
listOfTracks.add(new TrackDescription(currentID, db.getNameFromTrackID(currentID), db.getDateFromTrackID(currentID), "Whistler", populateTrack.totalDuration(), populateTrack.totalDistance()));
trackIDPosition.moveToNext();
}
trackStatsListView.setAdapter(null);
final StatsAdapter statsAdapter = new StatsAdapter(getActivity(), listOfTracks);
//setting an adapter to put list data into the ListView
trackStatsListView.setAdapter(statsAdapter);
//setting the onClick for each element in the list - will replace current fragment with new fragment
trackStatsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
if (recordedTracksClicked) {
//getting the ID of the track selected
Bundle itemClicked = new Bundle();
itemClicked.putLong("trackID", listOfTracks.get(listOfTracks.size() - 1 - i).getId());
//adding the id as an extra (argument) for the next fragment
Fragment trackStatsFragment = new TrackStatsFragment();
trackStatsFragment.setArguments(itemClicked);
android.app.FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
//replacing fragment, we push to backStack so that StatsFragment is still navigable with the back button
transaction.replace(R.id.fragmentContainer, trackStatsFragment);
transaction.addToBackStack(null);
transaction.commit();
}
}
});
}
});
recordedTracksButton.callOnClick();
return view;
}
AllTimeAdapter 和 RecordedTrackAdapter:
//helper class to populate ListView
class StatsAdapter extends BaseAdapter {
private ArrayList<TrackDescription> listOfTracks;
private Context context;
//Constructor
StatsAdapter(Context context, ArrayList<TrackDescription> listOfTracks) {
this.context = context;
this.listOfTracks = listOfTracks;
}
//total number elements in list
@Override
public int getCount() {
return listOfTracks.size();
}
//returns the object of an item at index i in ListView
@Override
public Object getItem(int i) {
return listOfTracks.get(i);
}
//used for returning index of Database element
@Override
public long getItemId(int i) {
return i;
}
//method which populates ListView. The Row design is specified in list_of_tracks_row.xml
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//ViewHolder is a kind of cache and is a public helper class. When an object is scrolled outside of view
//(into recycler), its data is store in ViewHolder, so that it can be quickly loaded when the user scrolls over it again.
ViewHolder viewHolder;
if (view == null) {
//inflating layout list_of_tracks_row.XML on each iteration
view = layoutInflater.inflate(R.layout.list_of_tracks_row, viewGroup, false);
//populating ViewHolder object
viewHolder = new ViewHolder();
viewHolder.tv1 = (TextView) view.findViewById(R.id.trackName);
viewHolder.tv2 = (TextView) view.findViewById(R.id.trackDate);
viewHolder.tv3 = (TextView) view.findViewById(R.id.trackLocation);
viewHolder.tv4 = (TextView) view.findViewById(R.id.trackDuration);
viewHolder.tv5 = (TextView) view.findViewById(R.id.trackDistance);
//associating current view with the relevant ViewHolder
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
//setting the text of the TextViews in the row
//newest to oldest
viewHolder.tv1.setText(listOfTracks.get(listOfTracks.size() - 1 - i).getName());
viewHolder.tv2.setText(listOfTracks.get(listOfTracks.size() - 1 - i).getDate());
viewHolder.tv3.setText(listOfTracks.get(listOfTracks.size() - 1 - i).getLocation());
viewHolder.tv4.setText(millisToHMS(listOfTracks.get(listOfTracks.size() - 1 - i).getDuration()));
viewHolder.tv5.setText(String.valueOf((int) listOfTracks.get(listOfTracks.size() - 1 - i).getDistance()) + "m");
//TODO: to speed up fragment load time, use distance and duration stored in database.
// viewHolder.tv5.setText(String.valueOf((int) skiCompanionDatabase.getDistanceFromTrackID(30)) + "m");
return view;
}
}
class allTimeBestAdapter extends BaseAdapter {
private Context context;
private AppPreferences appPreferences;
public allTimeBestAdapter(Context context) {
this.context = context;
this.appPreferences = new AppPreferences(context);
}
@Override
public int getItemViewType(int position) {
return position;
}
//number of different types in list, ie. speed, altitude...
@Override
public int getViewTypeCount() {
return 8;
}
@Override
public int getCount() {
return 6;
}
@Override
public Object getItem(int i) {
return null;
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//ViewHolder is a kind of cache and is a public helper class. When an object is scrolled outside of view
//(into recycler), its data is store in ViewHolder, so that it can be quickly loaded when the user scrolls over it again.
final ViewHolder viewHolder;
//i is the current row number. Switch statement determines the layout to be inflated depending on the row number
//row 0: speed: track_list_row_speed , row 1: altitude: track_list_row_altitude , etc...
switch (i) {
/* DURATION */
case 0:
if (view == null) {
//inflating layout specific to the row 1, ie. track_list_row_speed
view = layoutInflater.inflate(R.layout.track_list_row_duration, viewGroup, false);
//populating ViewHolder object
viewHolder = new ViewHolder();
viewHolder.tv1 = (TextView) view.findViewById(R.id.statsListTotalDuration);
viewHolder.tv2 = (TextView) view.findViewById(R.id.statsListAscentDuration);
viewHolder.tv3 = (TextView) view.findViewById(R.id.statsListDescentDuration);
//associating current view with the relevant ViewHolder
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.tv1.setText(millisToHMS(appPreferences.getAllTimeTotalDuration()));
viewHolder.tv2.setText(millisToHMS(appPreferences.getAllTimeAscentDuration()));
viewHolder.tv3.setText(millisToHMS(appPreferences.getAllTimeDescentDuration()));
// viewHolder.tv1.setText(millisToHMS(track.getTotalDuration()));
// viewHolder.tv2.setText(millisToHMS(track.getAscentDuration()));
// viewHolder.tv3.setText(millisToHMS(track.getDescentDuration()));
break;
/* DISTANCE */
case 1:
if (view == null) {
//inflating layout specific to the row 1, ie. track_list_row_speed
view = layoutInflater.inflate(R.layout.track_list_row_distance, viewGroup, false);
//populating ViewHolder object
viewHolder = new ViewHolder();
viewHolder.tv1 = (TextView) view.findViewById(R.id.statsListTotalDistance);
viewHolder.tv2 = (TextView) view.findViewById(R.id.statsListAscentDistance);
viewHolder.tv3 = (TextView) view.findViewById(R.id.statsListDescentDistance);
//associating current view with the relevant ViewHolder
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.tv1.setText(String.valueOf((int) appPreferences.getAllTimeTotalDistance()) + 'm');
viewHolder.tv2.setText(String.valueOf((int) appPreferences.getAllTimeAscentDistance()) + 'm');
viewHolder.tv3.setText(String.valueOf((int) appPreferences.getAllTimeDescentDistance()) + 'm');
break;
/* SPEED */
case 2:
if (view == null) {
//inflating layout specific to the row 1, ie. track_list_row_speed
view = layoutInflater.inflate(R.layout.track_list_row_speed, viewGroup, false);
//populating ViewHolder object
viewHolder = new ViewHolder();
viewHolder.tv1 = (TextView) view.findViewById(R.id.statsListTopSpeed);
viewHolder.tv2 = (TextView) view.findViewById(R.id.statsListAvgSpeed);
//associating current view with the relevant ViewHolder
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
//multiplying by 18/5 converts m/s to km/h
viewHolder.tv1.setText(String.valueOf(appPreferences.getAllTimeTopSpeed() * (18 / 5)).substring(0, String.valueOf(appPreferences.getAllTimeTopSpeed() * (18 / 5)).indexOf('.') + 2) + "km/h");
viewHolder.tv2.setText(String.valueOf(appPreferences.getAllTimeAvgSpeed() * (18 / 5)).substring(0, String.valueOf(appPreferences.getAllTimeAvgSpeed() * (18 / 5)).indexOf('.') + 2) + "km/h");
break;
/* PACE */
case 3:
if (view == null) {
//inflating layout specific to the row 1, ie. track_list_row_speed
view = layoutInflater.inflate(R.layout.track_list_row_pace, viewGroup, false);
//populating ViewHolder object
viewHolder = new ViewHolder();
viewHolder.tv1 = (TextView) view.findViewById(R.id.statsListBestPace);
viewHolder.tv2 = (TextView) view.findViewById(R.id.statsListAvgPace);
//associating current view with the relevant ViewHolder
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
//multiplying by 18/5 converts m/s to km/h
viewHolder.tv1.setText(secondsToMS(appPreferences.getAllTimeBestPace()));
viewHolder.tv2.setText(secondsToMS(appPreferences.getAllTimeAvgPace()));
break;
/* ALTITUDE */
case 4:
if (view == null) {
view = layoutInflater.inflate(R.layout.track_list_row_altitude, viewGroup, false);
viewHolder = new ViewHolder();
viewHolder.tv1 = (TextView) view.findViewById(R.id.statsListMinAltitude);
viewHolder.tv2 = (TextView) view.findViewById(R.id.statsListMaxAltitude);
viewHolder.tv3 = (TextView) view.findViewById(R.id.statsListGainAltitude);
viewHolder.tv4 = (TextView) view.findViewById(R.id.statsListLossAltitude);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
//setting the text of the TextViews in the row
viewHolder.tv1.setText(String.valueOf((int) appPreferences.getAllTimeMinAltitude()) + 'm');
viewHolder.tv2.setText(String.valueOf((int) appPreferences.getAllTimeMaxAltitude()) + 'm');
viewHolder.tv3.setText(String.valueOf((int) appPreferences.getAllTimeGainAltitude()) + 'm');
viewHolder.tv4.setText(String.valueOf((int) appPreferences.getAllTimeLossAltitude()) + 'm');
break;
/* GRADIENT */
case 5:
if (view == null) {
view = layoutInflater.inflate(R.layout.track_list_row_gradient, viewGroup, false);
viewHolder = new ViewHolder();
viewHolder.tv1 = (TextView) view.findViewById(R.id.statsListMaxGradient);
viewHolder.tv2 = (TextView) view.findViewById(R.id.statsListGainGradient);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.tv1.setText(String.valueOf((int) appPreferences.getAllTimeMaxGradient()) + '\u00B0');
viewHolder.tv2.setText(String.valueOf((int) appPreferences.getAllTimeAvgGradient()) + '\u00B0');
}
return view;
}
}
更新:XML代码:
list_of_track_row:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_height="match_parent">
<TextView
android:id="@+id/trackName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:text="Track name"
android:textColor="@color/colorStatsListTitle"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/trackDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignEnd="@+id/trackName"
android:layout_alignLeft="@+id/trackName"
android:layout_alignRight="@+id/trackName"
android:layout_alignStart="@+id/trackName"
android:layout_below="@+id/trackName"
android:text="Date"
android:textSize="12sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/trackName" />
<TextView
android:id="@+id/trackLocation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignEnd="@+id/trackDate"
android:layout_alignLeft="@+id/trackDate"
android:layout_alignRight="@+id/trackDate"
android:layout_alignStart="@+id/trackDate"
android:layout_below="@+id/trackDate"
android:text="Location"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/trackDate" />
<ImageView
android:id="@+id/imageView"
android:layout_width="29dp"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/trackLocation"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignTop="@+id/trackName"
app:layout_constraintBottom_toBottomOf="@+id/trackLocation"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@mipmap/ic_chevron_right" />
<TextView
android:id="@+id/trackDistance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/trackDistanceDescription"
android:layout_alignEnd="@+id/trackDistanceDescription"
android:layout_alignLeft="@+id/trackDistanceDescription"
android:layout_alignRight="@+id/trackDistanceDescription"
android:layout_alignStart="@+id/trackDistanceDescription"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="0.0 km"
android:textAlignment="center"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@+id/imageView"
app:layout_constraintEnd_toEndOf="@+id/trackDuration"
app:layout_constraintStart_toStartOf="@+id/trackDuration"
app:layout_constraintTop_toBottomOf="@+id/trackDuration" />
<TextView
android:id="@+id/trackDuration"
android:layout_width="wrap_content"
android:layout_height="16dp"
android:layout_above="@+id/trackDurationDescription"
android:layout_alignEnd="@+id/trackDurationDescription"
android:layout_alignLeft="@+id/trackDurationDescription"
android:layout_alignRight="@+id/trackDurationDescription"
android:layout_alignStart="@+id/trackDurationDescription"
android:layout_marginEnd="24dp"
android:layout_marginTop="8dp"
android:text="00:00:00"
android:textAlignment="center"
android:textSize="12sp"
app:layout_constraintEnd_toStartOf="@+id/imageView"
app:layout_constraintTop_toTopOf="@+id/imageView" />
</android.support.constraint.ConstraintLayout>
对于以后遇到此问题的任何人:2017 年发布的新开发的 ConstraintLayout 有一个 bug/glitch。我已在我的自定义 ListView 行中切换到 RelativeLayout,世界再次正常。