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.
Related
In my android app I pull data from http requests.
In my layout I want to show images dynamically with Glide library.
I get the image urls but I can not find a way to show them in my layout.
In my layout file I have:
<LinearLayout
android:id="#+id/social_media_layout"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="60dp"
android:gravity="center_vertical">
</LinearLayout>
Somehow I want to add imageviews(dynamically) in my LinearLayout.
For example: If I get 2 image urls from the request I need two imageviews in my linearlayout.
Note: I want to load images with Glide library.
Any idea would be helful.
Thanks.
You could make a new XML file for item_social_media.xml
For example
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="60dp" >
<ImageView
android:id="#+id/social_media_icon"
/>
<!-- More customization as needed -->
</RelativeLayout>
And you can inflate that and add into the LinearLayout.
final Context context = MainActivity.this; // TODO: Get a context
// Inflate and update the view
View socialMediaItem = LayoutInflater.from(context).inflate(R.layout.item_social_media);
ImageView icon = (ImageView) socialMediaItem.findViewById(R.id.social_media_icon);
// TODO: Glide ... into(icon);
// Add to the LinearLayout
linearLayout.addView(socialMediaItem);
You should better use ListView or RecycleView . But if you insist on adding them into LinearLayout dynamically, then:
LinearLayout layout = (LinearLayout)findViewById(R.id.social_media_layout);
// assuming that image_urls_list contains the images urls
for(int i=0;i<image_urls_list.size();i++)
{
ImageView image = new ImageView(this);
// set whatever width and height you want to give
image.setLayoutParams(new android.view.ViewGroup.LayoutParams(100,100));
// load image using Glide
Glide.with(context).load(image_urls_list.get(i)).into(image);
// Adds the view to the layout
layout.addView(image);
}
You might want to add a HorizontalScrollView tag as a parent tag to your LinearLayout so that you can scroll horizontally.
I'm looking to replicate airbnb's app image slider where you have one image at the top of a view that you can horizontally swipe and it automatically goes to the next image upon swipe. I created a horizontalscrollview but it doesn't quite have the right functionality. It doesn't flip from image to image, upon swipe it sort of scrolls along the image and eventually to the next image. I've googled around quite a bit and haven't seen a non deprecated solution.
Any ideas?
EDIT - adding some of my code per request:
Basically at a high level I'm pulling in imageURLs from my AWS database (in a different class not shown below) and then trying to load those URLs into a horizontalscrollview using Picasso.
//generic instructions to allow insertion of pictures into a horizontalimageslider
public View insertPhoto(String path){
LinearLayout layout = new LinearLayout(getActivity());
layout.setGravity(Gravity.CENTER);
ImageView imageView = new ImageView(getActivity());
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
Picasso.with(getActivity() ).load(path).into(imageView); //tried this but got errors when running > resize(layout.getWidth(), layout.getHeight()), also tried .fit() after .load image wouldn't load
layout.addView(imageView);
return layout;
}
private class GetApartmentTask extends AsyncTask<ApiConnector,Long,Apartment >
//after a doInBackground
#Override
protected void onPostExecute(Apartment apartment) {
//to get image URL from database to then use with Picasso to download the image
mImageURLArraylist = mApartment.getApartmentImageArrayList();
for (int z = 0 ;z<mImageURLArraylist.size(); z++) {
mLinearLayout.addView(insertPhoto("http:" + mImageURLArraylist.get(z)) );
}
}}
in onCreateView method (alongside other things obviously)
mLinearLayout = (LinearLayout) v.findViewById(R.id.details_page_apartment_picture);
MyXML (relevant part)
<HorizontalScrollView
android:id="#+id/horizontal_scroll_view"
android:layout_width="match_parent"
android:layout_height="500dp"
android:fillViewport="true">
<LinearLayout
android:id="#+id/details_page_apartment_picture"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:orientation="horizontal">
</LinearLayout>
</HorizontalScrollView>
After many hours of frustration and some help getting over the finish line, the answer to swiping some part of the screen in this way is to use a viewpager.
Some great references:
swipe some part of the screen
http://developer.android.com/training/animation/screen-slide.html
What is the role of " isViewFromObject (View view, Object object)" in FragmentStatePagerAdapter?
my working code is provided in another question I posted that got me over the finish line :) --
Android ViewPager Won't Show Second Page?
I don't know the specifics of the airbnb app image slider, but it sounds like you could use flexslider. It's basically a JQuery toolkit. I have used it before in a website and it seems to have the functionality you are looking for.
https://www.woothemes.com/flexslider/
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.
I've been grappling with this problem throughout the life of my project. I have many lists in my project and most of them have headers. I have been making a separate layout file and adding it to the list using addHeaderView(). The problem is that when the data (ArrayList, in my case) is empty, the header doesn't appear. After hours of searching for a way to reuse the header layout as an empty view, I gave up and decided to replicate the layout in code and assign it as an empty view using setEmptyView(). The problem with this is that a lot of the headers contain clickable views and so I have to double all of my clickable logic for every view that is duplicated. I tried to include the header before but failed, mostly because I still don't quite understand how layouts are inflated, etc.
Finally, I have come up with a solution that I would like to share with the community, in case others are having a similar problem. I don't know if this is the best way to solve this problem and any feedback or suggestions would definitely be welcomed.
here is the code for the layout that contains the list list view:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<ListView
android:id="#+id/lv_my_list"
style="#style/ListStyle"
android:headerDividersEnabled="false"
/>
<include
layout="#layout/my_list_header"
android:id="#+id/my_list_empty"
/>
</LinearLayout>
the style defines the layout width and height among other things.
now I have the layout file that contains the header view
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="#+id/my_list_header"
>
<Button
android:id="#+id/my_list_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Click Me"
/>
</LinearLayout>
I know LinearLayout is not very efficient and I am experimenting with using merge or other efficiency measures, but this is the first version that works so I'm going with it for now. Finally the code:
// set up the header
myListView = (ListView)findViewById(R.id.lv_my_list);
View header = View.inflate(this, R.layout.my_list_header, null);
Button b = (Button)header.findViewById(R.id.my_list_button);
b.setOnClickListener(this);
myListView.addHeaderView(header);
// set up the empty view
LinearLayout ll = (LinearLayout)findViewById(R.id.my_list_empty);
b = (Button)ll.findViewById(R.id.my_list_button);
b.setOnClickListener(this);
meLocalListView.setEmptyView(ll);
The reason I wrapped the button in a layout is because I can set each instance of the button to use this as an OnClickListener and then refer to both of them with a single id: R.id.my_list_button in my onClick method. I need to test this a lot more but it seems to work for now. I haven't implemented it on all my lists yet, just the one so it might not work in all situations. If you have any suggestions please let me know because this has been a problem for me for a long time now. One problem might be that if you want to instantiate the button from the ID you would probably have to go through this entire process again to access the correct IDs?
If you want to show the header of a ListView when the list is empty, what you really want to do is to show the list itself rather than a separate empty view. So, the simplest way is to check whether your list is empty and set the list visible if it is not already:
getListView().setVisibility(View.VISIBLE);
You can test this very easily with the following code:
public class TestListActivity extends ListActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_listview);
// create the empty grid item mapping
String[] from = new String[] {};
int[] to = new int[] {};
// prepare the empty list
List<HashMap<String, String>> fillMaps = new ArrayList<HashMap<String, String>>();
// fill in the grid_item layout
SimpleAdapter adapter = new SimpleAdapter(this, fillMaps, R.layout.test_listitem, from, to);
View listHeader =
((LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE))
.inflate(R.layout.test_listheader, null, false);
getListView().addHeaderView(listHeader);
getListView().setAdapter(adapter);
}
}
The list is empty, but the header is visible.
My solution is to create a view with the layout for the header, but set the background to be the same as the list items.
android:background="#android:drawable/list_selector_background"
But my solution does not work if I use 'include' to embed the header layout from another layout file. Do not know why.
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.