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;
}
Related
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 */
}
Do you know if it is possible to know if an Android Widget ScrollView can scroll?
If it has enough space it doesn't need to scroll, but as soon as a dimension exceeds a maximum value the widget can scroll.
I don't see in the reference a method who can give this information.
Maybe is it possible to do something with the size of the linearlayout inside the scrollview?
I used the following code inspired by https://stackoverflow.com/a/18574328/3439686 and it works!
ScrollView scrollView = (ScrollView) findViewById(R.id.scrollView);
int childHeight = ((LinearLayout)findViewById(R.id.scrollContent)).getHeight();
boolean isScrollable = scrollView.getHeight() < childHeight + scrollView.getPaddingTop() + scrollView.getPaddingBottom();
Thanks to: #johanvs and https://stackoverflow.com/a/18574328/3439686
private boolean canScroll(HorizontalScrollView horizontalScrollView) {
View child = (View) horizontalScrollView.getChildAt(0);
if (child != null) {
int childWidth = (child).getWidth();
return horizontalScrollView.getWidth() < childWidth + horizontalScrollView.getPaddingLeft() + horizontalScrollView.getPaddingRight();
}
return false;
}
private boolean canScroll(ScrollView scrollView) {
View child = (View) scrollView.getChildAt(0);
if (child != null) {
int childHeight = (child).getHeight();
return scrollView.getHeight() < childHeight + scrollView.getPaddingTop() + scrollView.getPaddingBottom();
}
return false;
}
In addition to #johanvs response:
You should wait for view beign displayed
final ScrollView scrollView = (ScrollView) v.findViewById(R.id.scrollView);
ViewTreeObserver viewTreeObserver = scrollView.getViewTreeObserver();
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
scrollView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
int childHeight = ((LinearLayout) v.findViewById(R.id.dataContent)).getHeight();
boolean isScrollable = scrollView.getHeight() < childHeight + scrollView.getPaddingTop() + scrollView.getPaddingBottom();
if (isScrollable) {
//Urrah! is scrollable
}
}
});
I'm having a bit of a problem setting the addonSlider() (aka Sliding menu) width for menu/shadow.
I looked inside the AddonSlider class and SliderMenu class and didn't find anything that refers to setting the width of menu/shadow.
The only thing regarding that i found was this:
private void attach(View view, int gravity) {
if (view == null) {
return;
}
final ViewGroup.LayoutParams initialParams = view.getLayoutParams();
DrawerLayout.LayoutParams params;
if (initialParams instanceof DrawerLayout.LayoutParams) {
params = (LayoutParams) initialParams;
} else if (initialParams != null) {
params = new LayoutParams(initialParams);
} else {
params = new LayoutParams(android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
android.view.ViewGroup.LayoutParams.MATCH_PARENT);
}
params.gravity = gravity;
view.setLayoutParams(params);
ViewParent parent = view.getParent();
if (parent != null) {
((ViewGroup) parent).removeView(view);
}
requestDrawerLayout();
mDrawerLayout.addView(view, gravity == Gravity.NO_GRAVITY ? 0 : -1, params);
}
but messing a bit with this settings got me nowhere
So finally i got what i wanted. It passed me, but all i had to do is override the:
<dimen name="menu_width">200dp</dimen>. attribute
Thanx to Prototik for that
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
Hi I'm using the TouchListView control from here: https://github.com/commonsguy/cwac-touchlist
and I've added some buttons to add to the list in the footer:
mFooter = getLayoutInflater().inflate(R.layout.edit_homepage_footer_layout, null);
mListView = (TouchListView) findViewById(R.id.sectionList);
mListView.addFooterView(mFooter);
It all seems to be working fine until I drag an item in the list, at which point the footer collapses (to the height of one list item I think) obscuring the buttons I have added.
Can anyone suggest a fix/workaround for this?
I actually worked this out shortly after asking it (always the way...)
The issue is in the doExpansion() and unExpandViews() methods which were modifying every item in the list including the footer. To fix it I created a method to check whether we are dealing with a draggable item or the footer:
private boolean isDraggableItem(View view) {
View dragger = view.findViewById(grabberId);
return dragger != null;
}
And then modified the methods mentioned as follows:
private void unExpandViews(boolean deletion) {
for (int i = 0; ; i++) {
View v = getChildAt(i);
if (v == null) {
if (deletion) {
// HACK force update of mItemCount
int position = getFirstVisiblePosition();
int y = getChildAt(0).getTop();
setAdapter(getAdapter());
setSelectionFromTop(position, y);
// end hack
}
layoutChildren(); // force children to be recreated where needed
v = getChildAt(i);
if (v == null) {
break;
}
}
if (isDraggableItem(v)) { //check this view isn't the footer
ViewGroup.LayoutParams params = v.getLayoutParams();
params.height = mItemHeightNormal;
v.setLayoutParams(params);
v.setVisibility(View.VISIBLE);
}
}
}
private void doExpansion() {
Log.d(logTag, "Doing expansion");
int childnum = mDragPos - getFirstVisiblePosition();
if (mDragPos > mFirstDragPos) {
childnum++;
}
View first = getChildAt(mFirstDragPos - getFirstVisiblePosition());
for (int i = 0; ; i++) {
View vv = getChildAt(i);
if (vv == null) {
break;
}
int height = mItemHeightNormal;
int visibility = View.VISIBLE;
if (vv.equals(first)) {
// processing the item that is being dragged
if (mDragPos == mFirstDragPos) {
// hovering over the original location
visibility = View.INVISIBLE;
} else {
// not hovering over it
height = 1;
}
} else if (i == childnum) {
if (mDragPos < getCount() - 1) {
height = mItemHeightExpanded;
}
}
if (isDraggableItem(vv)) { //check this view isn't the footer
ViewGroup.LayoutParams params = vv.getLayoutParams();
params.height = height;
vv.setLayoutParams(params);
vv.setVisibility(visibility);
}
}
}
Would be worth updating the github project to include this I think.