2015-01-22 4 views
1

Я получаю некоторый контент из API, который мне нужно показать в приложении для Android. Содержание приходит в формате JSON, который выглядит примерно так:Динамическое создание нескольких Gridviews

{ 
    "items": [ 
    { 
     "catalog_items": [ 
     { 
      "date": "23-01-2015", 
      "content": "Trimmer 1 description", 
      "name": "Trimmer 1" 
     }, 
     { 
      "date": "25-01-2015", 
      "content": "Trimmer 2 description", 
      "name": "Trimmer 2" 
     } 
     ..... 
     ..... 
     ], 
     "item_category": "Trimmer" 
    }, 
    { 
     "catalog_items": [ 
     { 
      "date": "13-08-2014", 
      "content": "Shirt description here", 
      "name": "John Player Shirt" 
     } 
     ], 
     "item_category": "Shirts" 
    }, 
    { 
     "item_category": "Woolen" 
    } 
    ], 
    "pages": [ 
    { 
     "date": "24-01-2015", 
     "content": "This is some content about page 1", 
     "name": "Sample Page title 1" 
    }, 
    { 
     "date": "26-01-2015", 
     "content": "This is some content about page 2", 
     "name": "Sample Page title 2" 
    } 
    ] 
} 

я должен создать панель в приложение, которое строится в следующем порядке, на основании приведенных выше данных JSON:

Top Menu 
===================== 
Trimmers (Gridview) 

Trimmer1 Trimmer2 
Trimmer3 Trimmer4 

====================== 
Shirts (Gridview) 

John Players 

====================== 
Pages (Listview) 

Page1 
Page2 

Мои Фрагмент панели мониторинга извлекает этот JSON. Моя раскладка Приборная панель:

fragment_home.xml

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/relativeLayout1" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content"> 
</RelativeLayout> 

и My Dashboard активность выглядит следующим образом:

public class HomeFragment extends Fragment { 
    ..... 
    ..... 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 
     View rootView = inflater.inflate(R.layout.fragment_home, container, false); 
     try { 

      JSONObject obj = new JSONObject(loadJSONFromAsset("input.json")); 
      if(obj.has("catagories")) { 
       JSONArray catag = obj.getJSONArray("items"); 
       for(int i=0; i< catag.length();i++){ 
        JSONObject catitem = catag.getJSONObject(i); 
        JSONArray posts = catitem.getJSONArray("catalog_items"); 
        for(int j=0;j<posts.length();j++){ 
         JSONObject postitem = posts.getJSONObject(j); 
         catList.add(postitem.getString("name")); 
        } 

        addGridtoLayout(catitem.getString("item_category"),catList); 
       } 
      } 
     } catch (JSONException e){ 
      e.printStackTrace(); 
     } 

     return rootView; 

} 
    public void addGridtoLayout(String title, ArrayList<String> itemList) 
     { 
      RelativeLayout ll = new RelativeLayout(getActivity()); 
      RelativeLayout.LayoutParams parambs = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT); 
      ll.setLayoutParams(parambs); 


      TextView tv = new TextView(getActivity()); 
      tv.setText(title); 
      tv.setId(R.id.layout1); 

      RelativeLayout.LayoutParams lay = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); 
      ll.addView(tv, lay); 

      GridView gridView= new GridView(getActivity()); 
      gridView.setLayoutParams(new GridView.LayoutParams(GridLayout.LayoutParams.MATCH_PARENT, GridLayout.LayoutParams.MATCH_PARENT)); 
      gridView.setNumColumns(GRID_COL_NUM); 
      gridView.setAdapter(new HomeGridAdapter(getActivity(), itemList)); 
      RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT); 
      params.addRule(RelativeLayout.BELOW, tv.getId()); 
      ll.addView(gridView, params); 

      mainLayout.addView(ll); 
     } 

Это код только для элементов (GridView).

То, что я собираюсь, в основном обертывает каждый gridview и заголовок в режиме релятивирования. И относительные макеты будут отображаться ниже первого, начиная с первого элемента. Но gridviews складываются друг над другом, и все элементы отображаются в одной строке.

Есть ли какой-либо метод, поэтому я могу определить, какие релятивизаторы каждого вида сетки появятся ниже предыдущего? Кроме того, есть ли лучший подход к достижению этого? Я имею в виду, что основным требованием является генерация динамического числа gridviews. Так что генерировать макет «на лету» - это единственный способ сделать это?

Спасибо, что прочитали этот длинный пост.

+0

Вы пытаетесь использовать вертикальный LinearLayout? Я не уверен, что дать каждому gridview вес будет работать или нет. – jobcrazy

+0

@jobcrazy: Android всегда удивлял меня, когда я исследовал больше вариантов. «TableLayout» представляется вполне возможным в этом подходе. Я обновлю, как только получу желаемый макет. О вертикальной компоновке, я тоже попробую. Спасибо за предложение – ashutosh

ответ

2

Ну, как я уже упоминал в comment, я сделал слегка модифицированный код и работает действительно потрясающе. Поэтому я собираюсь уточнить, что я сделал. Может быть, это может помочь кому-то.

Поскольку я должен генерировать Gridviews с несколькими секциями, я изначально думал о создании таблиц с использованием TableLayout и добавлении к ним TableRows. Каждый TableRow будет проведение RelativeView буди: образ

  1. элемента (от JSON) имени
  2. элемента (из JSON)

Итак, я изначально создал этот код:

HomeFragment.java

public class HomeFragment extends Fragment { 
    ..... 
    ..... 

    ArrayList<String> itemList; 
    private JsonHelper jsonHelper; 
    private static final int GRID_COL_NUM = 3; 
    TableRow tbh; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { 

    View rootView = inflater.inflate(R.layout.fragment_home, container,false); 
    TableLayout table = (TableLayout) rootView.findViewById(R.id.tableLayout); 
    table.setStretchAllColumns(true); 
    table.setShrinkAllColumns(true); 

    try { 
     JSONObject obj = new JSONObject(loadJSONFromAsset("input.json")); 
     if(obj.has("catagories")) { 
      JSONArray catag = obj.getJSONArray("items"); 
      for(int i=0; i< catag.length();i++){ 
       JSONObject catitem = catag.getJSONObject(i); 
       JSONArray items = catitem.getJSONArray("catalog_items"); 
       if(items.length() > 0) { 
       //Add a Grid Title for this category (span=6, full width) 
       TableRow tbr = addRowTitle(catitem.getString("cat_name")); 
       table.addView(tbr); //Add this title row to the table 

       itemList = new ArrayList<>(); //Hold all items for each category 
       for(int j=0;j<items.length();j++){ 
        JSONObject singleItem = items.getJSONObject(j); 
        //I am trying to show only 3 items in a row, so add new row after 3 
        if(j % 3 == 0){ 
         tbh = addRowGrid(); //add new row and repeat so after 3 
         table.addView(tbh); //Add this to the table, we will fill items below 
        } 

        LinearLayout lnr = new LinearLayout(getActivity()); 
        TableRow.LayoutParams params = new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT,TableRow.LayoutParams.WRAP_CONTENT); 
        params.gravity = Gravity.CENTER; //Center the items 
        lnr.setLayoutParams(params); 
        lnr.setOrientation(LinearLayout.VERTICAL); //As per your need. worked for me 

        //Item's Image 
        ImageView itemImg = new ImageView(getActivity());       itemImg.setImageResource(R.drawable.ic_communities); //Default icon for item 


        TextView itemLabel = new TextView(getActivity()); 
        itemLabel.setText(singleItem.getString("name")); 
        itemLabel.setTypeface(Typeface.SERIF, Typeface.BOLD); 

        lnr.addView(postImg,params); 
        lnr.addView(postLabel,params); 
        tbh.addView(lnr); //Now we have image and content, wrap in linear layout and add to the row. 
        itemList.add(singleItem.getString("name")); //This step is not needed for now. I just wrote this to use this array for other purposes. 
        } 
     //I am all confused at this point if I have really closed all of curly braces. Please confirm 
       } 
      } 
     } 
    } catch (JSONException e){ 
      e.printStackTrace(); 
    } 

    return rootView; 

    } 

    public TableRow addRowGrid() 
    { 
     return new TableRow(getActivity()); 
    } 

    public TableRow addRowTitle(String titleb) 
    { 
     TableRow rowTitle = new TableRow(getActivity()); 
     rowTitle.setGravity(Gravity.CENTER_HORIZONTAL); 
     // title column/row 
     TextView title = new TextView(getActivity()); 
     title.setText(titleb); 

     title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); 
     title.setGravity(Gravity.CENTER); 
     title.setTypeface(Typeface.SERIF, Typeface.BOLD); 

     TableRow.LayoutParams params = new TableRow.LayoutParams(); 
     params.span = 6; 

     rowTitle.addView(title, params); 
     return rowTitle; 
    } 
... 
... 
} 

Весь этот код работает для одного макета таблицы, определенной в макете: fragment_home:

<?xml version="1.0" encoding="utf-8"?> 
<ScrollView 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/card_scrollview" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_alignParentBottom="true" 
    android:layout_alignParentTop="true"> 
<RelativeLayout 
    android:id="@+id/relativeLayout1" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content"> 

    <TableLayout 
     android:id="@+id/tableLayout" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:layout_alignParentTop="true" 
     android:layout_alignParentLeft="true" 
     android:layout_alignParentStart="true"></TableLayout> 

</RelativeLayout> 
</ScrollView> 

Таким образом, вся таблица генерируется на лету. Работала очень хорошо. Я могу прикрепить обработчик кликов к каждой строке для прослушивания, и мне, возможно, придется установить тег для каждого представления, чтобы получить щелкнутый элемент. Тогда я подумал о более целесообразном и гибком подходе. Что делать, если я добавляю gridview к каждой строке, а не добавляя LinearLayouts к каждому столбцу? Итак, я решил изменить мой код на этот подход: 1.Один TableRow будет содержать заголовок каждой категории, и к нему добавится второй Tablerow, который будет удерживать gridview. 2. Теперь я могу использовать пользовательский адаптер сетки, с помощью которого я мог бы лучше изменить макет каждого элемента, т. Е. Через XML вместо того, чтобы покалывать здесь «на лету». 3. Вышеуказанный пункт также получил меня кликер. Поэтому настройка метки не требуется.

ПРИМЕЧАНИЕ: Приведенный выше подход работал так же, как и ниже, работает тоже (как же). Таким образом, вы можете использовать как

Таким образом, создать функцию, которая бы добавить заголовок к каждой категории товара и функции для добавления элементов в сетку, и сетки в ряд:

HomeFragment.java (GridView версии)

public class HomeFragment extends Fragment { 

    private static final int GRID_COL_NUM = 3; 
    TableRow tbh; 

    public HomeFragment(){} 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 

     View rootView = inflater.inflate(R.layout.fragment_home, container, false); 
     TableLayout table = (TableLayout) rootView.findViewById(R.id.tableLayout); 
     table.setStretchAllColumns(true); 
     table.setShrinkAllColumns(true); 

     try { 

      JSONObject obj = new JSONObject(loadJSONFromAsset("input.json")); 
      if(obj.has("catagories")) { 
       JSONArray catag = obj.getJSONArray("catagories"); 
       for(int i=0; i< catag.length();i++) { 
        JSONObject catitem = catag.getJSONObject(i); 
        if (catitem.has("items")) { 
         JSONArray items = catitem.getJSONArray("catalog_items"); 
         if (items.length() > 0) { 
          //Add row with title catname 
          TableRow tbr = addRowTitle(catitem.getString("cat_name")); //Add category Name as title 
          table.addView(tbr); //Same I did previously 

          ArrayList<String> itemList = new ArrayList<>(); 
          for (int j = 0; j < items.length(); j++) { 
           JSONObject singleItem = posts.getJSONObject(j); 
           itemList.add(singleItem.getString("name")); 
          } 

          tbh = addGridRow(itemList); //Create Grid of collections and add it to a tablerow 
          table.addView(tbh); //Add this tablerow to table 
         } 
        } 
       } 
      } 
      if(obj.has("pages")) { 
       JSONArray pages = obj.getJSONArray("pages"); 
       if(pages.length() > 0) { 
        TableRow tbr = addRowTitle("Pages"); 
        table.addView(tbr); 

        ArrayList<String> pageList = new ArrayList<>(); 
        for (int i = 0; i < pages.length(); i++) { 
         JSONObject page = pages.getJSONObject(i); 
         pageList.add(page.getString("name")); 
        } 
        tbh = addGridRow(pageList); 
        table.addView(tbh); 
       } 
      } 
     } catch (JSONException e){ 
      e.printStackTrace(); 
     } 

     return rootView; 
    } 

/** 
* Now this is a life saver. Gridviews aren't friendly with scrollviews (I might be wrong, but happens with me everytime), especially if generated dynamically. Hence this function calculates height of each item of gridview dynamically and hence sets the total view height adapted from https://stackoverflow.com/a/22555947/1136491 
**/ 
    public void setGridViewHeightBasedOnChildren(GridView gridView, int columns) { 
     ListAdapter listAdapter = gridView.getAdapter(); 
     if (listAdapter == null) { 
      // pre-condition 
      return; 
     } 

     int totalHeight = 0; 
     int items = listAdapter.getCount(); 
     int rows = 0; 

     View listItem = listAdapter.getView(0, null, gridView); 
     listItem.measure(0, 0); 
     totalHeight = listItem.getMeasuredHeight(); 

     float x = 1; 
     if(items > columns){ 
      x = items/columns; 
      rows = (int) (x + 1); 
      totalHeight *= rows; 
     } 

     ViewGroup.LayoutParams params = gridView.getLayoutParams(); 
     params.height = totalHeight; 
     gridView.setLayoutParams(params); 

    } 

    public TableRow addGridRow(ArrayList gridItemList) 
    { 
     TableRow gridrow = new TableRow(getActivity()); 
     GridView gv = new GridView(getActivity()); 
     TableRow.LayoutParams params = new TableRow.LayoutParams(
       TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT); 
     gv.setLayoutParams(params); 
     gv.setNumColumns(GRID_COL_NUM); //3 columns grid 
     gv.setAdapter(new HomeGridAdapter(getActivity(), gridItemList)); //Custom grid adapter I was talking about. See Below 
     gridrow.addView(gv); 
//Thanks for not messing up my gridview inside scrollview 
     setGridViewHeightBasedOnChildren(gv,GRID_COL_NUM); //3 Columns 
     return gridrow; 
    } 

//Simply add title above the gridview 
    public TableRow addRowTitle(String titleb) 
    { 
     TableRow rowTitle = new TableRow(getActivity()); 
     rowTitle.setGravity(Gravity.CENTER_HORIZONTAL); 
     // title column/row 
     TextView title = new TextView(getActivity()); 
     title.setText(titleb); 

     title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); 
     title.setGravity(Gravity.CENTER); 
     title.setTypeface(Typeface.SERIF, Typeface.BOLD); 

     TableRow.LayoutParams params = new TableRow.LayoutParams(); 
     params.span = 6; 

     rowTitle.addView(title, params); 
     return rowTitle; 
    } 
.... 
} 

Теперь мой пользовательский адаптер HomeGridAdapter.java

public class HomeGridAdapter extends BaseAdapter { 
    ArrayList<String> result; 
    Context context; 

    private static LayoutInflater inflater=null; 
    public HomeGridAdapter(Context context, ArrayList<String> itemList) { 
     // TODO Auto-generated constructor stub 
     this.result=itemList; 
     this.context=context; 
     inflater = (LayoutInflater)context. 
       getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

    } 

    @Override 
    public int getCount() { 
     // TODO Auto-generated method stub 
     return result.size(); 
    } 

    @Override 
    public Object getItem(int position) { 
     // TODO Auto-generated method stub 
     return position; 
    } 

    @Override 
    public long getItemId(int position) { 
     // TODO Auto-generated method stub 
     return position; 
    } 

    public class Holder 
    { 
     TextView tv; 
     ImageView img; 
    } 
    @Override 
    public View getView(final int position, View convertView, ViewGroup parent) { 
     // TODO Auto-generated method stub 
     Holder holder=new Holder(); 
     View rowView; 
     //Layout mentioned below 
     rowView = inflater.inflate(R.layout.home_grid_layout, null); 
     holder.tv=(TextView) rowView.findViewById(R.id.textView1); 
     holder.img=(ImageView) rowView.findViewById(R.id.imageView1); 
     //Item's Text 
     holder.tv.setText(result.get(position)); 
     //Item's Image 
     holder.img.setImageResource(R.drawable.ic_launcher); 
     //A click listener to each gid item 
     rowView.setOnClickListener(new View.OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       // TODO Auto-generated method stub 
       Toast.makeText(context, "You Clicked "+result.get(position), Toast.LENGTH_SHORT).show(); 
      } 
     }); 

     return rowView; 
    } 

} 

home_grid_layout.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" > 

    <ImageView 
     android:id="@+id/imageView1" 
     android:layout_gravity="center" 
     android:layout_width="88dp" 
     android:layout_height="88dp" 
     android:layout_marginTop="5dp" 
     android:layout_marginBottom="5dp" 
     android:src="@drawable/ic_launcher" /> 

    <TextView 
     android:id="@+id/textView1" 
     android:layout_gravity="center" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:textSize="15dp" 
     android:layout_marginTop="5dp" 
     android:layout_marginBottom="5dp" 
     android:text="TextView" /> 

</LinearLayout> 

Так что я в настоящее время использую Gridview версию TableLayout. Я мог бы достичь того, чего хотел, но я действительно приветствовал бы любые предложения здесь. Надеюсь, что этот ответ кому-то поможет.

Благодарим вас за это долгое время.

Смежные вопросы