Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android : Putting Grid of dynamic&custom objects inside another Grid of dynamic&custom objects

I am working on an Android project in which I am using the 'SuperSlim' framework for creating a grid view of Notes(Custom class) along with data to be displayed. Notes in the Database have a many-to-one relationship with Sections(Custom class). And Sections in turn have many-to-one relationship with Canvas.

All information for section, notes is dynamically retrieved from server as a List.

Now I am at the point, where I am able to display a Grid view of Sections, and put text information in the Grid like Section-name, etc. For testing, purposes, I also inserted statically retrieved text from a note. I am new to Android programming, so please don't mind if the code looks messed up.

Now these are the problems I am facing :

1) How to display a Grid of Sections and within each section displayed, I would like to display a Grid of Notes. As there is one-to-many relationship, there can be many Notes per section. This is my primary problem.

2) With displaying the above stuff, I would like to keep the SectionName field editable, and I have a REST method with which I can edit the Section-name, but I require the section-id as well. It is available on click, I would like to maintain that.

3) The Grid of Notes displayed within a Section should be clickable, so I can later open something similar to Modal, so user can read the entire note and edit it.

The below screenshot indicates my current situation :

Screenshot The left side mobile was the original how List of Grid Sections should look like. I modified it, to display more information, just for testing, and using SuperSlim to add information a bit more properly.

Please note, currently in the code, I am statically calling the NotesList method for a hardcoded Section. This is not desired. Finally code :

GroupSectionActivity :

public class GroupSectionActivity extends ActionBarActivity {

    private SectionServiceImpl sectionService = new SectionServiceImpl();

    private static volatile List<RestSection> restSectionList = new ArrayList<>();

    private static volatile Long groupAccountId;

    private static volatile Integer canvasid;

    static final String msectionname = "msectionname";
    static final String msectionid = "msectionid";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_section_activity);

        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            groupAccountId = extras.getLong("groupid");
            canvasid = extras.getInt("canvasid");
        }

        if(savedInstanceState == null){
            getFragmentManager().beginTransaction().add(R.id.container, new NoteFragments(), "msectionname").commit();
        }

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        if(toolbar!=null){
            setSupportActionBar(toolbar);
        }

        restSectionList = this.sectionService.getSectionByCanvas(canvasid);

        ArrayList<HashMap<String, String>> restSectionArrayList = new ArrayList<HashMap<String, String>>();
        for (RestSection restSection : restSectionList) {

            HashMap<String, String> sectionDisplay = new HashMap<>();
            sectionDisplay.put("msectionid", String.valueOf(restSection.getMsectionid()));
            sectionDisplay.put("msectionname", restSection.getMsectionname());
            restSectionArrayList.add(sectionDisplay);
        }

       /* listView = (ListView) findViewById(R.id.seclist);

        sectionLazyAdapter = new SectionLazyAdapter(this, restSectionArrayList);

        listView.setAdapter(sectionLazyAdapter);

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                                    int position, long id) {
                int sectionId = restSectionList.get(position).getMsectionid();
                Log.d("Sectionid is ", String.valueOf(sectionId));
                *//*Intent intent = new Intent(GroupSectionActivity.this, GroupSectionActivity.class);
                intent.putExtra("groupid", groupAccountId);
                intent.putExtra("sectionid", sectionId);
                startActivity(intent);
                finish();*//*

            }
        });

        addSectionButton = (Button) findViewById(R.id.sectionAddButton);
        addSectionButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int val = addGroupSection();
                if (val == 0) {
                    sectionName.setError("Section Name cannot be null");
                } else {
                    sectionName.clearComposingText();
                    sectionName.clearAnimation();
                    sectionName.setText("");
                    Toast.makeText(getApplicationContext(), "Section added", Toast.LENGTH_LONG).show();
                }
            }
        });*/

    }

    public Integer addGroupSection(){
    /*    sectionName = (EditText) findViewById(R.id.sectionNameTextField);
        if (!(sectionName.getText().toString().isEmpty())) {
            RestSection restSection = new RestSection();
            restSection.setMsectionname(sectionName.getText().toString());
            return this.sectionService.addGroupSection(restSection,canvasid);
        }
*/
        return 0;
    }

    @Override
    public void onBackPressed() {
        Intent intent = new Intent(GroupSectionActivity.this, GroupCanvasActivity.class);
        intent.putExtra("groupid", groupAccountId);
        startActivity(intent);
        finish();
    }

    private NoteFragments getSectionsFragment() {
        return (NoteFragments) getFragmentManager().findFragmentByTag(msectionname);
    }
}

SectionLazyAdapter :

public class SectionLazyAdapter extends BaseAdapter{

    private Activity activity;
    private ArrayList<HashMap<String, String>> data;
    private static LayoutInflater inflater=null;

    public SectionLazyAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
        activity = a;
        data=d;
        inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    public int getCount() {
        return data.size();
    }

    public Object getItem(int position) {
        return position;
    }

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

    public View getView(int position, View convertView, ViewGroup parent) {
        View vi=convertView;
        if(convertView==null)
            vi = inflater.inflate(R.layout.activity_group_section, null);

        TextView sectionName = (TextView)vi.findViewById(R.id.sectionname); // title
        HashMap<String, String> sectionList = new HashMap<String, String>();
        sectionList = data.get(position);

        sectionName.setText(sectionList.get(GroupSectionActivity.msectionname));

         return vi;
    }
}

NoteAdapters :

public class NoteAdapters extends RecyclerView.Adapter<NoteViewHolder> {

    private NoteServiceImpl noteService = new NoteServiceImpl();

    private static final int LINEAR = 0;

    private final Context mContext;

    private SectionServiceImpl sectionService = new SectionServiceImpl();

    List<RestSection> restSectionList = new ArrayList<>();


    private final ArrayList<LineItem> mItems;

    public NoteAdapters(Context context, int headermode) {
        mContext = context;

        int sectionManager = -1;

        int sectionFirstPosition = 0;

        mItems = new ArrayList<>();

        restSectionList = this.sectionService.getSectionByCanvas(2500);

        for (int i = 0; i < restSectionList.size(); i++) {
            String header = restSectionList.get(i).getMsectionname();
            RestNote restNote = this.noteService.getFirstNoteForSection(restSectionList.get(i).getMsectionid());
            mItems.add(new LineItem(header, true, sectionManager, sectionFirstPosition, restNote.getMnotetext()));

        }
    }

    @Override
    public NoteViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view;
        view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_group_section, parent, false);
        return new NoteViewHolder(view);
    }

    @Override
    public void onBindViewHolder(NoteViewHolder holder, int position) {
        final LineItem item = mItems.get(position);
        final View itemView = holder.itemView;
        holder.bindText(item.text);
        holder.bindNoteData(item.otherText);
        final GridSLM.LayoutParams lp = GridSLM.LayoutParams.from(itemView.getLayoutParams());

        lp.setSlm(item.sectionManager == LINEAR ? LinearSLM.ID : GridSLM.ID);
        lp.setColumnWidth(mContext.getResources().getDimensionPixelSize(R.dimen.grid_column_width));
        lp.setFirstPosition(item.sectionFirstPosition);
        itemView.setLayoutParams(lp);
    }

    @Override
    public int getItemCount() {
        return mItems.size();
    }

   /* @Override
    public void onClick(View v) {
        if(v instanceof ImageView){
            Log.d("Image","Clicked");
        } else {
            Log.d("Text","Clicked");
        }
    }*/

    private static class LineItem {

        public int sectionManager;

        public int sectionFirstPosition;

        public boolean isHeader;

        public String text;

        public String otherText;

        public LineItem(String text, boolean isHeader, int sectionManager,
                        int sectionFirstPosition, String otherText) {
            this.isHeader = isHeader;
            this.text = text;
            this.sectionManager = sectionManager;
            this.sectionFirstPosition = sectionFirstPosition;
            this.otherText = otherText;
        }
    }
}

NoteFragments :

public class NoteFragments extends Fragment {

    private ViewHolder mViews;

    private NoteAdapters noteAdapters;

    private int mHeaderDisplay;

    private boolean mAreMarginsFixed;

    private Random mRng = new Random();

    private Toast mToast = null;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.section_fragment, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mViews = new ViewHolder(view);
        mViews.initViews(new LayoutManager(getActivity()));
        noteAdapters = new NoteAdapters(getActivity(), mHeaderDisplay);
        mViews.setAdapter(noteAdapters);
    }

    @Override
    public void onSaveInstanceState(Bundle outState){
        super.onSaveInstanceState(outState);
    }

    private static class ViewHolder {

        private final RecyclerView mRecyclerView;

        public ViewHolder(View view) {
            mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
        }

        public void initViews(LayoutManager lm) {
            mRecyclerView.setLayoutManager(lm);
        }

        public void scrollToPosition(int position) {
            mRecyclerView.scrollToPosition(position);
        }

        public void setAdapter(RecyclerView.Adapter<?> adapter) {
            mRecyclerView.setAdapter(adapter);
        }

        public void smoothScrollToPosition(int position) {
            mRecyclerView.smoothScrollToPosition(position);
        }
    }

}

NoteViewHolder :

public class NoteViewHolder extends RecyclerView.ViewHolder {

    private TextView textView;
    private TextView noteData;
    private ImageView imageView;

    public NoteViewHolder(View itemView) {
        super(itemView);
        textView = (TextView) itemView.findViewById(R.id.sectionname);
        imageView = (ImageView) itemView.findViewById(R.id.sectionimage);
        noteData = (TextView) itemView.findViewById(R.id.noteText);
    }

    public void bindText(String text){
        textView.setText(text);
    }

    public void bindImage(Bitmap bitmap){
        imageView.setImageBitmap(bitmap);
    }

    public void bindNoteData(String data){
        noteData.setText(data);
    }
}

XML Files : activity_group_section.xml :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="5dip" >

    <FrameLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="15dp"
        android:orientation="vertical">
        <ImageView
            android:id="@+id/sectionimage"
            android:layout_width="140dp"
            android:layout_height="200dp"
            android:scaleType="fitXY"
            android:padding="5dp"
            android:src="@drawable/sectionbackground"
            />

        <TextView
            android:id="@+id/sectionname"
            android:layout_width="90dp"
            android:layout_height="match_parent"
            android:text="@string/textView"
            android:visibility="visible"
            android:gravity="center"
            android:layout_gravity="center_horizontal|top"
            android:maxLines="1"
            android:ellipsize="end"
            android:scrollHorizontally="true"
            android:layout_marginTop="10dp" />

        <TextView
            android:layout_width="97dp"
            android:layout_height="160dp"
            android:id="@+id/noteText"
            android:layout_gravity="center_horizontal|bottom"
            android:layout_marginBottom="10dp"
            android:layout_marginTop="30dp" />
    </FrameLayout>
</RelativeLayout>

SectionFragment :

<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/recycler_view"
    android:scrollbars="vertical"
    android:layout_width="match_parent"
    android:clipToPadding="false"
    android:layout_height="wrap_content" />

Model classes for Section and Notes :

public class RestSection {

    private int msectionid;

    private String msectionname;

    private int mxposition;

    private int myposition;

    private int msectionwidth;

    private int msectionheight;
}
public class RestNote {

    private int mnoticesid;

    private String mnotetext;

    private String mnotetag;

    private String mnotecolor;

    private double mnoteorder;
}

I hope my question is clear, if there is anything required, kindly let me know.

like image 317
We are Borg Avatar asked Aug 13 '15 08:08

We are Borg


People also ask

Is GridLayout deprecated?

GridLayout is also not deprecated.

What can I use instead of grid layout in Android?

Some of the most commonly used layouts are LinearLayout, Constraint Layout, RelativeLayout, and GridLayout. Suppose you need to display the elements linearly, whether horizontally or vertically; you can use LinearLayout.


1 Answers

You are actually quite close to your implementation but there are a few things to note. Your top-level grid is set up for using ListView/GridView Adapters while your 2nd level grid is set up for RecyclerView.Adapters. All this is well and good once you know what you're doing. However, I would recommend using one or the other all the way through (preferably RecyclerView.Adapters as these are more scalable). To keep things simple, though, I will give the solution using your current setup:

Top-level (BaseAdapter/ListAdapter + GridView)

You should be passing in your entire data-set to the top-level adapter, e.g. ArrayList of RestSection instead of ArrayList of HashMap. HashMap could be a member of RestSection if this data is needed but it seems as though this can be replaced by a simple string. The RestSection data-structure should also have a member that is a list of RestNotes. The item-view for this adapter should have a RecyclerView, which is inside NoteFragment in your case. This will potentially replace noteText in activity_group_section.xml. In the getView() of your adapter, you should be setting the adapter of this RecyclerView with the notes belonging to the section. See the following code snippets for details.

Data Structures:

public class RestSection {
    private int msectionid;
    private String msectionname;
    private int mxposition;
    private int myposition;
    private int msectionwidth;
    private int msectionheight;

    private List<RestNote> mnotes;
}

public class RestNote {
    private int mnoticesid;
    private String mnotetext;
    private String mnotetag;
    private String mnotecolor;
    private double mnoteorder;
}

SectionLazyAdapter:

public class SectionLazyAdapter extends BaseAdapter{
    private List<RestSection> data;

    //... 

    public View getView(int position, View convertView, ViewGroup parent) {
        View vi=convertView;
        if(convertView==null)
            vi = inflater.inflate(R.layout.activity_group_section, null);

        RestSection mySection = data.get(position);

        TextView sectionName = (TextView)vi.findViewById(R.id.sectionname); // title
        sectionName.setText(mySection.getSectionName());

        NoteFragments noteGridView = (NoteFragments) vi.findViewById(R.id.notegridfragment);
        noteGridView.setRecyclerViewAdapter(new NoteAdapter(mySection.getNotes()));
        return vi;
    }
}

activity_group_section.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="5dip" >

    <FrameLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="15dp"
        android:orientation="vertical">
        <ImageView
            android:id="@+id/sectionimage"
            android:layout_width="140dp"
            android:layout_height="200dp"
            android:scaleType="fitXY"
            android:padding="5dp"
            android:src="@drawable/sectionbackground"
            />

        <TextView
            android:id="@+id/sectionname"
            android:layout_width="90dp"
            android:layout_height="match_parent"
            android:text="@string/textView"
            android:visibility="visible"
            android:gravity="center"
            android:layout_gravity="center_horizontal|top"
            android:maxLines="1"
            android:ellipsize="end"
            android:scrollHorizontally="true"
            android:layout_marginTop="10dp" />
        <fragment android:name="com.mypackagename.NoteFragments"
            android:layout_width="97dp"
            android:layout_height="160dp"
            android:id="@+id/notegridfragment"
            android:layout_gravity="center_horizontal|bottom"
            android:layout_marginBottom="10dp"
            android:layout_marginTop="30dp" />
    </FrameLayout>
</RelativeLayout>

2nd-level (RecyclerView.Adapter + RecyclerView)

This adapter should take a list of Notes as it's data-set (as shown in SectionLazyAdapter above). Use the Note data to populate the UI as before. See code snippets below.

NoteFragments:

public class NoteFragments extends Fragment {
    private RecyclerView noteGridView;
    // ...

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        // as before
        noteGridView = (RecyclerView) view;
    }

    public void setRecyclerViewAdapter(NoteAdapter adapter){
        noteGridView.setAdapter(adapter);
    }
}

NoteAdapter:

public class NoteAdapters extends RecyclerView.Adapter<NoteViewHolder> {
    private List<RestNote> mItems;

    public NoteAdapters(List<RestNote> notes) {
        super();

        mItems = notes;
    }

    @Override
    public void onBindViewHolder(NoteViewHolder holder, int position) {
        // populate as before... make sure that RestNote has all of the data required
    }
}

You will of course have to reorder your data to the required format but I think it will be easier to display the data in this way.

I hope that this helps.

like image 191
J. Beck Avatar answered Oct 13 '22 08:10

J. Beck