I have a library that allows for CircularImageView but I have a problem I can't fix.
I add it in my layout this way:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<com.mikhaellopez.circularimageview.CircularImageView
android:id="#+id/circularImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/test"
app:civ_border="true"
app:civ_border_color="#3f51b5"
app:civ_border_width="8dp"
app:civ_shadow="true"
app:civ_shadow_color="#3f51b5"
app:civ_shadow_radius="10" />
</LinearLayout>
<LinearLayout
android:layout_width="240dp"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">
<SeekBar-
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- ... -->
</LinearLayout>
On some picture I have a black background that appears in the view (On PNG images but ic_launcherfor example works well):
I can fix the problem when I change the onMesure method.
Before:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec);
int imageSize = (width < height) ? width : height;
setMeasuredDimension(imageSize, imageSize);
}
After:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec);
/*int imageSize = (width < height) ? width : height;
setMeasuredDimension(imageSize, imageSize);*/
setMeasuredDimension(width, height);
}
But with this modification my view isn't centered:
Could someone help me so to fix the black background or find a new way to center my view?
Related
I've created an InnerCustomView and although I'm overriding onMeasure, the view height is not set as the desired height.
Here is some context.
I have a CustomView. This view has a container (RelativeLayout) and inside here I have 4 InnerCustomViews plus two guidelines that I need to place in the container. For simplicity, I'm only showing here one of those InnerCustomViews because I can't manage to set this view to my width and height requirements.
This is the CustomView layout relevant information:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/grey">
<ImageView
android:id="#+id/image"
....
/>
<RelativeLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/red"
android:layout_below="#+id/image">
<View
android:id="#+id/guide"
android:layout_width="12dp"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:background="#android:color/holo_green_dark" />
.......
<...InnerCustomView
android:id="..."
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toEndOf="#id/guide"
android:background="#color/green"
... />
</RelativeLayout>
</RelativeLayout>
In CustomView I'm doing this:
#Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//Based on the container size I calculate the InnerCustomView desiredSize
innerCustomView.measure(MeasureSpec.makeMeasureSpec(desiredSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(desiredSize, MeasureSpec.EXACTLY));
}
The InnerCustomView only has an ImageView and a TextView
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:background="#drawable/grey">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
I have this in InnerCustomView:
public class InnerCustomView extends LinearLayout {
//Default constructors and other stuff.
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
measureChildren(widthMeasureSpec, heightMeasureSpec);
//Here I'm loging the values in widthMeasureSpec and heightMeasureSpec and I can see that they are the desiredSize
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
}
}
If you look at the image bellow, except height, my layout is as expected. The vertical guide (dark green) is in the correct place and the InnerCustomView is at it's right. The problem is that the width and height are not the ones I've passed when I called measure.
Width takes the available space and height also thus taking the whole height of the view (light green)
On the other hand, the InnerCustomView content has the desiredSize (grey).
Any ideia why is this happening?
I've tried to invalidate() the view, requestLayout(), forceLayout() but with no success.
So my custom TextView is cutting off the last line of text in some cases. I'm using a custom font. It seems to only cut off the last word. I changed my custom text views to regular ones, which forces my text views to use standard fonts instead of my custom one, and suddenly the sizing works.
Theory on issue: While using the DDMS tool to see the layout sizes around my views and comparing custom font version vs regular font version, it looks like it measures the height of the characters properly--if it didn't it would cut off part of the y's, g's, and p's on my bigger, custom font. But then it doesn't properly guess the amount of lines my bigger font will take up, and measures the amount of lines as if it were the smaller, non-custom font. So when a string ends with a two letter word which is just on the edge of wrapping, it doesn't think it needs to wrap to the next line and cuts it off.
Layout for inside the ViewPager which includes the problem child CustomTextView:
<LinearLayout
android:id="#+id/header_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="-12dp"
android:paddingRight="-12dp"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.CardView
snip>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
snip>
<!---v--- this is the problem child--->
<com.snip.custom.views.CustomTextView
android:id="#+id/label"
style="#style/typographyParagraphBody"
android:layout_centerHorizontal="true"
android:gravity="center"
android:layout_marginBottom="20dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:text="#{carouselItemViewModel.label}"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
</LinearLayout>
Boring ViewPager:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
if (h > height){
height = h;
}
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
My layout file:
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#{carouselViewModel.carouselBackgroundColor}"
android:orientation="vertical">
<com.snip.custom.views.CustomTextView
android:id="#+id/text"
style="#style/irrelevant"
android:text="#{carouselViewModel.text}"/>
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="-17dp"
android:layout_gravity="top"
android:layout_below="#id/text"
app:tabBackground="#drawable/dot_tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
app:tabPaddingEnd="5dp"
app:tabPaddingStart="5dp"
app:viewPager="#{{viewPager}}" />
<com.snip.custom.views.CustomViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:paddingEnd="20dp"
android:paddingStart="20dp"
android:layout_below="#id/tab_layout"
app:currentItem="#{carouselViewModel.carouselCurrentItemSubject}"
app:setOffscreenPageLimit="#{carouselViewModel.carouselOffscreenPageLimitSubject}"
app:itemView="#{carouselViewModel.carouselItemViewSelector}"
app:items="#{carouselViewModel.carouselItems}"
app:onAdapterChangeListener="#{carouselViewModel.carouselAdapterChangeSubject}"
app:onPageChangeListener="#{carouselViewModel.carouselPageChangeSubject}"/>
</RelativeLayout>
Looks like I needed more code to measure the children properly, since they weren't aware of their layout parameters. So I remeasure them by applying the parent widthMeasureSpec.
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
if (h > height){
height = h;
}
height = Math.max(child.getMeasuredHeight(), measureViewHeight(child, widthMeasureSpec));
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private int measureViewHeight(View view, int widthMeasuredSpec) {
view.measure(getChildMeasureSpec(widthMeasuredSpec,
getPaddingLeft() + getPaddingRight(),
view.getLayoutParams().width),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
return view.getMeasuredHeight();
}
I have listView with items created dynamicaly.Each item is my custom view and contains(from top to bottom) header,imageView and footer.I set item's height in the onMeasure method.I'd like imageView's height to be exactly
image_height=item_height-(footer_height+header_height)
I set footer/header height in the xml(constant value)
However when I try to get footer/header height it returns 0
#Override
public void onMeasure(int widthSpec, int heightSpec) {
super.onMeasure(widthSpec,heightSpec);
int widthMode = MeasureSpec.getMode(widthSpec);
int widthSize = MeasureSpec.getSize(widthSpec);
int heightMode = MeasureSpec.getMode(heightSpec);
int heightSize = MeasureSpec.getSize(heightSpec);
//float ar=896f/768f;
int itemWidth=widthSize/IMGS_PER_ROW;
int calculated_width =widthSize;
int calculated_height = (int) (itemWidth*(1/IMG_ASPECT_RATIO));
if(!initialized) {
Image img=new Image(this.getContext());
int dy=((ImageView)this.findViewById(R.id.separator)).getHeight();//returns 0
Log.d("item",calculated_width+","+calculated_height+","+dy);
initialized=true;
}
this.setMeasuredDimension(calculated_width, calculated_height);
}
Item layout:
<?xml version="1.0" encoding="utf-8"?>
<com.rhyboo.net.listtest.ListItemView 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"
android:orientation="vertical">
<TextView
android:text="Title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/title_text"
android:gravity="left"
android:textSize="24sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:id="#+id/items_container"
android:layout_marginBottom="30dp"
android:layout_marginTop="30dp">
</LinearLayout>
<ImageView
android:layout_width="match_parent"
android:layout_height="30dp"
app:srcCompat="#color/colorAccent"
android:id="#+id/separator"
android:layout_gravity="bottom" />
</com.rhyboo.net.listtest.ListItemView>
I want use ImageView in my project, but it shows additional space in the layout. How can I remove the additional space?
This image shows the problem:
XML code:
<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="wrap_content"
tools:context="com.tellfa.smsbox.activities.Dialog_image_show">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:src="#drawable/cover_menu_bg" />
</RelativeLayout>
</RelativeLayout>
I don't want use android:scaleType="centerCrop".
Use the imageview like these
<ImageView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="#drawable/icon"
android:id="#+id/imv"
android:scaleType="fitCenter" />
Try this custom ImageView class
public class ResizableImageView extends ImageView {
public ResizableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
Drawable d = getDrawable();
if(d!=null){
// ceil not round - avoid thin vertical gaps along the left/right edges
int width = View.MeasureSpec.getSize(widthMeasureSpec);
int height = (int) Math.ceil((float) width * (float) d.getIntrinsicHeight() / (float) d.getIntrinsicWidth());
setMeasuredDimension(width, height);
}else{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
}
And use this class as below
<your_package.ResizableImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:src="#drawable/cover_menu_bg" />
For anyone looking for solution for both orientations. Here is my approach with samples:
First, my xml:
<?xml version="1.0" encoding="utf-8"?>
<com.example.michal.fillimageview.CustomLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="#f0f000"
android:orientation="vertical">
<com.example.michal.fillimageview.ResizableImageView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:adjustViewBounds="true"
android:src="#drawable/p600_900" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/background_dark"
android:text="Hello World!"
android:textColor="#android:color/holo_red_dark"
android:textSize="30sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/background_dark"
android:text="Hello World!"
android:textColor="#android:color/holo_red_dark"
android:textSize="30sp" />
</com.example.michal.fillimageview.CustomLinearLayout>
Class:
public class ResizableImageView extends ImageView {
public ResizableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Drawable d = getDrawable();
if (d != null) {
// ceil not round - avoid thin vertical gaps along the left/right edges
int width = View.MeasureSpec.getSize(widthMeasureSpec);
int height = View.MeasureSpec.getSize(heightMeasureSpec);
if (height > width) {//portrait
if (d.getIntrinsicWidth() > d.getIntrinsicHeight()) {
height = (int) Math.ceil((float) width * (float) d.getIntrinsicHeight() / (float) d.getIntrinsicWidth());
setMeasuredDimension(width, height);
} else {
width = (int) Math.ceil((float) height * (float) d.getIntrinsicWidth() / (float) d.getIntrinsicHeight());
setMeasuredDimension(width, height);
}
} else {//landscape
width = (int) Math.ceil((float) height * (float) d.getIntrinsicWidth() / (float) d.getIntrinsicHeight());
setMeasuredDimension(width, height);
}
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
}
Samples for specific images:
600x900 portrait
600x900 landscape
800x600 portrait
800x600 landscape
I need to place an image (a logo) on top of the android screen and I need it to be as wide as the entire screen and I need its' height to be proportional to the width, the same proportion as in the original image. So far, everything I've tried resulted in misproportioned images or images covering the entire screen. How do I fix this?
<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"
tools:context=".MainActivity"
android:background="#color/blue">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="#+id/linearLayout"
android:layout_centerVertical="true"
>
<EditText
android:id="#+id/username"
android:layout_width="fill_parent"
android:layout_height="50dp"
android:layout_marginLeft="#dimen/margin_main"
android:layout_marginRight="#dimen/margin_main"
android:hint="#string/username"
android:textColorHint="#fff"
android:gravity="center"
android:background="#drawable/input_background"
android:layout_marginBottom="#dimen/margin_main"
android:textColor="#fff"
/>
<EditText
android:id="#+id/password"
android:layout_width="fill_parent"
android:layout_height="50dp"
android:inputType="textPassword"
android:layout_marginLeft="#dimen/margin_main"
android:layout_marginRight="#dimen/margin_main"
android:hint="#string/password"
android:textColorHint="#fff"
android:gravity="center"
android:background="#drawable/input_background"
android:layout_marginBottom="#dimen/margin_main"
android:textColor="#fff"/>
<Button
android:id="#+id/login_button"
android:layout_width="fill_parent"
android:layout_height="50dp"
android:text="#string/login"
android:layout_marginLeft="#dimen/margin_main"
android:layout_marginRight="#dimen/margin_main"
android:background="#drawable/button_yellow_background"
android:textStyle="bold"
android:textSize="20sp"
android:textColor="#color/blue"/>
</LinearLayout>
<ImageView
android:id="#+id/logo"
android:layout_width="315dp"
android:layout_height="100dp"
android:background="#drawable/logo"/>
</RelativeLayout>
The image in question is the logo.
All you need to do is change
<ImageView
android:id="#+id/logo"
android:layout_width="315dp"
android:layout_height="100dp"
android:background="#drawable/logo"/>
to
<ImageView
android:id="#+id/logo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="#drawable/logo"/>
Note: Doing this might result in a stretch image if your image is smaller than the screen width.
Try to set scaleType to fitXY:
<ImageView
android:id="#+id/fullImg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="#drawable/your_image_resource"
android:scaleType="fitXY" />
If you want to do it at runtime you can do that:
// set the ratio (if it can change it's also possible get it from resource id)
double aspect_ratio = 16/9;
// getting a ref to your ImageView
ImageView yourImageView = (LinearLayout) findViewById(R.id.imageView);
// get DisplayMetrics to get screen sizes
DisplayMetrics met = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(met);
// if you have a "activity_horizontal_margin" in your style
int t = getResources().getDimensionPixelSize(R.dimen.activity_horizontal_margin);
int width = (int)((met.widthPixels-2*t));
// otherwise just
int width = (int)((met.widthPixels-2*t));
// go on calculate height
int height = width * aspect_ratio;
// ending with layour params setting
yourImageView.setLayoutParams(new LayoutParams(width, height);
else if you want to do it in xml, you could do something like that
<ImageView
android:id="#+id/yourImageView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="#drawable/logo"
android:scaleType="centerInside" />
You should do that at runtime.
Solution 1
Display display = getWindowManager().getDefaultDisplay();
ImageView imageView = (LinearLayout) findViewById(R.id.imageView);
int width = display.getWidth();
int height = (int) width * 0.75; // 0.75 if image aspect ration is 4:3, change accordingly
imageView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, height);
This would make the image to fill the screen width and height as per the aspect ratio of the original image. To use this method you need to hardcode the aspect ratio.
Solution 2 From Scale Image to fill ImageView width and keep aspect ratio
Create a custom image view and do this
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
try {
Drawable drawable = getDrawable();
if (drawable == null) {
setMeasuredDimension(0, 0);
} else {
float imageSideRatio = (float)drawable.getIntrinsicWidth() / (float)drawable.getIntrinsicHeight();
float viewSideRatio = (float)MeasureSpec.getSize(widthMeasureSpec) / (float)MeasureSpec.getSize(heightMeasureSpec);
if (imageSideRatio >= viewSideRatio) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = (int)(width / imageSideRatio);
setMeasuredDimension(width, height);
} else {
int height = MeasureSpec.getSize(heightMeasureSpec);
int width = (int)(height * imageSideRatio);
setMeasuredDimension(width, height);
}
}
} catch (Exception e) {
e.printStackTrace();
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}