I have a list of timetable-events and would like to lay them out as in the image.
You can ignore the backgroundgrid as I will not use one.
Every event in the timetable has a start- and endtime. The height of the item in the view is related to the duration of the event. The list is observed with LiveData so changes to the timetable need to update the screen.
I considered the following approaches:
a) Using a recyclerView. Unfortunatly this either lays out the items from left to right and scrolls vertically or lays them out vertically but scrolls horizontally. I basicly need vertical layout, jumping to the next column when necessary with vertical scrolling.
b) using a gridlayout (not gridview) and spanning items over rows. Drawback is that all items need to be a multiple of a single row. This assumes all events have a duration which is a multiple of a minimum time. I can use 1 or 5 minutes as that minimum duration, but it would result in a lot of rows. Furthermore I am not sure about updating the screen, the scrolling and if this is memory efficient.
c) using a parent scroll-layout with five vertical lineairlayouts. Programmatically adding the items to the corresponding lineairlayout with the right heigth. This adds all the viewitems to the layout even if they are not visible on screen. I can forget about LiveData updates I guess.
Is there another option I have overlooked? Or can I use a recyclerView anyway? How do I do that?
P.S. I am still using Java but started to learn Kotlin
You can use Android Week View
Android Week View is an android library to display calendars (week view or day view) within the app. It supports custom styling.
Features
Week view calendar
Day view calendar
Custom styling
Horizontal and vertical scrolling
Infinite horizontal scrolling
Live preview of custom styling in xml preview window
Add below dependencies
implementation 'com.github.alamkanak:android-week-view:1.2.6'
WeekView in your xml layout.
<com.alamkanak.weekview.WeekView
android:id="#+id/weekView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:eventTextColor="#android:color/white"
app:textSize="12sp"
app:hourHeight="60dp"
app:headerColumnPadding="8dp"
app:headerColumnTextColor="#8f000000"
app:headerRowPadding="12dp"
app:columnGap="8dp"
app:noOfVisibleDays="3"
app:headerRowBackgroundColor="#ffefefef"
app:dayBackgroundColor="#05000000"
app:todayBackgroundColor="#1848adff"
app:headerColumnBackground="#ffffffff"/>
You can use tableLayout.
Example -
<TableLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:shrinkColumns="*" android:stretchColumns="*"
android:background="#ffffff">
<TableRow
android:id="#+id/tableRow1"
android:layout_height="wrap_content"
android:layout_width="match_parent">
<TextView
android:id="#+id/TextView04"
android:text="Row 2 column 1"
android:layout_weight="1" android:background="#dcdcdc"
android:textColor="#000000"
android:padding="20dip"
android:gravity="center"/>
<TextView
android:id="#+id/TextView04"
android:text="Row 2 column 2"
android:layout_weight="1" android:background="#d3d3d3"
android:textColor="#000000"
android:padding="20dip"
android:gravity="center"/>
<TextView
android:id="#+id/TextView04"
android:text="Row 2 column 3"
android:layout_weight="1" android:background="#cac9c9"
android:textColor="#000000"
android:padding="20dip"
android:gravity="center"/>
</TableRow>
For tutorials refer-
https://androidexample.com/Table_Layout_-_Android_Example/index.php?view=article_discription&aid=74
May be you can achieve this using FlexboxLayout.
Google flexbox-layout
I did not find an appropiate library or layout so I ended up writing my own view, calculating in onDraw the position of every appointment. It was not as hard as it sounds.
Related
I'm confused. I want to show the map and on below of map show 5 buttons. I use RelativeLayout, but the program just show Product button. Why? I'm confused which layout i use (Linear,Relative,Frame or absolute )!! Please help me. and How can i correct this code?
location.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/frame"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.google.android.maps.MapView
android:id="#+id/mapView"
android:apiKey="0cPRv243zM1_S3ydsNg8MJP9_6BfCp642jOhPvQ"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/background"
android:layout_gravity="bottom"
android:orientation="horizontal" >
<Button
android:id="#+id/button_home"
style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTop="#drawable/home_icon"
android:text="#string/button_home"
android:textColor="#color/text_home" />
<Button
android:id="#+id/button_product"
style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTop="#drawable/product_icon"
android:onClick="Product"
android:text="#string/button_product"
android:textColor="#color/text_product" />
</LinearLayout>
</LinearLayout>
To answer your specific problem: Instead of saying that the home button is to the left of the product button, you should say that the product button is to the right of the home button. When a RelativeLayout is inflated, the layout is parsed in a linear way so if view A it positioned relative to view B, view B must come first.
<Button
android:id="#+id/button_home"
style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTop="#drawable/home_icon"
android:text="#string/button_home"
android:textColor="#color/text_home"/>
<Button
android:id="#+id/button_product"
style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/button_home"
android:drawableTop="#drawable/product_icon"
android:onClick="Product"
android:text="#string/button_product"
android:textColor="#color/text_product" />
Add this to the product button and delete the layout_toLeftOf from the home button.
android:layout_toRightOf="#id/button_home"
You can use gravity and alignment to position the home button and then have the other four buttons following it, each one positioned to the right of the one before it.
Good luck
RelativeLayout by default places these 2 buttons together, so you can just see the latter.
And the line
android:layout_toLeftOf="#+id/button_product"
is wrong. #+id creates an id, use #id in such cases.
I would recommend LinearLayout for the situation. Place these buttons in it, and adjust them with some margin.
LinearLayout : LinearLayout is used when we need to arrange the
widgets/views in a horizontal or vertical manner.
The direction of arrangement can be set to horizontal or vertical,
by default it is being horizontal.
TableLayout : If the Layout's widgets/views need to be arranged
in the form of rows and columns, we use this layout object.
This is similar to html tables. The cells can span columns.
The TableLayout do not display its border. We can be made to
shrink and stretch by setting the respective properties of the columns,
"TableRow" is another helper widget which should be used in conjunction
with the TableLayout.
RelativeLayout : Here the position of each of the widgets/view is
in relative/dependent to each other. For example, when a layout is needed
such that it has a text view just to the left of an Edit Textbox, and a button
just below the EditText. The relation between the views are taken care in
one iteration, hence if view B’s position is dependent on view A’s position,
view A must come first in the layout.
FrameLayout : This is a very simply layout which is used to hold a section
of the screen blank, for displaying an item or group of items at run time. All the
elements added in the framelayout will be added to the top left of the screen.
AbsoluteLayout : When there is a need is to specify exact x and y co-ordinate
position of the view, then AbsoluteLayout need to be used. This layout is
difficult to maintain.
I want some tips in how to complete one task.
We got three EditTexts, a button and a llistview.
The idea here is when the button is pressed, the texts from the three EditTexts will be show in a listview, side by side, giving the impression that we got a table here.
The problem here is I don't know how to do it. I've tried to search something on the net, but I just got nothing.
I'd really appreciate if you could help.
Thaks for the attention and have a nice day.
There are a couple ways to achieve what you want. If I'm understanding correctly you have a listview and a button. When you click the button, you want 3 editTexts to appear in your listview side by side so that it looks like a table.
The simplest solution is have your list item layout, inflated in your listadapter, simply be a linearlayout with weightSum="3" containing 3 edittexts with layout_weight="1" and layout_width="0dp"
so your list_item.xml would look something like:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="3">
<EditText android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:visibility="invisible"/>
<EditText android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:visibility="invisible"/>
<EditText android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:visibility="invisible"/>
</LinearLayout>
Then, in the onClick for your button, iterate through the children of the list row and set the visibilities to visible.
As for adding rows dynamically, use a listadapter and a collection and use the notifydatasetchanged to update the list when your collection gains/loses items.
I have a listview.
The list items must be populated using code and in the following pattern
The odd numbered list items must be placed aligned with the left side of the screen.
The even numbered list items must be place aligned with the right side of the screen.
The width must depend on the size of the content.
These task must be performed using code.
<LinearLayout android:id="#+id/list_item"
android:paddingLeft="5dip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical" >
<TextView android:id="#+id/text_view"
android:autoLink="all"
android:paddingTop="6dip"
android:paddingBottom="3dip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:linksClickable="false"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#ff000000"
android:textSize="18sp" />
</LinearLayout>
note:i use cursor adapter to bind the data with listview
You must see Google I/O 2010 - The world of ListView to understand how ListView works.
For your situation in getView(...) method of your list adapter you could add something like this:
if(position%2==0){
//even
convertView.setGravity(Gravity.RIGHT);
} else{
//odd
convertView.setGravity(Gravity.LEFT);
}
In order to set width dependency on content change all "layout_width properties" to "wrap_content" in your xml above.
Also it would be useful to read ListView Tips & Tricks post series.
Hope I've got the question correctly.
I'm trying to layout views in a relative layout on a tablet, much like a bookshelf. There will be so many across, then a new row is created.
My initial state looks like this:
<ScrollView
android:layout_marginTop="150sp"
android:layout_marginLeft="50sp"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<RelativeLayout
android:id="#+id/user_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<!-- Add User Avatar -->
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="#drawable/user_frame" />
<ImageView
android:id="#+id/demo_image"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="#drawable/add_user"
android:layout_marginLeft="10px" />
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="#drawable/user_name_background"
android:layout_marginLeft="10px" />
<TextView
android:id="#+id/user_name"
android:layout_width="180px"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textStyle="bold"
android:gravity="center_horizontal"
android:text="Add New User" />
</RelativeLayout>
</RelativeLayout>
</ScrollView>
I'm fetching records from a database, and for each record I need to place a version of the "add user avatar" section as seen above. I'd like to do 5, then wrap to a new row.
My initial idea was to use a layout inflater and add the views programmatically, using RelativeLayout.LayoutParams to set the layout_toRightOf values.
There must be an easier way though. I've seen lots of applications using the "bookshelf" metaphor.
There are a few options I can think of.
Instead of using a relative layout, why not use LinearLayouts with the horizontal attribute?
Using a TableLayout, much like the LinearLayout
Use a ListView with a custom adapter to fill five 'Add User Avatar's' per ListRow
Laying out views programmatically is fairly simple. I do this for all of my activities / views. I love Android's XML layout concept but find that as soon as the views become at all dynamic based on external data (such as your database) then it gets too complex.
I choose what my outermost layout will be and then only instantiate that layout in the XML. Then in my activity I find the outer layout using the normal find by id call and then use a sequence of add(View) method calls to add my dynamically created views or layouts as needed.
You will need to take into account different screen orientations, pixel densities and sizes. Device Independent Pixels will become your friend. For example, to create an image view, you would load the bitmap, figure out how much to resize it (if needed) and then set it as the drawable for a new ImageView instance, that you then add to the layout.
Sounds like your outer layout will be a scroll view with a vertical linear layout inside, that then has a horizontal layout for each "shelf" that then have up to five image views for each "book"
When I do a ListActivity my ListView works correctly : I can scroll by dragging with the TouchScreen or with the Mouse Wheel.
However when I incorporate a ListView in a layout (with buttons, textview, linearLayouts, ect... ) I can't scroll it by dragging, I can just scroll with the mouse wheel.
How can I enable the "touch" scroll of a listView (outside a list activity) ?
Try adding android:isScrollContainer="true" to your ListView definition. That ought to do it.
Another couple points of advice:
You can have the ListView automatically show the "Not found" TextView by using ListView.setEmptyView()
You should use dip or pt for your fonts, not sp. Try your app out on 3 different AVDs, one with a QVGA skin, one with HVGA, and one with WVGA, and I think you'll see what I mean. I would recommend pt except for the fact that the Droid has a glaring bug which causes font points to be incorrectly scaled. Try dips instead.
<LinearLayout
android:id="#+id/results_panel"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/panel_background"
android:orientation="vertical"
android:layout_marginTop="10dip"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:layout_marginBottom="10dip"
android:visibility="invisible">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/results"
android:textSize="18sp"
android:textStyle="bold"
android:shadowColor="#7299e1"
android:shadowRadius="2.0"
android:shadowDx="3"
android:shadowDy="2"
android:gravity="center"/>
<TextView
android:id="#+id/results_panel_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/not_found"
android:textSize="18sp"
android:gravity="center"/>
<ListView
android:id="#+id/results_list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:cacheColorHint="#0000"
android:background="#0000"
android:layout_weight="0.5"/>
</LinearLayout>
The first linear layout Visibility is set programmaticaly to visible (so don't worry about that;)).
The first TextView is a title which appear above the ListView.
The second TextView Visibility is set to visible if I have no item otherwise to gone.
The ListView display the items and is set to visible if I have items otherwise to gone.
The items are Strings in a string Array displayed with an Array adapter.
Eventually I've found out ! Sorry it's entirely my fault : my layout is really complex and I've shown you the part containing the listView but I had forgotten that my whole screen was embedded in a scrollview. And so there was a conflict between this listView and the ScrollView parent.
Excuse me again and thank you for your answers and advises !