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);
}
}
Related
/* Code snipet from the MainActivity */
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* Linear layout */
LinearLayout layout = (LinearLayout)findViewById(R.id.main_container);
/* Creating two similar custom views */
CustomView row1 = new CustomView(this); /* First row */
CustomView row2 = new CustomView(this); /* second row */
layout.add(row1,0);
layout.add(row2,1);
}
CustomView.java
public class CustomView extends View {
public final String TAG = "CustomView";
Context context;
private Drawable backgroundDrawable;
Rect backGroundDrawableRect;
public TextMessageView(Context context) {
super(context);
this.context = context;
backgroundDrawable = ContextCompat.getDrawable(context,R.drawable.background_drawable);
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
backGroundDrawableRect.left = left;
backGroundDrawableRect.right = right;
backGroundDrawableRect.bottom = bottom;
backGroundDrawableRect.top = top;
backgroundDrawable.setBounds(backGroundDrawableRect);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
/* 100 pixel height for the view */
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),100);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(backgroundDrawable != null) {
backgroundDrawable.draw(canvas);
}
}
}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:id="#+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</LinearLayout>
The problem is that the view added in the second row of the linear layout is not getting displayed. During debugging, when i enabled the 'show layout bound ' in developers option , I found that the view in the second row was taking its required space but the content which is a drawable was not getting displayed.
The Canvas coordinates are automatically adjusted to the view's position so you need to set the left and top bounds of your Drawable to zero instead:
backGroundDrawableRect.left = 0;
backGroundDrawableRect.right = right - left;
backGroundDrawableRect.bottom = bottom - top;
backGroundDrawableRect.top = 0;
Change in CustomView
public class CustomView extends View {
public final String TAG = "CustomView";
Context context;
private Drawable backgroundDrawable;
Rect backGroundDrawableRect;
public CustomView(Context context) {
super(context);
this.context = context;
backgroundDrawable = ContextCompat.getDrawable(context,R.drawable.ic_launcher);
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
/* backGroundDrawableRect.left = left;
backGroundDrawableRect.right = right;
backGroundDrawableRect.bottom = bottom;
backGroundDrawableRect.top = top;
backgroundDrawable.setBounds(backGroundDrawableRect);
*/
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
/* 100 pixel height for the view */
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),100);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(backgroundDrawable != null) {
backgroundDrawable.draw(canvas);
}
}
and your launcher activity do this change
public class Test extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test1);
/* Linear layout */
LinearLayout layout = (LinearLayout) findViewById(R.id.main_container);
/* Creating two similar custom views */
CustomView row1 = new CustomView(getApplicationContext()); /* First row */
row1.setBackgroundColor(Color.RED);
CustomView row2 = new CustomView(getApplicationContext()); /* Second row */
row2.setBackgroundColor(Color.GREEN);
layout.addView(row1);
layout.addView(row2);
}
}
padding does not work as expected in custom ViewGroup
Hi:
My layout have the following structure:
RelativeLayout(with padding)
MainView(ViewGroup)
And the activety_main.xml:
<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"
android:background="#ffffff"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
tools:context=".MainActivity" >
<com.example.testandroid.MainView
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
MainView:
public class MainView extends ViewGroup {
public MainView(Context context, AttributeSet as) {
super(context);
addView(new MyView(context, null));
}
#Override
protected void dispatchDraw(Canvas canvas) {
canvas.drawColor(Color.GREEN);
super.dispatchDraw(canvas);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
for (int i = 0, len = getChildCount(); i < len; i++) {
View v = getChildAt(i);
v.layout(l,t,r,b);
}
}
}
MyView:
public class MyView extends SurfaceView implements Callback {
public MyView(Context contex, AttributeSet as) {
super(contex, as);
getHolder().addCallback(this);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
refresh();
}
private void refresh() {
SurfaceHolder holder = getHolder();
synchronized (holder) {
Canvas canvas = holder.lockCanvas();
if (canvas != null) {
try {
Paint p = new Paint();
p.setColor(Color.RED);
canvas.drawCircle(10, 10, 10, p);
} finally {
holder.unlockCanvasAndPost(canvas);
}
}
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
refresh();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
Now, this is what I got now:
As you can see, the viewgroup I created MainView has a background of green.
And MainView add a MyView dynamically whose background is black here.
Now, the problem is that what the MyView have a padding relative to MainView? Because I want it take all the space of MainView, that's to say, the greed should be invisible.
Why?
But
When you layout your children, it needs to be relative to your position.
To fill yourself you would do child.layout(0, 0, getWidth(), getHeight());.
Try doing this ...
<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"
android:layout_margin="16dp"
tools:context=".MainActivity" >
<com.example.testandroid.MainView
android:layout_width="match_parent"
android:layout_height="600dp"
/>
</RelativeLayout>
I have a relative layout inside a scrollview, then i created a new view with this code:
public class DrawView extends View {
Paint paint = new Paint();
public DrawView(Context context) {
super(context);
}
#Override
public void onDraw(Canvas canvas) {
paint.setColor(Color.BLACK);
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.STROKE);
canvas.drawRect(5, 5, 140, 140, paint);
}
}
Then i try to use layout.addView(DrawView) to add the new view to the relative layout, so it can be scrollable with the rest of the content, but is doesn't work, nothing shows up..
Am i missing something ?
Edit:
DrawView formas;
GifMovieView gif;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final RelativeLayout layout = new RelativeLayout(this);
final ScrollView scrollView = new ScrollView(this);
//gif = new GifMovieView(this, t_img);
formas = new DrawView(this);
layout.addView(formas);
scrollView.addView(layout);
this.setContentView(scrollView);
inicializar();
load(layout);
}
You will probably want to override onMeasure() in your DrawView. Otherwise your view will have size of 0x0 pixels.
You can start with something as simple as
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(200, 200);
}
just to prove it works, but you will need to do some more meaningful, based on what are contents of your view.
Start from this article to see help on overriding onDraw() and onMeasure()
I have a custom View, which extends RelativeLayout.
This Relative Layout should consist of Rectangles which extends View, and this Rectangles should be painted by a bitmap and have a TextView in it..
But i cant add this Rectangles to the RelativeLayout so that they are below of each other.. it seems that the LayoutParams do not work.. Can you help me please?
Custom View extends RelativeLayout
public class DrawView extends RelativeLayout {
private Context context;
public DrawView(Context context, ArrayList<String> dragFieldText, ArrayList<String> targetFieldText, int height, int width) {
super(context);
this.context = context;
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.FILL_PARENT);
Rectangle.count = 1;
for (int i = 0; i < targetFieldText.size(); i++) {
Rectangle targetRectangle = new Rectangle(context);
this.addView(targetRectangle);
}
Rectangle tmpRect = null;
for (int i = 0; i < dragFieldText.size(); i++) {
Rectangle dragRectangle = new Rectangle(context);
if(tmpRect != null){
tmpRect.setId(i);
lp.addRule(RelativeLayout.BELOW, tmpRect.getId());
dragRectangle.setLayoutParams(lp);
}
this.addView(dragRectangle);
tmpRect = dragRectangle;
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = View.MeasureSpec.getSize(widthMeasureSpec);
int height = View.MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
}
Rectangle extends View
public class Rectangle extends View{
public Rectangle(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(getSomeBitmapImg(), new Matrix(), null);
}
I ran into a mysterious ANR with my application which uses Pictures to record drawing command (paths, clips, text, etc.) and then draws these Pictures into Views held by a ScrollView. I was able to reproduce the issue with the below activity. In this activity, scrolling down in the ScrollView will produce an ANR as soon the bottom of the square is reached. Has anyone else ran into this? Any suggestions on how to avoid it?
public class AnrTest extends Activity
{
public void onCreate(Bundle saveInstBundle)
{
super.onCreate(saveInstBundle);
ScrollView sc = new ScrollView(this);
MyView view = new MyView(this);
sc.addView(view);
setContentView(sc);
}
class MyView extends View
{
Picture mPic;
public MyView(Context context)
{
super(context);
mPic = new Picture();
Canvas picCanvas = mPic.beginRecording(300, 900);
Paint p = new Paint();
p.setColor(Color.RED);
picCanvas.drawRect(20, 20, 100, 100, p);
picCanvas.clipRect(0, 0, 100, 100);
mPic.endRecording();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
//set a height larger than the screen, so that we can scroll.
setMeasuredDimension(300, 900);
}
protected void onDraw(Canvas canvas)
{
canvas.drawPicture(mPic);
}
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
//set a height larger than the screen, so that we can scroll.
setMeasuredDimension(300, 900);
requestLayout();
}
You made the child larger than it's parent. requestLayout() will resolve your issue.