I used a FragmentTransaction to add a Fragment into a FrameLayout. I want to dynamically change the margin of the RelativeLayout used by the Fragment. However, the margins are not changing with RelativeLayout.layoutParams. I also used setMargins() and it didnt work.
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.infocard, container, false);
RelativeLayout infoLayout = (RelativeLayout) view.findViewById(R.id.info);
infoLayout.setOnClickListener(new EmptyClickListener());
final int width = 250;
final int height = 320;
int leftMargin = 0;
int topMargin = 0;
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(width, height);
if (x - width < 0) {
leftMargin = 0;
System.out.println("left " + leftMargin);
}
else {
leftMargin = x - width;
}
if (y >= 450 && y <= 480) {
topMargin = y - height;
}
params.leftMargin = leftMargin;
params.topMargin = topMargin;
infoLayout.setLayoutParams(params);
Try using
FrameLayout.LayoutParams
instead of
RelativeLayout.LayoutParams
Layouts expect the params type to be the type from their parent container rather than the View type that you are setting them on
Related
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 have a nested LinearLayout (or other type of layout), and I would just like to sum up all the horizontal values of margins/paddings of this view and its parent and potentially grandparents and so on.
I just need the clean width of this Layout which will be window width minus all horizontal margins/paddings.
I've started like that:
private int sumMargins(View view) {
LayoutParams params = (LayoutParams) view.getLayoutParams();
int margins = params.leftMargin + params.rightMargin + view.getPaddingStart() + view.getPaddingEnd();
ViewParent parent = view.getParent();
while (parent != null) {
// here I need to recursively gather all nested parents margins/paddings
// (add them to the `margins` variable)
}
return margins;
}
ViewGroup.MarginLayoutParams will give you access to the margins of a view. The following code will follow the hierarchy of views up to the top-level DecorView and sum left/right margins and padding.
private int sumMargins(View view) {
ViewGroup.MarginLayoutParams marginParams;
int margins = 0;
View decorView = getWindow().getDecorView();
while (view != null && view != decorView) {
marginParams = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
if (marginParams != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
margins += marginParams.getMarginStart() + marginParams.getMarginEnd() +
view.getPaddingStart() + view.getPaddingEnd();
} else {
margins += marginParams.leftMargin + marginParams.rightMargin +
view.getPaddingLeft() + view.getPaddingRight();
}
}
view = (View) view.getParent();
}
return margins;
}
I have successfully added a new view to the bottom of my layout using the resources on Stack Exchange and other. However, if I try to add a second view programmatically, the two views appear to overlap.
This code block successfully adds a new view to my layout file.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RelativeLayout activityMain = (RelativeLayout)findViewById(R.id.activity_main);
// First view
View playControlsPanelMinimized = new View(this);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
final float scale = activityMain.getContext().getResources().getDisplayMetrics().density;
float dps = 10;
int pixels = (int) (dps * scale + 0.5f);
params.height = pixels;
playControlsPanelMinimized.setLayoutParams(params);
playControlsPanelMinimized.setBackgroundColor(Color.parseColor("#00FFFF"));
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
activityMain.addView(playControlsPanelMinimized);
However, when I add a second view by simply repeating the code with new variables, I see there is an overlap behavior, to the effect that I only see the first view.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RelativeLayout activityMain = (RelativeLayout)findViewById(R.id.activity_main);
// First view
View playControlsPanelMinimized = new View(this);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
final float scale = activityMain.getContext().getResources().getDisplayMetrics().density;
float dps = 10;
int pixels = (int) (dps * scale + 0.5f);
params.height = pixels;
playControlsPanelMinimized.setLayoutParams(params);
playControlsPanelMinimized.setBackgroundColor(Color.parseColor("#00FFFF"));
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
activityMain.addView(playControlsPanelMinimized);
// Second View
View playControlsPanelMinimized2 = new View(this);
RelativeLayout.LayoutParams params2 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
final float scale2 = activityMain.getContext().getResources().getDisplayMetrics().density;
float dps2 = 10;
int pixels2 = (int) (dps2 * scale2 + 0.5f);
params2.height = pixels2;
playControlsPanelMinimized2.setLayoutParams(params2);
playControlsPanelMinimized2.setBackgroundColor(Color.parseColor("#00FFFF"));
params2.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
activityMain.addView(playControlsPanelMinimized2);
edit:
I changed activity_main.xml to LinearLaout, and adjusted my variables accordingly, but now I no longer see the views.
LinearLayout activityMain = (LinearLayout)findViewById(R.id.activity_main);
// First View
View playControlsPanelMinimized = new View(this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
final float scale = activityMain.getContext().getResources().getDisplayMetrics().density;
float dps = 10;
int pixels = (int) (dps * scale + 0.5f);
params.height = pixels;
playControlsPanelMinimized.setLayoutParams(params);
playControlsPanelMinimized.setBackgroundColor(Color.parseColor("#00FFFF"));
//params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
activityMain.addView(playControlsPanelMinimized);
edit
I am trying a new technique with the relative layout method to no avail as of yet
View playControlsPanelMinimized = new LinearLayout(this);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
final float scale = activityMain.getContext().getResources().getDisplayMetrics().density;
float dps = 10;
int pixels = (int) (dps * scale + 0.5f);
params.height = pixels;
playControlsPanelMinimized.setLayoutParams(params);
playControlsPanelMinimized.setBackgroundColor(Color.parseColor("#00FFFF"));
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
activityMain.addView(playControlsPanelMinimized);
View A = new View(this);
View B = new View(this);
RelativeLayout.LayoutParams params2 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
A.setLayoutParams(params2);
B.setLayoutParams(params2);
playControlsPanelMinimized.addView(A);
playControlsPanelMinimized.addView(B);
Replace your RelativeLayout activity_main with LinearLayout which have orientation horizontal or vertical
Use lnearLayout instead of Relative layout, may be you need to use weightsum
set orientation to vertical / horizontal
put view right of other view and set it in xml .
I'm using this ItemDecoration class for GridLayout -> https://github.com/devunwired/recyclerview-playground/blob/master/app/src/main/java/com/example/android/recyclerplayground/GridDividerDecoration.java
But the problem is, my first row in GridLayout is an image and I set the span to 2.
You can view my screen as per screenshot below :
How to skip the first row so that ItemDecoration didn't draw on the Image?
Below is the code that I'm using to add the ItemDecoration :-
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new GridLayoutManager(getActivity(), 2);
mLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
return position == 0 ? 2 : 1;
}
});
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter.setHighlightsCallbacks(this);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mRecyclerView.addItemDecoration(new GridDividerDecoration(getActivity()));
I also modified the drawHorizontal method in GridDividerDecoration class to only draw if imageview is null but still not working :-
public void drawHorizontal(Canvas c, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
if (child.findViewById(R.id.home_imgHeader) == null) {
final RecyclerView.LayoutParams params =
(RecyclerView.LayoutParams) child.getLayoutParams();
final int left = child.getRight() + params.rightMargin + mInsets;
final int right = left + mDivider.getIntrinsicWidth();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
}
Any help?
Assuming your items don't individually have solid backgrounds (i.e. the white color is from the parent), the simplest fix would be to move the code from onDrawOver() to onDraw(). This will draw the gridlines underneath your child view contents and it will be hidden under the header image.
Otherwise, the code you are using assumes that the grid lines are always drawn to the top of the view in drawHorizontal() (notice top is a value that never changes). You would need to modify that function to account for the bottom of the first item and start drawing there. Something like:
public void drawHorizontal(Canvas c, RecyclerView parent) {
final View topView = parent.findViewHolderForAdapterPosition(0);
int viewBottom = -1;
if (topView != null) {
final RecyclerView.LayoutParams params =
(RecyclerView.LayoutParams) child.getLayoutParams();
viewBottom = child.getBottom() + params.bottomMargin + mInsets;
}
final int top = viewBottom > parent.getPaddingTop() ? viewBottom : parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();
… /* Remaining Code */
}
I'm trying to add buttons dynamically depending on screen width.
i.e. if I get 6 buttons then I need to position them accordingly, so that the buttons appear at the center with equal spacings on left parent and right parent.
Here is the piece of code which I'm trying but no result:
private void btmBarBtns(int position) {
RelativeLayout rlLayout;
RelativeLayout.LayoutParams layoutParams;
int leftMargin = scrWidth/pageCount;
CommonMethods.getSystemOutput("Left Margin::::"+leftMargin);
for (int i = 0; i < pageCount; i ++ ) {
rlLayout = (RelativeLayout) findViewById(R.id.ivBottomBar);
layoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
layoutParams.leftMargin = leftMargin;
ib = new ImageButton(this);
ib.setId(i);
ib.setLayoutParams(layoutParams);
ib.setBackgroundResource(R.drawable.white_circle_32x32);
rlLayout.addView(ib);
leftMargin = leftMargin + 70;
if (ib.getId() == position) {
ib.setBackgroundResource(R.drawable.black_circle_32x32);
}
}
}
In the above code I have a Relative layout with height 25dp and width fill_parent. I am able to add the buttons but they are not positioned at the center.
If all you want to is center those ImageButtons with equal space left and right then you could simple wrap them in a LinearLayout and then center that LinearLayout in the parent RelativeLayout:
RelativeLayout rlLayout = (RelativeLayout) findViewById(R.id.parent);
LinearLayout container = new LinearLayout(this);
for (int i = 0; i < 5; i++) {
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
ImageButton ib = new ImageButton(this);
ib.setId(i);
ib.setLayoutParams(layoutParams);
ib.setBackgroundResource(R.drawable.ic_launcher);
container.addView(ib);
if (ib.getId() == position) {
ib.setBackgroundResource(R.drawable.black_circle_32x32);
}
}
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL,
RelativeLayout.TRUE);
rlLayout.addView(container, layoutParams);
If you want to write more code just to do the above then you could modify your current layout and add this element as an anchor:
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_centerHorizontal="true"
android:id="#+id/anchor" />
and then in code position the ImageButtons to the left and right of this anchor View:
int anchorId = R.id.anchor;
int btnsNr = 6; // this is the number of Buttons
RelativeLayout rlLayout = (RelativeLayout) findViewById(R.id.parent);
if (btnsNr % 2 != 0) {
anchorId = 1000;
btnsNr--;
ImageButton imgb = new ImageButton(this);
imgb.setImageResource(R.drawable.shop_open);
imgb.setId(anchorId);
RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
rlp.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
rlLayout.addView(imgb, rlp);
}
int whichPart = 1;
while (whichPart >= 0) {
int previousId = anchorId;
for (int i = 0; i < (btnsNr / 2); i++) {
RelativeLayout.LayoutParams tmp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
if (whichPart == 1) {
tmp.addRule(RelativeLayout.LEFT_OF, previousId);
} else {
tmp.addRule(RelativeLayout.RIGHT_OF, previousId);
}
ImageButton imgb = new ImageButton(this);
previousId += whichPart == 1 ? -1 : 1;
imgb.setId(previousId);
imgb.setImageResource(R.drawable.shop_open);
rlLayout.addView(imgb, tmp);
}
whichPart--;
}
If you want to calculate the number of ImageButtons that fit the screen(and center them horizontally) you should have mentioned.