I have a StaggeredGridLayoutManager that loads 20 cards which contain images (loaded from cache, network, or storage with Picasso) in a 2 column wide grid.
Issue:
Currently, as you scroll down the list the images are loaded as the cards slide into view like this video:
https://www.youtube.com/watch?v=1xMNmMjqEbI
Desired solution:
What I would like to happen is for the images to load offscreen, so there is a seamless UX like this video:
https://www.youtube.com/watch?v=4c7ZID7yjII
These videos are from a blog post which solves this problem using LinearLayoutManager, not StaggeredGridLayoutManager. I cannot seem to figure out the equivalent solution for this issue. I'm fairly new to android development and have tried to read through the documentation but I canot seem to find anything leading to a solution.
Code:
// Setup RecyclerView
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.gridview_posts);
mRecyclerView.setHasFixedSize(true);
// Setup StaggeredGridLayoutManager
mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(mLayoutManager);
// Set Adapter
mPostsAdapter = new PostAdapter(rootView.getContext(), posts);
mRecyclerView.setAdapter(mPostsAdapter);
// Start RestClient & get posts
restClient = new RestClient(getString(R.string.api_location));
getPosts();
Preload the images to show in a cache, so instead of loading them while you scroll the list, they're already on memory.
Picasso.with(this).load("url").fetch();
Also, remove the Picasso fadeIn animation.
Picasso.with(this).load("url").noFade().into(imageView);
Just figured out a partial solution to my own problem. Going to post it for anyone new like myself that is trying to figure this out.
The RecyclerView method setItemViewCacheSize(int size) will keep the disired amount of items in cache so you dont have flickering type loading of views.
I have not found a lookahead solution though to load a specific amount of views ahead of time.
For me it's working
Picasso.get()
.load(uploadCurrent.getImageUrl())
.placeholder(R.drawable.logoblack_loading)
.config(Bitmap.Config.RGB_565)
.into(holder.imageView);
XML:
<?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="wrap_content"
android:layout_margin="2dp"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ImageView
android:id="#+id/id_imgItem"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"/>
<TextView
android:id="#+id/textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/id_imgItem"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:gravity="center_horizontal"
android:textSize="18sp"/>
</RelativeLayout>
Related
Good afternoon!
I am updating the normal(smart) admob banners for admob Anchored adaptive banners, I am following the example of google but I have several doubts.
I use LinearLayout as a general structure and not RelativeLayout like the google example.
When using the code to display the banner, it underlines two lines.
Example new code banner admob:
<FrameLayout
android:id="#+id/ad_view_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_alignParentBottom="true" />
Yellow underline in android studios (in my code):
android:layout_centerInParent="true"
Message or warning:
Invalid layout param in a LinearLayout: layout_centerInParent
android:layout_alignParentBottom="true"
Message or warning:
Invalid layout param in a LinearLayout: layout_alignParentBottom
Example complet code banner google-admob:
https://github.com/googleads/googleads-mobile-android-examples/blob/master/java/admob/AdaptiveBannerExample/app/src/main/res/layout/activity_my.xml
In the application the test ads are displayed well and work. But I don't like the messages of the underlined code (to avoid problems)
Before I used this code for my SMART banners:
<LinearLayout
android:id="#+id/ad_view_container"
android:orientation="vertical"
android:gravity="bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</LinearLayout>
Could I use the same code for Anchored adaptive banners? or does it have to be FrameLayout..?
thank you for answers
Try This
android:layout_gravity="center_horizontal|bottom"
We are using android API 17 in our application. I have defined a layout containing two images vies as below:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/image_container_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/image_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/image_1_resource"/>
<ImageView
android:id="#+id/image_2"
android:layout_marginTop="3dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/image_container_layout"
android:src="#drawable/image_2_resource"/>
This layout is included inside another layout as below:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
style="#style/wizard_content_style"
tools:context=".ui.Wizard"
android:orientation="vertical"
android:gravity="center_vertical"
android:layout_gravity="center_vertical"
>
<include layout="#layout/image_container_layout"
android:id="#+id/included_view"
/>
<TextView
style="#style/wizard_content_text_style_medium"
android:id="#+id/text_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/included_view"
android:layout_centerHorizontal="true"
android:gravity="center_horizontal"
android:layout_gravity="center_horizontal"
android:text="#string/instruction"
android:layout_marginBottom="15dp"/>
The reason that the layout is included is that we want to reuse it in two more layouts.
Now based on some condition I want to hide or show the image views inside image_container_layout.
The java code looks like this:
containerLayout = (ViewGroup) ((Activity) getAndroidContext()).getLayoutInflater().inflate(R.layout.image_container_layout, null);
image1 = (ImageView) containerLayout.findViewById(R.id.image_1);
image2 = (ImageView) containerLayout.findViewById(R.id.image_2);
switch (accuracy) {
case 1:
log().i(getClass().getSimpleName(), "case 1 chosen");
image1.setVisibility(View.VISIBLE);
image2.setVisibility(View.GONE);
log().i(getClass().getSimpleName(), "image 1 has been shown");
break;
case 2:
image1.setVisibility(View.GONE);
image2.setVisibility(View.VISIBLE);
break;
case 3:
image1.setVisibility(View.VISIBLE);
image2.setVisibility(View.VISIBLE);
break;
}
I am debugging this code and I am sure the code is running. The log messages are printed in Logcat as well, but nothing happens no change in the images. Also, both images are always shown.
I wonder if there is something that I have to do when working with the included layout?
Thanks for any help in advance.
Based on answers I got below, seems that inflating a view will create a new object and because of this, changes in the visibility are not shown on the user interface.
Then the question is that if we have a wizard and inside 3 different pages of the wizard I want to have an image and depending on some condition I want to show or hide the image, what is the best solution? I mean I want to reuse the code which is responsible for hiding and showing the image regardless which page of wizard is active.
Why are you complexing with so much code. If you include some layout in your xml then you can use those widgets also same as the xml have. There is no need to inflate.
ImageView image_2 = findViewById(R.id.image_2);
image_2.setVisbility(Visible.GONE);
You said at this comment the code not inside activity but wherever it is you inflated a new layout to your view currently displaying by this line:
containerLayout = (ViewGroup) ((Activity) getAndroidContext()).getLayoutInflater().inflate(R.layout.image_container_layout, null);
When you try to change visibility of those images actually it works, i think so. But if your activity or fragment layout contains image_container_layout maybe you see
those images.
And I wonder that what do you do with inflated view containerLayout. Do you add it to inside of any other view. If you dont it wont be visible for you.
you have to use it like this:
View included_view1 = findViewById(R.id.included_view1);
ImageView image_1 = included_view1.findViewById(R.id.image_1);
ImageView image_2 = included_view1.findViewById(R.id.image_2);
image_1.setVisibility(View.VISIBLE);
image_1.setVisibility(View.GONE);
image_2.setVisibility(View.VISIBLE)
image_2.setVisibility(View.GONE)
View included_view2 = findViewById(R.id.included_view2);
ImageView image_11 = included_view2.findViewById(R.id.image_1);
ImageView image_22 = included_view2.findViewById(R.id.image_2);
image_11.setVisibility(View.VISIBLE);
image_11.setVisibility(View.GONE);
image_22.setVisibility(View.VISIBLE)
image_22.setVisibility(View.GONE)
Above code will be helpful in the case of multiple time you want to use same layout.
i trying to get a layout just like the image below for a game in android studio
currently my xml is
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.dreacot.testmymemory.Game">
<ImageView
android:id="#+id/imageView"
android:layout_width="72dp"
android:layout_height="115dp"
app:srcCompat="#drawable/backside"
tools:layout_editor_absoluteX="53dp"
tools:layout_editor_absoluteY="136dp" />
<ImageView
android:id="#+id/imageView4"
android:layout_width="72dp"
android:layout_height="115dp"
app:srcCompat="#drawable/backside"
tools:layout_editor_absoluteX="156dp"
tools:layout_editor_absoluteY="136dp" />
<ImageView
android:id="#+id/imageView3"
android:layout_width="72dp"
android:layout_height="115dp"
app:srcCompat="#drawable/backside"
tools:layout_editor_absoluteX="266dp"
tools:layout_editor_absoluteY="136dp" />
<ImageView
android:id="#+id/imageView6"
android:layout_width="72dp"
android:layout_height="115dp"
app:srcCompat="#drawable/backside"
tools:layout_editor_absoluteX="53dp"
tools:layout_editor_absoluteY="285dp" />
<ImageView
android:id="#+id/imageView5"
android:layout_width="72dp"
android:layout_height="115dp"
app:srcCompat="#drawable/backside"
tools:layout_editor_absoluteX="156dp"
tools:layout_editor_absoluteY="285dp" />
<ImageView
android:id="#+id/imageView2"
android:layout_width="72dp"
android:layout_height="115dp"
app:srcCompat="#drawable/backside"
tools:layout_editor_absoluteX="266dp"
tools:layout_editor_absoluteY="285dp" />
i want more cards to be added on the next level eg lvl 2
do i need to make several layouts for each level?
also i want each card to show its face when it is clicked
and finally i feel i am not doing the right thing as i feel xml files cannot be called into the gameplay is there a better way to do this layout(maybe programmatically)?
could anyone help?
The way you are doing it is not the proper way to do it, In this way maybe you can achieve this for 6 cards. What if you have let's say 100 cards or may be 1000, will you add 100 images in Layout and get reference of 100 images in Activity and set Click Listeners and animations to turn the side on 100 images?
Use "GridView" and Adapter for your views, it will do your work with ease.
Check this: https://developer.android.com/guide/topics/ui/layout/gridview.html
You have to do it programmatically.
1. Use RecyclerView with GridLayoutManager to show your card as grid style.
2. Create a layout with just a CardView with single ImageView for your single card item.
3. Create an custom RecyclerView.Adapter<> and use it with RecyclerView to populate your card data on CardView.
4. Add onItemClick listener to Adapter to flip to the specific Card item and do something as per your needs.
Here are some useful links about RecyclerView:
Android RecyclerView with GridLayoutManager Example
Android GridLayoutManager with RecyclerView in Material Design
Simple Android grid example using RecyclerView with GridLayoutManager
Here is a good library for CardView animation.
Hope this will help~
My Problem
I've been trying to get my Recycler View's items to animate as I scroll down. These items are loaded from a local XML and passed through my custom adapter.
I'm using this library for my adapter animation
I noticed that no matter what I tried, the items would just not animate at all, or they would animate all at once (every item would slide in on screen at the same time).
What I've Tried So Far
Utilizing the library I mentioned, I tried animating items in my RecyclerView.Adapter.
> IndexFragment.java snippet
//Create an adapter
SongAdapter adapter = new SongAdapter(songs, getContext());
//Set adapter
AlphaInAnimationAdapter alphaAdapter = new AlphaInAnimationAdapter(adapter);
alphaAdapter.setFirstOnly(false);
recyclerView.setAdapter(adapter);
recyclerView.setHasFixedSize(true);
This one failed somehow. I also tried the setItemAnimator method which also failed.
recyclerView.setItemAnimator(new SlideInLeftAnimator());
Layout Structure
So I assume it has something to do with my RecyclerView being inside of two NestedScrollView's.
Another person seemed to be having a similar issue
Below are some portions of my layout files
activity_main.xml
....
<!-- Fragment Container -->
<android.support.v4.widget.NestedScrollView
android:id="#+id/contentContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
....
This is where I put my fragments
index_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/nestedScrollView"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.v4.widget.NestedScrollView>
This is pretty much my Recyclerview and its parent Nested Scrollview.
item_song.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="1dp">
<!--I have two text views in here. Removed them just for this snippet -->
</LinearLayout>
<!-- This displays a background on each item when I press them AKA touch effects -->
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
android:clickable="true"
android:background="?android:attr/selectableItemBackground" />
</FrameLayout>
This is the structure of each item in the Recyclerview. I inflate this layout for each item. Pretty straightforward.
Any ideas as to what I could do to solve this issue? Thanks.
So after much testing, I finally came up with a solution that worked.
Change the fragment container in activity_main.xml from NestedScrollView to RelativeLayout or perhaps LinearLayout.
Remove the parent NestedScrollView and keep only the RecyclerView in index_fragment.xml.
Animations now work at last. Yay!
Apparently, it is a bad idea to put your RecyclerView inside of a NestedScrollView.
I read somewhere that because of having to load the proper height of its child layout, the NestedScrollView has to wait for it to completely load, in order to know the total height of the RecyclerView. However, I'm not totally sure if that's the reason, so feel free to correct me.
Hope this helps someone!
I'm trying to program a disc golf scoring app on Eclipse for my android phone. I'd like to set it up for up to 6 players, but mostly 2 people will use it for a game. The data is being stored in a sqlite DB, and I am using a SimpleCursorAdapter to populate the data for holes that have already been scored. here is that code:
private void fillData() {
Cursor notesCursor = mDbHelper.fetchAllNotes();
startManagingCursor(notesCursor);
// Create an array to specify the fields we want to display in the list (only TITLE)
String[] from = new String[]{DiscGolfDbAdapter.KEY_HOLE,
DiscGolfDbAdapter.KEY_PAR,
DiscGolfDbAdapter.KEY_TOM_HOLE,
DiscGolfDbAdapter.KEY_TOM_GAME,
DiscGolfDbAdapter.KEY_CRAIG_HOLE,
DiscGolfDbAdapter.KEY_CRAIG_GAME,
DiscGolfDbAdapter.KEY_TOMS_POSITION,
DiscGolfDbAdapter.KEY_SKIP_PLAYER
};
// and an array of the fields we want to bind those fields to (in this case just text1)
int[] to = new int[]{R.id.schole, R.id.scpar, R.id.scth, R.id.sctg, R.id.scch, R.id.sccg, R.id.sctp,
R.id.skip};
// Now create a simple cursor adapter and set it to display
SimpleCursorAdapter notes =
new SimpleCursorAdapter(this, R.layout.hole_info, notesCursor, from, to);
setListAdapter(notes);
}
From searching the internet I've found what I think are two posibilities that SHOULD work, but do not.
First I've tried the XML Attribute: android.visibility. It looks like this in the PORTION of the view that I am trying to "test" hide:
<LinearLayout android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android.visibility="GONE">
<TextView android:id="#+id/scch"
android:layout_width="45dip"
android:gravity="right"
android:textSize="25sp"
android:layout_height="wrap_content"/>
<TextView android:id="#+id/sccg"
android:layout_width="45dip"
android:gravity="right"
android:textSize="25sp"
android:layout_height="wrap_content"/>
</LinearLayout>
I have tried it with "GONE", "Gone" and "gone". NONE of them work in the eclipse emulator OR on my actual phone. So, there is no point in trying to parameterize this attribute.
Next I've tried setting the XML attribute for android:layout_height to "0dip". This indeed works in the emulator and on my phone WHEN IT IS HARDCODED.
Then I moved to the next logical step (as I see it), storing a parameter in the DB so that I can "show" or "not show" the item DEPENDING on conditions within the record. So, I've stored a field in the DB with two values "0dip" and "wrap_content". I pass these to the layout as shown in the java above as R.id.skip. I've also added these to the output just to audit that they are really there. Here is that XML:
<LinearLayout android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="#+id/skip">
<TextView android:id="#+id/scch"
android:layout_width="45dip"
android:gravity="right"
android:textSize="25sp"
android:layout_height="wrap_content"/>
<TextView android:id="#+id/sccg"
android:layout_width="45dip"
android:gravity="right"
android:textSize="25sp"
android:layout_height="wrap_content"/>
</LinearLayout>
<TextView android:id="#+id/skip"
android:gravity="center"
android:layout_width="315dip"
android:textSize="10sp"
android:layout_height="wrap_content"/>
In the above test, both via the Eclipse emulator and my android phone, the last TextView confirms that the DB contains either "0dip" or "wrap_content", BUT the LinearLayout with:
android:layout_height="#+id/skip">
behaves as if it were "0dip" ALL of the TIME. In other words, I cannot PROGRAMMATICALLY" affect the XML attribute for android:layout_height.
If there is a better/more standard way of accomplishing what I am trying to do, please share - BUT BE CLEAR. I am new, so CODE EXAMPLES wwill work best for me.
May 29th - It seems to me (based on testing) that you cannot alter layout attributes for the layout specified in this code:
SimpleCursorAdapter notes = new SimpleCursorAdapter(this,
R.layout.hole_info,
notesCursor, from, to);
setListAdapter(notes);
Anything I try leads to some error ort another. So, I've seen examples of custom list adapters where these attributes are altered, so I'm trying to convert to a custom list adapter.
Why not do it in code?
LinearLayout ll = (LinearLayout)findViewById(R.id.your_layout_id);
ll.setVisibility(View.GONE);
Your XML layout code
android.visibility="GONE"
should be
android:visibility="GONE"
Change visible of a LinearLayout like Gabriel NeguĊ£ say:
LinearLayout ll =
(LinearLayout)findViewById(R.id.your_layout_id);
ll.setVisibility(View.GONE);
or change height of LinearLayout:
LinearLayout ll = (LinearLayout)findViewById(R.id.your_layout_id);
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) ll.getLayoutParams();
lp.height = 0; // or lp.height = LinearLayout.LayoutParams.WRAP_CONTENT;
ll.setLayoutParams(lp);
What about this guy's solution http://enjoyandroid.wordpress.com/2012/03/12/customizing-simple-cursor-adapter/
Kind of worked for me.