Two gridView with one scroll in android - android

In a activity i need two GridView each of them take as much as it needs as height. No gridview has separate scrollbar but they have only one scrollbar.
I tried something like this.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<GridView
android:id="#+id/gridView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content" //as much height as it needs
android:background="#9C5353"
android:gravity="center"
android:horizontalSpacing="20dp"
android:numColumns="2"
android:layout_weight="1"
android:scrollbars="none"
android:stretchMode="columnWidth"
android:verticalSpacing="20dp" >
</GridView>
<GridView
android:id="#+id/gridView2"
android:layout_width="fill_parent"
android:layout_height="wrap_content" //as much height as it needs
android:scrollbars="none"
android:numColumns="1"
android:layout_weight="1"
android:horizontalSpacing="20dp"
android:verticalSpacing="20dp"
android:gravity="center"
android:stretchMode="columnWidth" >
</GridView>
</LinearLayout>
I tried many times but cant get any solution.
Please can anyone have any solution of this??

you can set the GridView Fixed ,and use ScrollView include them
public class FixedGridView extends GridView {
public FixedGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public FixedGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FixedGridView(Context context) {
super(context);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(
Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}

Extending on tesla1984's answer, here is my complete working code. It works as expected:
Create a new class named FlexGridView as follows, and save it on a known location inside your project. (I used a folder called "views")
package your.project.id.views;
public class FixedGridView extends GridView {
public FixedGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public FixedGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FixedGridView(Context context) {
super(context);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = View.MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, View.MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
Then, on your XML, do something like this:
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<your.product.id.views.FixedGridView
android:id="#+id/gridViewPublic"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:numColumns="1"
android:stretchMode="columnWidth"
android:horizontalSpacing="10"
android:verticalSpacing="10"
android:background="#color/transparent_color" />
<your.product.id.views.FixedGridView
android:id="#+id/gridViewPrivate"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10"
android:layout_marginBottom="10"
android:numColumns="2"
android:stretchMode="columnWidth"
android:horizontalSpacing="10"
android:verticalSpacing="10"
android:background="#color/transparent_color" />
</LinearLayout>
</ScrollView>

Related

scrollview with listview not working

I've only included one direct child in the scroll view , and i've added the below codes in the java files. When i remove the Utility method the listview appear fully, but doesnt work as a scrollview
ScrollView sv_fragment_globe;
sv_fragment_globe = (ScrollView)rowView.findViewById(R.id.sv_fragment_globe);
sv_fragment_globe.smoothScrollTo(0,0);
Utility.setListViewHeightBasedOnChildren(holder.lv_globe);
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/sv_fragment_globe"
android:fillViewport="true"
>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="0dp"
android:orientation="vertical"
>
<ImageView
android:layout_width="fill_parent"
android:layout_height="200dp"
android:src="#drawable/home_hospital1"
android:id="#+id/iv_vp_globe"
android:scaleType="fitXY"
/>
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/lv_globe"
>
</ListView>
</LinearLayout>
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
If you have more than two scrolling views inside any Layout, then the parent scrolling view will only scrolls. Follow the steps below to allows the child's scrolling elements to scroll.
Step 1:
Create a custom ListView.
public class ExpandableHeightListView extends ListView
{
boolean expanded = false;
public ExpandableHeightListView(Context context)
{
super(context);
}
public ExpandableHeightListView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public ExpandableHeightListView(Context context, AttributeSet attrs,int defStyle)
{
super(context, attrs, defStyle);
}
public boolean isExpanded()
{
return expanded;
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
// HACK! TAKE THAT ANDROID!
if (isExpanded())
{
// 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();
}
else
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public void setExpanded(boolean expanded)
{
this.expanded = expanded;
}
}
Step 2: Add the line below after initializing the Listview object.
lv_selected_time_zone.setExpanded(true);
Try this
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="1"
>
<ImageView
android:layout_width="match_parent"
android:layout_height="200dp"
android:src="#android:drawable/home_hospital"
android:id="#+id/iv_vp_globe"
android:scaleType="fitXY"
/>
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/lv_globe"
android:layout_weight="1"
>
</ListView>
</LinearLayout>
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>

ListView inside ScrollView makes adapter call multiple times

Here is the sample code,
contact.xml
<ScrollView
android:id="#+id/scroll_view"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
android:layout_marginBottom="55dp">
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:id="#+id/card_view"
style="#style/ContentFrame"
android:layout_marginTop="20dp"
android:layout_marginBottom="15dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:id="#+id/msg_listview_frame"
android:layout_marginTop="10dp">
<com.android.bundle.helper.NonScrollListView
android:id="#+id/contact_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#color/white_lilac"
android:dividerHeight="1dp"
android:footerDividersEnabled="false"
android:scrollbars="none">
</com.android.bundle.helper.NonScrollListView>
</LinearLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
</ScrollView>
To make ListView non-scrollable, I'm using this custom class NonScrollListView.
NonScrollListView.java
public class NonScrollListView extends ListView {
public NonScrollListView(Context context) {
super(context);
}
public NonScrollListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NonScrollListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
}
}
The adapter is been called more than 40 times, I have tried a couple of options from StackOverflow like changing listview height = fill_parent as well as match_parent.
I know this is an old issue, I'm new to android not able to resolve this one. Kindly help to resolve this issue.
Note: At any cost, ListView has to be inside ScrollView. I want to make CardView be scrollable.
Thanks

ScrollView with ExpandableHeightGridView doesn't scroll

I want the homepage of my app to have different sections containing a list of items in every section. For this I have used a ScrollView. Inside the scrollview I have put a search area, and a ExpandableHeightGridView (this is a custom class that help the GridView to expand the space inside the ScrollView based on the number of items).
But regardless of this the scrollView doesn't work and search box appears at the top of the screen, meanwhile the GridView scrolls as if it wasn't inside ScrollView.
Below is my Code:
activity_main.xml
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/njoftime_background">
<ScrollView
android:id="#+id/sv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"
android:layout_marginTop="?android:attr/actionBarSize"
android:orientation="vertical">
<RelativeLayout
android:id="#+id/sr"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#drawable/event_background_block"
android:padding="5dp">
<RelativeLayout
android:id="#+id/search_area"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:focusableInTouchMode="true"
android:background="#drawable/njoftime_item_background">
<ImageButton
android:id="#+id/btn_search"
android:layout_width="65dp"
android:layout_height="35dp"
android:layout_alignParentRight="true"
android:layout_marginLeft="1dp"
android:background="#color/njoftime_main_color"
android:onClick="searchPressed"
android:scaleType="fitCenter"
android:src="#drawable/ic_search_white" />
<EditText
android:id="#+id/search_text"
android:layout_width="fill_parent"
android:layout_height="35dp"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="#+id/btn_search"
android:background="#null"
android:ems="20"
android:imeOptions="actionSearch"
android:inputType="text"
android:maxLines="1"
android:paddingLeft="7dp"
android:textColor="#color/njoftime_desc"
android:textCursorDrawable="#null"
android:textSize="17sp" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/search_categories_area"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/search_area"
android:paddingBottom="7dp"
android:paddingTop="13dp">
<GridView
android:id="#+id/search_grid"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:drawSelectorOnTop="false"
android:horizontalSpacing="2dp"
android:numColumns="4" />
</RelativeLayout>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.example.crs.tempus.ExpandableHeightGridView
android:id="#+id/njoftime_list"
android:layout_width="match_parent"
android:horizontalSpacing="5dp"
android:verticalSpacing="5dp"
android:layout_marginTop="5dp"
android:layout_height="wrap_content"
android:background="#color/white"
android:drawSelectorOnTop="true"
android:numColumns="1" />
</RelativeLayout>
</LinearLayout>
</ScrollView>
<RelativeLayout
android:id="#+id/left_drawer"
android:layout_width="230dp"
android:layout_height="fill_parent"
android:layout_gravity="start"
android:layout_marginTop="?android:attr/actionBarSize"
android:background="#color/white"
android:orientation="vertical">
<ExpandableListView
android:id="#+id/list_slidermenu"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#color/white"
android:choiceMode="singleChoice"
android:dividerHeight="1dp"
android:drawSelectorOnTop="true"
android:groupIndicator="#null"
android:paddingBottom="13dp"
android:paddingLeft="7dp"
android:paddingRight="7dp"
android:paddingTop="13dp"></ExpandableListView>
</RelativeLayout>
</android.support.v4.widget.DrawerLayout>
ExpandableHeightGridView
public class ExpandableHeightGridView extends GridView
{
boolean expanded = false;
public ExpandableHeightGridView(Context context)
{
super(context);
}
public ExpandableHeightGridView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public ExpandableHeightGridView(Context context, AttributeSet attrs,
int defStyle)
{
super(context, attrs, defStyle);
}
public boolean isExpanded()
{
return expanded;
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
// HACK! TAKE THAT ANDROID!
if (isExpanded())
{
// Calculate entire height by providing a very large height hint.
// View.MEASURED_SIZE_MASK represents the largest height possible.
int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
}
else
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public void setExpanded(boolean expanded)
{
this.expanded = expanded;
}
}
The ExpandableHeightGridView, is used also in another activity and it works.
Any idea?
1) In your ExpandableHeightGridView class use below code inside your onMeasure override method. It works in my case.
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
Or
2) In your code you might need to call setExpanded method of ExpandableHeightGridView class and set it to true.
Hope one of this solution would works for you.
UPDATED---------
try to use a customScollview,create one CustomScrollview like this and use this
public class CustomScrollView extends ScrollView {
public CustomScrollView(Context context) {
super(context);
}
public CustomScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public CustomScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}
}
android:fillviewport="true"
add this in your ScrollView ,like this
<CustomScrollView
android:fillviewport="true"
android:id="#+id/sv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white">

Combining layout_weight and maxHeight

I'm quite new to Android programming and I'm stuck on an simple problem.
I have a basic homepage with some buttons and a logo. I use a LinearLayout and the layout_weight attribute to distribute all the components.
Here is my code :
<LinearLayout 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"
android:orientation="vertical"
tools:context="iut.project.findmeapp.MainActivity" >
<ImageView
android:id="#+id/activityMainAppLogoIv"
android:layout_width="match_parent"
android:layout_height="#dimen/null_height"
android:contentDescription="#string/description_logo"
android:layout_weight="1"
android:maxHeight="#dimen/img_maxHeight"
android:layout_margin="#dimen/img_margin"
android:src="#drawable/ic_launcher" />
<Button
android:id="#+id/activityMainMyEventsBtn"
android:layout_width="match_parent"
android:layout_height="#dimen/null_height"
android:layout_marginTop="#dimen/button_margin_vertical"
android:layout_marginBottom="#dimen/button_margin_vertical"
android:layout_weight="1"
android:text="#string/my_events" />
<Button
android:id="#+id/activityMainMyContactsBtn"
android:layout_width="match_parent"
android:layout_height="#dimen/null_height"
android:layout_marginTop="#dimen/button_margin_vertical"
android:layout_marginBottom="#dimen/button_margin_vertical"
android:layout_weight="1"
android:text="#string/my_contacts" />
<Button
android:id="#+id/activityMainLastNotifBtn"
android:layout_width="match_parent"
android:layout_height="#dimen/null_height"
android:layout_marginTop="#dimen/button_margin_vertical"
android:layout_marginBottom="#dimen/button_margin_vertical"
android:layout_weight="1"
android:text="#string/last_notification" />
<TextView
android:id="#+id/activityMainCopyrightTv"
android:layout_width="match_parent"
android:layout_height="#dimen/null_height"
android:gravity="center"
android:layout_weight="0.5"
android:layout_margin="#dimen/tw_margin"
android:text="#string/copyright" />
</LinearLayout>
(Note : #dimen/null_height is 0dp)
My problem is that I want the image to scale with the size of the screen, but I don't want it pixelated : I have set a maximum height of 200px.
The following lines don't seem to work, because the image has no limit and totally ignores the maxHeight attribute.
android:layout_weight="1"
android:maxHeight="#dimen/img_maxHeight"
Actually it looks like this (example image) :
It works perfectly, but when I set maxHeight to 10px for example, nothing changes.
How can I achieve this ? I highly prefer to use a LinearLayout.
Thank you in advance.
Thanks to Evripidis Drakos for pointing me in the right direction. Just need a check to only set the max height if it's actually required.
public class MaxHeightImageView extends ImageView {
public static final int MAX_HEIGHT_NOT_SET = -1;
public static final int INDEX_MAX_HEIGHT = 0;
private static final int[] STYLE_ATTRIBUTE_ARRAY = {
android.R.attr.maxHeight,
};
private int myMaxHeight;
public MaxHeightImageView(Context context) {
super(context);
init(context, null);
}
public MaxHeightImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public MaxHeightImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public MaxHeightImageView(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int size = MeasureSpec.getSize(heightMeasureSpec);
if(MAX_HEIGHT_NOT_SET != myMaxHeight && size > myMaxHeight) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(myMaxHeight, MeasureSpec.AT_MOST);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private void init(Context context, AttributeSet attrs) {
if(context != null) {
TypedArray ta = context.obtainStyledAttributes(attrs,
STYLE_ATTRIBUTE_ARRAY);
myMaxHeight = ta.getDimensionPixelSize(INDEX_MAX_HEIGHT, 0);
} else {
myMaxHeight = MAX_HEIGHT_NOT_SET;
}
}
}
I dont think that you can combine layout_weight with maxHeight.
You could try subclassing ImageView to override the onMeasure method like so:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(200, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
if u want to set exact height for your image u should use weightSum property with weight
edit:
for fixed height do not give weight for imageview just take parent layout for imageview then add weight for that linear layout(parent layout) and for imageview give height as wrap content and maxHeight. when u use weight with height="0dp" the content will capture the whole height so it will ignore maxHeight.
try this
<LinearLayout 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:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:weightSum="5"
tools:context="iut.project.findmeapp.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="#+id/activityMainAppLogoIv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:contentDescription="#string/quantity_hint"
android:maxHeight="200px"
android:src="#drawable/ic_launcher" />
</LinearLayout>
<Button
android:id="#+id/activityMainMyEventsBtn"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="my_events" />
<Button
android:id="#+id/activityMainMyContactsBtn"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="my_contacts" />
<Button
android:id="#+id/activityMainLastNotifBtn"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="last_notification" />
<TextView
android:id="#+id/activityMainCopyrightTv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight=".5"
android:gravity="center"
android:text="copyright" />
</LinearLayout>

How to force GridView to generate square cells in Android

How can I force an android GridView to generate square cells (Cell's height equal to cell's width)
GridView has 10*9 cells and the app must support multiple screens !
I used a Linear Layout:
row_grid.xml
<LinearLayout 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:padding="0dp" >
<ImageView
android:id="#+id/item_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:src="#drawable/ic_launcher" >
</ImageView>
</LinearLayout>
and GridView:
activity_main.xml
<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:background="#drawable/katy" >
<GridView
android:id="#+id/gridView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:horizontalSpacing="0dp"
android:numColumns="4"
android:stretchMode="columnWidth"
android:verticalSpacing="0dp" >
</GridView>
</RelativeLayout>
Each cell of GridView contains a image that has same width and height.
images are larger than cells and must stretch to fit in cells.
First, you're going to want to create a custom View class that you can use instead of the default LinearLayout you're using. Then you want to override the View's onMeasure call, and force it to be square:
public class GridViewItem extends ImageView {
public GridViewItem(Context context) {
super(context);
}
public GridViewItem(Context context, AttributeSet attrs) {
super(context, attrs);
}
public GridViewItem(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec); // This is the key that will make the height equivalent to its width
}
}
Then you can change your row_grid.xml file to:
<path.to.item.GridViewItem xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/item_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="#drawable/ic_launcher" >
</path.to.item.GridViewItem>
Just be sure to change "path.to.item" to the package where your GridViewItem.java class resides.
I also removed your LinearLayout parent since it wasn't doing anything for you there.
Edit:
Also changed scaleType from fitXY to centerCrop so that your image doesn't stretch itself and maintains its aspect ratio. And, as long as it's a square image, nothing should be cropped, regardless.
You can Override your linear layout
public class MyLinearLayout extends LinearLayout {
public MyLinearLayout(Context context) {
super(context);
}
public MyLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec); // This is the key that will make the height equivalent to its width
}
}
then use it in the item_grid.xml
<?xml version="1.0" encoding="utf-8"?>
<com.example.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/item_grid"
android:layout_margin="2dp"
android:padding="3dp"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Category Name"
android:textStyle="bold"
android:textColor="#color/colorPrimary"
android:id="#+id/tvCategoryName" />
</com.example.MyLinearLayout>
How about using ConstraintLayout?
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="3dp">
<ImageView
android:id="#+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerCrop"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Works nicely, thank you! A small improvement I required would be always pick the smaller value, to prevent overshooting the screen:
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if(heightMeasureSpec < widthMeasureSpec) {
super.onMeasure(heightMeasureSpec, heightMeasureSpec);
} else if(widthMeasureSpec < heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;
public class GridViewItem extends RelativeLayout {
public GridViewItem(Context context) {
super(context);
}
public GridViewItem(Context context, AttributeSet attrs) {
super(context, attrs);
}
public GridViewItem(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec); // This is the key that will make the height equivalent to its width
}
}
If your grid item just have an image then the answer is very good. But you want to add multiple items in your grid item then you must create Your Custom GridViewItem extending the layout you want your grid item to be. For example in my case I had RelativeLayout as the parent view so I created GridViewItem extending the RelativeLayout and it worked flawlessly.
Just make sure that your images are square. And make the container wrap_content.

Categories

Resources