I am trying to put a custom listView into a scrollView and when I scroll down and up I lose the top items in the listView which are a TextView and a CheckBox for some reason.
Here's my code:
activity_program.xml
<?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="vertical" >
<TextView
android:id="#+id/tv_program_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.10"
android:text="Program name"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/tv_program_info"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_weight="0.20"
android:text="program info, talk abt sets, reps, weight etc..." />
<ListView
android:id="#+id/android:list"
android:layout_width="match_parent"
android:layout_height="395dp" >
</ListView>
<Button
android:id="#+id/bt_savework"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.10"
android:text="Save Workout" />
</LinearLayout>
My custom listView contains these:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp" >
<TextView
android:id="#+id/tv_exercice_title"
android:layout_width="270dp"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/cb_exercicedone"
android:layout_alignParentTop="true"
android:gravity="center_vertical"
android:text="Exercice title"
android:textAppearance="?android:attr/textAppearanceMedium" />
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_below="#+id/tv_exercice_title"
android:orientation="horizontal" >
<CheckBox
android:id="#+id/cb_setdone"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="7dp"
android:text="Set" />
<TextView
android:id="#+id/tv_set_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="3dp"
android:text="1" />
<TextView
android:id="#+id/tv_reps"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:text="Reps x" />
<EditText
android:id="#+id/et_reps_number"
android:layout_width="47dp"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="number" />
<TextView
android:id="#+id/tv_weight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:text="Weight" />
<EditText
android:id="#+id/et_weight_number"
android:layout_width="65dp"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="number" />
<TextView
android:id="#+id/tv_kgorlbs"
android:layout_width="59dp"
android:layout_height="wrap_content"
android:text="kg/lbs"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<CheckBox
android:id="#+id/cb_exercicedone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignRight="#+id/linearLayout1" />
</RelativeLayout>
In my ListActivity I use a custom adapter to fill the ListView with the above template and only edit the tv_set_number (for now) then set the tv_exercice_title's visibility to "gone" to add more sets.
If you think the problem could be in my java code let me know in the comment and I will post it.
Please tell me what's the problem.
Here's some screenshots:
Before I scroll:
image 1
After I scroll:
image 2
Seems to me you are using the ListView to generate different kinds of rows and you're missing some steps. You could also consider to rethink the structure, as maybe this would better fit into a ExpandableListView: from the screenshots you post seems like you'd have a set of rows that hierarchically belong to a group view.
The ExpandableListView would fit this purpose, and also allow to collapse/expand the groups. I'd take a look at it, it's really easy, you'd only have to make the adapter descend from ExpandableListViewAdapter and provide methods to obtain the Group views (Your title & checkbox) and the item views (the sets with reps, weight, etc...)
If, on the contrary, you want to make it with a ListView, there are some issues to care about (I'll call TITLE ROWS to those with the title & checkbox, and regular rows to the regular ones)
What is happening now is, when you create a view and this view is not a TITLE ROW, you are setting the visibility of the title to GONE. But if you scroll, ie., DOWN and a TITLE row has to appear from the upper edge, the View you are given to recycle is the one that just left the screen by the lower edge, that was probably a REGULAR ROW. So in getView() you not only have to set Visibility to GONE for regular rows, but also back to VISIBLE for Title Rows. Google an explanation on how View recycling works for ListView and you'll understand it right away.
ListView provides a mechanism to help in these cases: The View Types:
You declare 2 "row types" overriding getViewTypeCount() and getItemViewType(int position) in your adapter. Type 0 will be TITLE ROWS, and Type 1 would be REGULAR ROWS.
In getView / convertView you'll generate / reuse the 2 different views separately based on the type.
.
#Override
public int getViewTypeCount() {
return 2; // you have 2 different types
}
#Override
public int getItemViewType(int position) {
if (position IS A TITLE ROW) return 0; else return 1;
}
... and then in getView() {
if (getItemViewType(position) == 0) {
// it's a TITLE ROW, create / reuse it accordingly
} else {
// it's a REGULAR ROW, create / reuse it accordingly
}
This has the advantage that ListView does some of the dirty work for you, so you'll be given the correct view type to recycle.
Related
I want the width of the cell to change depending on the length of the inner text.
Currently, width = 160dp is fixed, but
If I put wrapcontent
As you can see, each cell is set according to the length of the data, even if they correspond to the same column.
The number of rows can be changed, but the number of columns is 4.
I want to go through all data content in that column and set the width of that column to fit the longest text in that column.
RecyclerViewitem.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="160dp"
android:layout_height="match_parent"
android:text=""
android:padding="3dp"
android:id="#+id/tv_po"
android:textStyle="bold"
android:gravity="center" />
<TextView
android:layout_width="160dp"
android:layout_height="match_parent"
android:text=""
android:padding="3dp"
android:id="#+id/tv_qty"
android:textStyle="bold"
android:gravity="center" />
<TextView
android:layout_width="160dp"
android:layout_height="match_parent"
android:text=""
android:padding="3dp"
android:id="#+id/tv_material"
android:textStyle="bold"
android:gravity="center" />
<TextView
android:layout_width="350dp"
android:layout_height="match_parent"
android:text=""
android:padding="3dp"
android:id="#+id/tv_info"
android:textStyle="bold"
android:gravity="center" />
</LinearLayout>
</LinearLayout>
I'm not sure you're going to want to do that, the RV adapter loads one View at a time until the RecyclerView is full. Every time a bigger View gets loaded by the adapter all the existing Views would need to be redrawn. Then if the largest view gets removed from the screen you would need to refresh all the views to match the new existing view. This will use a lot of resources to continuously reload the images and could cause the app to freeze. But If you are really keen on setting this up check out the following question.
How to set textview height for the largest string in android recyclerview?
You can use Chips(Material Design) for your requirement.
https://material.io/components/chips/android#using-chips
I am creating a chatting app in Android.
I was able to create the normal text chat list view with the following as the list item layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/chat_msg_view"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"/>
<TextView
android:id="#+id/msg_send_time"
android:layout_width="250dp"
android:layout_height="20dp"
android:layout_below="#+id/chat_msg_view"
android:layout_margin="2dp"
android:paddingTop="2dp"
android:textColor="#android:color/holo_blue_dark" />
<TextView
android:id="#+id/msg_status"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_below="#+id/msg_send_time"
android:layout_margin="2dp"
android:paddingTop="2dp"
android:textColor="#android:color/holo_blue_dark" />
</RelativeLayout>
But now i am trying to send images as well via chat. So now i need to replace the first TextView in the above layout to ImageView if content being sent is IMAGE.
What is a good approach to do this.
There are lots of approaches you can use. If you are using a list view adapter you can use itemType to change the entire list item layout (good if you are changing the entire layout, but can be a bit complicated) or you can place an image view at the same location in your layout as the text view and show or hide which ever one you are using. I.E. If showing image, show the image view and hide the text view, if you are showing the text view, show the text and hide the image. Then you don't need to insert/remove views at run time, which is a little more complicated.
Your layout might look a bit like this...
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/chat_msg_view"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"/>
<ImageView
android:id="#+id/chat_image_view"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:visibility="gone"/>
<TextView
android:id="#+id/msg_send_time"
android:layout_width="250dp"
android:layout_height="20dp"
android:layout_below="#+id/chat_msg_view"
android:layout_margin="2dp"
android:paddingTop="2dp"
android:textColor="#android:color/holo_blue_dark" />
<TextView
android:id="#+id/msg_status"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_below="#+id/msg_send_time"
android:layout_margin="2dp"
android:paddingTop="2dp"
android:textColor="#android:color/holo_blue_dark" />
</RelativeLayout>
Notice how chat_image_view is also aligned to parent left.. it will be on top of the text view, but it has visibility "gone" so you wont see it.
Hope this helps, good luck.
I am just starting to develop android apps. I have a layout question. I want to create the main screen for my app. It is a menu with 7 options, each options would be an icon at the left, a short text and a check at the left (on/off component).
I have written it in a list view element, I have created a simple adapter with this layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView android:id="#+id/icon"
android:layout_width="?android:attr/listPreferredItemHeight"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:src="#drawable/ic_action_io"/>
<TextView android:id="#+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/icon"
android:layout_alignParentTop="true"
android:textAppearance="?android:attr/textAppearanceLarge"
android:singleLine="true" />
</RelativeLayout>
Menu will have always 7 options, I would like that the listview filled the height of the screen. Each element with the same height. Is it possible that with listview? Or, perhaps would be better making the menu out of a list view?
I have been reading about linear layout and the weight property. Please, could you help me? It is my first layout, I would thank any advice aboput layout I should use.
Thanks a lot, best regards!
P.D: Sorry for my english.
I would use a Linearlayout and inside i put all the items to be displayed...
Something like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<RelativeLayout android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
<ImageView android:id="#+id/icon"
android:layout_width="?android:attr/listPreferredItemHeight"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:src="#drawable/ic_launcher"/>
<TextView android:id="#+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/icon"
android:layout_alignParentTop="true"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Texto"
android:singleLine="true" />
</RelativeLayout>
<RelativeLayout android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
<ImageView android:id="#+id/icon"
android:layout_width="?android:attr/listPreferredItemHeight"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:src="#drawable/ic_launcher"/>
<TextView android:id="#+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/icon"
android:layout_alignParentTop="true"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Texto"
android:singleLine="true" />
</RelativeLayout>
<!-- Repeat the item five times more -->
</LinearLayout>
if you want all the items to be displayed (without a scroll) then there's no use in a ListView. use a LinearLayout instead and set the layout_weight of each menu item to 1.
As the others guys said is better use the LinearLayout. And like you mentioned you can use weight attribute too.
Equally weighted children
To create a linear layout in which each child uses the same amount of space on the screen, set the android:layout_height of each view to "0dp" (for a vertical layout) or the android:layout_width of each view to "0dp" (for a horizontal layout). Then set the android:layout_weight of each view to "1".
As you are trying to implement a Menu, I think the best approach is substitute each RelativeLayout(with textview and imageview) for a button. So, your layout will be like that:
<?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"
android:weightSum="7.0" > //Defines the maximum weight sum
<Button
android:id="#+id/button1"
android:layout_width="match_parent"
android:height="0dp"
android:layout_weight="1"
android:text="Option 1"
android:drawableLeft="#drawable/icon1"
android:onClick="handleOption"/> // method to handle onClick
<Button
android:id="#+id/button2"
android:layout_width="match_parent"
android:height="0dp"
android:layout_weight="1"
android:text="Option 2"
android:drawableLeft="#drawable/icon2"
android:onClick="handleOption"/> // method to handle onClick
//Add more five buttons
.
.
.
In your activity, you should load this layout, using setContentView() and you must implement a method handleOption like below to handle onClick event of each button.
public view handleOption(View view)
{
switch(view.getId()) ....
}
In that way, you do not need implement onClickListener Interface, have one method to each button and set the onClickListener for each button.
I am trying a task that should probably be simple..I want one button at the bottom across the bottom of the screen (floating preferably), while I have a scrollable list above that (I was able to do this in a tutorial with a simple listview and buitton).But, my list is a LinearLayout that I fill with a SimpleCursorAdapter and a viewBinder. Since I am using this LinearLayout I keep getting One button per line item, instead of one at the bottom of the screen. I have tried wrapping it with a table layout, relative layout, using two LinearLayouts, etc. Every time I get one button per line. Is this because of the way I am getting the data with a cursor adapter and filling it into the listview? Do I need to use a "merge" in my xml file? Is there a way to make two xml files and then call them both? Do I need to switch to a ListView or another way of displaying the data? This is my first app that I am trying start to finish on my own, so some of this stuff trips me up. I will include my code for the LinearLayout, please note that this is just the list without my extra button added (i deleted all my failed attempts). So I would be looking to modify the code below to contain one button that floats at the bottom of the screen all the time.
<LinearLayout android:id="#+id/LinearLayout01"
android:layout_width="290dp"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:hapticFeedbackEnabled="true">
<Button
android:id="#+id/BtnToClick"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="myClickHandler"
android:drawableLeft="#+drawable/android_button"
android:gravity="left|center_vertical"
android:background="#android:color/transparent"
android:hapticFeedbackEnabled="true"
android:layout_weight=".1">
</Button>
<TextView android:text=""
android:id="#+id/tvViewRow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone">
</TextView>
<TextView android:text="#+id/text11"
android:id="#+id/text11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone">
</TextView>
<TextView
android:id="#+id/text5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="3dip"
android:gravity="left|center_vertical"
android:layout_weight=".20"/>
<TextView
android:id="#+id/text9"
android:layout_column="5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="3dip"
android:gravity="center|center_vertical"
android:layout_weight=".1"/>
<TextView
android:id="#+id/text10"
android:layout_column="6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="3dip"
android:gravity="left|center_vertical"
android:layout_weight=".15"/>
<TextView
android:id="#+id/text12"
android:layout_column="8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:padding="3dip"
android:gravity="left|center_vertical" />
<Button
android:id="#+id/BtnToClick2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="myClickHandler3"
android:gravity="center|center_vertical"
android:background="#+drawable/coup0a"
android:hapticFeedbackEnabled="true"
>
</Button>
Thanks in advance!
-Joe
You need to add the button as a footer or a header according to your needs. You can try this code .The R.layout.header and footer are separate xml layout files which you would have to define.
View header = inflater.inflate(R.layout.header,null);
View footer = inflater.inflate(R.layout.footer,null);
addHeaderView(header);
addFooterView(footer);
You should absolutely use a listview for this job. Listviews are highly optimized for displaying many entries. Just let your activity extend from a ListActivity and create a layout xml file with a listview widget that has the id "#android:id/list" and the listview activity will hook onto that list automatically. You are free to place other widgets in the layout aswell. Here is an example layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
<Button
android:id="#+id/chooseOther"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/add_fav"/>
</LinearLayout>
It has a list with a button sitting on the bottom of the screen at all times, even if you have a long list of items.
I have this ListView whose items i'd like to hide depending on the selection of a RadioGroup. Currently I'm passing a boolean to the ListAdapter due to the RadioGroup having only two options. My items contain a checkbox and i want to either show the entire list or just the ones with the check boxes checked. I'm succeeding at hiding the items but the dividers still show, how can i fix this?
Look how it looks like
http://www.mediafire.com/i/?wa2s0ngq027vjwr
http://www.mediafire.com/i/?9i6ggj2fdsns2da
(I'm new, so i can't upload images here)
The xml for my row would be:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:padding="1dip" android:gravity="center_vertical"
android:background="#FFF">
<CheckBox android:id="#+id/dispositivo_tv"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:textColor="#000000" android:textSize="15dip"
android:layout_alignParentLeft="true" />
<LinearLayout android:id="#+id/botones"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:layout_alignParentRight="true" android:gravity="center_vertical">
<ImageButton android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="#+id/button_foto"
android:src="#drawable/camera" android:background="#FFF"
android:paddingRight="15dip" android:visibility="invisible"></ImageButton>
<ImageButton android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="#+id/button_comentario"
android:src="#drawable/comment_add" android:background="#FFF"
android:paddingRight="15dip"></ImageButton>
</LinearLayout>
</RelativeLayout>
and the xml block for the ListView would be:
<LinearLayout android:layout_width="fill_parent"
android:layout_height="fill_parent" android:orientation="horizontal"
android:padding="5dip" android:background="#layout/list_box">
<ListView android:id="#android:id/list" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:cacheColorHint="#00000000"
android:headerDividersEnabled="false" android:footerDividersEnabled="false
</ListView>
</LinearLayout>
and what i use to hide the row when the boolean i told you about is set FALSE is:
wrapper.getDispositivo().setVisibility(View.GONE);
wrapper.getFoto().setVisibility(View.GONE);
wrapper.getComentario().setVisibility(View.GONE);
PS: wrapper is the instance of the class where i have all the elements of the row, i.e. the checkbox (getDispositivo()), and a couple of image buttons (getFoto(), getComentario())
Thanks in advance...
How about using custom dividers in your relative layout and setDivider(null); so once you hide the layout the dividers are hidden as well. I wanted to actually add this as a comment. But it comes only after 50 reps so had to put it as a answer.