I am currently working on an application in which I have to taken into account two ListViews one above another and that too with a common scroll. I know this is not the best practice, instead I should have taken just a single ListView but the problem is with the layouts that doesn't seem to be possible with a sinlge ListView. Actually my first ListView will contain list of friend requests that I can accept or ignore and that are not static and can vary with no limit and second list will contain my friends which may vary too i.e not static. If i have to only show these two things, then I should have preferred single ListView and can be easily done but the actual problem arises when i have to add an Alphabetical sorting of my second list i.e my friends list using side bar and that is applicable only for my second list not for first one. This one is the screenshot without side bar
but alphabetical side bar will be there for new connections. So I don't think, this can be possible with a single list since alphabetical side bar will be added to the whole list not the part of a list. so right now I am trying to save myself from using ScrollView for my two ListViews since that will be very expensive. so I need the best way as how to go with this type of structure. Should take two ListView inside ScrollView or it can be done with a single ListView that will be more preferred.
Please pour your suggestions. Thanks in advance.
What about putting your two ListViews one after the other inside a LinearLayout container and you put that container inside a ScrollView? Then (programatically) you calculate the total height that the ListView needs to be in order to wrap all it's content, so your ListViews will never scroll but your ScrollView will. Here is the idea:
Layout
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- Container -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<!-- Your list views -->
<ListView
android:id="#+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
<ListView
android:id="#+id/listView2"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
</ScrollView>
Code
private void resizeListView(ListView listView) {
ListAdapter adapter = listView.getAdapter();
int count = adapter.getCount();
int itemsHeight = 0;
// Your views have the same layout, so all of them have
// the same height
View oneChild = listView.getChildAt(0);
if( oneChild == null)
return;
itemsHeight = oneChild.getHeight();
// Resize your list view
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)listView.getLayoutParams();
params.height = itemsHeight * count;
listView.setLayoutParams(params);
}
You may want to (actually you need to) wait for the ListView to get drawn so getChildAt(int index) can actually return a View and avoid getting a null. You can achieve this adding this to your onCreate:
ViewTreeObserver listVTO = listView.getViewTreeObserver();
listVTO.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
listView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
resizeListView(listView);
}
});
Just a suggestion, you may want to try the new RecyclerView because it can handle recycling with different types of Views
Related
Created a two way scrollable gridlayout for a TV app
view structure from layout file
<?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="#021257"
android:orientation="vertical">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/rvThumbnail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#021257"
android:orientation="vertical"/>
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
so i have used a gridlayoutmanager(orientation vertical) and spancount being 49 (24hrs *2)+1 for images displaying column. The first row is to display timeline divided into half hour slots and first column is to display channels, each channel will have its own programs running under different time slots. Now that i achieved to scroll the gridlayout both ways, now i have two more things to do.
1) When scrolled horizontally, the channels column(first column) also gets scrolled and hence gets hidden(it has to scroll vertically though, since there can be 20+ channels). Now i need to make this column static wen scrolling horizontally and rest other columns must scroll normally
2) When scrolled vertically, the timeline row (first row) also gets scrolled and hence gets hidden(it has to scroll horizontally though, since the row has to display 24 hrs). Now i need to make this row static wen scrolling vertically and rest other rows must scroll normally.
Is this possible to achieve ? I appreciate your help
The Feasible approach will be to go with three recycle view
a)Vertical recycle view for channel listing
b)Horizontal recycle view for Timing listing
c)Recycle view with grid layout manager for the data
Use scrollChange listener of grid recycle view(Recycle view used for data)
/**
* Use scroll values
*/
public void setScroll() {
mDataRecycleView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
#Override
public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
//you can now play on scroll value of this recycle view and change the scroll value of other recycle views.
// you can get your view here and also know the value of view so based on value you can handle it here so it's very easy.
}
});
}
Try and let me know if this approach works for you and incase any query then comment below so we can solved your problem.
Try TableView project from Github.
TableView is a powerful Android library for displaying complex data
structures and rendering tabular data composed of rows, columns and
cells. TableView relies on a separate model object to hold and
represent the data it displays. This repository also contains a sample
app that is designed to show you how to create your own TableView in
your application.
Get concept from this project and modify what you want.
Hope this explanation helps you :)
I am trying to create a gridview consisting of 15x20 textviews and I want the textviews to be populated from bottom to top. e.g getChildAt(0) will refer to the grid at bottom left. Right now it is always referencing top left grid.
I have tried
android:stackFromBottom="true"
but it isn't working. Below is my code, hope someone could give some insight what am i doing wrong. Thanks!
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/sample_main_layout">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="313dp"
android:layout_weight="0.18">
<GridLayout
android:id="#+id/map_grid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:columnCount="15"
android:descendantFocusability="afterDescendants"
android:gravity="center"
android:horizontalSpacing="30dp"
android:paddingLeft="20dp"
android:rowCount="20"
android:stackFromBottom="true"
android:stretchMode="columnWidth"
android:verticalSpacing="30dp">
</GridLayout>
Using some of the solution you guys suggested, I created a function that correct my index for the grid. It will reference the grid from the last position.
EDIT :
public int correctIndex(int index) {
int mul = (int) Math.floor(index /15);
int remainder = index%15;
remainder = 15-remainder;
int correctedIndex = 300-(mul*15+remainder);
return correctedIndex;
}
You don't need to fill the GridView in reverse order.. You just need to read it in reverse order.
Instead of:
gridView.getChildAt(position);
Use:
gridView.getChildAt(gridView.getChildCount() - position - 1);
Of course, you should replace by the variable that you are using position - 1
android:stackFromBottom="true" doesn't mean your items will be placed in the opposite order.
It just means that if there is extra gap due to fewer items, space will be left in the top.
To place the items in opposite order, you will need to use override the getItem(int position) method to return item in reverse order in the adapter of the GridView.
To make android:stackFromBottom="true" work you must be using <GridView> instead of <GridLayout>.
I could be wrong but if you load in something like an array for the data in the grid view, then you can just reverse the array before loading it, or do what #W0rmH0lesaid above
I want to use a RecyclerView(list like) below another RecyclerView(Grid like) as in flipboard
I tried two RecyclerView inside ScrollView with wrap content but nothing is showing.
I can able to see two views if it is placed in linear layout and equal weight is added to it. But that does not look like this app View.
This is my layout
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="#+id/parent_category_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minWidth="#dimen/default_small_padding"
android:gravity="center"
android:visibility="visible"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/category_grid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnWidth="150dp"
android:gravity="center"
android:visibility="visible"/>
</LinearLayout>
There's actually a really simple way to achieve the desired layout with just one RecyclerView!
The key is using a GridLayoutManager and its SpanSizeLookup.
First of all define your GridLayoutManager like this:
GridLayoutManager layoutManager = new GridLayoutManager(context, spanCount);
where spanCount is the maximum amount of spans/columns you want to have. In your case, spanCount should be 2;
Now you need a way to tell this layoutManager how many spans an item should span.
A simple way would be to use a viewtype/ViewHolder for items that should span just one column and another one for items that span the whole width.
Let's assume you define the viewtype for grid-items as VIEWTYPE_GRID_ITEM and the viewtype for standard listitems as VIEWTYPE_LIST_ITEM.
You can then use these viewtypes to tell the layoutManager when to use just one span:
layoutManager.setSpanSizeLookup(new SpanSizeLookup() {
#Override
public int getSpanSize(int position){
return adapter.getItemViewType(position) == VIEWTYPE_GRID_ITEM ? 1 : spanCount;
}
});
Finally, set the layoutManager to your RecyclerView:
recyclerView.setLayoutManager(layoutManager);
And that's it!
I don't think that they use two ListViews (or ListView + GridView).
I think they use a ListView ( the one in the bottom) and they add a custom Header to this list (the one in the top), which look like a GridView.
Or if they use a Recyclerview, they can achieve this by using a different layout in the adapter for the first item.
PS: it's not recommended to use two scrollable view inside each other (like Recyclerview inside ScrollView).
In android we are advise to use only one scrollable view at time , if you want to use one scrollable view inside other one refer below links.
1)Android list view inside a scroll view
2) https://stackoverflow.com/questions/6210895/listview-inside-scrollview-is-not-scrolling-on-android
I'm trying to show a list of data in an android activity. Normally anyone would do that with a simple ListView which I have used many times before. But now I'm having an application with a fixed header and footer, with the middle part (the content) scrolling underneath both the header and the footer. In the middle section I would like to add other components both above and below the list of data, but the entire part must be scrollable. I tried adding components (like a button, textview etc) to a listview but the lay-out builder in Eclipse won't let me do that.
So I started using a ScrollView where you can easily add any component you like. But I am not allowed to add a ListView to a ScrollView, which I can understand as it would create a strange effect (as both are able to scroll).
Next I wanted to use a TableLayout to dynamically add TableRows, but on multiple websites it is said to be slow and 'not the way to do it'. I also couldn't find an elegant way to add the seperator between each item. With a ListView that would all be done very easily.
The following image probably explaines at best the effect I want: http://tinyurl.com/bvkec5d
The table with the 'Table Data' header can possibly have a lot of items and thus can become very large in length. What I don't want is that the table has a fixed size and the items are scrollable within that table. I actually want the table to grow in size and the ScrollView containing the table should therefore be growing as well. I also want the infobox above the table to scroll along (as with any other components which might be added later).
What is the best way to achieve this effect?
You can use a simple vertical LinearLayout (or a RelativeLayout) that contains your static header and footer, and use a ListView between them. You can set header and footer views on the ListView to add the scrollable header and footer content. For simplicity of example here's the LinearLayout way:
<LinearLayout android:orientation="vertical"
android:layout_height="match_parent"
android:layout_width="match_parent">
<!--static header content... can be any kind of view-->
<TextView
android:layout_width="match_parent"
android:layout_weight="0"
android:layout_height="wrap_content"/>
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<!--static footer content... can be any kind of view-->
<TextView
android:layout_width="match_parent"
android:layout_weight="0"
android:layout_height="wrap_content"/>
</LinearLayout>
And in code, you can say:
ListView theList = (ListView)findViewById(R.id.list);
// example of creating header and footer views from inflation or by instantiation in code
View myHeaderView = getLayoutInflater().inflate(R.layout.myHeaderLayout,theList,false);
View myFooterView = new TextView(this, some layout params);
theList.addHeaderView(myHeaderView);
theList.addFooterView(myFooterView);
ListView.addHeaderView and ListView.addFooterView should enable you to add other static views (whose content could be updated dynamically) to the top or bottom of a ListView:
public void addHeaderView (View v)
Since: API Level 1 Add a fixed view to appear at the top of the list.
If addHeaderView is called more than once, the views will appear in
the order they were added. Views added using this call can take focus
if they want.
NOTE: Call this before calling setAdapter. This is so ListView can
wrap the supplied cursor with one that will also account for header
and footer views.
I have a ListView that with alphabetical headers for each letter. I also have an index function that brings the letter headers to the top of the screen.
My problem is when I reach the end of the list setSelection is unable to bring the last few headers to the top because it will not scroll past the end of the list.
My question is this: Is there a way to add a blank space to the end of the screen dependent on screen size? I would like to scroll until the last item in the list is at the top of the listView.
The easiest way to add space is to add padding in xml and set clipToPadding:"false".
For RecyclerView
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="20dp"
android:paddingBottom="20dp"
android:clipToPadding="false"/>
For ListView
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="20dp"
android:paddingBottom="20dp"
android:clipToPadding="false"/>
And same goes for the ScrollView
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="20dp"
android:paddingBottom="20dp"
android:clipToPadding="false"/>
This specifically adds the blank space to top and bottom but hide the space when you scroll the view.
Try the followings:
View footer = new View(getActivity());
footer.setLayoutParams( new AbsListView.LayoutParams( LayoutParams.FILL_PARENT, 100 ));
mListView.addFooterView(footer, null, false);
I'm assuming you are using an extension of BaseAdapter to populate your ListView?
There may be a built-in way to do what you are asking, but I don't know of one. If you end up creating it yourself, how about this approach:
Return list.size() + EXTRA in getCount()
Modify getItem() to return something sane if it asks for an item not in your list
Modify getView() to configure the given view as a simple horizontal padding with the same height as the rest of your views if the position index is more than your list size
You would need to fiddle around with the EXTRA constant to see what value is best.