Loading an image that is larger than the width of a Galaxy Tab 2 P5100 (running 4.1.2) into an ImageView adds some sort of top/bottom padding to the loaded image.
Here's a screenshot with Show layout boundaries turned on:
Here's how it should look (from a Nexus 10 running 4.4.2):
The code I use (for both examples above) is
public class ImageBugActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bug);
// This bug is still reproducible if I use the
// Universal-Image-Loader library or if I change the dimensions of
// the image to a different width
loadImage("http://placehold.it/1600x1000", (ImageView)findViewById(R.id.image));
}
private void loadImage(final String url, final ImageView view) {
new Thread(new Runnable() {
#Override
public void run() {
try {
final Bitmap bitmap = BitmapFactory.decodeStream(new URL(url).openConnection().getInputStream());
runOnUiThread(new Runnable() {
#Override
public void run() {
view.setImageBitmap(bitmap);
}
});
} catch (Exception e) {
Log.e("loadImage", e.getMessage(), e);
}
}
}).start();
}
}
And the layout file is
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="On a Galaxy Tab 2 the image below it is pushed to the center of the remaining space." />
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top" />
</LinearLayout>
Does this seem to be an Android/Samsung bug or am I making a dumb mistake?
Setting the android:scaleType of the ImageView to "fitStart" should do the trick.
You should use "match_parent" for layout_height of the ImageView.
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="top" />
Related
I have an ImageView inside of a LinearLayout which is an item of a RecyclerView. I have all these views' width as MATCH_PARENT.
Now, I'm trying to calculate the heigth using the aspect ratio before the image is loaded so there's no resizing.
But, what I've seen is that before the image is loaded, its width is zero.
The thing is that I'm doing similar things in other parts of the app and it's working fine, I don't really know what I'm missing here.
RecyclerView item:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:background="#android:color/white">
<LinearLayout
...
</LinearLayout>
<!-- This is the image -->
<ImageView
android:id="#+id/descubre_shop_banner"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp"
android:adjustViewBounds="true"
android:scaleType="centerCrop"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#color/colorLightText"
android:layout_marginRight="16dp"
android:layout_marginLeft="16dp"
android:layout_marginBottom="8dp"/>
</LinearLayout>
ViewHolder
mBannerTarget = new Target()
{
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from)
{
mShopBannerImageView.setImageBitmap(bitmap);
// Wrap content when the images is loaded.
mShopBannerImageView.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
mShopBannerImageView.setBackgroundColor(-1);
mShopBannerImageView.setAlpha(1.0f);
Animation fadeOut = new AlphaAnimation(0, 1);
fadeOut.setInterpolator(new AccelerateInterpolator());
fadeOut.setDuration(250);
mShopBannerImageView.startAnimation(fadeOut);
LOADED = true;
}
#Override
public void onBitmapFailed(Drawable errorDrawable)
{
mShopBannerImageView.setBackgroundColor(
mContext.getResources().getColor(android.R.color.holo_red_dark));
mShopBannerImageView.setAlpha(0.2f);
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable)
{
// This is 0
Log.d(Properties.TAG, "" + mShopBannerImageView.getWidth());
// Remove the old bitmap
mShopBannerImageView.setImageBitmap(null);
// Set the height using the width and the aspect ratio.
mShopBannerImageView.getLayoutParams().height =
(int) (mShopBannerImageView.getWidth() * shop.getAspectRatio());
// Set a color while loading.
mShopBannerImageView.setBackgroundColor(
mContext.getResources().getColor(R.color.colorAccent));
mShopBannerImageView.setAlpha(0.25f);
}
};
I tried to set the width of the ImageView and its parent as MATCH_PARENT in code but no luck. Any clue of what's going on?
Regards,
The views dimensions is always 0 before being fully created, if you wanted to know the actual width, you have to use the method: post():
view.post(new Runnable() {
#Override
public void run() {
// This is where width would be different than 0
}
});
That being said, you should actually use an other method to keep the ratio than actually calculating it yourself!
See this thread for further information How to scale an Image in ImageView to keep the aspect ratio
I want to toggle 90-degree rotation when an image is tapped:
#UiThread // Android Annotations
void loadImage(ImageSource uri) {
image.setMinimumScaleType(SCALE_TYPE_CENTER_CROP);
image.setMaxScale(8);
image.setImage(uri); // I've tried the ImageViewState variant
image.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (image.getRotation() < 1) {
image.setRotation(90);
} else {
image.setRotation(0);
}
}
});
}
Where the image is defined in a fragment:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
It's working, but the 90-degree rotated image does not occupy the whole screen. It has white background at the top and bottom.
How do I fix this?
It's setOrientation(), not setRotation(). The latter method belongs to View.
I am stuck trying to resize ImageView objects.
The issue is that when I set the width/height programmatically, I see the width/height change with the debugger tool in eclipse.
However, the image will not scale to the new size, and maintains its current ratios. In some cases it even puts the original image at its current size, and moving to a different activity will resize it (somewhat) correctly.
Screenshots:
After opening the app
http://imgur.com/ha9s9rL
After opening and closing a different activity
http://imgur.com/DrBIJaI
I would like for the images to sit next to each other, with the same width/height for each image.
onCreate() Method:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_behavior);
listView = (ListView) findViewById(R.id.display_behavior_listview);
List<Behavior> behaviorList = parseCatagories();
List<View> views = getCatagoryViewsFromBehaviorList(behaviorList);
// Setup array adapter
BehaviorRow behaviorRows[] = getBehaviorRows(views);
int viewCount = 0;
View view;
for (BehaviorRow row : behaviorRows) {
if (viewCount < views.size()) {
view = views.get(viewCount);
row.setBehaviorOne(view);
viewCount++;
view = views.get(viewCount);
row.setBehaviorTwo(view);
viewCount++;
}
Log.i("BehaviorRowDat", row.toString());
}
BehaviorRowAdapter adapter = new BehaviorRowAdapter(getApplicationContext(), R.layout.catagory_row,
behaviorRows);
listView.setAdapter(adapter);
}
onWindowFocusChanged() Method:
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
ImageView catagoryOne;
ImageView catagoryTwo;
for (int i = 0; i < listView.getChildCount(); i++) {
catagoryOne = (ImageView) listView.getChildAt(i).findViewById(R.id.catagory_space_one);
catagoryTwo = (ImageView) listView.getChildAt(i).findViewById(R.id.catagory_space_two);
resizeImageView(catagoryOne);
resizeImageView(catagoryTwo);
}
}
Resize Image Code:
private ImageView resizeImageView(ImageView image) {
// Set length/width
int length = calculateLengthOfImages();
image.getLayoutParams().height = length;
image.getLayoutParams().width = length;
// Set Padding
int padding = calculatePaddingOfImages();
image.setPadding(padding, padding, padding, padding);
return image;
}
XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/catagory_row_created"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:orientation="horizontal"
android:padding="10dp"
android:weightSum="1" >
<ImageView
android:id="#+id/catagory_space_one"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:contentDescription="#string/catagory_placeholder"
android:scaleType="centerCrop" />
<ImageView
android:id="#+id/catagory_space_two"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:contentDescription="#string/catagory_placeholder"
android:scaleType="centerCrop" />
</LinearLayout>
Try changing the scaleType attribute in your ImageViews to:
android:scaleType="fitXY"
Alternatively, you can add this line in your resizeImageView() method:
image.setScaleType(ScaleType.FIT_XY);
Hope that helps!
Replace your xml with this:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/catagory_row_created"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:orientation="horizontal"
android:padding="10dp">
<ImageView
android:id="#+id/catagory_space_one"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginRight="5dp"
android:layout_marginEnd="5dp"
android:scaleType="centerCrop" />
<ImageView
android:id="#+id/catagory_space_two"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:scaleType="centerCrop" />
</LinearLayout>
In onCreate() of your activity, add this:
final ImageView imageView1 = (ImageView) findViewById(R.id.catagory_space_one);
final ImageView imageView2 = (ImageView) findViewById(R.id.catagory_space_two);
imageView1.post(new Runnable() {
#Override
public void run() {
imageView1.getLayoutParams().height = imageView1.getWidth();
imageView1.requestLayout();
}
});
imageView2.post(new Runnable() {
#Override
public void run() {
imageView2.getLayoutParams().height = imageView2.getWidth();
imageView2.requestLayout();
}
});
So what basically I did is I have stretched the two images' width equally to take the whole space in xml using layout_weight, then I have set the images' height to be like their respective widths in code. So now they are square-shaped.
Hope that helps.
i need some guidance. I need to make a custom view that touched and drag up the screen slides out of the screen. I have tried this cool library: here but this is dependend to exactly 2 layouts. The one that is slided out and the one that remains after that. What i have now is buggy and ugly.
public class DemoActivity extends Activity {
private SlidingUpPanelLayout mLayout;
private RelativeLayout layout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
layout = (RelativeLayout) findViewById(R.id.panel);
final int defaulttop = layout.getTop();
final int defaultbottom = layout.getBottom();
RelativeLayout dragView = (RelativeLayout) findViewById(R.id.dragView);
mLayout = (SlidingUpPanelLayout) findViewById(R.id.sliding_layout);
mLayout.setDragView(dragView);
mLayout.setPanelSlideListener(new PanelSlideListener() {
#Override
public void onPanelSlide(View panel, float slideOffset) {
}
#Override
public void onPanelExpanded(View panel) {
System.out.println("panel expanded");
}
#Override
public void onPanelCollapsed(View panel) {
System.out.println("panel collapsed");
}
#Override
public void onPanelAnchored(View panel) {
System.out.println("anchored");
}
#Override
public void onPanelHidden(View panel) {
System.out.println("panel is hidden now");
}
});
}
#Override
public void onBackPressed() {
if (mLayout != null && mLayout.isPanelExpanded()) {
mLayout.collapsePanel();
} else {
super.onBackPressed();
}
}
}
The layout:
<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=".DemoActivity" >
<com.sothree.slidinguppanel.SlidingUpPanelLayout
xmlns:sothree="http://schemas.android.com/apk/res-auto"
android:id="#+id/sliding_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent"
android:gravity="bottom"
sothree:dragView="#+id/dragView"
sothree:panelHeight="60dp"
sothree:paralaxOffset="60dp"
sothree:shadowHeight="0dp" >
<RelativeLayout
android:id="#+id/panel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/unt"
android:orientation="vertical" >
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:text="Sleep" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/dragView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent"
android:clickable="true"
android:focusable="false" >
</RelativeLayout>
</com.sothree.slidinguppanel.SlidingUpPanelLayout>
</RelativeLayout>
it slides up but leaves a white background in the back. If i touch the screen then it slides. So, i need a new path. Did anyone confrunted with something similar? I need a hint, not code. Thanks.
I have used the library you mentioned here and it worked out fine for me. You might have not set the drag view/layout
Do use mSlidingPanelLayout.setDragView(YourLayout) to set the layout that can be dragged
I have done something like this previously but with a button.
I did it using Animation class when moving it by OnTouchListener. While you have to be careful while using it and control the X and Y values of the layout.
I'm trying to have one image be a background for another, using the svg-android library. When I view the image on my Samsung Galaxy Nexus (4.3, Sprint), the background image doesn't display. When I view it on the emulator, it's there correctly. I've even removed the foreground, and this stays the same. Here's the key parts of the XML layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<com.kd7uiy.hamfinder.SvgView
android:id="#+id/svgImage"
android:src="#raw/paper"
android:layout_alignLeft="#+id/scroll"
android:layout_alignRight="#id/scroll"
android:layout_alignTop="#id/scroll"
android:layout_above="#+id/buttons"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ScrollView
android:id="#+id/scroll"
android:scrollbars="none"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/buttons"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:background="#android:color/transparent"
android:layout_below="#id/adView">
<TableLayout
android:id="#+id/tableView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:shrinkColumns="1"
android:stretchColumns="1"
/>
</ScrollView>
</RelativeLayout>
And the custom class. Note I tried a tip from svg-android without luck:
public class SvgView extends View {
Picture picture;
long startTime;
float scaleFactor;
public SvgView(Context context,AttributeSet attrs) {
super(context,attrs);
setImage(attrs.getAttributeResourceValue("http://schemas.android.com/apk/res/android","src", 0));
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
{
disableHardwareAcceleration();
}
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void disableHardwareAcceleration()
{
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
public SvgView(Context context) {
super(context);
}
public void setImage(int img_resource)
{
// Parse the SVG file from the resource
SVG svg = SVGParser.getSVGFromResource(getResources(),img_resource);
picture = svg.getPicture();
}
public void onDraw(Canvas canvas) {
if (picture!=null)
{
scaleFactor=Math.min((float)getHeight()/picture.getHeight(),(float)getWidth()/picture.getWidth());
canvas.scale((float)scaleFactor,(float)scaleFactor);
canvas.drawPicture(picture);
}
}
}
Lastly, here's the image from my Galaxy Nexus, and the emulator. Note the difference in the background.
It turns out the provided tip was in the right direction, but I had a small typo. The hardware acceleration seems to be the culprit. As I don't have anything that complex, disabling it is just fine. I almost had the right solution, just had the wrong comparitor. Changing the code as follows fixes it:
public SvgView(Context context,AttributeSet attrs) {
super(context,attrs);
setImage(attrs.getAttributeResourceValue("http://schemas.android.com/apk/res/android","src", 0));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
{
disableHardwareAcceleration();
}
}