I have the following code to generate button objects with a set text, onClick command (more or less), height, width, and margins
private Button generateButton(String text, char command, int height, int width, int left, int top){
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(getDP(width),getDP(height));
lp.setMargins(getDP(left),getDP(top),0,0);
Button button = new Button(this.getContext());
button.setText(text);
button.setLayoutParams(lp);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.d("Command",""+ command);
}
private char command;
private View.OnClickListener init(char var){
command = var;
return this;
}
}.init(command));
return button;
}
Along with this method to get the dp
private int getDP(int size){
return (int) (size * this.getContext().getResources().getDisplayMetrics().density);
}
But when I run the app the button have the proper height and width, along with the proper text and onclick action, but they have no margins, they're all bunched up into one corner
The view hierchy according to the Layout Inspector in Android studio goes
DecorView
LinearLayout
FrameLayout
FitWindowLinearLayout
ContentFrameLayout
CoordinatorLayout
ViewPager
ConstraintLayout
ConstraintLayout
Buttons
And from what I've read online, LayoutParams has to be from the same class as the layout, as is LinearLayout.LayourParams, or ConstraintLayout.LayoutParams and I've tried all the layout types that made sense to me and still no margins
It might be worth noting this is in a fragment
For views that are children of ConstraintLayout, you need to add horizontal and vertical constraints. Otherwise they layout will not know how to place them, and places them at the top left corner.
You can use the ConstraintLayout.LayoutParams, and set the constraints by
lp.leftToLeft, lp.leftToRight and similar methods here
So for example if you want to place these buttons one after the other vertically, you will constraint each button horizontally to the parent, and vertically to the previous button.
public void setMargins (int left, int top, int right, int bottom)
This is the signature for setMargins method. You call the method with right = 0 and bottom = 0. So you will not have the margins on right and bottom. Try to set some values for right and bottom.
You should use LayoutParams to set your button margins:`
LayoutParams params = new LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT
);
params.setMargins(left, top, right, bottom);
yourbutton.setLayoutParams(params);
Depending on what layout you're using you should use RelativeLayout.LayoutParams or LinearLayout.LayoutParams.
And to convert your dp measure to pixel, try this:
Resources r = mContext.getResources();
int px = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
yourdpmeasure,
r.getDisplayMetrics()
);
`
Related
I've been browsing the entire internet, but I could not find any answer to this question. I want to create a background, some image buttons, along with a bunch of moving graphics (circles). Since I do not know how to overwrite a xml layout with moving graphics, I chose to customly create my view, draw the background, the imageButtons and the circles (2D graphics).
public class GameView extends View implements UtilConstants
since I extended the View class, I had to call the super class constructor in my constructor
GameView(Context context) {
super(context);
this.context = context;
this.paint = new Paint();
}
and to implement the onDraw method, which acts like the java paintComponent
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas); // necessary for some reason
setGridBackground(); // sets the background
paint.setColor(Color.parseColor("#FF0000"));
canvas.drawCircle(this.x += 10, 300, 20, paint); //moves my graphics (ball) within the screen
drawScoreInLeftUpperCorner(canvas, 20); // paints a string text on the screen
setAbilitiesImages(); // places some imageButtons
try {
Thread.sleep(THREAD_REFRESH_RATE_MS);
} catch (InterruptedException ex) {
System.out.println(ex);
}
invalidate();
}
Now, to get to my problem:
I do not know how to set those ImageButtons !!! I am trying
private void setAbilititesImages() {
ImageButton imageButton = new ImageButton(this.context); // is this ok to put the argument this.context??
imageButton.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
imageButton.setImageResource(R.drawable.monster); // set my resource
RelativeLayout relativeLayout = findViewById(R.id.in_game_layout); // what is the purpose of this???
if (relativeLayout != null) { // it never enters this if, relativeLayout is always null
relativeLayout.addView(imageButton);
}
}
Aaaaand the image button never shows up...why is it necessary to use Relative/Linear layouts? That R.id.in_game_layout I created is just an empty RelativeLayout xml. Can't I just use something like
imageButton.setImageResource(R.drawable.monster); // set my resource
imageButton.setBounds(.....);
(View)this.add(imageButton); ???
ImageButton requires a parent view to be hosted in it. The parent View can be a RelativeLayout, a linearlayout or a ConstraintLayout.
In your case, the instance relativeLayout is always null because you not specify the view parent in which you do findViewById.
You should make something like :
RelativeLayout relativeLayout = view.findViewById(R.id.in_game_layout);
You need to add layout param to your parent Relative layout also to display your Image button appropriately.
Example
RelativeLayout relativeLayout = findViewById(R.id.relativeLayout);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
ImageButton imageButton = new ImageButton(this);
imageButton.setImageDrawable(getResources().getDrawable(R.drawable.ic_launcher_background,null));
relativeLayout.addView(imageButton,params);
I need to show popup window directly above button. My button is placed inside scroll view, and popup always shown below button. Here is my code:
private void showPopup(View view, String text) {
if (infoPopup == null) {
LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
View popupView = layoutInflater.inflate(R.layout.popup_credit_request_passport, null);
TextView tvPopupText = popupView.findViewById(R.id.tv_popup_text);
tvPopupText.setMovementMethod(new ScrollingMovementMethod());
tvPopupText.setText(text);
FrameLayout flBackground = popupView.findViewById(R.id.fl_background);
flBackground.setBackground(new BubbleDrawable(getContext(), R.color.azure, 16, 16, 8));
infoPopup = new PopupWindow(popupView,
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
infoPopup.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
infoPopup.setOutsideTouchable(true);
infoPopup.showAtLocation(view, Gravity.TOP, (int) view.getX(), (int) view.getY());
} else {
dismissInfoPopup();
}
}
But it is not work. Please hep me.
Change Gravity to Top and reset your coordinates according to your requirement.
infoPopup.showAtLocation(view, Gravity.TOP, 0, (int) view.getY());
When you have to show the popup, find out the location of the button in the screen, then use the showAtLocation() method as Prachi Said using Gravity.TOP and the x,y coordinates of the button on screen...
I want to add an ImageView within the onClick() of the Button. But the ImageView should be aligned to the centre of the button.
How can I do this pragmatically?
I'm creating a new instance of the ImageView to be added on top of the View that called it and it's position is equivalent of the View that called it.
How can I get the X and Y coordinates?
EDIT:
#Override
public void onClick(final View v) {
if(v.getWidth() > v.getHeight()) size = v.getHeight();
if(v.getWidth() < v.getHeight()) size = v.getWidth();
RelativeLayout.LayoutParams button = new RelativeLayout.LayoutParams(size,size);
buttonc = new ImageView(getApplicationContext());
buttonc.setBackgroundResource(R.drawable.round);
layout.addView(buttonc,button);
I'm using the above code to attempt to pragmatically set the size of the ImageView to that of the button, and it's working.
As for the coordinates, I still haven't figured it out.
To add clarity: I'm attempting to create a rounded ripple effect over the view that calls it.
I suggest a better solution create an image view before hand place it in the xml as you see fit,at first set its visibility to false .
On click switch its visibilty to true, and the image will appear
This solution is easier than what you are searching.
Feel free to ask questions
to add Imageview
#Override
public void onClick(final View v) {
//LinearLayout
LinearLayout linearLayout= new LinearLayout(this);
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
//ImageView
ImageView imageView = new ImageView(this);
//image resource
imageView.setImageResource(R.drawable.specs);
//image position
imageView.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT));
//adding view to layout
linearLayout.addView(imageView);
//make visible to program
setContentView(linearLayout);
}
Read this and this. Attempted to apply the post's answers, but the button remains without margins when I build and run the app. What am I doing wrong?
public class ResultsActivityA extends Activity {
Button button, submitButton;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//...
LinearLayout activityResultsA= new LinearLayout(this);
Button submitButton=new Button(this);
LayoutParams dimensions= new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
activityResultsA.setLayoutParams(dimensions);
LayoutParams viewDimensions= new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
LayoutParams buttonDimensions= new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
buttonDimensions.setMargins(50, 40, 0, 0);
submitButton.setLayoutParams(buttonDimensions);
activityResultsA.setOrientation(LinearLayout.VERTICAL);
submitButton.setText("Home");
submitButton.setId(5555);
activityResultsA.addView(submitButton);
setContentView(activityResultsA);
addListenerOnButton();
}
}
Margins that you're expecting will be seen in lower density devices (ldpi) or medium density devices (mdpi) but not in higher density devices (hdpi, xxhdpi, ...).
setMargins(top, left, bottom, right) accepts int values in px unit. In your case, You're actually passing 50px, 40px, and 0px.
You need to convert those values from dp to px
public static int convertDPtoPX(Context context, int dpValue) {
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
return dpValue * displayMetrics.densityDpi;
}
I wrote ((LinearLayout.LayoutParams)submitButton.getLayoutParams()).setMargins(left, top, right, bottom); after addView, but before setContentView and it set the margins.
I'm trying to do an animation that goes like this:
The context:
I have two EditText's I need that when you click over one, the another one come out from behind the first one. Here you have some pictures to get a image of what I want.
To do this obviously I need a TranslateAnimation in order to move the second EditText from behind the first one.
My approach:
The first thing that I could thought was in use a FrameLayout put the EditText one over another, and then in the onTouch event of the first one do a TranslateAnimation on the second one. The problem with this is that if I have the FrameLayout height in wrap_content then the animation will be invisible to the user. And if I change on runtime the height of the FrameLayout I will leave a void below the first EditText as you can see in this picture:
The second solution that I thought was add one AnimationListener to the TranslateAnimation and in the onAnimationStart method change the height of the FrameLayout. But the problem with this is that the height of the FrameLayout changes too abruptly. I want keep the animation smooth.
My question:
How can I get a smooth animation of the second EditText from behind the first one, changing the height of the FrameLayout as the second EditText moves down?
Thanks!
Update:
I changed the FrameLayout by a RelativeLayout I searched and there's no difference for this case. I tried scale this RelativeLayout that contains both of the EditText with an AnimationScale in order to display the animation smoothly, but didn't work. Here is my code:
protected void expanse() {
Log.d("Accordion", "expandAccordion");
//Translate the top of the second EditText to its bottom
TranslateAnimation translateSecond = new TranslateAnimation(second.getLeft(), second.getLeft(),
second.getTop(), second.getBottom());
translateSecond.setDuration(1000);
//Scale the relative layout to show the both of them
ScaleAnimation scaleContainer = new ScaleAnimation(container.getLeft(), container.getLeft(),
container.getTop(), second.getBottom());
scaleContainer.setDuration(1000);
//At the end of the scaling, change the height of the relative layout
scaleContainer.setAnimationListener(new AnimationListenerAdapter() {
#Override
public void onAnimationEnd(Animation animation) {
RelativeLayout.LayoutParams params = (LayoutParams) container.getLayoutParams();
params.height = second.getBottom();
container.setLayoutParams(params);
super.onAnimationEnd(animation);
}
});
container.startAnimation(scaleContainer);
second.startAnimation(translateSecond);
}
BTW I can guarantee that if I hardcode some large height like 350dp, the animation is displayed correctly.
UPDATE:
I tried moving both, the second EditText and the layout below. This is the code. BTW for another reasons I changed the ListView by a custom ViewPager, this doesn't change anything.
public class MainActivity extends FragmentActivity {
private EditText first;
private EditText second;
private HoboViewPager pager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pager = (HoboViewPager) findViewById(R.id.pager);
pager.setPageTransformer(true, new RotationPageTransformer());
pager.setAdapter(new SampleAdapter(this, getSupportFragmentManager()));
first = (EditText) findViewById(R.id.location_search_field);
second = (EditText) findViewById(R.id.term_search_field);
first.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
expanseSecondField();
return true;
}
});
}
protected void expanseSecondField() {
TranslateAnimation translateSecondField = new TranslateAnimation(second.getLeft(), second.getLeft(),
second.getTop(), second.getBottom());
translateSecondField.setFillAfter(true);
translateSecondField.setDuration(1000);
TranslateAnimation translateContainer = new TranslateAnimation(pager.getLeft(), pager.getLeft(),
pager.getTop(), pager.getTop() + second.getBottom());
translateContainer.setFillAfter(true);
translateContainer.setDuration(1000);
pager.startAnimation(translateContainer);
second.startAnimation(translateSecondField);
}
}
This didn't work because the TranslateAnimation of the container is executed immediately. The result is the same that when I was trying to change the size of the container at the end of the animation.
How use the 2nd option & try performing two translate animations in tandem: 1 on the EditText, then one on the FrameLayout? Give them both the same exact deltas and duration. This way, the FrameLayout will move down smoothly, then at the end of the animation, change the height of the FrameLayout.
Hope this helps :)