Android : Putting Grid of dynamic&custom objects inside another Grid of dynamic&custom objects
Asked Answered
S

1

14

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.

Smiley answered 13/8, 2015 at 8:36 Comment(0)
N
1

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.

Nyhagen answered 18/10, 2015 at 21:40 Comment(1)
I will try it out and give you a reply. Thanks for the information. Please note it will take some time.Smiley

© 2022 - 2024 — McMap. All rights reserved.