I currently have this code working. What I'm doing is downloading an image using Picasso and loading it into an imageView, which is inside a RecyclerView item.
Recycler Item XML
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_item"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardPreventCornerOverlap="false"
app:cardElevation="4dp"
app:cardCornerRadius="4dp"
app:cardUseCompatPadding="true">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Loading View -->
<com.wang.avi.AVLoadingIndicatorView
android:id="#+id/avloadingitem"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:visibility="gone"
app:indicator="BallClipRotate"
app:indicator_color="#color/colorAccent"/>
<!-- Imagen -->
<com.wallakoala.wallakoala.Views.ProductImageView
android:id="#+id/grid_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:riv_corner_radius_bottom_left="4dp"
app:riv_corner_radius_bottom_right="4dp"
app:riv_corner_radius_top_left="4dp"
app:riv_corner_radius_top_right="4dp"/>
<!-- Pie de foto -->
<RelativeLayout
android:id="#+id/footer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:alpha="0.75">
<!-- Info extra -->
<include android:id="#+id/extraInfo"
layout="#layout/product_footer_extra"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="visible"/>
<!-- Info principal -->
<include android:id="#+id/mainFooter"
layout="#layout/product_footer"
android:layout_height="#dimen/footer_height"
android:layout_width="match_parent"
android:layout_below="#id/extraInfo"/>
</RelativeLayout>
</FrameLayout>
</android.support.v7.widget.CardView>
This is my custom ImageView.
public class ProductImageView extends RoundedImageView
{
public ProductImageView(Context context)
{
super(context);
}
public ProductImageView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public ProductImageView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(), (int)(getMeasuredWidth() * 1.32f));
}
}
I know the aspect ratio of the images, so I can do this in onMeasure method to tell Android the height I want:
setMeasuredDimension(getMeasuredWidth(), (int)(getMeasuredWidth() * 1.32f));
So now it works perfectly with images with that aspect ratio,however, I want to get rid of this, as I want to download images with different aspect ratios. So, how can I tell Android to fit the width and adjust the height of the imageView maintaining the aspect ratio?
Thanks in advance,
Think you should add the adjustViewBounds attribute to your image tag
<ImageView
android:id="#+id/thumbview"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_gravity="center"
android:adjustViewBounds="true"/>
You ImageView in xml should have height wrap_content, like this..
<ImageView
android:id="#+id/grid_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY"/>
then, you should use post() method with picasso lib to load image from server.
imageView.post(new Runnable() {
#Override
public void run() {
Picasso.with(mActivity).load(path).resize(imageView.getWidth(), 0).into(imageView);
}
}); break;
There is a lib called ''Glide''. You can do this simply loading the image into a imageview and call .centercrop
ex: Glide.with(yourFragment)
.load(yourUrl)
.centerCrop()
.into(yourView);
Font> https://github.com/bumptech/glide/wiki/Transformations
What you're looking is: .fit().centerCrop() or .fit().centerInside()
Picasso
.with(context)
.load(imageUrl)
.fit()
.centerCrop()
// or .centerInside()
.into(myImageView)
fit: wait until the size of the ImageView can be measured, and resize the image to fit the ImageView
centerInside: The image will be displayed completely, but might not
fill the entire ImageView (Mantains aspect ratio)
centerCrop: scales the image so that it fills, cropping the extra
Related
I'm trying to create a GridLayout with images. The grid has 3 columns.
I have a few problems though:
The ImageViews are going off the screen, as shown in the image below. The GridLayout isn't properly setting the width of the ImageViews to fit.
There is no space/margin between the ImageViews, even though I have set the horizontalSpacing and verticalSpacing properties for the GridLayout.
Here is my current code. What should I change to fix my two problems?
<GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnCount="3"
android:horizontalSpacing="10dp"
android:verticalSpacing="10dp"
android:stretchMode="columnWidth">
<ImageView
android:layout_width="130dp"
android:layout_height="130dp"
android:background="#color/Color_DarkRed" />
<ImageView
android:layout_width="130dp"
android:layout_height="130dp"
android:background="#color/Color_DarkRed" />
<ImageView
android:layout_width="130dp"
android:layout_height="130dp"
android:background="#color/Color_DarkRed" />
<ImageView
android:layout_width="130dp"
android:layout_height="130dp"
android:background="#color/Color_DarkRed" />
<ImageView
android:layout_width="130dp"
android:layout_height="130dp"
android:background="#color/Color_DarkRed" />
<ImageView
android:layout_width="130dp"
android:layout_height="130dp"
android:background="#color/Color_DarkRed" />
</GridLayout>
Update
Following this answer, I tried using the following layout:
<GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnCount="3">
<com.my.package.view.SquareImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/Color_DarkRed" />
<com.my.package.view.SquareImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/Color_DarkRed" />
<com.my.package.view.SquareImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/Color_DarkRed" />
</GridLayout>
But it comes out looking like the image below. Each ImageView takes up the entire width of the screen:
http://i.imgur.com/p8AXcKN.png
You should reduce the layout_width="130dp" because your screen isn't guaranteed to be 390dp
Change the images or you can also use Square Image View for proper sizing of your Grid Items.
Create a separate class for defining the size dynamically for your ImageView that should inherit ImageView class as shown below:
public class SquareImageView extends ImageView {
public SquareImageView(Context context) {
super(context);
}
public SquareImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
int width = getMeasuredWidth();
setMeasuredDimension(width, width);
}
}
The setMeasuredDimension(width, width); will automatically set your height as the width.
In xml file use this class as a view in place of ImageView as shown below:
<com.packagepath.SquareImageView
android:id="#+id/Imageview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
I have a ListView with an ImageView and TextView, I want to set the width of the image as 2/3 of the screen.
How do I create a custom ImageView to do this? This is what I've tried so far.
Custom View
public class CustomImageListView extends ImageView {
public CustomImageListView(Context context) {
super(context);
}
public CustomImageListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomImageListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// Snap
// to
int width = MainActivity.width;
int height = MainActivity.height;
int w = width *2/5;
int h = w *4/6;
setMeasuredDimension(w, h);
// setMeasuredDimension(ChoseImage.width, ChoseImage.height); // Snap to
// //
// width
}
}
The custom View XML
<tuannt.tinmoi.custom.CustomImageListView
android:id="#+id/ivAvater"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/nomage" />
You can define a horizontal linear layout with WeightSum = 3 and inside it put another layout with with layout_weight = 1, the remaining portion will be of weight = 2, so you can put your imageView there. Refer below:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/fullscreen"
style="#style/translucent"
android:orientation="horizontal"
android:weightSum="3">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_gravity="right"
android:gravity="center"
android:background="#88000000"
android:id="#+id/sidebar"
android:layout_weight="1" >
</RelativeLayout>
<!-- other views, with a total layout_weight of 2 -->
</LinearLayout>
You don't need to create a Custom View to achieve this. You can make use of the layout_weight attribute.
This would be your layout for every item in the ListView.
item_in_listview.xml:
<?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:orientation="horizontal">
<ImageView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
The layout_weight attribute is explained in this question.
In a nutshell, layout_weight specifies how much of the extra space in
the layout to be allocated to the View.
I am trying to achieve following structure (image below). As you can see there are two sections with RecyclerViews and CardViews in it. These two sections are divided by two TextViews with Buttons.
Each section should match screen width (minus indent between cards). Each CardView has square ImageView in it. So the height of CardView itself depend on screen width: card_height = screen_width - indent_between_cards + space_for_card_text. To achieve this behaviour I use simple SquareImageView, which looks like this:
public class SquaredImageView extends ImageView {
public SquaredImageView(Context context) {
super(context);
}
public SquaredImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquaredImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
setMeasuredDimension(width, width);
}
}
The CardView layout looks like this:
<CardView
android:id="#+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="0dp"
android:background="#color/snow"
android:clickable="true"
android:orientation="vertical">
<!-- Image -->
<com.test.views.SquaredImageView
android:id="#+id/card_image"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- Content -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="32dp"
android:orientation="horizontal">
<!-- Title -->
<TextView
android:id="#+id/card_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:singleLine="true"
android:textColor="#color/stone_dark"
android:textSize="14sp" />
<!-- Button -->
<ImageView
android:id="#+id/card_menu"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:clickable="true"
android:scaleType="center"
android:src="#drawable/ic_menu" />
</LinearLayout>
</CardView>
It means, that RecyclerView's adapter don't know the dimensions of CardView in advance.
As you probably know, RecyclerView has no system, which can measure its child-views, to make wrap its content correctly.
But unpredictable SquareImageView + fullscreen RecyclerView works fine in most of cases except the one described in this question.
So what's the problem? You should use your own LayoutManager or WrappableLayoutManager by #se-solovyev to solve your problem.
The problem is in unpredictable SquareImageView. When LayoutManager tries to measure its child, it gets nothing. It means that RecyclerView displayed in fullscreen (as if height and width are set to match_parent).
So the question is: how to make RecyclerView with unpredictable SquareImageViews wrap its content correctly?
I have a ScrollView that contain one imageView
I want this imageView matching the parent width, full width of the screen and then keep ratio aspect, so wrapping the height.
My options where :
- layout_widht : match_parent
- layout_height : wrap_content
- scaletype : centerCrop
Here is the code
<?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="wrap_content"
android:fillViewport="true" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:id="#+id/cellarWineImageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:src="#drawable/etiquette_unknown" />
</LinearLayout>
</ScrollView>
Here is the result
If I just put a fixe height 348dp the result is here
After fighting, I suspect that the wrap content, consider the original height of the image, doesn't matter if the size change due to match parent of the width. Please help for such basic topic. And I hope we can handle this without making any code...
Based on Akshat Agarwal great answer, we can use simple stuff by extending ImageView into a a new component : AspectRatioImageView, and then reusing it directly in the layout.
package com.yourpackage.widgets;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageView;
public class AspectRatioImageView extends ImageView {
public AspectRatioImageView(Context context) {
super(context);
}
public AspectRatioImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AspectRatioImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (getDrawable() == null)
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
else {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = width * getDrawable().getIntrinsicHeight() / getDrawable().getIntrinsicWidth();
setMeasuredDimension(width, height);
}
}
}
Now to use it in the XML:
<com.yourpackage.widgets.AspectRatioImageView android:layout_centerHorizontal="true"
android:src="#drawable/yourdrawable" android:id="#+id/image"
android:layout_alignParentTop="true" android:layout_height="wrap_content"
android:layout_width="match_parent" android:adjustViewBounds="true" />
This works great on my project, by just changing curent ImageView, by this new packageName. Then everything worked perfectly.
Try putting on LinearLayout, ImageView and ScrollView your android:layout_height="fill_parent" to see if works.
Try this way,hope this will help you to solve your problem.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<ImageView
android:id="#+id/cellarWineImageView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:src="#drawable/ic_launcher"
android:scaleType="fitXY" />
</LinearLayout>
change the layout like this
<?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="wrap_content"
android:fillViewport="true" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:minHeight="348dp"
android:orientation="vertical" >
<ImageView
android:id="#+id/cellarWineImageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:minHeight="348dp"
android:src="#drawable/ic_launcher" />
</LinearLayout>
I have an image and I want to put it to full the screen fitting by width but cropping the top of the image, like this:
The red area is the image and the red one is the phone screen/parent layout. Of course, preserving aspect ratio. Is it possible in XML instead of programatically?
Ok for that You should Do This Steps:--
1). Make Linear Layout
2). apply the image as background
3). set the view at top to crop the background of layout.
i think you got what i am talking.
for example this is the xml:--
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#android:color/white">//background color of your screen
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="put the resource id of the image you want to crop"
android:orientation="vertical" >
<View
android:layout_width="match_parent"
android:layout_height="250dp"
android:background="#android:color/white" // background color of your screen
/>
</LinearLayout>
</LinearLayout>
Please tell me if there is any issue implementing it..
thanks enjoy,...
use
android:src="#drawable/img"
android:scaleType="fitEnd"
instead of
android:background
fitEnd retains aspect ratio as is written here
Finally I solved my problem using a custom view:
public class ResizableImageView extends ImageView {
public ResizableImageView(Context context) {
super(context);
}
public ResizableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ResizableImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Drawable drawable = getDrawable();
if (drawable != null) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int diw = drawable.getIntrinsicWidth();
if (diw > 0) {
int height = width * drawable.getIntrinsicHeight() / diw;
setMeasuredDimension(width, height);
return;
}
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
And, the XML file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_margin="0dp"
android:padding="0dp"
tools:context=".SplashActivity" >
<com.xxx.widgets.ResizableImageView
android:id="#+id/imageSplash"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_margin="0dp"
android:padding="0dp"
android:src="#drawable/img_splash"
tools:ignore="ContentDescription" />
</RelativeLayout>