0

Is it possible to create a ListView where each row in the list is a unique layout (you do not know the layout structure because it is dynamically generated at run time)?

edit:

So my rows might be something like:

  1. [---][-------][--][----------------]
  2. [-------][----------][-------------]
  3. [-][-------][----------][----------]

and so forth (assume the right side is aligned). Each one will most likely be unique. I know ListView assumes that the structure of the recycled view is the same as each row item but is there any way to use a Listview for dynamically created rows?

public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        ViewHolder holder = null;

        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.guide_program_row, null);
            holder = new ViewHolder();
            holder.programRow = (LinearLayout)convertView.findViewById(R.id.program_row);

            Log.i(TAG, "New Row; position = " + position);
        }
        else {
            Log.i(TAG, "Cached Row; position = " + position);
            holder = (ViewHolder)convertView.getTag();
        }

        holder.programRow.addView(buildRow(programLengths));

        return convertView;
    }       

static class ViewHolder {
    LinearLayout programRow;
}

public LinearLayout buildRow(int [] programLengthRow) {
    Display display = getWindowManager().getDefaultDisplay();
    int screenWidth = display.getWidth();
    int screenHeight = display.getHeight();

    int programCellWidth = screenWidth / 5;
    int programCellHeight = (int)(screenHeight * 0.6 / 9);
    int timeLeft = maxTimes;

    LinearLayout programRow = new LinearLayout(getApplicationContext());

    for (int j = 0; j < maxTimes; j++) {
        if (timeLeft <= 0)
            break;       

        Movie movie = movieList.get(j);
        LinearLayout programCell = (LinearLayout)mInflater.inflate(R.layout.guide_program_cell, null);
        TextView programText = (TextView)programCell.findViewById(R.id.program_cell_text);

        if (programLengthRow[j] > timeLeft) {
            programCell.setLayoutParams(new LinearLayout.LayoutParams(programCellWidth * timeLeft, programCellHeight));
            programText.setText(movie.title + " >>");
        }
        else {
            programCell.setLayoutParams(new LinearLayout.LayoutParams(programCellWidth * programLengthRow[j], programCellHeight));
            programText.setText(movie.title);
        }


        timeLeft = timeLeft - programLengthRow[j];
        programRow.addView(programCell);
    }

    return programRow;
}
Android Noob
  • 491
  • 2
  • 7
  • 10
  • i would answer that yes, you can, but where are you stuck? do you have a listadapter that provides your listview with the row views? – njzk2 Aug 09 '11 at 16:10

1 Answers1

1

Yes. Please see this question as it relates. It basically says:

getViewTypeCount() - this methods returns information how many types of rows do you have in your list

getItemViewType(int position) - returns information which layout type you should use based on position

And it has a link to a tutorial for more help.

Community
  • 1
  • 1
Jack
  • 9,156
  • 4
  • 50
  • 75
  • These assume that you know the layouts in advance right? Right now, I do not create the rows in an XML file. Each row contains a huge number of TextView cells of varying length (like in an EPG) and you don't know the length ahead of time. – Android Noob Aug 09 '11 at 16:19
  • This should be able to be applied to dynamically created views as you want. Basically just replace any getViewById(id) instances with your custom built dynamic view. – Jack Aug 09 '11 at 16:59
  • Also, each row is a LinearLayout and inside the LinearLayout is a variable number of TextViews of varying length (see edit in original question). – Android Noob Aug 09 '11 at 17:11
  • Can you describe more precisely what you are trying to accomplish? Do you just need each row to have 1, 2, or 3 items depending on some condition? – Jack Aug 09 '11 at 17:21
  • I guess my next question is .... what is wrong with your code specifically? It seems as if what you are doing would work fine. – Jack Aug 09 '11 at 17:47
  • It starts to garbage collect like crazy when I scroll down too far and thus cause the user to experience "hiccups" in the UI. – Android Noob Aug 09 '11 at 17:52
  • HMM I might've stumbled upon a fix!! I added holder.programRows.removeAllViews() before the holder.programRows.addView() statement and it doesn't stutter anymore when I scroll too far. If I'm reading the ddms right, I can see that it garbage collects often but the listview doesn't use more memory (stays at 8% free whereas before, it would go down to 2%, then 1%). – Android Noob Aug 09 '11 at 17:59
  • Now what if I have huge rows :( ? – Android Noob Aug 09 '11 at 18:01
  • You should limit the size of your rows somehow. – Jack Aug 09 '11 at 18:53
  • About what I said before..the removeAllViews() method was not a good idea since it triggers the GC constantly. The GC churn was not noticeable when the rows were small, but after increasing the size, it was pretty bad. Still looking for some kind of solution involving recycling. There are only 2 apps on the Android market I've seen that implement a grid-style EPG -- Foxtel and Comcast Xfinity. The former uses a free scrolling grid but consumes so much memory that it hiccups; the latter has some kind of ListView + Horizontal ScrollView thing going on with View recycling. – Android Noob Aug 09 '11 at 21:12
  • I'm trying to aim for the Xfinity implementation, specifically their View recycling mechanism, but I can't really figure out how they managed to do it. – Android Noob Aug 09 '11 at 21:14