android how to set custom LinearLayout height half of width Inside herself.
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec / 2);
}
i use this code but child's are cut off.
public class CustomLinearLayout extends LinearLayout {
private static final float RATIO = 0.5f;
public CustomLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onMeasure(int widthSpec, int heightSpec) {
int customHeight = MeasureSpec.makeMeasureSpec(
(int)(MeasureSpec.getSize(widthSpec) * RATIO), MeasureSpec.EXACTLY);
super.onMeasure(widthSpec, customHeight);
}
}
Related
I want to make a view that it's width and height is always equal.
when user define a specfied height and width in xml, it chooses a smaller one.
for example:
<com.mmmmar.ControlView
android:layout_width="100dp"
android:layout_height="200dp"
android:background="#f00" />
it run well.
However, when I make width lager than height, It runs unexpectedly.
green block is something I draw on this view, red block is the background I set in xml to indicate the area of view.
<com.mmmmar.ControlView
android:layout_width="200dp"
android:layout_height="100dp"
android:background="#f00" />
here is my code
public class ControlView extends View {
private final static int DEFAULT_SIZE = 200;
private int mDrawRadius;
private Paint mPaint;
public ControlView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
// configure paint
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setDither(true);
mPaint = paint;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int size = dp2px(DEFAULT_SIZE, getContext());
int width = calculateSpec(widthMeasureSpec, size);
int height = calculateSpec(heightMeasureSpec, size);
int radius = Math.min(width, height);
// width should equal height.
setMeasuredDimension(radius, radius);
mDrawRadius = radius;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = mPaint;
paint.setColor(Color.GREEN);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(0, 0, mDrawRadius, mDrawRadius, paint);
}
public int dp2px(float dp, Context context) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
public int calculateSpec(int measureSpec, int defaultSize) {
int mode = View.MeasureSpec.getMode(measureSpec);
int size = View.MeasureSpec.getSize(measureSpec);
int realSize;
if (mode == View.MeasureSpec.EXACTLY) {
realSize = size;
} else {
// For Mode :UNSPECIFIED and AT_MOST
realSize = Math.min(size, defaultSize);
}
return realSize;
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int size = dp2px(DEFAULT_SIZE, getContext());
int width = calculateSpec(widthMeasureSpec, size);
int height = calculateSpec(heightMeasureSpec, size);
int radius = Math.min(width, height);
// width should equal height.
setMeasuredDimension(radius, radius);
mDrawRadius = radius;
}
You do not need to set measured dimension after calculating.
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Your logic comes here to pick smallest border
super.onMeasure(smallest_border_that_you_pick,smallest_border_that_you_pick)
}
Would be fix your problem.
I'm writing a custom view, which is having a ScrollView as a parent, because, the custom view height exceeds the screen's height. The problem that I'm facing is that I cannot scroll the layout.
The fragment which is added in the activity's UI:
public class FragmentHour extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance) {
HourView view = new HourView(getActivity());
ScrollView sv = new ScrollView(getActivity());
sv.setFillViewport(true);
sv.addView(view);
return sv;
}
}
The custom view:
public class HourView extends View {
// Default rectangle for one row, used to know the sizes
private Rect mDefRect;
// Paint to draw the lines
private Paint mPaint;
public HourView(Context context) {
super(context);
init();
}
public HourView(Context context, AttributeSet set) {
super(context, set);
init();
}
public HourView(Context context, AttributeSet set, int defStyle) {
super(context, set, defStyle);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setColor(Color.GRAY);
mPaint.setStrokeWidth(UIUtils.dpToPx(getContext(), 0.5f));
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// Create a default rectangle, for one row
// We need to recreate the rectangle multiple times, because getWidth() == 0
int height = UIUitls.dpToPx(getContext(), 50); // dpi to px
mDefRect = new Rect(0, 0, getWidth(), height);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
int verticalOffset = 0;
for (int i = 0; i < 24; i++) {
int cellHeight = mDefRect.height();
verticalOffset += cellHeight;
canvas.drawLine(0, verticalOffset, getWidth(), verticalOffset, mPaint);
}
}
}
The code above will result:
As I said, the problem is that I cannot scroll the view, probably because the child view's height, it's the size of it's parent.
I have tried to override the onMeasure method:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mDefRect != null) {
int measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
int newHeight = mDefRect.height() * 24;
setMeasuredDimension(measuredWidth, newHeight);
// super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.EXACTLY));
}
else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
I have tried to register for layout-change, then change the Layout parameters:
private void init() {
// ...
post(new Runnable() {
#Override
public void run() {
getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#SuppressLint("NewApi")
#SuppressWarnings("deprecation")
#Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
getLayoutParams().height = mDefRect.height() * 24;
// postInvalidate();
}
});
}
});
}
I'm trying to create a custom LinearLayout where the height is 80% of the width.
I created a class that extends LinearLayout and overrides onMeasure(). I thought I could manipulate the passed-in widthMeasureSpec and heightMeasureSpec, but all I get is a LinearLayout with no height.
Actually, I have a TextView in it, so all I see is the TextView with no other height applied to the layout.
I'm hoping someone can tell me what's wrong with this:
public class CustomLinearLayout extends LinearLayout {
public CustomLinearLayout(Context context) {
super(context);
}
public CustomLinearLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int adjustedHeight = (int) (MeasureSpec.getSize(widthMeasureSpec) * 0.8);
int measureSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int adjustedHeightMeasureSpec =
MeasureSpec.makeMeasureSpec(adjustedHeight, measureSpecMode);
super.onMeasure(widthMeasureSpec, adjustedHeightMeasureSpec);
}
}
EDIT: Okay, this is strange. The code decided to work after I restarted Eclipse and ran it again.
You should change mode to exactly, like :
int measureSpecMode = MeasureSpec.EXACTLY;
One issue might be that the height that the layout calculates is based on the children, i.e. the layout will be taller the more stuff it has in it.
One obvious problem with your code however is that you have not called
setMeasuredDimension(widthMeasureSpec, adjustedHeightMeasureSpec);
in the onMeasure() method. You instead still have the super.onMeasure. In order for your custom measured heights and widths to be used you have to call this method. In fact you can delete the last line of your code in onMeasure and replace it with the line above.
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, (int)(widthMeasureSpec*0.8));
}
You can use this code to adjust your layouts height to any ratio:
private static final float RATIO = 80f / 100f;
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
int width = getMeasuredWidth();
int height = getMeasuredHeight();
int widthWithoutPadding = width - getPaddingLeft() - getPaddingRight();
int heigthWithoutPadding = height - getPaddingTop() - getPaddingBottom();
int maxWidth = (int) (heigthWithoutPadding * RATIO);
int maxHeight = (int) (widthWithoutPadding / RATIO);
if (widthWithoutPadding > maxWidth) {
width = maxWidth + getPaddingLeft() + getPaddingRight();
} else {
height = maxHeight + getPaddingTop() + getPaddingBottom();
}
setMeasuredDimension(width, height);
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
}
You can vary the RATIO constant according to your need.
I'm currently using the library TouchImageView here:
https://github.com/MikeOrtiz/TouchImageView
This works perfectly fine when I fill the entire phone's screen with the TouchImageView, but how would I constrain the visible area to a square?
I've tried:
public class SquareTouchImageView extends TouchImageView {
public SquareTouchImageView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public SquareTouchImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareTouchImageView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
setMeasuredDimension(width, width);
}
}
But that doesn't let me scroll down to show the rest of the image (if it's taller than it is wide)
Is there a way I can enable a square TouchImageView?
If so how would I be able to do it?
I've solved it by doing the following and I hope this helps whoever else might have this issue in future.
public class SquareTouchImageView extends TouchImageView {
public SquareTouchImageView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public SquareTouchImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareTouchImageView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Drawable drawable = getDrawable();
if (drawable == null || drawable.getIntrinsicWidth() == 0
|| drawable.getIntrinsicHeight() == 0) {
setMeasuredDimension(0, 0);
return;
}
int drawableWidth = drawable.getIntrinsicWidth();
//int drawableHeight = drawable.getIntrinsicHeight();
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
//int heightSize = widthSize;// MeasureSpec.getSize(heightMeasureSpec);
//int heightMode = widthMode;// MeasureSpec.getMode(heightMeasureSpec);
viewWidth = setViewSize(widthMode, widthSize, drawableWidth);
viewHeight = viewWidth;// setViewSize(heightMode, heightSize,
// drawableHeight);
//
// Set view dimensions
//
setMeasuredDimension(viewWidth, viewHeight);
//
// Fit content within view
//
fitImageToView();
}
}
You may have to change some variables in TouchImageView from private to protected.
And XML:
<com.aura.app.widget.SquareTouchImageView
android:id="#+id/scrollingImage"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true" />
I want to increase height of my custom TextView so I can draw some lines below TextView. Can anyone help me how can I do that? Here is my custom textview.
CustomTextView
public class CustomTextView extends TextView{
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);init();
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs); init();
}
public CustomTextView(Context context) {
super(context);init();
}
private Paint mStrokeBrush;
private void init(){
mStrokeBrush= new Paint();
mStrokeBrush.setStrokeWidth(5f);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(0f, getHeight());
canvas.drawLine(0, 0, getWidth(), 0, mStrokeBrush);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
Edit: I removed a bunch of code which wasn't relevant to your question. Sorry if it caused confusion.
This is a modification of my own code, which adds 20dp to the view's height.
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int viewWidth = MeasureSpec.getSize(widthMeasureSpec);
int viewHeight = MeasureSpec.getSize(heightMeasureSpec);
//
// Set view dimensions. Add 20dp.
//
int dp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics());
setMeasuredDimension(viewWidth, viewHeight + dp);
}