second imageview not displaying anything - java

I have a problem displaying two images (software generated) at the same time.
Here is the xml snippet for the layout containing the imageviews.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#005400"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.5"
android:background="#ff0000"
>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/output_img1"
android:contentDescription="First image"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.5"
android:background="#ffff00"
>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/output_img2"
android:contentDescription="Second Image"/>
</RelativeLayout>
</LinearLayout>
Here is the snippet where i create the objects to address the imageviews (in the onCreateView of the Fragment containing the imageviews:
outImage1 = (ImageView)view.findViewById(R.id.output_img1);
outImage1.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
outImage2 = (ImageView)view.findViewById(R.id.output_img2);
outImage2.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
Here is the function that displays the image (scaling it) in the first imageview (this works, and is part of the code for the Fragment containing the imageviews):
public void displayOutImg(Bitmap map){
int bitmapWidth = map.getWidth();
int bitmapHeight = map.getHeight();
int widthParent = outImage1.getWidth();
int heightParent = outImage1.getHeight();
float density = DisplayContext.getResources().getDisplayMetrics().density;
float xScale = ((float) widthParent * density) / bitmapWidth;
float yScale = ((float) heightParent * density) / bitmapHeight;
float minScale = (xScale<yScale)?xScale:yScale;
Matrix matrix = new Matrix();
matrix.postScale(minScale, minScale);
Bitmap scaled = Bitmap.createBitmap(map, 0, 0, bitmapWidth, bitmapHeight, matrix, true);
outImage1.setImageBitmap(scaled);
}
Here is the function to display the image in the second imageview (this seems to do nothing, and is also in the code of the Fragment containing the imageviews):
public void displayOutImg2(Bitmap map){
int bitmapWidth = map.getWidth();
int bitmapHeight = map.getHeight();
int widthParent = outImage2.getWidth();
int heightParent = outImage2.getHeight();
float density = DisplayContext.getResources().getDisplayMetrics().density;
float xScale = ((float) widthParent * density) / bitmapWidth;
float yScale = ((float) heightParent * density) / bitmapHeight;
float minScale = (xScale<yScale)?xScale:yScale;
Matrix matrix = new Matrix();
matrix.postScale(minScale, minScale);
Bitmap scaled = Bitmap.createBitmap(map, 0, 0, bitmapWidth, bitmapHeight, matrix, true);
outImage2.setImageBitmap(scaled);
}
I am trying to display side by side the images resulting from two different processing methods on the same data, but only the first one shows. I thought it might be a problem with the results of the second method, but even if I pass the results of the first one to the displayOutImg2() nothing shows in the second imageview.
I also tried to see if perhaps I was calling the second function from somewhere in my code that could not access the GUI for some reason. So I called it right after the first one (as in, the line below), to no avail. The functions are called from my main activity, like so (images is the Fragment that contains the imageviews):
public void drawFirst(Bitmap result){
images.displayOutImg1(result);
delayedHide(AUTO_HIDE_DELAY_MILLIS);
}
public void drawSecond(Bitmap result){
images.displayOutImg2(result);
delayedHide(AUTO_HIDE_DELAY_MILLIS);
}
My googling failed me so far, and I was not able to find a solution to this issure, which appears to me should be something rather basic. I am sorry if this is something obvious but I have been programming in java for android only for the past couple weeks.
Thanks.

Are you sure that the image actually not behind the other imageview?? To display views over each other you must use FrameLayout for that. Or just use canvas with paint to draw two images over each other.

Related

Change a view margins programmatically

So I have a RecyclerView that has 250dp bottom margin
And I need to set the bottom margin programmatically to 0dp then set it back to 250dp, I have tried this but it's working just to set it 0dp and it doesn't work setting it to 250dp back:
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) linearLayoutRv.getLayoutParams();
params.setMargins(0,0,0,250); // params.setMargins(0,0,0,0); at first
linearLayoutRv.setLayoutParams(params);
There's some unnecessary things but here's the xml file :
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/linearLayoutRv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:layout_marginBottom="250dp"
android:gravity="center"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="51dp"
android:gravity="center">
//textview
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="51dp"
android:orientation="horizontal">
//some buttons
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="5dp"
android:padding="4dp"
android:scrollbars="vertical" />
</LinearLayout>
When you set margins programatically, you set value in pixels, not dp. Source of LayoutParams:
/**
* Sets the margins, in pixels. A call to {#link android.view.View#requestLayout()} needs
* to be done so that the new margins are taken into account. Left and right margins may be
* overridden by {#link android.view.View#requestLayout()} depending on layout direction.
* Margin values should be positive.
*
* #param left the left margin size
* #param top the top margin size
* #param right the right margin size
* #param bottom the bottom margin size
*
* #attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginLeft
* #attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginTop
* #attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginRight
* #attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginBottom
*/
public void setMargins(int left, int top, int right, int bottom) {
leftMargin = left;
topMargin = top;
rightMargin = right;
bottomMargin = bottom;
mMarginFlags &= ~LEFT_MARGIN_UNDEFINED_MASK;
mMarginFlags &= ~RIGHT_MARGIN_UNDEFINED_MASK;
if (isMarginRelative()) {
mMarginFlags |= NEED_RESOLUTION_MASK;
} else {
mMarginFlags &= ~NEED_RESOLUTION_MASK;
}
}
You need convert your dp to pixels:
Int yourDP = 250
Resources r = getResources();
float px = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
yourDP,
r.getDisplayMetrics()
);
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) linearLayoutRv.getLayoutParams();
params.setMargins(0,0,0,(int) px); // params.setMargins(0,0,0,0); at first
linearLayoutRv.setLayoutParams(params);
The problem is that setMargins accepts values not in dp (density independent pixels) unit but in px (pixel) unit.
You must convert your value of 250 to dp before passing it to the params object.
Context context = ...; // place 'this' if you are in an Activity or 'requireContext()' if you are in a Fragment
Resources res = context.getResources();
float dp250 = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 250, res.getDisplayMetrics());
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) linearLayoutRv.getLayoutParams();
params.setMargins(0, 0, 0, dp250);
linearLayoutRv.setLayoutParams(params);
dp250 will result in a different number of pixels on different devices. It depends on the resolution and physical screen size.
You can easily do this with MotionLayout.
Just convert parent ConstraintLayout to MotionLayout, create MotionScene
and in code use transitionToEnd() and transitionToStart()
example
it was working but in pixels, so i added this method:
public static int convertDpToPixel(int dp, Context context){
return dp * ((int) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}
and changed this:
params.setMargins(0,0,0,convertDpToPixel(250,getContext()));

Set Layout width percentage of the total screen width

Is there's way to set Button width 50% of the total screen size (from java code).
I have found a few answers but i would like to change Button size with java code instead of XML.
Try this out..
DisplayMetrics metrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
int height = metrics.heightPixels;
ViewGroup.LayoutParams params = yourButton.getLayoutParams();
params.width = metrics.widthPixels;
try {
double ratio = 0.5;
params.height = Double.valueOf(ratio * height).intValue();
yourButton.setLayoutParams(params);
} catch (Exception e) {
e.printStackTrace();
}
Many ways to achieve this, you could try like below:
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
ViewGroup.LayoutParams params= yourBtn.getLayoutParams();
params.width= width * 1/2;
yourBtn.setLayoutParams(params);
yourBtn.requestLayout();
It's so simple just do.
button.getLayoutParams().width = Resources.getSystem().getDisplayMetrics().widthPixels/2;
I hope it Helps
possible with of Guideline constraint
Guideline
Utility class representing a Guideline helper object for
ConstraintLayout. Helper objects are not displayed on device (they are
marked as View.GONE) and are only used for layout purposes. They only
work within a ConstraintLayout.
A Guideline can be either horizontal or vertical:
Vertical Guidelines have a width of zero and the height of their
ConstraintLayout parent Horizontal Guidelines have a height of zero
and the width of their ConstraintLayout parent Positioning a Guideline
is possible in three different ways:
specifying a fixed distance from the left or the top of a layout
(layout_constraintGuide_begin) specifying a fixed distance from the
right or the bottom of a layout (layout_constraintGuide_end)
specifying a percentage of the width or the height of a layout
(layout_constraintGuide_percent) Widgets can then be constrained to
a Guideline, allowing multiple widgets to be positioned easily from
one Guideline, or allowing reactive layout behavior by using percent
positioning.
See the list of attributes in ConstraintLayout.LayoutParams to set a
Guideline in XML, as well as the corresponding
ConstraintSet.setGuidelineBegin(int, int),
ConstraintSet.setGuidelineEnd(int, int) and
ConstraintSet.setGuidelinePercent(int, float) functions in
ConstraintSet.
<android.support.constraint.Guideline
android:id="#+id/guideline3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.50" />
**
Example
**
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.constraint.Guideline
android:id="#+id/guideline3"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.50" />
<TextView
android:id="#+id/textView3"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:text="TextView"
app:layout_constraintBottom_toTopOf="#+id/guideline4"
app:layout_constraintTop_toTopOf="#+id/guideline3"
tools:layout_editor_absoluteX="104dp" />
<android.support.constraint.Guideline
android:id="#+id/guideline4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.80" />
</android.support.constraint.ConstraintLayout>
Example with Layout height 50% of screen
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toTopOf="#+id/guideline4"
app:layout_constraintTop_toTopOf="parent">
</RelativeLayout>
<android.support.constraint.Guideline
android:id="#+id/guideline4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.50" />
2nd Way
getDefaultDisplay ()
public abstract Display getDefaultDisplay () Returns the Display upon
which this WindowManager instance will create new windows.
Despite the name of this method, the display that is returned is not
necessarily the primary display of the system (see
Display.DEFAULT_DISPLAY). The returned display could instead be a
secondary display that this window manager instance is managing. Think
of it as the display that this WindowManager instance uses by default.
To create windows on a different display, you need to obtain a
WindowManager for that Display. (See the WindowManager class
documentation for more information.)
Display mDisplay = getWindowManager().getDefaultDisplay();
final int width = mDisplay.getWidth();
final int height = mDisplay.getHeight();
// now simple height/2 use it as u want
something like this perhaps? Not sure if it will work exactly as you want it but thats the general idea of it
Configuration configuration = getActivity().getResources().getConfiguration();
int screenWidthDp = configuration.screenWidthDp;
final float scale = context.getResources().getDisplayMetrics().density;
int pixels = (int) (screenWidthDp * scale);
button1.setWidth(pixels*0.5);
Try
LayoutParams params = new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.setMargins(left, top, right, bottom);
yourbutton.setLayoutParams(params);
Resources r = mContext.getResources();
int px = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
yourdpmeasure,
r.getDisplayMetrics());

Wrong Y coordinate from TextView on Bitmap using Canvas.drawText

Please help me with my problem or at least give me advice.
I have ImageView with overlayed TextView. The user can drag text to any position on the image. After, I want to save the image with text at chosen position.
Layout (TextView add dynamically to root element):
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center_horizontal|center_vertical">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/root"
android:padding="0dp"
android:layout_margin="0dp">
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:adjustViewBounds="true"
android:scaleType="centerInside"/>
</FrameLayout>
</LinearLayout>
All problem in Y coordinate is always wrong. I'm try 2 function to find X and Y coordinates.
First:
public float[] getPosition(ImageView imageView, TextView textView) {
Matrix matrix = new Matrix();
imageView.getImageMatrix().invert(matrix);
float[] coord = {textView.getX(), textView.getY()};
matrix.mapPoints(coord);
return coord;
}
and better one, using this function give you accurate X.
private float[] getCoordinates(ImageView iv, Bitmap bm, float x, float y){
float projectedX = (float) ((double)x * ((double)bm.getWidth()/(double)iv.getWidth()));
float projectedY = (float) ((double)y * ((double)bm.getHeight()/(double)iv.getHeight()));
return new float[]{projectedX, projectedY};
}
Any advice? Y always higher than the desired position when Canvas draw text.
Here is my code to save data for Canvas.drawText:
Bundle bundle = new Bundle();
TextView textView = (TextView)relativeLayout.getChildAt(i);
bundle.putString("text", ((TextView) relativeLayout.getChildAt(i)).getText().toString());
bundle.putFloatArray("coord", getPosition(imageView,textView));
bundle.putFloat("size", size*scale);
new AsyncDraw().execute(bundle);
And after in AsyncTask:
Bundle bundle = bundles[0];
String text = bundle.getString("text");
float[] coord = bundle.getFloatArray("coord");
Canvas canvas = new Canvas(oriented);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setTextSize(bundle.getFloat("size"));
canvas.drawText(text, coord[0],coord[1],paint);
Try mapping the height values to your device screen metrics using TypedValue.applyDimension method

How to set relativelayout height equal to its width?

I searched a lot to find out how its gonna work and I got nothing.
I found some java code to do it dynamically but didn't work ant of theme and when opening the program, show a force close.
this is my code:
<LinearLayout android:baselineAligned="false"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<RelativeLayout
android:id="#+id/rlv1"
android:layout_width="match_parent"
android:layout_height="150dp"
android:layout_weight="1"
android:background="#drawable/rectengle2" >
</RelativeLayout>
<RelativeLayout
android:id="#+id/rlv2"
android:layout_width="fill_parent"
android:layout_weight="1"
android:background="#drawable/rectengle" >
</RelativeLayout>
</LinearLayout>
as you can see I created a rectangle shape and used it in a relative layout with a lineaer layout as parent and i splitted that linear layout verticali to two part for each relative layout.
now i want to set these relative layout height equal to its width to get a pure square rectangle.
i tried many way but ... can help me any guy please?? thnaks..
The simplest solution, imo, is to subclass RelativeLayout, and override onMeasure, providing to the super the same size for width and height. For instance
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
as pointed out by #ZakTaccardi, declare it in your layout like
<com.example.subclassrelativelayout
android:layout_width="match_parent"
android:layout_height="wrap_content" />
Finally I myself found out what to do in this situation. so i'm gonna explain how to solve for those who have or will have my problem.
in my xml ui file I set layout_weight=1 for a pair of relative layout that were in a linear layout to be splitted in the screen and actually width of each of them be the half of my screen width. my problem was about height and i tried many java codes to set relative layout height equals to its width.
finally i calculated the screen width in "DP" Term and set every relative layout's height to this. this is the solved code:
Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics ();
display.getMetrics(outMetrics);
float density = getResources().getDisplayMetrics().density;
float dpWidth = outMetrics.widthPixels / density;
RelativeLayout Rl1 = (RelativeLayout) findViewById(R.id.rlv1);
Rl1.getLayoutParams().height = (int) (dpWidth);
RelativeLayout Rl2 = (RelativeLayout) findViewById(R.id.rlv2);
Rl2.getLayoutParams().height = (int) (dpWidth);
so i got a pure square! Enjoy it. Thanks

How do you use a custom view in a HorizontalScrollView?

I've got a custom view (called CustomStrechView) which extends an ImageView. The point of this view is so that I can get an image to fill the view without losing the aspect ratio.
Now the CustomStrechView works fine when I use it in most applications, but when I try to apply it within my HorizontalScrollView, the images all seem to disappear. I'm not sure why this happens. I've tried removing the <HorizontalScrollView /> and when I do the images show back up, so I feel there is some property that needs to be set, but I can't seem to find it.
Can anyone point out what I’m doing wrong or a better way to get a custom view to work in a HorizontalScrollView?
Edit:
After playing around with this for a bit, I've determined that I can get the custom view to show the image only if I hardcode the width dimension, ie:
<com.example.dragdropshapes.CustomStrechView
android:layout_width="200dp"
Leaving the height as fill_parent is fine...
Code:
Here's how my custom view is being used in the xml file:
<!-- Removing this makes the images show up -->
<HorizontalScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true"
android:layout_marginTop="50dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:showDividers="middle"
android:orientation="horizontal">
<!-- Changing this to a normal ImageView makes the image show up -->
<com.example.dragdropshapes.CustomStrechView
android:id="#+id/pickshapes"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:clickable="true"
android:onClick="pickShapes"
android:background="#drawable/border"
android:src="#drawable/ic_launcher"
/>
<!-- There are 5 other custom ImageViews here -->
</LinearLayout>
</HorizontalScrollView>
Here's the major part of the custom view code:
public class CustomStrechView extends ImageView{
private final Drawable srcPic;
private final String TAG = "strechyTag";
private boolean changeSize = false;
private int Xpx;
private int Ypx;
public CustomStrechView(Context context) {
super(context);
srcPic = this.getDrawable();
}
//... other constructors, not really important...
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
Log.d(TAG, "in the onMeasure!!\n");
int width, height;
width = MeasureSpec.getSize(widthMeasureSpec);
height = width * srcPic.getIntrinsicHeight() / srcPic.getIntrinsicWidth();
setMeasuredDimension(width, height);
}
}
Through some debugging I was able to at least partially solve this myself. Turns out that the width acquired from the MeasureSpec.getSize(widthMeasureSpec); call was 0. Thus the calculation ended in width and height being 0 and the setMeasuredDimension call would then make the image invisible.
Now I'm saying I have this partially solved, because I still don't understand why I was getting that value of 0. I think it's because in a HorizontalScrollView the width isn't determined (it depends on the content within) thus whatever MeasureSpec.getSize(widthMeasureSpec); is actually doing is talking to the parent, and the parent in a normal Linear or RelativeLayout has a defined width where as in a HorizontalScrollView it does not... but that's just speculation at this point.
So I made a fix for it, if the width is 0 we run the calculation via the height instead. The height needed two cases to cover it to avoid divide by 0 errors (the else if and the else collectively).
Here's my current solution with the same xml file I noted in the Question.
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
if(width > 0)
height = width * srcPic.getIntrinsicHeight() / srcPic.getIntrinsicWidth();
else if(srcPic.getIntrinsicWidth() < srcPic.getIntrinsicHeight())
width = height / (srcPic.getIntrinsicHeight() / srcPic.getIntrinsicWidth());
else
width = height / (srcPic.getIntrinsicWidth() / srcPic.getIntrinsicHeight());
setMeasuredDimension(width, height);
}

Categories

Resources