I have a class Ball which extents View.Inside there i give some characteristics and implements onTouchEvent() so i can handle the movement.Also i use onDraw so i can draw the bitmap of the ball. in my activity class i crate a new Layout and i add the view to it so it can be displayed. Everything works fine except when, i try to add more balls to my layout they don't appear!Always the first added in layout ball is displayed!
Here's the onCreate code from activity class:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.HORIZONTAL);
int lHeight = LinearLayout.LayoutParams.WRAP_CONTENT;
int lWidth = LinearLayout.LayoutParams.WRAP_CONTENT;
Point point1 = new Point();
point1.x = 50;
point1.y = 20;
Point point2 = new Point();
point2.x = 100;
point2.y = 20;
Point point3 = new Point();
point3.x = 150;
point3.y = 20;
ColorBall ball1 = new ColorBall(this,R.drawable.bol_groen, point1);
ll.addView(ball1, new LinearLayout.LayoutParams(lHeight, lWidth));
setContentView(ll);
ColorBall ball2 = new ColorBall(this,R.drawable.bol_rood, point2);
ll.addView(ball2, new LinearLayout.LayoutParams(lHeight, lWidth));
setContentView(ll);
ColorBall ball3 = new ColorBall(this,R.drawable.bol_blauw, point3);
ll.addView(ball3, new LinearLayout.LayoutParams(lHeight, lWidth));
setContentView(ll);
}
What could possibly be the problem?I have try it also with only one setContentView() at the end.I am thinking that i can't use a Layout so i can draw bitmaps which are in a custom View!Am i right?
Should i change my code and create a View and inside there make an array with all the balls i want to be displayed and then set this View to be displayed from my main class of activity?(like this setContentView(customview)).
You are calling setContentView several times, while it is expected to call only once per activity initialization.
UPDATE:
Could you use this layout xml instead of programmatic way you use? This is just to be 100% sure the container to which you will add the ColorBalls is Ok.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:id="#+id/container"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
Just in case, here is the code to include it in the activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_name_of_layout);
LinearLayout container = (LinearLayout) findViewById(R.id.container);
..
container.addView(ball1);
container.addView(ball2);
..
}
Related
So I know there are a lot of questions like this, but none of the answers have had any effect.
I have a custom View that I am trying to put into a ScrollView (all programmatically). The ScrollView itself works fine, is where it needs to be, does what it's supposed to do and when tested by adding a TextView to it, still did what it was supposed to.
However when I create my custom View the view doesn't draw and it is as if nothing is there. The draw(Canvas canvas) method is never called (also tried with onDraw even though I don't know what the difference is but it still didn't work).
I have tried things such as setWillNotDraw(false) in the constructor, called View.invalidate() every time I want it to draw/redraw, nothing appears to be working.
Here is the relevant code:
ScrollView Initialized
sv = new ScrollView(env.getContext());
ScaledBounds sb = UsefulMethods.getScaledBounds(50, 200, BBEnvironment.WIDTH - 100, BBEnvironment.HEIGHT - 300);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(sb.getWidth(), sb.getHeight());
sv.setTranslationX(sb.getX());
sv.setTranslationY(sb.getY());
sv.setLayoutParams(params);
sv.setScrollbarFadingEnabled(false);
sv.setScrollBarSize(0);
sv.setBackgroundColor(Color.argb(150, 0, 255, 0));
Custom View Class
private class LevelSelectionView extends View {
private ArrayList<LevelButton> levelButtons;
public LevelSelectionView(Context context) {
super(context);
levelButtons = new ArrayList<LevelButton>();
int x = 20;
int y = 20;
for(int i = 0; i < 20; i++) {
levelButtons.add(new LevelButton(x, y, 100, 100, 10, i + 1));
levelButtons.get(i).unlock();
x += 100 + 20;
}
setWillNotDraw(false);
}
public void draw(Canvas canvas) {
super.draw(canvas);
System.out.println("is being called"); //except it isn't
Paint paint = new Paint();
paint.setAntiAlias(env.getCurrentSettings().getAntialias());
for(LevelButton lb : levelButtons)
lb.drawObject(canvas, paint);
}
}
Creating and adding custom view
LevelSelectionView lsView = new LevelSelectionView(sv.getContext());
lsView.setLayoutParams(new RelativeLayout.LayoutParams(sv.getLayoutParams().width, 1000));
lsView.setBackgroundColor(Color.argb(150, 0, 0, 255));
sv.addView(lsView);
Why is it not drawing and how do I get it to draw?
I tried like that and it works:
public class LevelSelectionView extends View {
private final static String TAG = LevelSelectionView.class.getSimpleName();
private final ArrayList<Button> mButtons;
private final Paint mPaint;
public LevelSelectionView(Context context) {
super(context);
mButtons = new ArrayList<Button>();
int x = 20;
int y = 20;
mPaint = new Paint();
// mPaint.setAntiAlias(env.getCurrentSettings().getAntialias());
Button myButton;
for (int i = 0; i < 20; i++) {
myButton = new Button(context);
myButton.setLayoutParams(new ViewGroup.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT));
mButtons.add(myButton);
// mButtons.get(i).unlock();
// x += 100 + 20;
}
setWillNotDraw(false);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (Button lb : mButtons)
Log.d(TAG, "is being called"); //except it isn't
// lb.drawObject(canvas, mPaint);
}
}
I don't know what is your LevelButton as it's a custom class.
I create the LevelSelectionView like that, using a FrameLayout but it's the same idea with the ScrollView:
FrameLayout container = (FrameLayout) findViewById(R.id.container);
LevelSelectionView view = new LevelSelectionView(this);
view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
container.addView(view);
Maybe your issue comes from the LevelButton or the context you use (as you use the Context from env to create the ScrollView and the Context of the ScrollView to create your custom class). You code is not clear as we don't know what is your env object as all your class are inner classes.
It looks like you need to properly implement onMeasure so the scrollview knows how tall that view is.
I am trying to create some Circles inside my layout, here is my drawable.circle code:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<gradient
android:angle="270"
android:endColor="#80FF00FF"
android:startColor="#FFFF0000" />
</shape>
but since I am trying to create 10 of this view and also do some functions on them I can't create them inside my layout file, I want to use array of views - here is what I got so far:
private View imageViewArray[];
private Random rand;
private int layoutwidth;
private int layoutheight;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rand = new Random();
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
layoutwidth = size.x;
layoutheight = size.y;
imageViewArray = new ImageView[10];
for (int i = 0; i < 10; i++) {
imageViewArray[i] = new View(this);
imageViewArray[i].setTag(i);
randomx = rand.nextInt((layoutwidth - layoutwidth / 3) + layoutwidth / 3);
randomy = rand.nextInt(layoutheight - layoutheight / 3);
imageViewArray[i].setX(randomx);
imageViewArray[i].setY(randomy);
rlt.addView(imageViewArray[i]);
}
How do I assign Circle.xml to all of these views? imageViewArray[i].set?
You can add your drawable xml file as background resource to the ImageView:
imageViewArray[i].setBackgroundResource(R.drawable.circle);
There's no reason not to draw them in the xml, except if the random part is necessary.
Anyway, in order to add views to your main view, create a layout with the circle only. Then inflate it.
final View inflatedView = LayoutInflater.from(this).inflate(R.layout.your_circle_id, null);
/*Manipulate the inflated view (for example, change location)*/
LinearLayout container = (LinearLayout)findViewById(R.id.your_main_layout);
container.addView(inflatedView);
I hope that I got you correctly. Change the LinearLayout if it's off a different type.
You should use java graphics classes to do it.
Is it possible to set the absolute position of a view in Android? (I know that there is an AbsoluteLayout, but it's deprecated...)
For example, if I have a 240x320px screen, how could I add an ImageView which is 20x20px such that its center is at the position (100,100)?
You can use RelativeLayout. Let's say you wanted a 30x40 ImageView at position (50,60) inside your layout. Somewhere in your activity:
// Some existing RelativeLayout from your layout xml
RelativeLayout rl = (RelativeLayout) findViewById(R.id.my_relative_layout);
ImageView iv = new ImageView(this);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 50;
params.topMargin = 60;
rl.addView(iv, params);
More examples:
Places two 30x40 ImageViews (one yellow, one red) at (50,60) and (80,90), respectively:
RelativeLayout rl = (RelativeLayout) findViewById(R.id.my_relative_layout);
ImageView iv;
RelativeLayout.LayoutParams params;
iv = new ImageView(this);
iv.setBackgroundColor(Color.YELLOW);
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 50;
params.topMargin = 60;
rl.addView(iv, params);
iv = new ImageView(this);
iv.setBackgroundColor(Color.RED);
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 80;
params.topMargin = 90;
rl.addView(iv, params);
Places one 30x40 yellow ImageView at (50,60) and another 30x40 red ImageView <80,90> relative to the yellow ImageView:
RelativeLayout rl = (RelativeLayout) findViewById(R.id.my_relative_layout);
ImageView iv;
RelativeLayout.LayoutParams params;
int yellow_iv_id = 123; // Some arbitrary ID value.
iv = new ImageView(this);
iv.setId(yellow_iv_id);
iv.setBackgroundColor(Color.YELLOW);
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 50;
params.topMargin = 60;
rl.addView(iv, params);
iv = new ImageView(this);
iv.setBackgroundColor(Color.RED);
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 80;
params.topMargin = 90;
// This line defines how params.leftMargin and params.topMargin are interpreted.
// In this case, "<80,90>" means <80,90> to the right of the yellow ImageView.
params.addRule(RelativeLayout.RIGHT_OF, yellow_iv_id);
rl.addView(iv, params);
In general, you can add a View in a specific position using a FrameLayout as container by specifying the leftMargin and topMargin attributes.
The following example will place a 20x20px ImageView at position (100,200) using a FrameLayout as fullscreen container:
XML
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/root"
android:background="#33AAFF"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
Activity / Fragment / Custom view
//...
FrameLayout root = (FrameLayout)findViewById(R.id.root);
ImageView img = new ImageView(this);
img.setBackgroundColor(Color.RED);
//..load something inside the ImageView, we just set the background color
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(20, 20);
params.leftMargin = 100;
params.topMargin = 200;
root.addView(img, params);
//...
This will do the trick because margins can be used as absolute (X,Y) coordinates without a RelativeLayout:
Just to add to Andy Zhang's answer above, if you want to, you can give param to rl.addView, then make changes to it later, so:
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 50;
params.topMargin = 60;
rl.addView(iv, params);
Could equally well be written as:
params = new RelativeLayout.LayoutParams(30, 40);
rl.addView(iv, params);
params.leftMargin = 50;
params.topMargin = 60;
So if you retain the params variable, you can change the layout of iv at any time after adding it to rl.
A more cleaner and dynamic way without hardcoding any pixel values in the code.
I wanted to position a dialog (which I inflate on the fly) exactly below a clicked button.
and solved it this way :
// get the yoffset of the position where your View has to be placed
final int yoffset = < calculate the position of the view >
// position using top margin
if(myView.getLayoutParams() instanceof MarginLayoutParams) {
((MarginLayoutParams) myView.getLayoutParams()).topMargin = yOffset;
}
However you have to make sure the parent layout of myView is an instance of RelativeLayout.
more complete code :
// identify the button
final Button clickedButton = <... code to find the button here ...>
// inflate the dialog - the following style preserves xml layout params
final View floatingDialog =
this.getLayoutInflater().inflate(R.layout.floating_dialog,
this.floatingDialogContainer, false);
this.floatingDialogContainer.addView(floatingDialog);
// get the buttons position
final int[] buttonPos = new int[2];
clickedButton.getLocationOnScreen(buttonPos);
final int yOffset = buttonPos[1] + clickedButton.getHeight();
// position using top margin
if(floatingDialog.getLayoutParams() instanceof MarginLayoutParams) {
((MarginLayoutParams) floatingDialog.getLayoutParams()).topMargin = yOffset;
}
This way you can still expect the target view to adjust to any layout parameters set using layout XML files, instead of hardcoding those pixels/dps in your Java code.
Just in case it may help somebody, you may also try this animator ViewPropertyAnimator as below
myView.animate().x(50f).y(100f);
myView.animate().translateX(pixelInScreen)
Note: This pixel is not relative to the view. This pixel is the pixel
position in the screen.
credits to bpr10 answer
Place any view on your desire X & Y point
layout file
<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"
tools:context="com.example.test.MainActivity" >
<AbsoluteLayout
android:id="#+id/absolute"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:id="#+id/rlParent"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="#+id/img"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/btn_blue_matte" />
</RelativeLayout>
</AbsoluteLayout>
</RelativeLayout>
Java Class
public class MainActivity extends Activity {
private RelativeLayout rlParent;
private int width = 100, height = 150, x = 20, y= 50;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AbsoluteLayout.LayoutParams param = new AbsoluteLayout.LayoutParams(width, height, x, y);
rlParent = (RelativeLayout)findViewById(R.id.rlParent);
rlParent.setLayoutParams(param);
}
}
Done
Try below code to set view on specific location :-
TextView textView = new TextView(getActivity());
textView.setId(R.id.overflowCount);
textView.setText(count + "");
textView.setGravity(Gravity.CENTER);
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12);
textView.setTextColor(getActivity().getResources().getColor(R.color.white));
textView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// to handle click
}
});
// set background
textView.setBackgroundResource(R.drawable.overflow_menu_badge_bg);
// set apear
textView.animate()
.scaleXBy(.15f)
.scaleYBy(.15f)
.setDuration(700)
.alpha(1)
.setInterpolator(new BounceInterpolator()).start();
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT);
layoutParams.topMargin = 100; // margin in pixels, not dps
layoutParams.leftMargin = 100; // margin in pixels, not dps
textView.setLayoutParams(layoutParams);
// add into my parent view
mainFrameLaout.addView(textView);
My code for Xamarin,
I am using FrameLayout for this purpose and following is my code:
List<object> content = new List<object>();
object aWebView = new {ContentType="web",Width="300", Height = "300",X="10",Y="30",ContentUrl="http://www.google.com" };
content.Add(aWebView);
object aWebView2 = new { ContentType = "image", Width = "300", Height = "300", X = "20", Y = "40", ContentUrl = "https://www.nasa.gov/sites/default/files/styles/image_card_4x3_ratio/public/thumbnails/image/leisa_christmas_false_color.png?itok=Jxf0IlS4" };
content.Add(aWebView2);
FrameLayout myLayout = (FrameLayout)FindViewById(Resource.Id.frameLayout1);
foreach (object item in content)
{
string contentType = item.GetType().GetProperty("ContentType").GetValue(item, null).ToString();
FrameLayout.LayoutParams param = new FrameLayout.LayoutParams(Convert.ToInt32(item.GetType().GetProperty("Width").GetValue(item, null).ToString()), Convert.ToInt32(item.GetType().GetProperty("Height").GetValue(item, null).ToString()));
param.LeftMargin = Convert.ToInt32(item.GetType().GetProperty("X").GetValue(item, null).ToString());
param.TopMargin = Convert.ToInt32(item.GetType().GetProperty("Y").GetValue(item, null).ToString());
switch (contentType) {
case "web":{
WebView webview = new WebView(this);
//webview.hei;
myLayout.AddView(webview, param);
webview.SetWebViewClient(new WebViewClient());
webview.LoadUrl(item.GetType().GetProperty("ContentUrl").GetValue(item, null).ToString());
break;
}
case "image":
{
ImageView imageview = new ImageView(this);
//webview.hei;
myLayout.AddView(imageview, param);
var imageBitmap = GetImageBitmapFromUrl("https://www.nasa.gov/sites/default/files/styles/image_card_4x3_ratio/public/thumbnails/image/leisa_christmas_false_color.png?itok=Jxf0IlS4");
imageview.SetImageBitmap(imageBitmap);
break;
}
}
}
It was useful for me because I needed the property of view to overlap each other on basis of their appearance, e.g the views get stacked one above other.
I've made a very simple customView, a gray rectangle with an arbitrary amount of red markings inside the rectangle marked by percentages.
public class DemoView extends View {
private ShapeDrawable mDrawable;
private ArrayList<ShapeDrawable> mMarks;
public DemoView(Context context, int[] marks) {
super(context);
int x = 0;
int y = 0;
int width = 100;
int height = 10;
// Timeline Initially empty
mDrawable = new ShapeDrawable(new RectShape());
mDrawable.getPaint().setColor(Color.GRAY);
mDrawable.setBounds(x, y, x + width, y + height);
// Add marks
if (marks != null && marks.length % 2 == 0) {
mMarks = new ArrayList<ShapeDrawable>(marks.length / 2);
ShapeDrawable mark;
for (int i = 1; i < marks.length; i = i + 2) {
mark = new ShapeDrawable(new RectShape());
mark.getPaint().setColor(Color.RED);
mark.setBounds(x + marks[i - 1], y, x + marks[i], y + height);
mMarks.add(mark);
}
}
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mDrawable.draw(canvas);
if (mMarks != null)
for (ShapeDrawable mark : mMarks)
mark.draw(canvas);
}
}
However I can't figure out how to make use of the view. Each time I try to add more than one of the view in a linearlayout or relativelayout, I only see one of the views.
XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/llayout"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello"
/>
</LinearLayout>
Layout code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout ll = (LinearLayout) findViewById(R.id.llayout);
demoview = new DemoView(this, new int[]{10,15,35,60});
demoview.setId(ID_NUM++);
ll.addView(demoview);
demoview2 = new DemoView(this, new int[]{0,1,3,6});
demoview2.setId(ID_NUM++);
ll.addView(demoview2);
demoview3 = new DemoView(this, new int[]{25,60});
demoview3.setId(ID_NUM++);
ll.addView(demoview3);
demoview4 = new DemoView(this, new int[]{15,60});
demoview4.setId(ID_NUM++);
ll.addView(demoview4);
}
Results in:
Is this the wrong route to take? Am I missing some obvious key to using this view multiple times? If this is not the correct route is there some other method to making a custom shape? Perhaps extending rectShape?
Following Mibollma's advice, I watched the video above, a video from Google I/O 2009 about speeding up your UI.
The information is most definitely still applicable two years later. Not only was I able to speed up all of my ListViews through the use of ViewHolder, I was able to find the answer to my question.
When creating a custom view, two methods must be overriden, the first is listed above: onDraw.
The missing method? onMeasure(). More information can be found here.
Is it possible to set the absolute position of a view in Android? (I know that there is an AbsoluteLayout, but it's deprecated...)
For example, if I have a 240x320px screen, how could I add an ImageView which is 20x20px such that its center is at the position (100,100)?
You can use RelativeLayout. Let's say you wanted a 30x40 ImageView at position (50,60) inside your layout. Somewhere in your activity:
// Some existing RelativeLayout from your layout xml
RelativeLayout rl = (RelativeLayout) findViewById(R.id.my_relative_layout);
ImageView iv = new ImageView(this);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 50;
params.topMargin = 60;
rl.addView(iv, params);
More examples:
Places two 30x40 ImageViews (one yellow, one red) at (50,60) and (80,90), respectively:
RelativeLayout rl = (RelativeLayout) findViewById(R.id.my_relative_layout);
ImageView iv;
RelativeLayout.LayoutParams params;
iv = new ImageView(this);
iv.setBackgroundColor(Color.YELLOW);
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 50;
params.topMargin = 60;
rl.addView(iv, params);
iv = new ImageView(this);
iv.setBackgroundColor(Color.RED);
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 80;
params.topMargin = 90;
rl.addView(iv, params);
Places one 30x40 yellow ImageView at (50,60) and another 30x40 red ImageView <80,90> relative to the yellow ImageView:
RelativeLayout rl = (RelativeLayout) findViewById(R.id.my_relative_layout);
ImageView iv;
RelativeLayout.LayoutParams params;
int yellow_iv_id = 123; // Some arbitrary ID value.
iv = new ImageView(this);
iv.setId(yellow_iv_id);
iv.setBackgroundColor(Color.YELLOW);
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 50;
params.topMargin = 60;
rl.addView(iv, params);
iv = new ImageView(this);
iv.setBackgroundColor(Color.RED);
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 80;
params.topMargin = 90;
// This line defines how params.leftMargin and params.topMargin are interpreted.
// In this case, "<80,90>" means <80,90> to the right of the yellow ImageView.
params.addRule(RelativeLayout.RIGHT_OF, yellow_iv_id);
rl.addView(iv, params);
In general, you can add a View in a specific position using a FrameLayout as container by specifying the leftMargin and topMargin attributes.
The following example will place a 20x20px ImageView at position (100,200) using a FrameLayout as fullscreen container:
XML
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/root"
android:background="#33AAFF"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
Activity / Fragment / Custom view
//...
FrameLayout root = (FrameLayout)findViewById(R.id.root);
ImageView img = new ImageView(this);
img.setBackgroundColor(Color.RED);
//..load something inside the ImageView, we just set the background color
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(20, 20);
params.leftMargin = 100;
params.topMargin = 200;
root.addView(img, params);
//...
This will do the trick because margins can be used as absolute (X,Y) coordinates without a RelativeLayout:
Just to add to Andy Zhang's answer above, if you want to, you can give param to rl.addView, then make changes to it later, so:
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 50;
params.topMargin = 60;
rl.addView(iv, params);
Could equally well be written as:
params = new RelativeLayout.LayoutParams(30, 40);
rl.addView(iv, params);
params.leftMargin = 50;
params.topMargin = 60;
So if you retain the params variable, you can change the layout of iv at any time after adding it to rl.
A more cleaner and dynamic way without hardcoding any pixel values in the code.
I wanted to position a dialog (which I inflate on the fly) exactly below a clicked button.
and solved it this way :
// get the yoffset of the position where your View has to be placed
final int yoffset = < calculate the position of the view >
// position using top margin
if(myView.getLayoutParams() instanceof MarginLayoutParams) {
((MarginLayoutParams) myView.getLayoutParams()).topMargin = yOffset;
}
However you have to make sure the parent layout of myView is an instance of RelativeLayout.
more complete code :
// identify the button
final Button clickedButton = <... code to find the button here ...>
// inflate the dialog - the following style preserves xml layout params
final View floatingDialog =
this.getLayoutInflater().inflate(R.layout.floating_dialog,
this.floatingDialogContainer, false);
this.floatingDialogContainer.addView(floatingDialog);
// get the buttons position
final int[] buttonPos = new int[2];
clickedButton.getLocationOnScreen(buttonPos);
final int yOffset = buttonPos[1] + clickedButton.getHeight();
// position using top margin
if(floatingDialog.getLayoutParams() instanceof MarginLayoutParams) {
((MarginLayoutParams) floatingDialog.getLayoutParams()).topMargin = yOffset;
}
This way you can still expect the target view to adjust to any layout parameters set using layout XML files, instead of hardcoding those pixels/dps in your Java code.
Just in case it may help somebody, you may also try this animator ViewPropertyAnimator as below
myView.animate().x(50f).y(100f);
myView.animate().translateX(pixelInScreen)
Note: This pixel is not relative to the view. This pixel is the pixel
position in the screen.
credits to bpr10 answer
Place any view on your desire X & Y point
layout file
<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"
tools:context="com.example.test.MainActivity" >
<AbsoluteLayout
android:id="#+id/absolute"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:id="#+id/rlParent"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="#+id/img"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/btn_blue_matte" />
</RelativeLayout>
</AbsoluteLayout>
</RelativeLayout>
Java Class
public class MainActivity extends Activity {
private RelativeLayout rlParent;
private int width = 100, height = 150, x = 20, y= 50;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AbsoluteLayout.LayoutParams param = new AbsoluteLayout.LayoutParams(width, height, x, y);
rlParent = (RelativeLayout)findViewById(R.id.rlParent);
rlParent.setLayoutParams(param);
}
}
Done
Try below code to set view on specific location :-
TextView textView = new TextView(getActivity());
textView.setId(R.id.overflowCount);
textView.setText(count + "");
textView.setGravity(Gravity.CENTER);
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12);
textView.setTextColor(getActivity().getResources().getColor(R.color.white));
textView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// to handle click
}
});
// set background
textView.setBackgroundResource(R.drawable.overflow_menu_badge_bg);
// set apear
textView.animate()
.scaleXBy(.15f)
.scaleYBy(.15f)
.setDuration(700)
.alpha(1)
.setInterpolator(new BounceInterpolator()).start();
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT);
layoutParams.topMargin = 100; // margin in pixels, not dps
layoutParams.leftMargin = 100; // margin in pixels, not dps
textView.setLayoutParams(layoutParams);
// add into my parent view
mainFrameLaout.addView(textView);
My code for Xamarin,
I am using FrameLayout for this purpose and following is my code:
List<object> content = new List<object>();
object aWebView = new {ContentType="web",Width="300", Height = "300",X="10",Y="30",ContentUrl="http://www.google.com" };
content.Add(aWebView);
object aWebView2 = new { ContentType = "image", Width = "300", Height = "300", X = "20", Y = "40", ContentUrl = "https://www.nasa.gov/sites/default/files/styles/image_card_4x3_ratio/public/thumbnails/image/leisa_christmas_false_color.png?itok=Jxf0IlS4" };
content.Add(aWebView2);
FrameLayout myLayout = (FrameLayout)FindViewById(Resource.Id.frameLayout1);
foreach (object item in content)
{
string contentType = item.GetType().GetProperty("ContentType").GetValue(item, null).ToString();
FrameLayout.LayoutParams param = new FrameLayout.LayoutParams(Convert.ToInt32(item.GetType().GetProperty("Width").GetValue(item, null).ToString()), Convert.ToInt32(item.GetType().GetProperty("Height").GetValue(item, null).ToString()));
param.LeftMargin = Convert.ToInt32(item.GetType().GetProperty("X").GetValue(item, null).ToString());
param.TopMargin = Convert.ToInt32(item.GetType().GetProperty("Y").GetValue(item, null).ToString());
switch (contentType) {
case "web":{
WebView webview = new WebView(this);
//webview.hei;
myLayout.AddView(webview, param);
webview.SetWebViewClient(new WebViewClient());
webview.LoadUrl(item.GetType().GetProperty("ContentUrl").GetValue(item, null).ToString());
break;
}
case "image":
{
ImageView imageview = new ImageView(this);
//webview.hei;
myLayout.AddView(imageview, param);
var imageBitmap = GetImageBitmapFromUrl("https://www.nasa.gov/sites/default/files/styles/image_card_4x3_ratio/public/thumbnails/image/leisa_christmas_false_color.png?itok=Jxf0IlS4");
imageview.SetImageBitmap(imageBitmap);
break;
}
}
}
It was useful for me because I needed the property of view to overlap each other on basis of their appearance, e.g the views get stacked one above other.