Reputation: 26
I have a listview with an array adapter, which shows different views to represent different properties of an item. The same item is added to the list multiple times, to create those views.
Since those views are unique, I created an enum to manage each view's inflation.
The problem is, maxDistanceTv
's text is not updated when setMaxDistanceText()
is called from onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
.
I tried using new Handler().post(new Runnable()...)
, runOnUiThread(new Runnable()...)
, .invalidate()
, .postInvalidate()
and none of them worked.
When debugging, I can see maxDistanceTv
's text(mText
) updating to the new correct value, but that change is not reflected in the UI.
The following is the relevant part of the enum:
public enum BleDeviceProperties implements IDevicePropertiesInflater {
ALERT_DISTANCE(R.layout.property_alert_distance, new IDevicePropertiesInflater() {
private TextView maxDistanceTv;
private SeekBar maxDistanceSb;
private BleDeviceInfo info;
private View view;
private void setMaxDistanceText(){
maxDistanceTv = (TextView) view.findViewById(R.id.max_distance_tv);
maxDistanceTv.setText(String.valueOf(info.getThreshold()));
}
private void setMaxDistanceProgress(){
maxDistanceSb = (SeekBar) view.findViewById(R.id.max_distance_sb);
maxDistanceSb.setMax(BleDeviceInfo.STEPS);
maxDistanceSb.setProgress(info.getThresholdNormalized());
maxDistanceSb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
info.setThresholdNormailized(progress);
BluetoothLeServiceMessanger.getInstance().sendNewRssiThresholdSet(info.getThreshold());
setMaxDistanceText();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
@Override
public void inflateData(View view, BleDeviceInfo info) {
this.info = info;
this.view = view;
setMaxDistanceText();
setMaxDistanceProgress();
}
}),
...
private int viewId;
private IDevicePropertiesInflater propertiesInflater;
@Override
public void inflateData(View view, BleDeviceInfo info) {
if(propertiesInflater != null){
propertiesInflater.inflateData(view,info);
}
}
public int getViewId() {
return viewId;
}
BleDeviceProperties(int viewId, IDevicePropertiesInflater propertiesInflater) {
this.viewId = viewId;
this.propertiesInflater = propertiesInflater;
}
}
public interface IDevicePropertiesInflater {
void inflateData(View view,BleDeviceInfo info);
}
public class DevicePropertiesAdapter extends ArrayAdapter<BleDeviceInfo>{
private static final int VIEW_TYPE_COUNT = 4;
private Activity activity;
public void setInfo(BleDeviceInfo info){
clear();
for(int i=0;i<VIEW_TYPE_COUNT;i++){
add(info);
}
notifyDataSetChanged();
}
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public int getViewTypeCount() {
return VIEW_TYPE_COUNT;
}
public DevicePropertiesAdapter(Activity activity, int resource) {
super(activity, resource);
this.activity = activity;
}
@Override
public View getView(int position, View view, final ViewGroup parent) {
View rowView;
if(view == null) {
LayoutInflater inflater = activity.getLayoutInflater();
rowView = inflater.inflate(BleDeviceProperties.values()[position].getViewId(), null);
}else{
rowView = view;
}
BleDeviceProperties.values()[position].inflateData(rowView, getItem(position));
return rowView;
}
}
Upvotes: 0
Views: 290
Reputation: 26
Eventually, Instead of calling setMaxDistanceText()
from onProgressChanged
, I tried:
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
info.setThresholdNormailized(progress);
BluetoothLeServiceMessanger.getInstance().sendNewRssiThresholdSet(info.getThreshold());
//setMaxDistanceText();
maxDistanceTv = (TextView) ((ViewGroup)seekBar.getParent()).findViewById(R.id.max_distance_tv);
maxDistanceTv.setText(String.valueOf(info.getThreshold()));
}
and it worked. I still don't know why the TextView does not update using the code in the original question.
EDIT: Read this here:
Never set the layout_height and layout_width of your listview to wrap_content as getView() will force your adapter to get some child for measuring the height of the views to be drawn in list view and can cause some unexpected behaviour like returning convertview even the list is not scrolled.always use match_parent or fixed width/height.
The original code worked perfectly after changing the values of layout_height
and layout_width
to match_parent
.
Upvotes: 1