1. Download our Official Android App: Forums for Android!

Apps Structuring an app with dynamic content

Discussion in 'Android Development' started by Brian Gentry, Apr 2, 2016.

  1. Brian Gentry

    Brian Gentry Lurker
    Thread Starter
    Rank:
    None
    Points:
    5
    Posts:
    4
    Joined:
    Apr 2, 2016

    Apr 2, 2016
    4
    0
    5
    Male
    I'm trying to learn about Android programming and I've given myself an assignment. I've got a working version that's maybe 70% complete and I'm struggling to go further. I think I have a problem with how I've laid out my program.

    The program is a counter. Just an on screen set of buttons and a display that let you count up by one or down by one. Or clear the counter. Pretty simple stuff. However, I want to allow the user to have more than one counter on screen at a time. Any amount that they want actually.

    So I created a mainactivity.java and a Counter.java . In the Counter.java I have a Counter class. This class contains all of the data and methods of a counter object. It also builds it's own View and adds the buttons, fields, etc. So the display and the data are encapsulated into the class itself.

    Mainactivity instantiates a Counter object on start up. When the user presses the "new counter" button, Mainactivity instantiates another counter object and adds it to the ArrayList that keeps track of all of the counters. With me so far? Good. :)

    After Mainactivity instantiates a Counter, it calls Counter.getLayout(). This returns a LinearLayout object which contains all of the Counter's buttons, etc. MainActivity then stuffs that Layout into the main layout on the main screen. So each new counter appears below the last one.

    BTW, Counter class also creates it's own button listener functions, etc. Amazingly this all works. I can build new counters and they all operate independently.

    The issues I'm running into are making buttons that will affect each counter, like Delete and Edit. If I build these buttons inside of the counter class, then I need some weird way to get MainActivity to be called when the buttons are pushed, because delete needs to actually remove the counter object, and it was instantiated from Mainactivity. So a button listener inside of Counter won't be able to do the job of removing that counter object and it's Layout.

    My workaround right now is that I build a wrapper layout inside of Mainactvity that wraps around the counter's layout. That wrapper has the delete button on it and mainactivity operates on that button, via it's listener, directly. This is ugly and feels WAY wrong.

    All of this is starting to tell me that I shouldn't be building the GUI objects inside of the Counter class. I guess I need to build the GUI display for each counter object inside of Mainactivity and then use some sort of data structure to keep track of both the Counter object, and the layout that displays that counter's data, contains it's buttons, button listeners, etc.

    I hope this all makes some sense. I'd very much appreciate advice on how to properly structure this.

    Thanks for reading.

    Brian.
     

    Advertisement

  2. LV426

    LV426 I say we take off and nuke this place from orbit
    Recognized Developer
    Rank:
     #12
    Points:
    1,988
    Posts:
    9,176
    Joined:
    Oct 16, 2015

    Oct 16, 2015
    9,176
    13,681
    1,988
    Male
    Software developer
    South West of England
    Clearly you've put a great deal of thought into this, which is super. Nice ideas about the encapsulation. All good stuff.

    There is an ideal feature of the Android SDK which allows you to construct dynamic UI layouts, and that is Fragments.
    The way I would approach this is to create a Counter fragment, which encapsulates all the UI layout and logic. At runtime you are able to instantiate any number of these Fragments, as needed. I urge you to check out some of the many tutorials and examples of their use.
     
  3. Brian Gentry

    Brian Gentry Lurker
    Thread Starter
    Rank:
    None
    Points:
    5
    Posts:
    4
    Joined:
    Apr 2, 2016

    Apr 2, 2016
    4
    0
    5
    Male
    I've done "Bucky's Tutorial" on Fragments. I understood about 90% of it. The main thing that hung me up was fragment communication using "Implements".

    I guess I should seek out another tutorial and see if I can understand it more fully.

    Thanks,

    Brian.
     
  4. Brian Gentry

    Brian Gentry Lurker
    Thread Starter
    Rank:
    None
    Points:
    5
    Posts:
    4
    Joined:
    Apr 2, 2016

    Apr 2, 2016
    4
    0
    5
    Male
    Ok, I've done a good bit of research and playing around with Fragments and I have some more understanding.

    I just a wrote a quick proof of concept with one fragment and one activity. Activity adds 3 instances of fragment to the fragment transaction manager. Then all 3 fragments show up on screen. So far so good.

    I should mention that I created the fragment layout with XML (as opposed to pure Java layout). Now, to create a listener for the button inside the Fragment:

    MyFragment.java
    Code (Text):
    1.  
    2. button = (Button) getActivity().findViewById(R.id.plus_button);
    3. button.setOnClickListener(
    4.         new Button.OnClickListener() {
    5.             public void onClick(View v) {
    6.                 b1_clicked();
    7.             }
    8.         }
    9. );
    10.  
    This works... but only for the first fragment! Which actually makes sense in some way right? I've defined a static XML layout, and then I'm referencing the ID of the button inside that layout (R.id.plus_button) . The button on the first fragment does it's job. The buttons on the 2nd and 3rd Fragments are "dead" and do nothing.

    So I'm left wondering if I can apply an XML layout to a Fragment that I'm going to instantiate more than one time on the same activity screen. My instinct is that I can't, and I need to go back to dynamically creating the GUI layout objects inside the Fragment class. Which kinda sucks, but I've done it before so...

    It would just be REALLY cool if I could do the layout in XML, yet still be able to instantiate the Fragment many times and have the button listeners work.

    What do you guys think?

    Thanks,

    Brian.
     
  5. LV426

    LV426 I say we take off and nuke this place from orbit
    Recognized Developer
    Rank:
     #12
    Points:
    1,988
    Posts:
    9,176
    Joined:
    Oct 16, 2015

    Oct 16, 2015
    9,176
    13,681
    1,988
    Male
    Software developer
    South West of England
    I think you are attaching the listener at the wrong point.
    This code

    Code (Text):
    1.  
    2. button = (Button) getActivity().findViewById(R.id.plus_button);
    3.  
    finds the first button in the Activity view, which matches the id R.id.plus_button of the first Fragment. This explains why the other buttons are dead - because they have no listener.

    What you want to do is find the Button matching that id within each Fragment view, and attach the onClick listener.
    In fact all I think you need to do is just omit the call to getActivity() in your MyFragment class:

    Code (Text):
    1.  
    2. button = (Button) findViewById(R.id.plus_button);
    3. button.setOnClickListener(
    4.         new Button.OnClickListener() {
    5.             public void onClick(View v) {
    6.                 b1_clicked();
    7.             }
    8.         }
    9. );
    10.  

    Edit: This guy is doing exactly what you want

    http://stackoverflow.com/questions/12536125/findviewbyid-within-fragment
     
  6. Brian Gentry

    Brian Gentry Lurker
    Thread Starter
    Rank:
    None
    Points:
    5
    Posts:
    4
    Joined:
    Apr 2, 2016

    Apr 2, 2016
    4
    0
    5
    Male
    Wow! Your words, plus the info at the link got me kicked off in the right direction. It works. :)

    The keys were:

    1. In the Fragment I had to save a reference to the View that I returned in OnCreateView:

    Code (Text):
    1.  
    2. public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    3.     fview = inflater.inflate(R.layout.counter_frag, container, false);
    4.     return fview;
    5. }
    6.  
    2. Now that I have a reference to the fragment's unique view, I need to use *that* instead of getActivity(). Like this:

    Code (Text):
    1.  
    2. plusbutton = (Button) fview.findViewById(R.id.plus_button);
    3. plusbutton.setOnClickListener(
    4.         new Button.OnClickListener() {
    5.             public void onClick(View v) {
    6.                 b1_clicked();
    7.             }
    8.         }
    9. );
    10.  
    Well that was simple. I feel like I've learned a little more about how views are used with Fragments now. Thank you!

    Android is really complicated with all of the Activity, View, Context, Fragment, etc... As a beginner it's hard to keep track of what is what. Experiences like this move my understanding along. :)

    Thanks again.

    Brian.
     

Share This Page

Loading...