Android: Set match_parent in custom view programmatically - android

I implemented a custom view where I can paint. I want to set it to MATCH_PARENT, so that it fills the screen independent of the screen orientation. When I change orientation to landscape it fills just 50% of width.
I changed onMeasure() but there was no effect:
public class DrawScreen extends View{
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if(context.getResources().getConfiguration().orientation==Configuration.ORIENTATION_LANDSCAPE){
setMeasuredDimension(screenWidth, screenHeight);
}else{
setMeasuredDimension(screenHeight, screenWidth);
}
}
}
public class MyService extends Service{
...
windowManager.addView(toolbox, params);
}

You could try the following:
final DrawScreen view = new DrawScreen(...);
final LayoutParams lp = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
view.setLayoutParams(lp);

Related

Extending a view which overrides onMeasure()

I have a view view1 which extends FrameLayout and overrides onMeasure() like this, so that it is rendered as a square:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
Now I want to create another view view2 which extends view1, but now I want view2 to have a height equal to the parent, and hence to cover the full screen. As of now, I get it as a square too.
How do I achieve this?
In view 1:
private boolean measureAsSquare = true;
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (measureAsSquare) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public void setMeasureAsSquare(boolean b) {
measureAsSquare = b;
}
In View2 constructor that subclasses view 1:
public View2(Context c) {
setMeasureAsSquare(false);
}
Then you can use normal layout weight and height for view 2 to assign its preferred size.
Since the onMeasure for Square was already overridden where it disregards the height passed to it, as per your code:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
One way to do what you want -- view2 which extends view1, but now I want view2 to have a height equal to the parent, and hence to cover the full screen -- is to also override onMeasure of view2 calling on setDimension like this...
public class Square2 extends Square {
public Square2(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
}
}
Here is a sample after I tried it out. (For code in Square View, I just copied your code in onMeasure).
Using Square:
For Squre2:
Hope this helps.

Gravity of a child TextView does not work with custom ViewGroup

I have the following classes:
public class MyGridView extends ViewGroup {
...
#Override
public void onSizeChanged(int xNew, int yNew, int xOld, int yOld) {
super.onSizeChanged(xNew, yNew, xOld, yOld);
// do calculations for drawing bounds of child views
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
View child;
Rect rect;
for (int i=0; i < getChildCount(); i++) {
child = getChildAt(i);
rect = getBoundsAtChildIndex(i)
child.layout(rect.left, rect.top, rect.right, rect.bottom);
}
}
...
}
AND
public class MyAdapter {
public void setMyGridView(MyGridView myGridView) {
// add a single TextView to my grid view
textView = createTextView(context);
addTextViewToGrid(textView);
container.add(textView);
}
private TextView createTextView(Context context) {
TextView textView = new TextView(context);
textView.setText("1");
textView.setTextColor(0xffffffff);
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12f);
textView.setTypeface(typeface);
textView.setGravity(Gravity.CENTER | Gravity.FILL);
// textView.setGravity(Gravity.RIGHT); // other tries to see gravity
// textView.setGravity(Gravity.FILL);
return textView;
}
private void addTextViewToGrid(TextView textView) {
myGridViewPtr.addView(textView, ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
}
...
}
I have created a custom grid view and adapter, where its children draw to the screen to the correct size and location. However, their gravity, set in the createTextView() is not observed.
I can set a background image to the textView and see it fill its space in the grid.
In contrast, the text in textView always draws in its top left corner, and it always stays at the text size I set it at 12sp, rather than scale to fit using Gravity.FILL.
Preferably, the text would scale to fit and center within the textview.
EDIT
I have added the following method for onMeasure() in ViewGroup:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
int height = getMeasuredHeight();
doUpdateOnSizeChanged(width, height);
for (int i = 0; i < getChildCount(); i++)
getChildAt(i).measure((int) viewDim.x, (int) viewDim.y);
setMeasuredDimension(width, height);
}
The children are supposed to be the same height, width as each other. The android example code for ViewGroup is more sophisticated than I require. For instance, I am not getting the max of all children width, height.
For my onMeasure(), the child width, height in ViewDim is width, height integers that are computed in doUpdateOnSizeChanged to be less than getMeasuredWidth, getMeasuredHeight.
The result is now text aligns in the bottom-left corner of the TextView.
onMeasure needed minor corrections, basically needing to rely on MeasureSpec:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width, height;
int cWidth1, cHeight1;
width = MeasureSpec.getSize(widthMeasureSpec);
height = MeasureSpec.getSize(heightMeasureSpec);
doUpdateOnSizeChanged(width, height);
cWidth1 = (int)viewDim.x; cHeight1 = (int)viewDim.y;
measureChildren(MeasureSpec.makeMeasureSpec(cWidth1, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(cHeight1, MeasureSpec.EXACTLY));
setMeasuredDimension(width, height);
}

How to change height of item in ListView?

I use auto resizing TextView as item in my ListView. This widget overrides onMeasure() and set height equal half of width. So text fits in this bounds. This widget also has listener, that called, when font size is changed. If new font size less than 14dp for example, I need to set height of widget equal to its width. So i set new value to flag and call requestLayout().
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
int height = width;
if (halfSize) {
height = width / 2;
}
setMeasuredDimension(width, height);
}
private void init(Context context) {
this.context = context;
final float halfModeMinFontSize = DisplayUtils.dpToPx(context, 14);
setOnResizeListener(new OnTextResizeListener() {
#Override
public void onTextResize(TextView textView, float oldSize, float newSize) {
if (newSize < halfModeMinFontSize) {
setHalfSize(false);
}
}
});
}
But calling of requestLayout() doesn't result. So how can I change height of ListViews item and initiate its measure?

customView in LinearLayout fills space

I'm using a custom view MaskCustomView by subclassing View. The width/height layout params for the custom view are both WRAP_CONTENT.
What happens is the custom view in the LinearLayout takes all the space. I can see that using uiautomatorViewer :
Code is :
public class MaskImageView extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mask_image);
LinearLayout container = (LinearLayout) findViewById(R.id.maskID);
MaskCustomView maskView = new MaskCustomView(this);
maskView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
container.addView(maskView);
}
public class MaskCustomView extends View {
private Bitmap bp;
private Paint p;
public MaskCustomView(Context context) {
super(context);
bp = BitmapFactory.decodeResource(getResources(), R.drawable.apple);
p = new Paint();
}
#Override
public void onDraw(Canvas canvas) {
canvas.drawBitmap(bp, 0, 0 , p);
super.onDraw(canvas);
}
}
}
xml layout :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:id="#+id/maskID"
android:layout_width="match_parent"
android:layout_height="match_parent">
Shouldn't just wrap content and don't use whole space for both height and width ?
Try to make your MaskCustomView override onMeasure:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if(bp == null) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} else {
setMeasuredDimension(MeasureSpec.makeMeasureSpec(bp.getWidth(), MeasureSpec.MODE_CONSTANT), MeasureSpec.makeMeasureSpec(bp.getHeight(), MeasureSpec.MODE_CONSTANT);
}
}

View Layout_Margin doesn't work inside the FrameLayout

I have a frameLayout and inside this layout there are several Views, and I want to margin each view from the top to a specific distance .
I have tried the following code, but it seems that it doesn't work
FrameLayout lytBoard = (FrameLayout) findViewById(R.id.lytBoard);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(width, height);
params.setMargins((int)board.cells.get(i).x1, (int)board.cells.get(i).y1, 0, 0);
CellView cv = new CellView(getApplicationContext());
cv.setLayoutParams(params);
lytBoard.addView(cv);
Cell View class:
public class CellView extends View {
public CellView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
setMeasuredDimension(size, size);
}
}
You are setting to the CellView, subclass of View, a layoutParams of the type LinearLayout.LayoutParams. In the definition of the method in View, the method setLayoutParams receives params of the type ViewGroup.LayoutParams and ViewGroup does not contains a margin property, so this may be the cause of the problem.
You can try to subclass LinearLayout instead of View.

Categories

Resources