I need to create a Fragment with a list of images.
I did the following:
RecyclerView;
CardView with an ImageView;
RecyclerView Adapter;
I have a list of urls with which I create an adapter. In the onBindViewHolder of the Adapter I use Picasso in order to load the images into the ImageView.
This approach works but I'm not sure it is the best. The images don't always have the right dimensions and I have a random bug, such as image appear and disappear during the scrolling.
What do you suggest?
EDIT:
XML Layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
card_view:cardCornerRadius="4dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter"
android:id="#+id/thumbnail"/>
</android.support.v7.widget.CardView>
I used the following approach and it works well for me.
The images don't always have the right dimensions
My ImageView
<ImageView
android:id="#+id/image_college_news"
android:layout_width="#dimen/dimen_90"
android:layout_height="#dimen/dimen_90"
android:scaleType="centerCrop"
android:src="#drawable/ic_default_image" />
And display the image using Universal Image Loader with the following setting:
DisplayImageOptions options = new DisplayImageOptions.Builder()
.imageScaleType(ImageScaleType.EXACTLY_STRETCHED)
.cacheInMemory(true)
.cacheOnDisk(true)
.considerExifParams(true)
.build();
Hope it helps.
Related
I'm building an app which has 2 fragment containers and takes screenshot feature.
the problem is whenever one of the 2 fragment containers update with another fragment(replaced) and I'm taking a screenshot it shows the previous fragments and not the updated ones.
I'm using getView().getRootView() within another fragment in the activity to take the screenshot.
any advice on why it happens?
Please be more elaborate about the problem or try to add the code.
If you are not using the FrameLayout, please use this.
Code for Adding FrameLayout:
<?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=".MainActivity">
<FrameLayout
android:id="#+id/your_placeholder"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"></FrameLayout>
</android.support.constraint.ConstraintLayout>
To add or replace new Fragments use the FragmentTransaction.
// Code inside the onCreate method
getSupportFragmentManager().beginTransaction()
.replace(R.id.your_placeholder, new TheOtherFragment())
.commit();
To take screen Shot :
View view = findViewById(R.id.your_placeholder);
view.setDrawingCacheEnabled(true);
view.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
Bitmap screenshot = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
To take screen Shot :
View view = findViewById(R.id.id_of_constraintLayout);
// Here you assign the view Variable to the id of the View hosting all your Views.
view.setDrawingCacheEnabled(true);
view.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
Bitmap screenshot = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
So, I'm working on a small project and I wanted to add StaggeredGridLayoutManagerto the file. While it works if I don't add an itemDecorator and no margin or padding in my layouts. As soon as I add margins it pushes the list to one side. I'm attaching a screenshot to clarify the issue.
Here is my Code:
recyclerView.setHasFixedSize(true);
StaggeredGridLayoutManager gridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
recyclerView.addItemDecoration(new EqualSpaceItemDecoration(8));
recyclerView.setLayoutManager(gridLayoutManager);
recyclerView.setAdapter(adapter);
And the Layout File for the item
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:id="#+id/wallpaper_item_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="#color/cardview_light_background"
app:cardCornerRadius="4dp"
app:cardElevation="4dp"
app:cardPreventCornerOverlap="false">
<ImageView
android:id="#+id/wallpaper_item_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.v7.widget.CardView>
</LinearLayout>
I've looked around for some time and am not able to find something that fixes the issues. Any help is appreciated. Thanks.
I don't know if you've already found the solution, but I'll leave the comment in case anyone else sees the question.
I was able to solve this problem by doing the following:
layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
Example:
StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
RecyclerView recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(layoutManager);
In kotlin use:
viewManager.gapStrategy = StaggeredGridLayoutManager.GAP_HANDLING_NONE
I am here because I am trying to set programmatically the layout_below parameter of some cardViews without success.
These cardViews are located inside a PercentRelativeLayout (I do not know if it is relevant but these cardviews have been added programmatically too).
I show you the code to make it clear.
...
<android.support.percent.PercentRelativeLayout
android:id="#+id/prl"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.CardView
xmlns:percent="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/cv0"
android:layout_width="match_parent"
percent:layout_heightPercent="65%"
percent:layout_marginTopPercent="2%"
percent:layout_marginLeftPercent="2%"
percent:layout_marginRightPercent="2%"
card_view:cardCornerRadius="2dp"
card_view:cardElevation="4dp">
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
xmlns:percent="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/cv1"
// here I would like to add android:layout_below="#+id/cv0"
android:layout_width="match_parent"
percent:layout_heightPercent="65%"
percent:layout_marginTopPercent="2%"
percent:layout_marginLeftPercent="2%"
percent:layout_marginRightPercent="2%"
card_view:cardCornerRadius="2dp"
card_view:cardElevation="4dp">
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
xmlns:percent="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/cv2"
// here I would like to add android:layout_below="#+id/cv1"
android:layout_width="match_parent"
percent:layout_heightPercent="65%"
percent:layout_marginTopPercent="2%"
percent:layout_marginLeftPercent="2%"
percent:layout_marginRightPercent="2%"
card_view:cardCornerRadius="2dp"
card_view:cardElevation="4dp">
</android.support.v7.widget.CardView>
</android.support.percent.PercentRelativeLayout>
...
I tried to do something like this in my Java code but without success.
PercentRelativeLayout prl = (PercentRelativeLayout) view.findViewById(R.id.prl);
CardView cv = (CardView) LayoutInflater.from(getActivity()).inflate(R.layout.cv_block, prl, false);
cv.setId(currentId++);
prl.addView(cv);
cv = (CardView) LayoutInflater.from(getActivity()).inflate(R.layout.cv_block, prl, false);
cv.setId(currentId++);
RelativeLayout.LayoutParams cv_lp = (RelativeLayout.LayoutParams) cv.getLayoutParams();
cv_lp.addRule(RelativeLayout.BELOW,currentId-2);
/* I have also tried to call cv.requestLayout() but nothing changed */
prl.addView(cv);
As you can see, I am trying to generate cardviews and insert them one below the other.
Thanks in advance for your help.
PercentRelativeLayout is depreciated, so you are encouraged to use other type of layout.
This class was deprecated in API level 26.1.0.
consider using ConstraintLayout and associated layouts instead. The following shows how to replicate the functionality of percentage layouts with a ConstraintLayout. The Guidelines are used to define each percentage break point, and then a Button view is stretched to fill the gap:
ConstraintLayout gives lots of opportunities.
More about PercentRelativeLayout deprecation here.
More about ConstraintLayout and how to use it here or video tutorial.
I have the following layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_gravity="top|center"
android:background="#drawable/rounded_corner"
android:layout_marginTop="50dp"
android:layout_width="250dp"
android:layout_height="350dp">
<ImageView
android:id="#+id/imageView1"
android:layout_width="match_parent"
android:layout_height="270dp"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
android:src="#drawable/card_image"
android:layout_gravity="top"
android:layout_marginTop="0dp"/>
</FrameLayout>
The image should fill the image with its rectangle and scale it keeping its aspect ratio. It works fine when I do not move the view:
But, when I move the view, the image is drawn outside of its bounds:
I am using this library to move the card.
How do I prevent that the ImageView draws its image outside its bounds?
I use this library with Picasso, something like the example below. I've modified the code you provided a bit to keep it familiar.
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_gravity="top|center"
android:background="#drawable/rounded_corner"
android:layout_marginTop="50dp"
android:layout_width="250dp"
android:layout_height="350dp">
<!-- Note that I've deleted a lot of properties from the ImageView -->
<!-- This is because Picasso will do a lot of that for us -->
<ImageView
android:id="#+id/image_view"
android:layout_width="match_parent"
android:layout_height="270dp"
android:src="#drawable/card_image"
/>
</FrameLayout>
When you've inflated the view, you can simply find the view using findViewById, as you'd usually do.
ImageView imageView = (ImageView) inflatedView.findViewById(R.id.image_view);
// Here comes the Picasso bit
Picasso.with(getActivity()) // You have to provide a Context
.load(R.drawable.card_image) // Can be a Uri, File or String path as well
.into(imageView); // Use .into(ImageView view, Callback callback) to register a listener for the image loading.
This will simply put the image into the ImageView without modifying it. You can add .centerCrop(), .fit() (example below) and other nifty methods to edit the image to the container properties automatically. Since you use centerCrop in your example I won't go into those, but refer to the Picasso github page I provided at the top for futher documentation.
To centercrop or fit the image, you add the method between load() and .into():
Picasso.with(getActivity())
.load(R.drawable.card_image)
.centerCrop()
.fit()
.into(imageView);
Another great feature of Picasso is how it deals with slow or non-successful loading: you can add placeholders and error resources:
Picasso.with(getActivity())
.load(R.drawable.card_image)
.placeholder(R.drawable.loading_image)
.error(R.drawable.error_image
.into(imageView);
Good luck!
I am using a DraggableGridView from here.
What I did before was add a simple programmatically built ImageViews to the grid. That works perfectly fine.
I am now trying to add a Layout instead. I tried RelativeLayout, Framelayout, FrameLayout inside of a RelativeLayout.
Here is my code as of now:
/**
* Rebuild the grid view, e.g. after the adapter has been filled or a backup is restored
*/
private void renewGrid()
{
dgv.removeAllViews();
for(int i = 0; i < adapter.getCount(); i++)
{
LayoutInflater inflater = (LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
dgv = (DraggableGridView) inflater.inflate(R.layout.grid_item_layout, dgv);
FrameLayout fl = (FrameLayout) dgv.findViewById(R.id.grid_images);
ImageView icon = (ImageView) fl.findViewById(R.id.qstile);
icon.setImageDrawable(res.getDrawable(res.getIdentifier("qstile_" + adapter.getItem(i), "drawable", packagename)));
}
}
Following the grid_item_layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal" >
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/grid_images">
<ImageView
android:layout_width="32dp"
android:layout_height="32dp"
android:src="#drawable/icon_delete"/>
<ImageView
android:id="#+id/qstile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</FrameLayout>
<TextView
android:id="#+id/invisible_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text=""
android:visibility="gone" />
</RelativeLayout>
The RelativeLayout gets inflated into the grid nicely. I can observe this via DDMS and the "Dump view hierachy" function. The tree shows all RelativeLayouts inside the grid, but each of it doesn't have any children.
BUT... That is not true. If I step through the code and observe the inflated layouts I can see the children. So they are set up, get added just like told in the XML, but don't get drawn.
The OnItemClick listener on the children of the grid also works...
Any hint about what I'm missing here? I already tried several ways, even creating the complete layout programmatically and then adding it to the grid as children. Still no luck. None of the children get added.
Is that maybe an issue with the used DraggableGridView?
After searching for another few hours I found a fix in this SO thread
Basically I now extend DraggableGridView from FrameLayout rather than ViewGroup. This hasn't had any noticeable side effects to me.