I am trying to figure out how would you implement something like an Android Settings View for both phones and tablets? It doesn't look like a ListView or RecyclerView utilizing CardView? Which Android class or component would you use to implement/design a similar looking ListView?
Its sort of a 2 column layout on tablets and one column layout on phones:
Any sample code or tips would be appreciated.
You can accomplish this by using a combination of RecyclerView and CardView for the General settings (Ex: Wireless and networks or Device), then you can use a GridView inside each card to hold the specific settings (Ex: WiFi or Controller). Then to accomplish the two column trick, use resource qualifiers on an xml file containing an integer for the number of columns you want to display.
I'll give you an overview of the code.
You have an xml file like recycler_layout.xml that holds the frame for everything.
<?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.support.v7.widget.RecyclerView
android:id="#+id/friend_rv"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Then you have the frame for a card with a GridView inside of it.
<?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.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/settings_card">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Your General Setting Title"
android:id="#+id/textView3" />
<GridView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="#+id/setting_content"
android:numColumns="#integer/yourColumnInteger"/>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
Finally you have a file like myIntegers.xml that contains yourColumnInteger where you define the value to be 1 if the user is on a phone (i.e. their screen is X size) and 2 if the user is on a tablet (i.e. their screen is Y size which is bigger than X)
Then all you have to do is wire up all the adapters for the thing. You'll need an adapter that populates the cards and an adapter for the GridView that populates the specific settings. (And I assume you understand that you will probably need another xml layout for the frame that makes of the specific settings like the setting icon and name in a vertical linear layout)
Related
I'm developing an app, the have 100 buttons. And I want to put all the buttons inside the screen. I'm using a GridLayout with all the buttons inside the problem that I am having is that the buttons are getting out of the screen.
This is the code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:id="#+id/content_main"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".MainActivity"
tools:showIn="#layout/app_bar_main"
android:layout_column="1">
<GridLayout
android:id="#+id/GridLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:columnCount="6"
android:rowCount="17"
android:orientation="vertical">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
app:srcCompat="#drawable/numero_1"
android:id="#+id/button1"/>
The question that I have is: Is this possible to do? And this is the best approach?
I made other test where I changed the size of the image. The result is not what i expected header
Result with a different size image
As you can see in the second image the buttons in the rows are inside the screen but the position of the buttons is not ok, there are a lot of space between the last button of the row and the end of the screen.
The solution that I am looking for, is to have a layout that don't allow the buttons to get out of the screen, and that resizes the space between the buttons and the edges automatically, if the screen size is different the layout will automatically adapt to the size of the screen.
I don't think that is possible. I would suggest you to use 6 vertical LinearLayouts in one horizontal, with weight 1 on inner ones. I know that that is not most optimized way, but it's easiest. Another would be to keep GridLayout and calculate size of images and set their size from Java code.
I am creating a messaging app and am currently working on the inbox. I'm using a RecyclerView to display the list of conversations and would like each list item to look like this:
Leftmost is the contact image at 90dp x 90dp
The first row has two columns--the contact name and the date. The date should not be a fixed size as I currently have it, but fit at most DD/MM/YYYY (can be smaller in the case of something like "Sunday") and should be anchored to the right margin. The contact(s) should expand as necessary to fill any space up to the date.
The second row contains as much text of the last message as will fit.
I was going to use layout_weight but that doesn't work in a RelativeLayout (and doesn't allow the contact names to elongate in the case of a shorter date) and LinearLayout doesn't let me use layout_toEndOf. I'm a newbie at Android development so I'm not sure if one of those is the "right" answer.
What's the proper way of accomplishing the layout I'm looking for?
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="#+id/conversation_info"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="#dimen/activity_horizontal_margin">
<RelativeLayout
android:id="#+id/conversation_image_layout"
android:layout_width="90dp"
android:layout_height="90dp">
<ImageView
android:id="#+id/conversation_contact_image"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>
<TextView
android:id="#+id/conversation_contact_name"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/activity_vertical_margin"
android:gravity="center_vertical"
android:textSize="#dimen/conversations_contact_font_size"
android:layout_toEndOf="#id/conversation_image_layout" />
<TextView
android:id="#+id/conversation_date"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_toEndOf="#id/conversation_contact_name"
android:gravity="right"
android:paddingRight="#dimen/activity_horizontal_margin"
android:textSize="#dimen/conversations_date_font_size" />
<TextView
android:id="#+id/conversation_snippet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/conversation_contact_name"
android:textSize="#dimen/conversations_snippet_font_size"
android:layout_toRightOf="#id/conversation_image_layout" />
</RelativeLayout>
</LinearLayout>
This is what a list item currently looks like (I haven't loaded contact images yet). It's fine for the most part (though my layout code is probably incredibly bloated so I'd appreciate if anyone could point out ways to make it more concise) but notice how the date isn't on the same level as the contact name and wraps:
One of the textView in question has the MarginTop attribute, and the other one doesn't. Either remove it on both or add it to both:
<TextView
android:id="#+id/conversation_contact_name"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/activity_vertical_margin"
android:gravity="center_vertical"
android:textSize="#dimen/conversations_contact_font_size"
android:layout_toEndOf="#id/conversation_image_layout" />
<TextView
android:id="#+id/conversation_date"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_toEndOf="#id/conversation_contact_name"
android:gravity="right"
android:layout_marginTop="#dimen/activity_vertical_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:textSize="#dimen/conversations_date_font_size" />
Also, I'd recommend that you use Linear Layouts with nested Linear Layouts and weights, for better performance on different screens and devices. This may all fall apart if you run it on a different device. Don't trust me, try it :)
After it became clear to me that some of the layout parameters didn't mean what I thought they did, I spent some more time looking at my choices.
It is not recommended to nest LinearLayouts/use layout_weight within a list item, as the number of views created increases rapidly as more items are added. I managed to minify my code and keep it in a single RelativeLayout with the following code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/conversation_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/activity_horizontal_margin">
<ImageView
android:id="#+id/conversation_contact_image"
android:layout_width="64dp"
android:layout_height="64dp"/>
<TextView
android:id="#+id/conversation_contact_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="#dimen/conversations_contact_font_size"
android:layout_toEndOf="#id/conversation_contact_image"/>
<TextView
android:id="#+id/conversation_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignBaseline="#id/conversation_contact_name"
android:textSize="#dimen/conversations_date_font_size"/>
<TextView
android:id="#+id/conversation_snippet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/conversation_contact_name"
android:textSize="#dimen/conversations_snippet_font_size"
android:layout_toEndOf="#id/conversation_contact_image"/>
</RelativeLayout>
Notable changes:
No nested tags - It was unnecessary to group the first line in its own layout
Used layout_alignBaseline - #Vucko pointed out that I was using marginTop on the contact name but not the date. Even after removing it, the two were still misaligned. android:gravity had no effect and it turns out none of these actually affect the text inside the layout
Used layout_alignParentEnd to fix the date issue. I've realized that in my case, a layout component usually only needs to reference one other in order to properly align itself relative to the rest of the layout.
I am thinking to create a layout whose height is much more than the screen height. OK say, the parent layout is LinearLayout and it is set to provide a vertical scrollbar automatically.
Inside the parent layout, there are many controls (listview, gridview, listboxes, editboxes etc). To make it easier for design, can I put listview in one xml, gridview in one xml, listbox in one, editbox in one etc and then later use some defined function to concatenate and allocate them all in the parent layout ?
If this is not possible, how can I design a layout that has many controls allocated that design screen can't fit at design time ?
xml_common.xml
code:
<?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="#dimen/common_topheader_width"
android:background="#drawable/topheaderfor9patch" >
<ImageView
android:id="#+id/xml_common_header_imageLogotop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="2dp"
android:layout_marginRight="#dimen/common_left_right_margin"
android:src="#drawable/qarrow" />
</RelativeLayout>
///////////////////////////////////////////
Main_view.xml
Code:
<?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:background="#drawable/mainbg"
android:orientation="vertical" >
<include layout="#layout/xml_common" />
</LinearLayout>
you can set different images as per your choice set in runtime of common view.
So far, my app is pretty simplistic and small. It has a few buttons here and there, but I can see it quickly getting out of hands with a ton of buttons. So my problem really, my activity_main.xml looks ridiculously ugly. It has a bunch of tags, so I was wondering, what's the "correct" way to generate buttons when you have a lot of these?
Use XML do define views. I would always recommend you to use xml, even if there are 20 Buttons.
Alternativly you can also set the button programmatically in code and at them to your layout. Just set the layout parameters and you are done.
Otherwise (if you have a list of many buttons and you need to scroll) a ListView or GridView would a good choice.
To make things cleaner in your XML, you can use include to reference other XML which defines a generic button with all its common properties.
So the button would be defined under genericbutton.xml placed in the layout folder:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onClick" />
</merge>
And then your main activity_main.xml will have something like this for three buttons:
<?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" >
<include
android:id="#+id/button1"
layout="#layout/genericbutton" />
<include
android:id="#+id/button2"
layout="#layout/genericbutton" />
<include
android:id="#+id/button3"
layout="#layout/genericbutton" />
</LinearLayout>
But in this case, you either set the same text for the buttons inside the genericbutton.xml or one by one in Java code. You cannot set it in the include tags.
My situation is following. I have one Activity that contains three main parts. At the top of this activity there is an tools panel with two ImageButtons. At the bottom of the activity there is also tools panel similar to top. Main component of this activity is at the center of the screen which is LinearLayout that contains 3x3 ImageButtons grid. To get the context I quickly describe purpose of these grid buttons. This 3x3 grid describes states of this buttons (lets say toggle button and its states are on/off) for particular day. So for one day you have one set of 3x3 and these have its own state for particular day.Now what I trying to achieve is to have functionality which allows user to scroll between grids or dates respectively. My idea is to have ViewFlipper as the main component of the activity (instead of LinearLayout) and one or more grid of buttons. This is what I already have. I am able to switch 3x3 to another 3x3 (with states) for another day. For this I simply copy/paste my 3x3 grid XML definition and put this as children to view flipper (x-times).My idea is to have one definition of 3x3 and reuse it x-times like some kind of template so I will be able to say "I want to have another 3x3 with so and so states for this day and I want it to add this as next child to ViewFlipper".For this purpose (to have component of 3x3) I simply made class which extends LinearLayour and within it I want to generate/reuse 3x3 definition for buttons. Sure I am able to do it by java code in this new class but is some way to do it with reusing of xml (which is better to maintain and to read)?I tried to use LayoutInflater but this is probably not what I am looking for.
Thanks in advance
Edit
Here is code for main layout with flipper
<ViewFlipper android:id="#+id/view_flip"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#FF0000">
<!-- Here goes 9x9 cubbie layout programaticaly -->
</ViewFlipper>
To this fipper I adding view with this layout (this code is assigned via LayoutInflater).
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#color/background" android:orientation="vertical"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:layout_weight="1">
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_weight="1" android:gravity="center">
<LinearLayout android:layout_width="wrap_content"
android:layout_height="wrap_content" android:orientation="vertical">
<ImageButton android:id="#+id/life_att_1" style="#style/AttributeButton" />
<TextView android:id="#+id/life_att_text_1" android:text="test"
style="#style/AttributeText" />
</LinearLayout>
...
</LinearLayout>
...
</LinearLayout>
EDIT 2
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#color/background" android:orientation="vertical"
android:layout_width="wrap_content" android:layout_height="fill_parent"
android:layout_weight="1" android:paddingLeft="16dip">
Only way I found here is to add paddingLeft attribute to wrapper LinearLayout (please refer to EDIT 2). I do not think that this is right solution but only solution I currently found.