Question

I have 4 TextViews in a GridView with a custom adapter in a given Fragment. My main Activity gets notified via a TimerTask to update the text color for the correct TextView. This works fine for all the TextViews except the first one when the app first starts. After that it works correctly like the rest of the TextViews.

In the Fragment in question:

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.short_press_info_fragment, container, false);
    GridView grid = (GridView) view.findViewById(R.id.grid_view);
    infoAdapter = new ShortPressInfoAdapter(mKeyInfo, getActivity());
    grid.setAdapter(infoAdapter);
    return view; 
}

In the adapter:

public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    if(convertView == null) {
        Log.d("GRID_VIEW", "inflating");
        LayoutInflater li = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = li.inflate(R.layout.grid_item, null);
        TextView text = texts[position] = (TextView) v.findViewById(R.id.gridItemText);
        Log.d("GRID_VIEW", "creating view");
        text.setText(mKeyInfo[position]);
        switch(position) {
        case 0:
            text.setBackgroundColor(mContext.getResources().getColor(R.color.blue));
            break;
        case 1:
            text.setBackgroundColor(mContext.getResources().getColor(R.color.yellow));
            break;
        case 2:
            text.setBackgroundColor(mContext.getResources().getColor(R.color.green));
            break;
        case 3:
            text.setBackgroundColor(mContext.getResources().getColor(R.color.red));
            break;
        default:
            break;
        }
    }
    return v;
}

In the main Activity:

public void emphasizeShort(final PressID p, final boolean b) {
runOnUiThread(new Runnable() {
  @Override
  public void run() {
    if(b) {
      Log.d(TAG, "setting short " + p + " to black");
      getShortTextView(p).setTextColor(getResources().getColor(R.color.black));
    }
    else {
      Log.d(TAG, "setting short " + p + " to white");
      getShortTextView(p).setTextColor(getResources().getColor(R.color.white));
    }
  }
});
}

The log shows me the same output no matter which TextView I'm trying to change when the app starts but the first TextView is the only one that simply doesn't change.

What would cause a View to ignore a change when an app starts but not after? And from this code I don't see why the first TextView is singled out.

Any help would be greatly appreciated.

EDIT: Here's the function that sends the request to emphasize the TextViews.

@Override
public boolean onTouch(final View v, final MotionEvent event) {
  if (event.getAction() == MotionEvent.ACTION_DOWN) { // button pressed
    pressTime = System.currentTimeMillis();
    timer = new Timer();
    timer.schedule(new TimerTask() {
      @Override
      public void run() {
        Log.d("TIMER_TASK", "short press "
            + (System.currentTimeMillis() - pressTime));
        mFourButtonListener.onShortPress(buttonID);
      }
    }, SHORT_PRESS_DELAY);
    timer.schedule(new TimerTask() {
      @Override
      public void run() {
        Log.d("TIMER_TASK", "long press "
            + (System.currentTimeMillis() - pressTime));
        mFourButtonListener.onLongPress(buttonID);
      }
    }, LONG_PRESS_DELAY);
    return true;
  } else if (event.getAction() == MotionEvent.ACTION_UP) {
    duration = System.currentTimeMillis() - pressTime;
    timer.cancel();
    timer.purge();
    if (duration >= SHORT_PRESS_DELAY && duration < LONG_PRESS_DELAY)
      mFourButtonListener.onShortRelease(buttonID);
    else if (duration >= LONG_PRESS_DELAY)
      mFourButtonListener.onLongRelease(buttonID);
    return true;
  }
  return false;
}
}

I'm getting desperate.

Était-ce utile?

La solution

There's a lot of missing code here, but if you're having a problem with it not working when the app is first starting, then the problem is likely caused by runOnUiThread, which is simply not reliable at startup. (i.e., not every task posted is guaranteed to run.)

Add a class-level Handler variable

Handler h;

and create it during onCreate

h = new Handler();

Then use h.post() instead of runOnUiThread.

Autres conseils

If no. of TextViews will stay 4, no matter what then don't use GridView. Use LineareLayout instead. Anyways your current approach will stop working if you add more TextViews. At first glance your getView() is faulty, you must do it like this:

public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    if(convertView == null) {
        Log.d("GRID_VIEW", "inflating");
        LayoutInflater li = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = li.inflate(R.layout.grid_item, null);
    } // <<<<------------------- 
    TextView text = (TextView) v.findViewById(R.id.gridItemText);
    Log.d("GRID_VIEW", "creating view");
    text.setText(mKeyInfo[position]);
    switch(position) {
    case 0:
        text.setBackgroundColor(mContext.getResources().getColor(R.color.blue));
        break;
    case 1:
        text.setBackgroundColor(mContext.getResources().getColor(R.color.yellow));
        break;
    case 2:
        text.setBackgroundColor(mContext.getResources().getColor(R.color.green));
        break;
    case 3:
        text.setBackgroundColor(mContext.getResources().getColor(R.color.red));
        break;
    default:
        break;
    } 
    return v;
}

Basically you must perform all state related operations every time getView() is called due to View recycling.

BTW why you are keeping reference to yourself in texts array? Its very very bad practice. Why do you need this?

If you want to change the colors at later stage then you need to change your whole logic. You need to do something similar to this:

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

public class MyAdapter extends BaseAdapter {

int[] colors = new int[4];

public MyAdapter(Context context) {
    colors[0] =  context.getResources().getColor(R.color.blue);
    colors[1] =  context.getResources().getColor(R.color.yellow);
    colors[2] =  context.getResources().getColor(R.color.green);
    colors[3] =  context.getResources().getColor(R.color.red);
}

@Override
public int getCount() { 
    return colors.length;
}

@Override
public Object getItem(int position) { 
    return colors[position];
}

@Override
public long getItemId(int position) { 
    return position;
}

public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    if(convertView == null) {
        Log.d("GRID_VIEW", "inflating");
        LayoutInflater li = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = li.inflate(R.layout.grid_item, null);
    } // <<<<------------------- 
    TextView text = (TextView) v.findViewById(R.id.gridItemText);
    Log.d("GRID_VIEW", "creating view");
    text.setText(mKeyInfo[position]);
    text.setBackgroundColor(colors[position]); 
    return v;
}
// call this method to change colors at later stage
public void changeColor(int position, int color){
    colors[position] = color;
    notifyDataSetChanged();
}

// call this method to change text at later stage
public void changeText(int position, String text){
    mKeyInfo[position] = text;
    notifyDataSetChanged();
}
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top