Ну, как я уже упоминал в comment, я сделал слегка модифицированный код и работает действительно потрясающе. Поэтому я собираюсь уточнить, что я сделал. Может быть, это может помочь кому-то.
Поскольку я должен генерировать Gridviews с несколькими секциями, я изначально думал о создании таблиц с использованием TableLayout и добавлении к ним TableRows. Каждый TableRow будет проведение RelativeView буди: образ
- элемента (от JSON) имени
- элемента (из 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. Я мог бы достичь того, чего хотел, но я действительно приветствовал бы любые предложения здесь. Надеюсь, что этот ответ кому-то поможет.
Благодарим вас за это долгое время.
Вы пытаетесь использовать вертикальный LinearLayout? Я не уверен, что дать каждому gridview вес будет работать или нет. – jobcrazy
@jobcrazy: Android всегда удивлял меня, когда я исследовал больше вариантов. «TableLayout» представляется вполне возможным в этом подходе. Я обновлю, как только получу желаемый макет. О вертикальной компоновке, я тоже попробую. Спасибо за предложение – ashutosh