Difficulty in setting dynamic setting CustomView to center of RelativeLayout - android

I have CustomView which is just an arc shape with some lines.
public class CustomDrawableView extends View {
private ShapeDrawable mDrawable;
private Paint paint = new Paint();
public CustomDrawableView(Context context, int startA, int endA) {
super(context);
int x = 0;
int y = 0;
int width = 400;
int height = 400;
paint.setColor(Color.BLACK);
mDrawable = new ShapeDrawable(new ArcShape(startA, endA));
mDrawable.getPaint().setColor(0xff74AC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
protected void onDraw(Canvas canvas) {
mDrawable.draw(canvas);
canvas.drawLine(0,0,400,0,paint);
canvas.drawLine(0, 0, 0, 400, paint);
canvas.drawLine(400,0, 400,400, paint);
}
}
Afterward I call out my linear layout from the xml file through its id add a framelayout to it. After that, I add CustomDrawableView and try to center it by using gravity. I went through many other questions and tried those solutions, but it just doesn't work for me. If it's worth noting, I notice when I use a regular view like a textview with no custom view in my layout, it centers perfectly.
public class MainActivity extends ActionBarActivity {
private RelativeLayout ll;
private CustomDrawableView testView;
private RelativeLayout.LayoutParams layout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// load the layout
LinearLayout linLayout = (LinearLayout)findViewById(R.id.ll);
linLayout.setOrientation(LinearLayout.VERTICAL);
/******** Experimental Code **********/
RelativeLayout rl = new RelativeLayout(this);
linLayout.addView(rl);
LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
CustomDrawableView arc = new CustomDrawableView(this,0,30);
CustomDrawableView arcTwo = new CustomDrawableView(this, 50, 30);
rl.setGravity(Gravity.CENTER_HORIZONTAL);
rl.addView(arc, lp);
rl.addView(arcTwo, lp);
rl.setBackgroundColor(Color.GRAY); }
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
I use the frame layout in so i can lay views over each other.

There are a few problems here.
First is that you need set the layout params for your RelativeLayout called "rl" when you add it to your LinearLayout called "linLayout." Do this with the following code:
RelativeLayout rl = new RelativeLayout(this);
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
linLayout.addView(rl, params);
Your other issue is that when you add your customViews to rl it is better to add a rule to the layout params than to use gravity. The code below demonstrates this:
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lp.addRule(RelativeLayout.CENTER_IN_PARENT);
CustomDrawableView arc = new CustomDrawableView(this,0,30);
CustomDrawableView arcTwo = new CustomDrawableView(this, 50, 30);
rl.addView(arc, lp);
rl.addView(arcTwo, lp);
Hope this helps!

Have you try to set rl's layout_width and layout_height to match_parent?
Try this code
/******** Experimental Code **********/
RelativeLayout rl = new RelativeLayout(this);
LayoutParams parems = new LayoutParams(LayoutParams.MATH_PARENT,
LayoutParams.MATH_PARENT);
rl.setParameters(parems);
linLayout.addView(rl);
UPDATE :
Please show your activity_main.xml code and notice your api level. If so, I'm going to run your code.
Otherwise, have you try to set layout size from onMeasure()?
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = 0;
switch (heightMode) {
case MeasureSpec.AT_MOST: // wrap_confent
heightSize = 400;
break;
case MeasureSpec.EXACTLY: // match_parent
heightSize = MeasureSpec.getSize(heightMeasureSpec);
break;
}
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = 0;
switch (widthMode) {
case MeasureSpec.AT_MOST: // wrap_confent
widthSize = 400;
break;
case MeasureSpec.EXACTLY: // match_parent
widthSize = MeasureSpec.getSize(widthMeasureSpec);
break;
}
setMeasuredDimension(widthSize, heightSize);
}

Related

Android addView and removeView in the same method

I'm calling this method that should redraw a pointer in the position given in every call.
ImageView ivPointer=null;
public void moveCursor(Bitmap bmPuntero, int x, int y)
{
RelativeLayout rl = (RelativeLayout) findViewById(R.id.gamelayout);
if (ivPointer!=null)
rl.removeView(ivPointer);
ivPointer = new ImageView(this);
ivPointer.setImageBitmap(bmPuntero);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(65, 65);
params.leftMargin = x;
params.topMargin = y;
rl.addView(ivPointer, params);
}
The result is that the bitmap isn't showed. If I remove the lines that remove the view, I see how the bitmap is drawn multiple times, so the add part should be correct.
Try this:
{
// Somewhere (in onCreate of the Activity for example):
RelativeLayout rl = (RelativeLayout) findViewById(R.id.gamelayout);
ImageView ivPointer = initPointer(this, bmPuntero); // Get image from somewhere
rl.addView(ivPointer);
}
// To update the cursor's po
public static void moveCursor(ImageView pointer, int x, int y) {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) pointer.getLayoutParams();
params.leftMargin = x;
params.topMargin = y;
pointer.setLayoutParams(params);
pointer.requestLayout(); // Refresh the layout
}
// Call this method to initialise the pointer (in onCreate of your Activity
// for example)
public static ImageView initPointer(Context context, Bitmap bmp) {
// Define the LayoutParams
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(65, 65);
params.leftMargin = DEFAULT_POS_X; // TODO: Constants to be defined
params.topMargin = DEFAULT_POS_Y;
// Init the ImageView
ImageView pointer = new ImageView(context);
pointer.setImageBitmap(bmp);
pointer.setLayoutParams(params);
return pointer;
}

onScrollChange() is not being called for every pixel scrolled on ScrollView

I want to add new child views after every 50 pixels of scrolling but the statement Log.d("scroll",scrollY+":"+oldScrollY); is missing some values i.e. scrollY = 149 and scrollY = 151 are there in Log but scrollY = 150 is missing. So the code doesn't run for scrollY = 150 and new child views is not added.
Although it works as it should for most of the values of scrollY but for few values of scrollY, the event is not being triggered.
How can i resolve this issue? Or is there any other way to achieve this.
public class MainActivity extends AppCompatActivity implements ScrollViewListener {
RelativeLayout parent;
TextView height;
ObservableScrollView scrollView;
int position=1;
View view1,view2;
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
parent = (RelativeLayout) findViewById(R.id.parent);
scrollView = (ObservableScrollView) findViewById(R.id.scroll_view);
LayoutInflater inflater = LayoutInflater.from(this);
view1 = inflater.inflate(R.layout.education,null, false);
view1.setId(R.id.parent+position);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.LEFT_OF,R.id.divider);
params.topMargin = 100;
params.rightMargin = 3;
parent.addView(view1, params);
position++;
final Animation leftAnimation = new TranslateAnimation(view1.getX()-50,view1.getX(),view1.getY()+100,view1.getY());
leftAnimation.setDuration(1000);
view1.setAnimation(leftAnimation);
scrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
#Override
public void onScrollChange(View view, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
Log.d("scroll",scrollY+":"+oldScrollY);
if((scrollY-oldScrollY)>0 && scrollY%50 == 0)
{
Log.d("scroll","abcghfg");
if(position%2==0)
{
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.RIGHT_OF,R.id.divider);
// params.topMargin = (position-1)*(view1.getLayoutParams().height)+position*100;
params.topMargin = 30;
params.leftMargin = 3;
params.addRule(RelativeLayout.BELOW,parent.getChildAt(position-1).getId());
Log.d("scroll","abc");
view2 = LayoutInflater.from(MainActivity.this).inflate(R.layout.education,null,false);
view2.setId(R.id.parent+position);
Animation rightAimation = new TranslateAnimation(view2.getX()+50,view2.getX(),view2.getY()+100,view2.getY());
rightAimation.setDuration(1000);
view2.startAnimation(rightAimation);
parent.addView(view2, params);
}
else
{
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.LEFT_OF,R.id.divider);
//params.topMargin = (position-1)*(view1.getLayoutParams().height)+position*100;
params.topMargin = 30;
params.rightMargin = 3;
params.addRule(RelativeLayout.BELOW,parent.getChildAt(position-1).getId());
Log.d("scroll","def");
view2 = LayoutInflater.from(MainActivity.this).inflate(R.layout.education,null,false);
view2.setId(R.id.parent+position);
Animation animation = new TranslateAnimation(view2.getX()-50,view2.getX(),view2.getY()+100,view2.getY());
animation.setDuration(1000);
view2.startAnimation(animation);
parent.addView(view2, params);
}
position++;
}
}
});
}
}
Thanks in advance.
Android doesn't render every pixel in a scroll, because it would be bad for performance. If you scroll really slow, you will see that your callback will be called for every pixel, but if you scroll fast, it will be called just when the render triggers.
In your case, you need to check if it rendered 50 or more pixels since last time you rendered the last view.

I want to display the image view at different position on the screen randomly

Here the ImageView is displaying only at one position, after closing the activity the next time the activity is opened the ImageView will be on another position... I want to display the ImageView randomly at diff position on the same activity itself. The image view should appear on one point suddenly the next second ImageView should disappear from that position and appear on the next position. How can i do it?
public class page2 extends ActionBarActivity {
ImageView b2;
int count = 0;
Handler handler = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_page2);
Intent c = getIntent();
String name = c.getStringExtra("t");
Toast.makeText(getApplicationContext(), name, Toast.LENGTH_SHORT).show();
b2 = (ImageView) findViewById(R.id.redball);
AbsoluteLayout.LayoutParams absParams =
(AbsoluteLayout.LayoutParams)b2.getLayoutParams();
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int width = displaymetrics.widthPixels;
int height = displaymetrics.heightPixels;
Random r = new Random();
absParams.x = r.nextInt(width ) ;
absParams.y = r.nextInt(height );
b2.setLayoutParams(absParams);
Animation animation = AnimationUtils.loadAnimation(page2.this, R.anim.fade);
// Animation animation1 = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.activity_move);
b2.startAnimation(animation);
// b2.startAnimation(animation1);
b2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
count = count + 1;
}
});
handler = new Handler();
final Runnable t = new Runnable() {
public void run() {
Intent d = new Intent(getApplicationContext(), Page3.class);
d.putExtra("count", count);
d.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(d);
}
};
handler.postDelayed(t, 4000);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_page2, menu);
return true;
}
Don't use AbsoluteLayout, Why not use a custom view draw it?
You can achieve this by using Imageview within FrameLayout. Just change the layoutParams of the image to change its position.
As I understand it, you want that each time the activity is opened, so f you dont want to actually view to the user that the ImageView moves, why are you using Animation? You may just dynamically add the ImageView to the activity each time, and each time assign it different Margin attributes.
LinearLayout layout = (LinearLayout) view.findViewById(R.id.linear);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);
params.setMargins(0, 0, 10, 0); //substitute parameters for left, top, right, bottom
ImageView iv = new ImageView(getActivity());
iv.setLayoutParams(params);
iv.setImageResource(R.drawable.yourimage);
layout.addView(iv);
for calucation
ContainerHeight = blinkerContainer.getHeight(); // total height of screen
ContainerWidth = blinkerContainer.getWidth(); //total width
blinkerHeight = blinkView.getHeight();
blinkerWidth = blinkView.getWidth();
minTopMargin = 30;
minLeftMargin = 30;
maxTopMargin = ContainerHeight - blinkerHeight - 30;
maxLeftMargin = ContainerWidth - blinkerWidth - 30;
for positioning
LinearLayout.LayoutParams params = (android.widget.LinearLayout.LayoutParams) blinkView
.getLayoutParams();
params.leftMargin = minLeftMargin
+ new Random().nextInt(maxLeftMargin - minLeftMargin);
params.topMargin = minTopMargin
+ new Random().nextInt(maxTopMargin - minTopMargin);
and you can use AlaramManager for Scheduling
Your solution is almost correct. Unfortunately, it looks like you're restarting the activity from your timer. Instead, you should just trigger the redraw.
This question has a couple of solutions on how to create a recurring timer. The solution with runOnUiThread() should allow you to execute the randomisation and re-displaying of the ImageView.

What is the 0, 0 Declaring, in ".setMargins(imgX, imgY, 0, 0)" ? Am I even understanding the X, Y coordinates correctly?

I'm currently trying to move an ImageButton to a certain X and Y location in my Android App. (Api level 15 to 22) and the size of the Image is not staying the same. Its distorting. I first assumed it was the declaring of 0, 0 in the following code:
marginParams.setMargins(imgX, imgY, 0, 0);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(marginParams);
img.setLayoutParams(layoutParams);
So I tried to wrap content. But it did nothing!
marginParams.setMargins(imgX, imgY, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(marginParams);
img.setLayoutParams(layoutParams);
Here is all of the code if needed:
public class MainActivity extends ActionBarActivity {
public EditText collectedTextEdit;
public ImageButton candyEdit;
public int collected = 0;
public int screenWidth = 300;
public int screenHeight = 300;
public final int candySize = 50;
Random random = new Random();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
collectedTextEdit = (EditText) findViewById(R.id.collectedText);
candyEdit = (ImageButton) findViewById(R.id.candy);
collectedTextEdit.setText("Collected: " + collected);
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
screenWidth = size.x;
screenHeight = size.y;
addListenerOnButton();
}
public void addListenerOnButton() {
candyEdit.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
collected += 1;
collectedTextEdit.setText("Collected: " + collected);
int candyX = random.nextInt(screenWidth);
int candyY = random.nextInt(screenHeight);
System.out.println(candyX + " : " + candyY);
//RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
MarginLayoutParams marginParams = new MarginLayoutParams(candyEdit.getLayoutParams());
marginParams.setMargins(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, candyX, candyY);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(marginParams);
//layoutParams.WRAP_CONTENT;
candyEdit.setLayoutParams(layoutParams);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
And here is the declaration of the ImageButton:
<ImageButton
android:layout_width="50dp"
android:layout_height="50dp"
android:id="#+id/candy"
android:background="#drawable/candy"
android:contentDescription="#string/candyImg"
android:clickable="true"
android:layout_below="#+id/collectedText"
android:layout_alignRight="#+id/collectedText"
android:layout_alignEnd="#+id/collectedText" />
Please help me! If you need any other code examples feel free to ask and I'll get right to it!

Error from starting a view from an activity

public class MAINActivity extends TabActivity {
host.addTab(host.newTabSpec("Settings")
.setIndicator("Settings", getResources().getDrawable(R.drawable.icon_user))
.setContent(new Intent(this, TwoDScrollView.class)));
........
}
public class TwoDScrollView extends Activity {
private RelativeLayout container;
private int currentX;
private int currentY;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.design);
container = (RelativeLayout)findViewById(R.id.container);
int top = 0;
int left = 0;
ImageView image1 = (ImageView)findViewById(R.id.imageView1);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(left, top, 0, 0);
container.addView(image1, layoutParams);
ImageView image2 = (ImageView)findViewById(R.id.imageView2);
left+= 100;
layoutParams.setMargins(left, top, 0, 0);
container.addView(image2, layoutParams);
ImageView image3 = (ImageView)findViewById(R.id.imageView3);
left= 0;
top+= 100;
layoutParams.setMargins(left, top, 0, 0);
container.addView(image3, layoutParams);
ImageView image4 = (ImageView)findViewById(R.id.imageView4);
left+= 100;
layoutParams.setMargins(left, top, 0, 0);
container.addView(image4, layoutParams);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
currentX = (int) event.getRawX();
currentY = (int) event.getRawY();
break;
}
case MotionEvent.ACTION_MOVE: {
int x2 = (int) event.getRawX();
int y2 = (int) event.getRawY();
container.scrollBy(currentX - x2 , currentY - y2);
currentX = x2;
currentY = y2;
break;
}
case MotionEvent.ACTION_UP: {
break;
}
}
return true;
}
}
When I trying to add the TwoDScrollView Class to the tabbars I got an error of IllegalStateException. The specified child already has a parent. You must removeView() on the child's parent first. What does all those means?
What's happening is that you are implicitly inflating your layout by calling setContentView which creates a bunch of views including four ImageViews apparently in a RelativeLayout. Then you're doing findViewById to find these ImageViews and the RelativeLayout, and after changing their margins programmatically, you add them back to the same layout which already contained them. This is why you get an exception. Those ImageViews already have a parent (the RelativeLayout) and you're trying to give them a new parent (even if it is that same RelativeLayout) without first removing them from their parent. You don't need to call addView at all in this case.

Categories

Resources