I am making an android app for diabetic patients. In that app I want to show the food item with their quantity for every meal for diet control. It should look somewhat like below:
RICE 100gm
POTATO 50gm
FISH 60gm
Those info will be obtained from my database dynamically. However I am facing problem arranging them. I want the food items to be aligned left and quantity aligned right of the screen. As below (dots denote the screen )
|-------------------------------------------------------|
|RICE 100gm |
|POTATO 50gm |
|FISH 60gm |
|-------------------------------------------------------|
To do that I have declared a relative Layout in xml file. The code looks as below :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</RelativeLayout>
</LinearLayout>
All I need to do now is to create textview and add them to this relative layout dynamically. But I am confused how to do that. Any hint please...
The final output should look something like below :
I would agree with #Szymon that the best way to do this is with a ListView. However, if you don't want to do that, here's how I would do it:
Create a separate layout for each item you want to display. Make it a RelativeLayout, and place all the TextViews there in accordance to how you want the items to be displayed (alignParentRight / alignParentLeft).
Dynamically create views by inflating this new layout, assign the text of the TextViews by using findViewById() on the views you inflate during runtime
Add the views to the LinearLayout
(EDIT: How to do Step 2:)
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.my_item_layout, null);
TextView tv1 = (TextView)view.findViewById(R.id.tv1);
tv1.setText(myText);
Related
how do i create a multiple row app with the same data for each row. This is how all the rows are to look like. it contains three text views and two spinners. this app is to help calculate the gpa of a student for one semester.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.mbedobe.android.samplegpacalculator.app.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="C1"
android:id="#+id/course_textView"/>
<Spinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/spinner"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/course_textView"
android:layout_toEndOf="#+id/course_textView"
android:layout_marginLeft="23dp"
android:layout_marginStart="23dp" />
<Spinner
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/spinner2"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/spinner"
android:layout_toEndOf="#+id/spinner"
android:layout_marginLeft="23dp"
android:layout_marginStart="23dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/spinner2"
android:layout_toEndOf="#+id/spinner2"
android:id="#+id/gradePoints"
android:layout_marginLeft="23dp"
android:layout_marginStart="23dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:layout_alignParentTop="true"
android:layout_toRightOf="#+id/gradePoints"
android:layout_toEndOf="#+id/gradePoints"
android:id="#+id/gradeValue"
android:layout_marginLeft="23dp"
android:layout_marginStart="23dp"/>
</RelativeLayout>
You should think about using a ListView with BaseAdapter.
The best solution is to use RecycleView
Use a RecyclerView with a custom adapter. The layout above will be the row layout for each row in this case.
Use the links above to understand how you can create your own Custom RecyclerView Adapters with Custom Layouts.
EDIT:
Ok, I'll give you the basics here. There are three major things you need for a custom RecyclerView.
They are:
List of Objects (your data)
A custom layout for each row
An Adapter that will transform your data onto the above layout.
Now, let's take an example and try and explain this.
You must have seen popular apps like Gmail, WhatsApp, etc.
When you open these apps, you see a list of Emails/Chats etc.
One thing to notice is that the layout for each row is same, even though the content inside them is different.
This tells us 2 things: first that the data must be a list of the same kind of objects, and secondly that the layout of each row is the same. So, to create such a listView or RecyclerView, we shouldn't need to create as many layouts as there are rows. One layout can be reused for each row.
So, two of our three needs are understood. The final item required is the Adapter. The adapter is what takes your List and converts each item from the list into a row on your RecyclerView. These rows are automatically created by the Adapter as the user scrolls through the list, and removed when the user can no longer see those rows.
If you want code for this, let me know. I'll upload code explaining this. But I would recommend you try it out on your own. It's not that hard.
Either use ListView, recyclerView or dynamically add the items in scrollview.
Use of ListView or RecyclerView will be the best approach for you.
I'll give you the last option that should be worked from java only if you are with good knowledged in java. ( only the steps not complete code)
1) your xml file should contain scroll view.
2) for each item to be added (3 textview 2 spinner), add a layout and provide layout params for it i.e width/height/orientation/background etc.
3)add this layout to the scrollview you created in xml by
findViewById(R.id.scrollviewId).add(layout)
4)create your textviews/spinners in and give them layout params.{ this process is much logical in a pattern of your design so must be very careful}
5)add all these textviews/spinners in the layout you created in step 3.
Note: according to your design requirements you might need to add other layouts in between the layout created in step 2/3 and other items created in step 4.
Here is the code you liked:
LinearLayout myLayout = (LinearLayout)findViewById(R.id.layout_in_xml);
for(int i = 0; i < required_fields.length; i++){
LinearLayout lr = new RelativeLayout(DisplaySadip.this);
LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lr.serLayoutParams(layoutParams);
lr.setOrientation(LinearLayout.HORIZONTAL);
//add linear layout to your layout in xml
myLayout.add(lr);
//add textview, spinner to this layout now
TextView tv1 = new TextView(YourActivity.this)
tv1.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
tv1.setText("......"+i);
lr1.add(tv1)
Spinner spinner1 = new Spinner(YourActivity.this)
spinner.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
Spinner spinner2 = new Spinner(YourActivity.this)
spinner.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
lr.add(spinner1);
lr.add(spinner2);
TextView tv2 = new TextView(YourActivity.this)
tv2.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
tv2.setText("......"+i);
lr.add(tv2)
TextView tv3 = new TextView(YourActivity.this)
tv3.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
tv3.setText("......"+i);
lr1.add(tv3)
}
it shall add add many no of views you want in your layout.
i've seen this question added on the stack but the information hasn't been helpful or successful yet, so i remain quite not sure.
The gist of what I'm trying to do:
I have a layout defined in xml, some_details_view.xml for example.
setContentView(R.layout.some_details_view);
It has a bunch of text views laid out using a parent relative layout, a linear header layout, a linear footer layout, a middle scroll layout that contains a relative layout that hold some label - value type of text views.
And at the bottom of the scroll view relative layout, I currently placed a frame layout as a place holder.
On create of the corresponding activity, I set text in respective text views with data handed over from previous activity; basic stuff.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/white" >
<LinearLayout
android:id="#+id/header"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true" >
...some header content
</LinearLayout>
<LinearLayout
android:id="#+id/footer"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="vertical" >
..some footer content
</LinearLayout>
<ScrollView
android:id="#+id/scroll"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#+id/footer"
android:layout_below="#+id/header"
android:layout_margin="5dip" >
<RelativeLayout
android:layout_width="fill_parent"
android:id="#+id/relativeScroll"
android:layout_height="wrap_content" >
...text views in relative layout
<FrameLayout
android:id="#+id/placeholder"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="#+id/moreInfoValue" />
</RelativeLayout>
</ScrollView>
</RelativeLayout>
After setting up text views for the given data, I use an async task to get some additional data that I want to show as a history list type of thing at the bottom of the static form layout. There could be 0 or more items so I either add 1 or more text views or none at all.
In the post execute, which I understand to run on the main UI thread, I try to find an exiting container Layout/view group and add either a new Linear Layout to which I add new text Views, or just add the new text views directly to the existing container layout.
here's the latest thing I tried:
ViewGroup mContainer = null; //defined as member variable of activity class and instatiated in on create
mContainer = (ViewGroup)findViewById(R.id.placeholder); //set in on create
LinearLayout ll = new LinearLayout(context); //on post execute of async task
ll.setOrientation(LinearLayout.VERTICAL);
mContainer.addView(ll); //add a new linear layout to an existing container layout
//add some new text view widgets items dynamically
for(NewDisplayItem item : items)
{
TextView tv = new TextView(context);
tv.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
tv.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
tv.setText(item.getSomeText());
ll.addView(tv); //add text view to new linear layout
}
When the UI loads I don't see new items added to my layout after stepping through and watching the controls get added using the code above.
Not sure what it is but something doesn't seem right about this approach in addition to the fact that it's not working. When the activity loads up, all the static views are setup and in view. I pop up a loading dialog, step through the async task stuff and I guess expect to see the dynamic controls add to the layout one by one?
First of all textView.setWidth(int) takes as parameter the width in pixels.
Second you should also set your layout parameters on the LinearLayout you are adding.
The way you should set LayoutParams is as follows :
ll.setLayoutParams(new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
the same for yout TextViews.
Ovidiu Latcu has a good answer. A good question is: is there a reason why you aren't using a ListView (which btw there ARE cases where what he's doing works better)? A ListView has a lot of mechanisms to help you keep from running out of RAM
I am trying to make an application that will have a set of screens that are similar in the fact that they will have a layout at the top, and at the bottom will have a set of buttons. Basically what happens is that one of the buttons at the bottom is a spinner, and each of the options that gets selected should inflate a layout into the top half of the screen, while leaving all of the buttons at the bottom.
What is the best way of going about this, without having to rewrite the part of the xml for the buttons at the bottom of the screen.
From the image above, I need the five buttons at the bottom to stay the same for all screens, while everything above it needs to be changed when one of the options is selected from the spinner.
My code currently is as follows: It currently puts up the buttons at the bottom, and the text in the red box, which will be on every screen. What I need to do is inflate the personal layout into the space in between.
setContentView(R.layout.people1);
if (v.getId() == R.id.service_user_button)
{
Spinner spinner = (Spinner) findViewById(R.id.people_spinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
getBaseContext(), R.array.service_user_array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
}
You want your layout to look something like this:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<ScrollView
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
>
<LinearLayout
android:id="#+id/theContent"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</ScrollView>
<!-- Buttons go inside this -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
At runtime you lookup the LinearLayout with the id 'theContent' and assign it's children to it.
You can also use the <include> tag. Check this explanation by Romain Guy.
There exists one more additional (not alternative!) possibility. The whole activity screen is always inserted into a FrameLayout. So, you can use as a root layout Merge instead of a root layout. The layout with buttons will have large top margin, so they will be placed at the bottom. Other layouts will be at the top, as they are. The theory is described here.
Of course, the common bottom layout should be placed into include.
Assumptions about the list (updated):
It will not contain more than 10 list elements (the list elements are defined by the xml layout below).
The height of every element is unknown, because the list element contain a LinearLayout that can have up to 20 child views (see xml below).
XML Layout of the list element:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation:"horizontal">
<!--
This LinearLayout is going to contain one or more
Views which will be added progammatically on runtime.
The number of children views added to it depend on the
data to be displayed, and the only assumption that can
be made is that there's will be no more than 20 child
views for one particular instance of this LinearLayout.
-->
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginRight="25dp"/>
<ImageButton
android:layout_width="25dip"
android:layout_height="25dip"
android:layout_gravity="center|top"
android:layout_marginLeft="-25dp"/>
</LinearLayout>
Questions:
Does it make any sense to use a ListView for a layout that has such freedom
in its structure (like the one above), and still being able to make use of the
convertView as passed in to the ListView#getView(...)?
As an alternative, would it be wrong to put all the list elements in an outer
LinearLayout and put this within a ScrollView? By doing this, I wouldn't get
caching abilities of the ListView, but maybe it wouldn't be so heavy given the
assumptions about the list? (see top). (Any pointers on how to make this alternative look and feel like a ListView? I'm thinking of applying standard colors and selectors etc.)
If you know some of your 10 elemets will be the same, you could use
getItemViewType(int position)
To be sure that the convertView will match your item type convertView
I am building something like a ListView, but I'm rolling my own because I want to do some custom stuff and have more control than using ArrayAdapters.
So I've defined part of my layout in XML, including one LinerLayout inside a ScrollView. My goal is to bind to that Linearlayout in code, then insert additional RelativeLayouts inside the LinearLayout using no XML, just code.
Here is my XML:
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/ListScroll"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:id="#+id/ListHolder"
android:layout_height="400px"
android:background="#323232"
>
<!--Here is where I want the RelativeLayouts to go... -->
</LinearLayout>
</ScrollView>
Then in code, I'm trying to add RelativeLayouts, each 50px in height, to the LinearLayout, the one above that has a height of 400px.
//The parent container - is defined above in XML.
itemContainer = new LinearLayout(context);
itemContainer = (LinearLayout)findViewById(R.id.ListHolder);
Layouts = new ArrayList<RelativeLayout>();
Layouts = LoadWithRelativeLayouts();
for(RelativeLayout listItem: Layouts){
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, 40);
listItem.setLayoutParams(params);
itemContainer.addView(listItem);
}
Each one of the layouts in the array has a text view in it that says "Test". When I step through the code, there are 10 elements in the array, and all of the textviews are there, so I would expect to see the 400px LinearLayout filled with 10 Relative layouts one after another, each with 50px height (and fill_parent width) reading "Test" - but all I see is one, as if only one got added, or they are all positioned on top of one another.
Getting screenshot now...
When you add something to a layout, you have to use layout params of that kind. So as you're adding to a LinearLayout, you should use LinearLayout.LayoutParams.
Then you'll probably also need to set your LinearLayout orientation to vertical, because right now the items you don't see are all in a row offscreen at the right :)
Try adding android:orientation="vertical" to the LinearLayout holding the RelativeLayouts.