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" />
Related
i'm trying to create a circular CardView. But I don't know how to do it. Is there any attribute with which I can get a Circular CardView?.
The XML code is the following:
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_view_outer"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_gravity="center"
card_view:cardBackgroundColor="#android:color/transparent"
card_view:cardCornerRadius="0dp"
card_view:cardElevation="3dp" >
</android.support.v7.widget.CardView>
Just use the shapeAppearanceOverlay attribute:
<com.google.android.material.card.MaterialCardView
android:layout_width="100dp"
android:layout_height="100dp"
app:cardBackgroundColor="#color/colorPrimaryLight"
app:shapeAppearanceOverlay="#style/circle"
/>
with:
<style name="circle">
<item name="cornerSize">50%</item>
</style>
<androidx.cardview.widget.CardView
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_margin="10dp"
app:cardCornerRadius="100dp"/>
May be changing app:cardCornerRadius to half of the width and height.
OR
May be Custom CardView
public class CircularCardView extends CardView {
public CircularCardView(#NonNull Context context) {
super(context);
}
public CircularCardView(#NonNull Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
}
public CircularCardView(#NonNull Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
setMeasuredDimension(width, width);
setRadius(width/2);
}
}
XML
<com.yourpackage.name.CircularCardView
android:layout_width="50dp"
android:layout_height="100dp"
android:layout_margin="10dp"
app:cardElevation="10dp"
/>
I wanted to have a circular image So did something like this
<androidx.cardview.widget.CardView
android:id="#+id/roundCardView"
android:layout_width="100dp"
android:layout_height="100dp"
android:elevation="0dp"
app:cardCornerRadius="10dp"
app:layout_constraintTop_toTopOf="#id/userName"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="20dp">
<ImageView
android:id="#+id/profilePic"
android:layout_width="100dp"
android:layout_height="100dp" />
</androidx.cardview.widget.CardView>
Its better if you migrate to androidx but you can use this code add shape to your card view
<app:android.support.v7.widget.CardView
android:layout_width="150dp"
android:layout_height="148dp"
android:elevation="12dp"
app:cardCornerRadius="75dp"
android:layout_centerHorizontal="true"
android:innerRadius="40dp"
android:shape="ring"
android:thicknessRatio="4">
</app:android.support.v7.widget.CardView>
This worked for me for all Android Versions
<androidx.cardview.widget.CardView
android:layout_width="90dp"
android:layout_height="90dp"
app:cardCornerRadius="45dp"
android:shape="ring"
app:cardElevation="5dp">
I have a layout which contains only a LinearLayour with 3 buttons inside.
I would want this 3 buttons to fill the screen vertically so I used "weigth=1" but I should also want the buttons to be square, that is, that their width is equal to their height.
Any way to do it?
Here's the .xml file
<?xml version="1.0" encoding="utf-8"?>
<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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="android.jose.se.Prueba"
android:background="#drawable/bg"
android:gravity="center">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="#+id/bHet"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#drawable/layer1"
android:onClick="cambiarBoton"/>
<Button
android:id="#+id/bGay"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#drawable/layer2"
android:onClick="cambiarBoton"/>
<Button
android:id="#+id/bLesbi"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#drawable/layer3"
android:onClick="cambiarBoton"/>
</LinearLayout>
</RelativeLayout>
I had similar issue and done it using Google's Percent Relative Layout that helps you manage view aspect ratio.
You can use it like this
<android.support.percent.PercentRelativeLayout
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="match_parent">
<Button
android:layout_width="match_parent"
app:layout_aspectRatio="100%"/>
</android.support.percent.PercentFrameLayout>
The best way to do this, is to make a new Class called Square button and this class should extend Button. Then in the onMeasure of this class, simply make your heightSpec as WidthSpec.
public class SquareButton extends Button {
public SquareButton(Context context) {
super(context);
}
public SquareButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onMeasure(int WidthSpec, int HeightSpec){
int newWidthSpec = HeightSpec ;
super.onMeasure(newWidthSpec, HeightSpec);
}}
Now you can use this SquareButton instead of a normal Button in your xml like this. The value of android:width attribute will be ignored.
<com.example.package.SquareButton
android:height = "0dp"
android:weight = "1"
android:width = "0dp"
/>
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?
currently I am developing a settings menu in a scrollview. The basic structure looks like the following:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:id="#+id/scrollview_settings"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="#dimen/paddingSmall">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/transparent_white_settings"
android:paddingTop="#dimen/paddingMedium"
android:paddingBottom="#dimen/paddingMedium">
<ImageView
android:id="#+id/logo"
android:layout_width="68dp"
android:layout_height="wrap_content"
android:src="#drawable/newspaper_logo_color"
android:layout_alignParentRight="true"
android:layout_margin="#dimen/paddingBig"
android:adjustViewBounds="true"/>
</RelativeLayout>
<!-- Layout News Uebersicht -->
<include layout="#layout/separator_line_grey"/>
<de.basecom.noznewsapp.views.FontTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="true"
android:textColor="#color/buttonHoverBackground"
android:textSize="#dimen/sliding_image_kicker_font_size"
android:paddingLeft="#dimen/paddingLarge"
android:paddingTop="#dimen/paddingMedium"
android:paddingBottom="#dimen/paddingMedium"
android:text="#string/news_overview"
android:textScaleX="#dimen/letter_spacing"
android:textStyle="bold"
android:gravity="center_vertical"
android:background="#color/settings_header_color"
android:layout_gravity="center_vertical"/>
<include layout="#layout/separator_line_grey"/>
<!-- News-Overview Issues -->
<LinearLayout
android:id="#+id/issue_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#color/transparent_white_settings">
<de.basecom.noznewsapp.views.NewsScrollListView
android:id="#+id/listview_issues"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants"
android:divider="#null"
android:dividerHeight="0dp" />
</LinearLayout>
<!-- Layout Einstellungen -->
<de.basecom.noznewsapp.views.FontTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="true"
android:textColor="#color/buttonHoverBackground"
android:textSize="#dimen/sliding_image_kicker_font_size"
android:paddingLeft="#dimen/paddingLarge"
android:paddingTop="#dimen/paddingMedium"
android:paddingBottom="#dimen/paddingMedium"
android:text="#string/settings"
android:textStyle="bold"
android:textScaleX="#dimen/letter_spacing"
android:gravity="center_vertical"
android:background="#color/settings_header_color"
android:layout_gravity="center_vertical"/>
<include layout="#layout/separator_line_grey"/>
<!-- Einstellungs- Werte -->
<LinearLayout
android:id="#+id/settings_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#color/transparent_white_settings">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/paddingLarge">
<de.basecom.noznewsapp.views.FontTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/receive_pushmessages"
android:textAllCaps="true"
android:textScaleX="#dimen/letter_spacing"
android:textSize="#dimen/sliding_image_kicker_font_size"
android:layout_centerVertical="true"
android:textColor="#color/buttonBackground"/>
<Switch
android:id="#+id/receive_pushmessages_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="#string/empty_string"/>
</RelativeLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>
For the listview I used a custom implementation, to give it a fix height and make it able to scroll within the scrollview (note: I have to use the listview within the scrollview, because I have lots of elements, so that using a linearlayout wouldn't be nice).
public class CustomListView extends ListView {
public CustomListView(Context context) {
super(context);
}
public CustomListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomListView(Context context, AttributeSet attrs,int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Calculate entire height by providing a very large height hint.
// But do not use the highest 2 bits of this integer; those are
// reserved for the MeasureSpec mode.
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
}
}
Each item of the listview contains a label and a gridview, which is all shown correctly. But now I want to implement the functionality, that the user can click on the label to show and hide the visibility of the gridview.
But if I click on the label and the gridview is shown, the height of the listview doesn't adapt to the new open element. It always stays at the same height and if I open an element, the elements below are no longer visible. This also even happens, if I call the requestLayout() method of the listview to trigger its onMeasure again.
Anybody got an idea what I am doing wrong?
EDIT: Updated my xml file :)
Finally I was only able to solve this issue by replacing Listview with a LinearLayout and add my items in code to the Layout.
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>