Android GridView stretchMode with Async ImageView Loading - android

I have the following GridView defined w/stretchMode set to "columnWidth".
<GridView android:id="#+id/grid"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:columnWidth="160dp"
android:numColumns="auto_fit"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:listSelector="#drawable/list_selector"
/>
Each item in the GridView is structured as follows.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="2dp"
>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<ImageView android:id="#+id/videoGridItemImage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
/>
<TextView android:id="#+id/videoGridItemDuration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#88000000"
android:textColor="#F1F1F1"
android:textAppearance="#android:style/TextAppearance.Small"
android:padding="2dp"
/>
</FrameLayout>
<TextView android:id="#+id/videoGridItemTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="left"
android:textAppearance="#android:style/TextAppearance.Medium"
android:textColor="#F1F1F1"
android:maxLines="1"
android:background="#88000000"
android:paddingLeft="2dp"
android:paddingRight="2dp"
/>
<TextView android:id="#+id/videoGridItemSubtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="left"
android:textStyle="italic"
android:textColor="#666"
android:textAppearance="#android:style/TextAppearance.Small"
android:maxLines="1"
android:background="#88000000"
android:paddingLeft="2dp"
android:paddingRight="2dp"
/>
</LinearLayout>
In the GridView's adapter, I'm async loading and displaying the images by passing the url and reference of the ImageView to a dedicated class. The class downloads the image into a bitmap and then updates the ImageView using setImageBitmap(). This workflow functions as expected; however, my images aren't filling the entire width of the ImageView. There's a small amount of paddding on the left/right sides. I realize that I can use scaleType="fitXY", but this isn't ideal as it skews the images. Setting the src attribute of ImageView to a local image scales just fine with stretchMode="columnWidth". My guess is that the ImageView is scaling to the original columnWidth and not the stretched/dynamic width. Does anyone have any insight as to why this is occurring and/or how to fix? Thanks in advance for your help.

You have two options:
Set your ImageView's layout_width to wrap_content. The ImageView will resize based on the size of the image and your column will adjust accordingly.
Set your ImageView's scaleType to centerCrop. This will try to fit the image into the imageview without skewing it and will just cut off any excess that doesn't fit. This will leave no blank space.

I had the same issue. My solution was to override the ImageView (in my case) FrameLayout to set it's height prior to image download. I wanted square tiles enforced in my GridView, and accomplished like so:
public class SquareFrameLayout extends FrameLayout {
public SquareFrameLayout(Context context) {
super(context);
}
public SquareFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareFrameLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
}
Each GridView item is this:
<com.my.client.ui.layout.SquareFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/discovery_tile"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageView
android:id="#+id/my_image"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="centerCrop"
android:cropToPadding="true"
android:contentDescription="#string/my_desc" />
</com.my.client.ui.layout.SquareFrameLayout>
Then in the GridView I used this:
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:name="com.my.client.ui.MyFragment"
android:id="#+id/my_gridview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="3"
android:verticalSpacing="0px"
android:horizontalSpacing="0px"
android:stretchMode="columnWidth"
android:gravity="fill" />

Related

Setting view height dependent on its width in android in layout xml

Is it possible that a view should make it height same as it's width?
or any other layout for this purpose, because for vector image it's compulsory to provide width and height.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/googleLoginBtn"
android:orientation="horizontal"
android:layout_centerVertical="true">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<ImageView
android:layout_width="fill_parent"
android:layout_height="<height should be equal to the width>"
app:srcCompat="#drawable/simple"
tools:ignore="MissingPrefix"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Snappy"
android:textColor="#FF4081"
android:textSize="30dp"
android:singleLine="true"
android:gravity="center"
android:layout_margin="10dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Type less, do more. Fastest way to transfer money & make other transactions."
android:layout_margin="10dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:srcCompat="#drawable/simple"
tools:ignore="MissingPrefix"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Smart"
android:textColor="#FF4081"
android:textSize="30dp"
android:gravity="center"
android:layout_margin="10dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Type less, do more. Fastest way to transfer money & make other transactions."
android:layout_margin="10dp"/>
</LinearLayout>
</LinearLayout>
Update:
I would use a ConstraintLayout today and use the property app:layout_constraintDimensionRatio="1:1"
Old Answer:
It's not possible entirely in xml without using a custom ImageView. This would be a solution:
public class SquareImageView extends ImageView {
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
setMeasuredDimension(width, width);
}
}
However if your Image is already Square you can use the normal ImageView:
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitCenter"
android:adjustViewBounds="true" />
A third solution would be setting the width and height directly in your Code:
LayoutParams params = imageView.getLayoutParams();
params.height = params.width ;
imageView.setLayoutParams(params);
You should be able to use the Percent support library for this.
You can either replace the LinearLayout the ImageViewis inside of with a PercentRelativeLayout and have the other views android:layout_belowor wrap the ImageView in a PercentFrameLayout.
I'm going to assume you've already defined the app namespace in this file as xmlns:app="http://schemas.android.com/apk/res-auto" since I see you using the namespace.
Once you've included the appropriate support library, the PercentFrameLayout approach would look something like this:
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<android.support.percent.PercentFrameLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="fill_parent"
app:layout_aspectRatio="100%"
app:srcCompat="#drawable/simple"
tools:ignore="MissingPrefix"/>
</android.support.percent.PercentFrameLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Snappy"
android:textColor="#FF4081"
android:textSize="30dp"
android:singleLine="true"
android:gravity="center"
android:layout_margin="10dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Type less, do more. Fastest way to transfer money & make other transactions."
android:layout_margin="10dp"/>
</LinearLayout>
Just a little update: The PercentFrameLayout class was deprecated in API level 26.1.0. Consider using ConstraintLayout and associated layouts instead. More information here: https://developer.android.com/reference/android/support/percent/PercentFrameLayout
use this
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
int myWidth = (int) (parentHeight * 0.5);
super.onMeasure(MeasureSpec.makeMeasureSpec(myWidth, MeasureSpec.EXACTLY), heightMeasureSpec);
}

How to use wrap_content with a maximum width?

I am trying to layout a view that should wrap its content, but it shouldn't be more than ~100dp less than its parent width. How can I do that using a RelativeLayout or some other layout? What I have right now will always make the view 100dp less than its parent so that there is space for another view.
This picture is an example of what I have:
As you can see, the text doesn't fill the whole box, so it could be smaller. But, it should never be larger than 100dp less than its parent, so that there is room for the time the message was sent.
This is my layout.
<?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:clipChildren="false"
android:orientation="vertical"
android:paddingBottom="10dp"
android:paddingRight="#dimen/horizontalMargin"
android:paddingTop="10dp">
<TextView
android:id="#+id/message_holder"
android:layout_toLeftOf="#id/blank"
android:layout_alignParentLeft="true"
android:layout_marginLeft="#dimen/horizontalMargin"
android:background="#drawable/message_corners"
style="#style/white_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="alsdkjf; alsdkf" />
<RelativeLayout
android:id="#+id/blank"
android:layout_width="wrap_content"
android:layout_height="1dp"
android:layout_alignParentRight="true"
android:minWidth="100dp">
</RelativeLayout>
<TextView
android:minWidth="100dp"
android:id="#+id/time"
style="#style/gray_text"
android:layout_toRightOf="#id/message_holder"
android:paddingLeft="10dp"
android:text="Yesterday,\n11:30 PM" />
<RelativeLayout
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignBottom="#id/message_holder"
android:layout_alignParentLeft="true"
android:background="#drawable/triangle" />
</RelativeLayout>
I have tried using the "minWidth" property on a blank view to the right of the message box to provide spacing, but it doesn't resize to be larger (which would make the message box smaller). When I don't have the blank view, and simply place the time TextView to the right of the message box, then that TextView isn't visible when the message box expands.
Update:
This is my "message_corners.xml":
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid
android:color="#color/green" >
</solid>
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" >
</padding>
<corners
android:radius="10dp">
</corners>
</shape>
Update 2:
This is what I am looking for in a layout with short text:
And this is what I am looking for in a layout with long text:
Here you go, a layout that does exactly what you want.
<?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:clipChildren="false"
android:paddingBottom="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp">
<RelativeLayout
android:id="#+id/blank"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#aaaaaa">
<LinearLayout
android:id="#+id/message_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="100dp">
<TextView
android:id="#+id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello?"
android:background="#00ff00" />
</LinearLayout>
<TextView
android:id="#+id/time"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/message_container"
android:layout_marginLeft="-100dp"
android:text="12:30 PM"
android:background="#ff0000" />
</RelativeLayout>
</RelativeLayout>
Short message
Long message
I know this is a really old question, but it's a frustrating problem I've encountered several times now and the existing answers weren't quite what I was looking for. Some colleagues and I came up with the following:
<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
android:orientation="vertical"
android:background="#FFFFFF">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#888888"
android:padding="10dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#00FF00"
tools:text="Short message."/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="0"
android:background="#CCCCCC"
tools:text="Yesterday,\n11:30pm"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="#888888"
android:padding="10dp"
android:orientation="horizontal">
<TextView
android:id="#+id/message_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#00FF00"
tools:text="Super ultra mega awesome long message which is going to help us take over the world."/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="0"
android:background="#CCCCCC"
tools:text="Yesterday,\n11:31pm"/>
</LinearLayout>
</LinearLayout>
Which looks like this when rendered:
The magic seems to be the zero value for the weight of the text box on the right (in addition to the non-zero weight value of the text box on the left, which some of the other answers already have).
Honestly, I can't explain exactly why it works, but after having looked for a solution to this for so long I'm not questioning it! :)
As an aside, I like this approach because it doesn't require any explicit or minimum widths, any intermediate wrapper views, or the use of clipping settings, margins, padding, etc. to implement view overlay.
What the author of this question really asks is, how to let the TextView expand to fit the message inside of it without overflowing the time TextView, and without leaving blank spaces.
Since you don't actually know the width of the whole screen, you can't tell your TextView to be 100dp less than it.
What you should do is wrap your TextView in a container which will have the toLeftOf rule, with the TextView only wrapping it's contents. This way, the container will expand all the way up to the right (without overflowing the time TextView) but the TextView will only wrap it's text contents (so, it won't extend any blank spaces)
Code
Instead of
<TextView
android:id="#+id/message_holder"
android:layout_toLeftOf="#id/blank"
android:layout_alignParentLeft="true"
android:layout_marginLeft="#dimen/horizontalMargin"
android:background="#drawable/message_corners"
style="#style/white_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="alsdkjf; alsdkf" />
Use
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="#id/blank"
android:layout_alignParentLeft="true"
android:layout_marginLeft="#dimen/horizontalMargin">
<TextView
android:id="#+id/message_holder"
android:background="#drawable/message_corners"
style="#style/white_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="alsdkjf; alsdkf" />
</LinearLayout>
By the way, your layout isn't very good. You should optimize it.
You can try the following arrangement of views and their widths:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="6dp"
>
<FrameLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/holo_blue_bright"
tools:text="Some long test is this which is support to wrap at the end of parent view"
/>
</FrameLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
tools:text="Yesterday,\n 11:30 PM"
/>
</LinearLayout>
Sat Sri Akal
This can also be achieved using ConstraintLayout
with 2 children in horizontal chain
1st child
layout width 0
constraint weight 1
constraint max width wrap
2nd child
layout width wrap content
A solution with ConstraintLayout using
app:layout_constrainedWidth
layout_constraintHorizontal_bias
layout_constraintHorizontal_chainStyle
.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/edt_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sample content"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toStartOf="#id/button_right"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/button_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Right Button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/edt_left"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
If you want to make time text on right and text message on its left, you can do something like that ( using this in relative layout) also you can use maxWidth not minWidth
<TextView
android:id="#+id/view_textView_timeText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="#id/view_textView_timeText"
android:maxWidth="100dp"/>
What you could do is put an empty view between the 2 views and keep its width as MATCH_PARENT and assign the textview to leftof this empty view and the empty view to left of the date view. Just make sure to keep the view empty.
As i understand you want to make the layout or the textview to be 100 dp less than the screen size
Which you can do by getting the screen width in pixels which is done by this
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
Then you could set the textbiew width to be less 100dp from the screen size hope this help
P.s I think you might want to convert dp to px but i am not sure
You can do like this(not the direct answer for the question ):
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="bottom"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:paddingLeft="45px"
android:text="asdfadsfsafasdfsakljkljkhjhkkhjkjhjkjhjkhjkhljkhlkhjlkjhljkhljkhlkjhljkhljkhlfasd"
android:textColor="#4a4a4a"
android:textSize="40px" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:paddingLeft="45px"
android:paddingRight="48px"
android:text="2017.08.09 13:00"
android:textColor="#9b9b9b"
android:textSize="34px" />
</LinearLayout>
I have a common solution to solve this kind of layout question:
Create a specific ViewGroup!
For the question above, the key point is how to set the correct maxWidth to the content view.
Create a SpecialViewGroup. The contentView is the left view, and the timeView is the right view.
class SpecialViewGroup #JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {
private lateinit var contentView: TextView
private lateinit var timeView: TextView
override fun onAttachedToWindow() {
super.onAttachedToWindow()
contentView = findViewById(R.id.content)
timeView = findViewById(R.id.time)
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
// measure the timeView firstly, because the contentView's maxWidth rely on it.
timeView.measure(
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
)
// then caculate the remained space for the contentView
val parentWidth = MeasureSpec.getSize(widthMeasureSpec)
val paddingHorizontal = paddingStart + paddingEnd
val view1MaxWidth = parentWidth - timeView.measuredWidth - paddingHorizontal
// set the maxWidth to the contentView
contentView.maxWidth = view1MaxWidth
// The rest thing will be handed over by LinearLayout
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
}
Use the SpecialViewGroup in your layout, like the usual LinearLayout.
<com.example.SpecialViewGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFBB86FC"
android:orientation="horizontal"
android:padding="10dp">
<TextView
android:id="#+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF3700B3"
android:padding="10dp"
android:text="adaasdasdasasdadasdasdaaaaaaaaaaaaaaaa"
android:textColor="#color/white" />
<TextView
android:id="#+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#FF018786"
android:padding="10dp"
android:text="1970-01-01"
android:textColor="#color/white" />
</com.example.archview.SpecialViewGroup>
And the result:
The benefits of this approach are obvious:
No extra nesting Layout.
Common to solve the similar layout questions.
Had the similar issue. Made it works with constraint.
<ConstraintLayout>
<TextView
android:id="#+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
app:layout_constraintEnd_toStartOf="#+id/option_info"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_max="wrap" />
<ImageView
android:id="#+id/option_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_info"
app:layout_constraintBottom_toBottomOf="#+id/title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/title"
app:layout_constraintTop_toTopOf="#+id/title" />
</ConstraintLayout>

Use of Zoom in ImageView inside ScrollView

I'm trying to use zoom in an ImageView. I've searched and tried so many codes but the problem is that I have ImageView inside an ScrollView because I have some other objects.
This is the last code if tried.
And here is xml 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="fill_parent"
tools:context=".ConsumoActivity"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/linearLayoutLogoFactor_consumo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal" >
<ImageView
android:id="#+id/imageViewLogoFactor_consumo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/logo_factorenergia" />
</LinearLayout>
<ScrollView
android:id="#+id/scrollViewConsumo"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true" >
<LinearLayout
android:id="#+id/linearLayoutConsumo2"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_gravity="center_horizontal"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="vertical" >
<TextView
android:id="#+id/textViewVerConsumo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:text="#string/etiqueta_ver_consumo"
android:textSize="#dimen/textSize"
android:layout_marginTop="10dp"
android:textStyle="italic"
android:textColor="#79b7e3" />
<LinearLayout
android:id="#+id/linearLayoutDireccionConsumo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="10dp"
android:weightSum="1.0">
<TextView
android:id="#+id/textViewlabelDireccionConsumo"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.3"
android:text="#string/etiqueta_direccion"
android:textSize="#dimen/textSize"
android:textStyle="bold" />
<TextView
android:id="#+id/textViewDireccionConsumo"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.7"
android:textSize="#dimen/textSize" />
</LinearLayout>
<com.example.factorenergia.CustomImageView
android:id="#+id/imageViewConsumo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="15dp"
android:adjustViewBounds="true"
android:scaleType="matrix" />
<RelativeLayout
android:id="#+id/linearLayoutImagenInferior_consumo"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginTop="20dp" >
<ImageView
android:id="#+id/imageViewImagenInferior_consumo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:adjustViewBounds="true"
android:src="#drawable/la_electrica_de_las_empresas" />
</RelativeLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
Image is ok but scroll is not working. Is there any way for solving that having ImageView inside ScrollView with some other objects?
This is probably because the overriden ImageView is handling all touch events. It should take only two-finger events and pass the rest of them back to the parent. You should return false from onTouchEvent, when the event is not for your ImageView.
The second option is to handle events in dispatchTouchEvent method of the ScrollView. You can handle one-finger events in the ScrollView and pass the rest of events to children. This is not recomended, because it may break a lot.
I've used an easy solution:
Let my layout as it was and when ImageView is clicked, go to a new one which only has the Image, using Mike Ortiz code at that question.
The answer provided by #Zielony clarified things for me, as I was struggling with a similar issue. I had a zoomable imageview inside scrollView, and both these views were conflicting. So I created a custom scrollView that intercepts touch events only if one finger is touching the screen. So, you will be able to interact with the imageview zooming feature with two fingers, and scroll our custom scrollView with one finger.
class CustomScrollView #JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0) : ScrollView(context, attrs, defStyleAttr) {
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
return if (ev.pointerCount < 2) {
super.onInterceptTouchEvent(ev)
} else {
false
}
}
}

Android layout: Make RadioGroup occupy screen width next to a square ImageView

I have this layout:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioGroup
android:id="#+id/MyTabs"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RadioButton ... />
<RadioButton ... />
</RadioGroup>
<SquareImageView
android:layout_height="match_parent" />
</LinearLayout>
and here's the code for the SquareImageView:
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);
}
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int size = getMeasuredHeight();//Math.min(getMeasuredWidth(), getMeasuredHeight());
setMeasuredDimension(size, size);
}
}
Now, what I want to achieve is this:
I want the RadioGroup to occupy as much space as possible. The height of the LinearLayout should adapt to the required height of the RadioGroup. Each RadioButton should occupy 50% of the RadioGroup. The SquareImageView should adapt it's height to match the height of the LinearLayout, and it's width should also adapt to make it square.
Is this even possible?
The RadioGroup is no problem on it's own, but the tricky part is the square ImageView because I cannot get it to adapt it's width automatically. It is square, but I need to set the width of it manually. If I do not set a width manually it seems to be square (in the Eclipse Preview Layout Manager) but it ends up outside of the screen and the RadioGroup occupies the entire screen width. If I set a too wide width there is dead space to the right of it.
Tried fiddling with all kinds of settings but nothing gets it quite right. I would like to avoid setting dimensions in absolute values, and rather let the height of the RadioGroup determine the rest of the Views' dimensions...
Try this:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioGroup
android:id="#+id/MyTabs"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weig="1" >
<RadioButton
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
... />
<RadioButton
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
... />
</RadioGroup>
<SquareImageView
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
You can try below steps:
1, Set the layout as below:
<RadioGroup
android:id="#+id/MyTabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="1" >
<RadioButton
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"
... />
<RadioButton
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"
... />
</RadioGroup>
<SquareImageView
android:layout_width="0dp"
android:layout_height="match_parent" />
2, Once the view loads, programatically find the height of linear layout and then programatically set the width of the squareview to this same value to make it a square
3, Find the width of the screen and then set the width of the radio group to the difference between screen width and above sqaureview width so that it occupies the remaining screen width.

How do I keep the aspect ratio on image buttons in android?

I have 5 square ImageButtons that I want to have lined up side by side on the bottom of the screen. I have each one set (different id's) as:
<ImageButton
android:id="#+id/box1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:layout_weight="1"
android:layout_margin="1dp"
/>
and I have the background assigned in main java like this:
int[] imageIds = new int[] {R.id.box1,R.id.box2,R.id.box3,R.id.box4,R.id.box5};
for(int i = 0; i<5; i++){
imageButtons[i] = (ImageButton) findViewById(imageIds[i]);
imageButtons[i].setBackgroundResource(R.drawable.blank);
}
What I would like to have it do is scale the width to fit neatly side-by-side at the bottom of the screen (which it does now ok), but have the height automatically scale to match the width as well. is this possible? I don't want to use setImageSource because then it puts a border around the imagebutton.
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/layoutButtons">
<com.package.SquareButton
android:layout_height="fill_parent"
android:layout_width="0dip"
android:layout_weight="1"
<ImageView
android:id="#+id/box1"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"/>
</com.package.SquareButton>
<com.package.SquareButton
android:layout_height="fill_parent"
android:layout_width="0dip"
android:layout_weight="1"
<ImageView
android:id="#+id/box2"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"/>
</com.package.SquareButton>
.........
</LinearLayout>
And then add this custom button class:
public class SquareButton extends LinearLayout {
public SquareButton(Context context) {
super(context);
}
public SquareButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
// This is used to make square buttons.
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
}
I have had a similar headache in trying to get my buttons in a row. The solution I found was to use ImageButton and the android:src property (setImageSource in code) in combination with android:background="#null"
As I understand it the background of an image button doesn't get affected by the adjustViewBounds, it is only the imageView which you set in android:src.
The default behavior is then to give you a square button with the imageView in the middle of it. You can override that by setting the background to #null, which leaves you with only the image.
You can then use either a LinearLayout or a table to layout your buttons. I did everything in XML and used the following layout to create a row of two buttons at the bottom of the screen that scale up or down maintaining the aspect ratio with different device screens sizes. Hope this helps.
<TableLayout
android:id="#+id/tableLayout2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="20dip"
android:stretchColumns="*">
<TableRow>
<ImageButton
android:id="#+id/button_one"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:layout_weight="0.5"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:onClick="clickOne"
android:background="#null"
android:src="#drawable/button_one_drawable" />
<ImageButton
android:id="#+id/button_two"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:layout_weight="0.5"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:onClick="clickTwo"
android:background="#null"
android:src="#drawable/button_two_drawable" />
</TableRow>
</TableLayout>
Instead of
android:scaleType="fitXY"
use:
android:scaleType="centerInside"
EDIT1: Try this one:
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/layoutToInflateButtons"
>
<ImageButton
android:id="#+id/box1"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:layout_weight="1"
android:layout_margin="1dp"
/>
</LinearLayout>
You can use Google's Percent Relative Layout that helps you to 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">
<ImageButton
android:id="#+id/box1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="fitXY"
app:layout_aspectRatio="100%"
android:layout_weight="1"
/>
</android.support.percent.PercentFrameLayout>
The aspect ratio 100% will make width same as height.
example:
android:layout_width="300dp"
app:layout_aspectRatio="178%"
a width 178% of the height. This is the format the layout_aspectRatio expects
You can read it in detail here
I am sure you want to have that 5 buttons of EQUAL width/height. If this is the case then take LinearLayout and put all those 5 buttons with layout_width="0dip" and layout_weight="1"
For example:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/layoutButtons">
<ImageButton
android:id="#+id/box1"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1"/>
<ImageButton
android:id="#+id/box2"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:layout_height="wrap_content"
android:layout_width="0dip"
android:layout_weight="1"/>
.........
</LinearLayout>
After checking Google I/O sample application from this year I've found that Google is using dimen values for specifying varios heights or widths based on the screen type. For details you can check the source code from http://code.google.com/p/iosched/.
You can specify the height of the button for exemple in values-xhdpi or values-sw720dp as:
<resources>
<dimen name="button_height">50dp</dimen>
</resources>
And then you can just use this dimen value when specifying the height:
android:layout_height="#dimen/button_height"
Set the width of the ImageButtons to fill_parent and use scaletype fitStart for the images that hug the left margin, and fitEnd for the ones on the right. Should do the trick, at least as far as your example image goes. You may have some spacing issues if the proportional width of the images exceed the screen width, but it should work for you.
ViewGroup.LayoutParams params = imageButtonName.getLayoutParams();
// Changes the height(or width) and width(or height) to the specified
params.height = layout.getWidth();
Look into making a custom ImageButton. I like this because its one class. Here is a button that adjusts its height based on the image aspect ratio. I imagine you can tweak to your needs :
public class AspectImageButton extends ImageButton {
public AspectImageButton(Context context) {
super(context);
// TODO Auto-generated constructor stub
this.getDrawable();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
Drawable d=this.getDrawable(); //grab the drawable
float fAspectRatio=(float)d.getIntrinsicWidth()/(float)d.getIntrinsicHeight();
float fHeight=(float)width/fAspectRatio;//get new height
setMeasuredDimension(width, (int)fHeight);
}
public AspectImageButton(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public AspectImageButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
}
then in xml just use it like this:
<com.package.AspectImageButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="#drawable/home_1b"
android:background="#null"
android:scaleType="fitXY"
android:adjustViewBounds="true" />

Categories

Resources