How do you use a custom view in a HorizontalScrollView? - java

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);
}

Related

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());

Android getMeasuredHeight get wrong value

I have the XML like this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000" >
<com.XXXXXXXXXXX.view
android:layout_width="200dp"
android:background="#ffffff"
android:layout_height="400dp"
android:layout_centerInParent="true" />
I get the view height in the method onMesure like this:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (!isMeasured)
{
isMeasured = true;
mViewHeight = getMeasuredHeight();
mViewWidth = getMeasuredWidth();...}
the mViewWidth is right(600px), but the mViewHeight is wrong(1626px).
Could someone give me some pointers?
Tks a lot.
getMeasuredHeight() will return the desired height for the child, not necessarily the height it actually gets. You also are taking the first measured value and setting your width/height to that. onMeasure can be called multiple times for different reasons. The intent is to say how much height/width your view desires with the given MeasureSpec constraints. onLayout will get called later with where your parent actually wants you, which may not match what you asked for in onMeasure.
Also, views already have a getWidth() and getHeight() which are valid after the layout pass. Do you need your own mViewWidth and mViewHeight?

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 to get height in pixels of LinearLayout with layout_weight

this is my first post. I am learning to code in java for android apps.
I am using a LinearLayout "variable named: ll" with a predefined layout_weight (which I want to change whenever I want in the future) and height and width set to MATCH_PARENT. I want to get the height of this LinearLayout in pixels. I fill this using java (ll.addView(variableForAnObject);).
I am trying to get its height using ll.getLayoutParams().height; but I am getting -1. Because I believe this is the constant for MATCH_PARENT. Setting the height to 0dp makes the ll invisible and gives height as 0.
Please tell me if there's a way to get its height. I think I can do this by getting screen height using DisplayMetrics and making nearly impossible calculations (for me, at least) but this will be too complex.
try with ll.getHeight() should work
if not, it's because android has not yet calculed its bounds, then:
//inside of onCreate method should work
ll.post(new Runnable() {
#Override
public void run() {
//maybe also works height = ll.getLayoutParams().height;
height = ll.getHeight();
}
});
It is -1 because its dimensions have not yet been set, whenever you set layout it takes some time to compute the actual values including height, width etc.
Use OnLayoutListener to listen when it has finished with the layout.
layout.onLayoutChange (View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
//Extract values here
height = view.getHeight();
width = view.getWidth()
}
See this for more about the OnLayoutListener
Define your LinearLayout in your class and use getHeight() and getWidth(). Example:
LinearLayout yourLayout = (LinearLayout) findViewById (R.id.yourLL);
double height = yourLayout.getHeight();
double width = yourLayout.getWidth();
Hope it helps! :)
Give the id field in your layout xml file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:id="#+id/<ID>>
Use this id to get reference in java class and find height and width:
LinearLayout linearLayout= (LinearLayout) findViewById (R.id.<ID>);
double height = linearLayout.getHeight();
double width = linearLayout.getWidth();

Android: Making the width and the height of a custom view equal

I am using a custom view (CoordinateGridView) in XML like this:
<com.android.catvehicle.CoordinateGridView
android:id="#+id/coordinateGrid"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
I am trying to get the width of the CoordinateGridView to fill the entire width of the screen. The height should then match the width -- therefore, the custom view should always be drawn as a square.
How do I do this?
Override the onMeasure function in CoordinateGridView:
public void onMeasure(int widthSpec, int heightSpec) {
super.onMeasure(widthSpec, heightSpec);
int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
setMeasuredDimension(size, size);
}
See https://github.com/chiuki/android-square-view for a full example.

Categories

Resources