0

I’m trying to make an app which displays a ListView with a custom Adapter where each item of this list contains an object of the class Track, which extends RelativeView.

The app allows user to drag TextViews over the ListView. Then, it calculates the position of the item of the ListView under the dragged ImageView, and then adds this ImageView to the RelativeLayout of the track object.

The problem I have is that after dragging the item over the Track object of the listView item, the TextView is added to the RelativeView of that object, but it is never shown. With the debugger I checked that the track object has indeed the expected child.

What I’m doing wrong here, should I update somehow the RelativeLayouts afterwards?

For making it easier, I substituted the code for the dragging of the TextView in the layout, and I just put a button that when clicked adds a text view to the Track in the position 0 of the ListView.

The reason of using this ListView for this is because I want to have that list to be scrollable. Is this a right approximation, or should I use better a LinearLayout, containing the Track objects, inside a scrollable container?

Many thanks

The Track Class

public class Track extends RelativeLayout {

 static public ArrayList<Track> trackList = new ArrayList<>();
public ArrayList<Light> lightsOnThisTrackList = new ArrayList<>();

Context context;
private String name;

LayoutInflater mInflater;

public Track(Context _context) {
    super(_context);
    context = _context;
    mInflater = LayoutInflater.from(_context);
    init();

}
public Track(Context _context, AttributeSet attrs, int defStyle)
{
    super(_context, attrs, defStyle);
    context = _context;

    mInflater = LayoutInflater.from(_context);
    init();
}
public Track(Context _context, AttributeSet attrs) {
    super(_context, attrs);
    context = _context;

    mInflater = LayoutInflater.from(_context);
    init();
}

public void init() {

    mInflater.inflate(R.layout.track_view, this, true);

    RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    this.setLayoutParams(params);

    final Track thisTrack = this;
    this.context = context;

    ImageView trackView = new ImageView(context);
    trackView.setImageResource(R.drawable.track);
    this.addView(trackView);
}

public void setName(String name) {
    this.name = name;
}

public String getName() {
    return name;
}

}

Until here, the drawable.track is showing in every item of the ListView.

The Adapter:

public class TrackListAdapter extends ArrayAdapter<Track> {

private static final String TAG = "TrackListAdapter";
private LayoutInflater layoutInflater;
ArrayList<Track> trackArrayList;
Context mContext;


public TrackListAdapter(Context context, int textViewResourceId, ArrayList<Track> _trackArrayList) {
    super(context, 0, _trackArrayList);

    layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    this.mContext = context;
    this.trackArrayList = _trackArrayList;
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {

    if (convertView == null) {
        convertView = layoutInflater.inflate(R.layout.track_list_item, null);
    }

    if (trackArrayList.size() != 0) {
        Track track = trackArrayList.get(position);
        TextView text = (TextView) convertView.findViewById(R.id.textView);
        text.setText(track.getName()); //This is working and gets updated

    }

    return convertView;
}

}

public class MainActivity extends AppCompatActivity {

private static final String TAG = "MainActivity";
RelativeLayout relativeLayout;

Context context;

ImageButton newItemButton ;
Button button;

public ListView trackListView;
TrackListAdapter trackListAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    context = getApplicationContext();

    relativeLayout = (RelativeLayout) findViewById(R.id.mainLayout);

    trackListView = (ListView) findViewById(R.id.trackListView);
    trackListAdapter = new TrackListAdapter(this, 0, Track.trackList);

    trackListView.setAdapter(trackListAdapter);

    //This button adds new track to the list

    button = (Button) findViewById(R.id.button);
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            Track.trackList.add(new Track(context));
            Log.i(TAG, "onClick " + Track.trackList.size());
            trackListAdapter.notifyDataSetChanged();
        }
    });

    //This button adds a new TextView to the track object of the item(0)
    //of the ListView. The view is added, according to the debugger, 
    //but it is not shown

    newItemButton = (ImageButton) findViewById(R.id.newItemButton );

    newItemButton .setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {

            Track track = trackListAdapter.getItem(0);
            track = (Track) findViewById(R.id.view);

            RelativeLayout.LayoutParams imParams =
                    new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);

            TextView text = new TextView(context);
            text.setText("hello world!");

            track.addView(text, imParams);
            trackListAdapter.notifyDataSetChanged();

            return false;
        }
    });

}

Track_view.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical"
 android:layout_width="match_parent"
 android:layout_height="match_parent">
</RelativeLayout>

track_list_item.xml

<?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


    <TextView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:textAppearance="?android:attr/textAppearanceLarge"
      android:text="Large Text"
      android:id="@+id/textView" />

    <com.example.microinnova.smartcontrol.Track
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:id="@+id/view" />

</LinearLayout>
gotramaval
  • 59
  • 7
  • From looking at your code, there's not place where you are actually changing the underlying data of your Adapter - so calling `trackListAdapter.notifyDataSetChanged()` has no effect. You need to add a method in your adapter that adds a `Track` (to the `ArrayList trackArrayList `). Add a method like `public void addItem(Track item){ trackArrayList.add(item); }` – ishmaelMakitla May 25 '16 at 10:12
  • There is the line `Track.trackList.add(new Track(context))` and `Track.trackList` is bounded to the adapter in the line `new TrackListAdapter(this, 0, Track.trackList)`. I dont think that is the problem, since the listView is showing the new Track after clicking `button`. The problem is that when clicking `newItemButton`, which is supposed to modify one of the Track objects that is already on the list, nothing is happening to that object visually. – gotramaval May 25 '16 at 12:17

1 Answers1

0

Finally I found the solution. The problem was on the way of referencing the object of the class Track were I wanted to place the view. The lines

 Track track = trackListAdapter.getItem(0);
        track = (Track) findViewById(R.id.view);

were indeed doing nothing as the first retrieved track was afterwards substituted by the content of the generic layout R.id.view. I found this nice piece of code here, which retrieves the view of an item in an specific position in a ListView.

  public View getViewByPosition(int pos, ListView listView) {
    final int firstListItemPosition = listView.getFirstVisiblePosition();
    final int lastListItemPosition = firstListItemPosition + listView.getChildCount() - 1;

    if (pos < firstListItemPosition || pos > lastListItemPosition) {
        return listView.getAdapter().getView(pos, null, listView);
    } else {
        final int childIndex = pos - firstListItemPosition;
        return listView.getChildAt(childIndex);
    }
}

Then the way to go in my case is:

        View view = trackListAdapter.getViewByPosition(trackNumber, trackListView);
        Track track = (Track) view.findViewById(R.id.view);

        track.addView(viewToAdd);

Then everything works as expected.

Community
  • 1
  • 1
gotramaval
  • 59
  • 7