I want to have a scroll bar in android showing each individual plant such that a user can press on one to select it, create a new Plant object he can then move around the screen.
I'm running into trouble populating this list.
I have a HorizontalScrollView:
bar = (HorizontalScrollView)findViewById(R.id.horizontalScrollView1);
The brunt of my code happens in
private LinearLayout loadBar(ArrayList<Plant> listOfPlants, HorizontalScrollView bar){
LinearLayout layout = new LinearLayout(getApplicationContext());
layout.setHorizontalScrollBarEnabled(true);
ImageView image= new ImageView(getApplicationContext());
ArrayList<View> images = new ArrayList<View>();
for (int i = 0; i < list.size(); i++) {
image = listOfPlants.get(i).getPhoto();
images.add(image);
}
layout.addTouchables(images);
return layout;
}
I want to add this linear layout to the scroll bar I'm creating but I don't see any way to do this. Or am I going about this the wrong way and is there a much simpler way to get what I want done?
You can take a ListView inside LinearLayout, that is inside horizontal scroll view as below:
<HorizontalScrollView ...........>
<LinearLayout ......>
<LinearLayout ......>
//List View Titles will be here
</LinearLayout>
<ListView ........ android:layout_weight="1" />
</LinearLayout>
</HorizontalScrollView>
Also, it is important to put layout_weight in the ListView. Hope it works for you. Also, you can check this customized horizontally scrollable listview tutorial.
Related
I have a custom XML file. I want to repeat this in a layout (say Relative) n number of times, dynamically (obviously).
I have seen many posts, but none helped. I am not looking for a ListView or Adapters or so. It's as simple as - A RelativeLayout. Inside it, adding the custom XML one above another. Any number of times.
With a static LinearLayout (Vertical orientation), adding the view dynamically results in rendering it once, not one below another. Don't know why. Although a TextView or so do repeat one below the other in a loop inside a LinearLayout (Vertical).
Then I dynamically created the layout (Relative), and inflated the custom XML. Displayed one. When I tried for another below the first it told me to remove child's parent first (Exception). If I do that and add again, its as good as removing the first rendered view and adding it again.
So how can I get multiple views in same layout?
A rough presentation of what I've attempted:
mainLayout = (RelativeLayout)findViewById(R.id.mainlay); //Mainlayout containing some views already
params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.BELOW,R.id.sideLayout); //sideLayout is an existing LinearLayout within the main layout.
View child = getLayoutInflater().inflate(R.layout.dynamiccustomlayout,null);
RelativeLayout r1 = new RelativeLayout(this);
r1.setLayoutParams(params);
r1.addView(child);
mainLayout.addView(r1);
mainLayout.setLayoutParams(params);
mainLayout.addView( child);
/* r2 = new RelativeLayout(this);
r2.setLayoutParams(params);
r2.addView(contentLayout); [Gives exception] */
This is how it worked out for me...
Before that, the issue with android is:
If you add dynamic views inside a LinearLayout (Horizontal), they will appear horizontally with new created instances, added to the view.
However, shockingly, it's not the same in case of LinearLayout (Vertical orientation). Hence the whole mess.
Solution:
The RelativeLayout layout file was binded with the variable, somewhat like this:
customLay = (RelativeLayout) mainLay.findViewById(R.id.dynamicCustomLayout);
Then, a Dynamic RelativeLayout was created within which the former variable is added/wrapped.
customLayout = new RelativeLayout(this);
customLayout.addView(customLay);
Every layout is assigned an id:
customLayout.setId(i);
And then a loop is run (2 if conditions for i=0 and i>0)
for i>0 (indicates the 2nd dynamic layout, to be added below the first), LayoutParameter is created:
params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
And then for i>0, using the ids of dynamic views, they are added one below the other:
//Following code below used id to place these views below each other to attain list type arrangement of views//
// i==0 for first view on top//
if (i == 0) {
params.addRule(RelativeLayout.BELOW, R.id.sideLayout);
customLayout.setLayoutParams(params);
}
// i>0 for views that will follow the first top//
else {
params.addRule(RelativeLayout.BELOW, i - 1);
customLayout.setLayoutParams(params);
}
Then added to main root layout, where all these views or cards need to be displayed:
includeLayout.addView(customLayout);
Ofcourse, the code is not just this. I have written the essential points that helped me achieve the target and that may help others in future.
So the main essence was ---
using a Dynamic RelativeLayout, to
bind the static RelativeLayout, and
assigning ids to the Dynamic RelativeLayout wrappers, and
on basis of ids use RelativeLayoutParameters to place the following
ids below the previous ones.
You have to instanciate every child by itself
View child = getLayoutInflater().inflate(R.layout.dynamiccustomlayout,null);
r1.addView(child);
View child2 = getLayoutInflater().inflate(R.layout.dynamiccustomlayout,null);
r1.addView(child2);
//ok, i do a analog thing in obne of my apps. here is the code:
public class FlxForm extends LinearLayout {
public FlxForm(Context context) {
super(context);
inflater = LayoutInflater.from(context);
inflater.inflate(R.layout.flxform, this);
this.setPadding(0, 0, 0, 0);
container = (LinearLayout) this.findViewById(R.id.flxform);
this.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
//here is my funtion to calculate the items i want to add, its a little bit too complicated, but in the end it works like:
for(int i=0;i<10;i++){
View x = inflater.inflate(R.layout.dynamiccustomlayout,null);
container.addview(x);
}
}
}
XML for the Form
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/flxform"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:background="#android:color/transparent"
android:orientation="vertical" >
</LinearLayout>
Then you can instantiate a "Form" Objekt and add it into a ScrollView
For doing this You would have to nest your RelativeLayout inside a ScrollView and Manage all the Scrolling, items adding, memory management, etc manually.
So the simple solution for adding n Number of Custom Views is to use a RecyclerView, ListView, GridView, etc with a neat CustomAdapter and Your Custom View.
Here is a nice example of using RecyclerView with custom Adapter :
http://code.tutsplus.com/tutorials/getting-started-with-recyclerview-and-cardview-on-android--cms-23465
I hope this Helps.
I've got a LinearLayout which includes among others two ListViews. Each ListView has it's own ArrayAdapter. Now the Scrolling shouldn't be in the ListViews, the user should see the whole Lists and scroll the whole view. Sourrounding the LinearLayout with a ScrollView doesn't work because of the inerhit Scrolling Views... .
How can I expand the ListViews and let the user scroll only the outer view?
You should not use a ListView this way.
List Views are meant to recycle views, which it cannot do if its not the view that is scrolling.
You could simply use a LinearLayout and add every single view to the layout. This would be better than using a ListView.
(This does not mean it is the best solution)
This can be done easily in RecyclerView. But in this case you are using ListViews so try listView.setScrollContainer(false);
may be it works for you
You should inflate Views Like this.
// from content View of activity or fragment
listView = (LinearLayout) findViewById(R.id.sos_list_view);
listView.removeAllViews();
List<SosObject> sosList = batabase.getAllItems();
for(SosObject t: sosList) {
LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Item layout
View view = inflater.inflate(R.layout.sos_prewivew_item, null);
TextView comment = (TextView) view.findViewById(R.id.sos_comment_text);
TextView date = (TextView) view.findViewById(R.id.sos_date_text);
TextView id = (TextView) view.findViewById(R.id.sos_answer_id);
TextView tittle = (TextView) view.findViewById(R.id.answer_tittle);
listView.addView(view);
}
}
Your xml Should look like:
<ScrollView>
<LinearLayout>
</LinearLayout > // Fist list
</LinearLayout > // Second list
</LinearLayout>
</ScrollView>
ListViews cannot be overriden to lose the scrolling ability. They seem to be designed as top-level objects that occupy the whole screen.
So basically you have 2 options here:
Convert all your elements into ListView's items
use LinearLayouts instead of ListViews and wrap all elements in a ScrollView
I am adding views dynamically in a linear layout as follows:
xml:
<LinearLayout
android:id="#+id/part1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:gravity="right"
android:orientation="horizontal" >
</LinearLayout>
java:
View linearLayout = findViewById(R.id.part1);
((LinearLayout) linearLayout).removeAllViews();
for (int i = 0; i < 15; i ++){
TextView tv = new TextView(this);
tv.setText(String.valueOf(i));
LinearLayout.LayoutParams lay = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
tv.setLayoutParams(lay);
tv.setBackgroundResource(R.drawable.msg);
tv.setId(i);
((LinearLayout) linearLayout).addView(tv);
}
Now i have two questions:
1) the text views are added horizontally correctly but if not fitting screensize, some of them won't appear, how to force it to continue adding in a new line once the horizontal space is full ?
2) textviews are added from left to right, how to add them from right to left ?
thanks
You need to understand how ViewGroups work, in this case, LinearLayout will add items horizontally or vertically without making position calculations for you unless you explicitly specify (jumping to next line is not one of them...), think of it as an item holder that will show items only on the space you specify for it (thats why some of the elements disappear...), by default the way LinearLayout arrange items is from left to right or up to down, if this do not fit your needs, you could go for any of the ViewGroup options android has, the most important might be:
RelativeLayout
FrameLayout
TableLayout
AbsoluteLayout(not recommended)
If you need some sort of Free Draw on the screen, you can always go for a View object, override onDraw, and play with the canvas of that object...
Regards!
I am new to android, and I am searching for a logic for grid view like pinterest(homescreen) app that has been build for i-phone. A large no. of images are coming from the server that I need to show in following form with pagination effect i.e loading images on scroll.
please reply if it is possible other way around. I'll be highly thankful.
If you want to perform loading of image on scroll then it will similar to List View.First save all data from WS URL then load on demand Now
Commonsware Endless Adapter For Listview,you can integrate it with GridView too
EndLessAdapter
Another way is to put your grid views in a ViewFlipper and then flip with an animation.
Use setInAnimation() and setOutAnimation() to set the animations and flip the pages with showNext() and showPrevious()
Create layout like as follow
<ScrollView...>
<LinearLayout....
android:id="#+id/linear1"
orientation="horizontal">
<LinearLayout....
android:id="#+id/linear2"
android:layout_weight="0.33"
orientation="vertical">
<LinearLayout....
android:id="#+id/linear3"
android:layout_weight="0.33"
orientation="vertical">
<LinearLayout....
android:layout_weight="0.33"
orientation="vertical">
</LinearLayout>
</ScrollView>
Now add your ImageView dynamically in layouts
linear1 = (LinearLayout) findViewById(R.id.linear1);
linear2 = (LinearLayout) findViewById(R.id.linear2);
linear3 = (LinearLayout) findViewById(R.id.linear3);
for(int i=0;i<n;i++)
{
ImageView iv = new ImageView(this);
iv.setImageResource(R.id.icon);
int j = count % 3; <----
if(j==0)
linear1.addView(iv);
else if(j==1)
linear2.addView(iv);
else
linear3.addView(iv);
}
Check: Staggered GridView
The StaggeredGridView allows the user to create a GridView with uneven rows similar to how Pinterest looks. Includes own OnItemClickListener and OnItemLongClickListener, selector, and fixed position restore.
This is old question, but for those that have similar problem:
Easiest way to accomplish this layout style is to use RecyclerView with StaggeredGridLayoutManager, like this:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
View recyclerView = findViewById(R.id.recycle_view);
assert recyclerView != null;
StaggeredGridLayoutManager gaggeredGridLayoutManager = new
StaggeredGridLayoutManager(2, 1);
recyclerView.setLayoutManager(gaggeredGridLayoutManager);
}
For the other part of question (pagging) it's best to receive your images in chunks (for example 50 images per request) and when user scrolls down (comes to the end) load more.
is it possible/advisable to have a nested listview?
i.e. a listView that's contained within a row of another listview?
an example would be where my main list is displaying blog posts, and then in each row, you'd have another list view for the comments for each post (that would be collapsible)
I had the same problem today, so this is what I did to solve it:
I have a ListView, with a CustomAdapter, and on the getView of the customAdapter, I have something like this:
LinearLayout list = (LinearLayout) myView.findViewById(R.id.list_musics);
list.removeAllViews();
for (Music music : albums.get(position).musics) {
View line = li.inflate(R.layout.inside_row, null);
/* nested list's stuff */
list.addView(line);
}
So, resuming, It's not possible to nest to ListViews, but you can create a list inside a row using LinearLayout and populating it with code.
Is what you're looking for the ExpandableListView? Of course, that's limited to only two levels of listings (but that sounds like it would work for your needs).
This sound like what you're looking for? If you're not, or if this doesn't work, I would suggest having two list views: one of, say, blog posts, and the second of comments, and an action on a blog post item takes you to the second view, populated with the relevant comments.
you can do it like this :
inside the parent listview row xml layout add the following table layout
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/table_show"
android:background="#beb4b4">
</TableLayout>
then you have to make a layout for the child list with name reply_row.xml
<?xml version="1.0" encoding="utf-8"?>
<TableRow android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/tv_reply_row"
android:textColor="#000"/>
</TableRow>
in your parent listview adapter getview method add the following code :
TableLayout replyContainer = (TableLayout)
// vi is your parent listview inflated view
vi.findViewById(R.id.table_show);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//child listview contents list
String [] replys = {"a","b","c","d"};
for (int i=0;i<replys.length;i++)
{
final View comments = inflater.inflate(R.layout.reply_row, null);
TextView reply_row = (TextView) comments.findViewById(R.id.tv_reply_row) ;
reply_row.setText(replys[i]);
//for changing your tablelayout parameters
TableLayout.LayoutParams tableRowParams=new TableLayout.LayoutParams
(TableLayout.LayoutParams.FILL_PARENT,TableLayout.LayoutParams.WRAP_CONTENT);
int leftMargin=3;
int topMargin=2;
int rightMargin=3;
int bottomMargin=2;
tableRowParams.setMargins(leftMargin, topMargin, rightMargin, bottomMargin);
comments.setLayoutParams(tableRowParams);
TableRow tr = (TableRow) comments;
replyContainer.addView(tr);
}
You'd better use one ListView, not nested. Nesting ListView is an inefficient way. Your ListView may not scroll smoothly and take up more memory.
You could organize your data structure to show nested data in one ListView. Or you can use this project PreOrderTreeAdapter.
It is convenient to show nested data in ListView or RecyclerView. It can be used to make ListView or RecyclerView collapsible, just change the way you provide your data than notify the adapter.