I added a linear layout in horizontal scroll view and in layout add some text views. Is it possible to get visible children in this layout.
This code get all child but i want to get visible (currently displaying) children only:
final HorizontalScrollView scroll = (HorizontalScrollView)findViewById(R.id.horizontalScrollView1);
LinearLayout linearLayout = ((LinearLayout)scroll.findViewById(R.id.linearLayout1));
int chilrenNum = linearLayout.getChildCount();
Well , after a bit of searching on SO I found this answer to listen to scroll events. Implement Scroll Event Listener in Android.
The idea is to override onScrollChanged in your ScrollView and keep track of the visible part of your scrollview in your activity.
Doing that you can easily get the visible views by a code that looks like this:
int currentPosition = lastXPosition; // lastXPosition gets updated from scroll event
int layoutWidth = linearLayout.getWidth();
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int childWidth = layoutWidth/linearLayout.getChildCount();
int firstVisibleXPos = currentPosition - width/2; // currentPosition will be in the middle of the screen
int lastVisibleXPos = currentPosition + width/2;
int indexOfFirstVisible = firstVisibleXPos/childWidth;
int indexOfLastVisible = lastVisibleXPos/ childWidth;
All the above code assumes fixed child view sizes . if you are using variable child size you will need to get their width first and keep track of it then calculate the visiblity based on index and position in parent view.
Related
I made a linear layout and it contain some Image views . when i move one with (set X(view.get x + 10)) function, it moves... but it moves behind other views. that the view become hidden.
and the other problem is when i get X & Y of the view, its always 0,0. but the view is in the middle of the screen. what should I do??? should i give up with linear layout??
if(wichmov == "right" ){
if(martin.getX() < width){
martin.setX(martin.getX()+ deltax);
}
else if(wichmov == "left"){
if(martin.getX() > 0){
martin.setX(martin.getX()- deltax );
}
}
}
this is how i move it.
When are you trying to call getX()? This might be something to look into: View getX() and getY() return 0.0 after they have been added to the Activity
If you're making the call in onCreate, it'll be zero.
I just figured it out.
I use a relative layout and then set the linear layout as match parent. After designing the background with the linear layout, I define an image view after the linear layout and inside of the relative layout, and then in Java, I set the position of it in the exact place I want it to (front of the special box of linear layout that I wanted it move), and width and height of it too.
The following code will help you to place your view to the exact place of your screen you want it, and set its width and height:
DisplayMetrics metrics = this.getResources().getDisplayMetrics(); //getting screen size
width = metrics.widthPixels;
height = metrics.heightPixels;
view.setX(width *5/8); //setting the place
view.setY(height/4);
LayoutParams para = view.getLayoutParams(); //set size of view
para.height = (int) (height/2);
para.width = (int) (width/4);
view.setLayoutParams(para);
I have a LinearLayout (vertical) with two child views in it. The 1st one is a ScrollView and the 2nd one is another layout with Visibility.GONE, its size is not fixed (determined by its children).
<LinearLayout vertical>
<ScrollView> ... </ScrollView>
<AnotherLayout visibility=GONE height=wrap_content> ... </AnotherLayout>
</LinearLayout>
At some point of time I want to show AnotherLayout. But, once it pops up, I also want to adjust the scrolling of my ScollView one. For this, I need to know the size of this AnotherLayout.
I'm doing something like that:
int oldHeight = scrollArea.getHeight();
linearLayout.setVisibility(VISIBLE);
int newHeight = scrollArea.getHeight();
But oldHeight and newHeight are still the same.
How can I calculate the new height?
The two dimensions are the same because visibility change took time and the line of code was run before that so it returns the same.
You can use a visibility listener to calculate the dimension after visibility change , You may use that
linearLayout.setTag(linearLayout.getVisibility());
linearLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int newVis = linearLayout.getVisibility();
if((int)linearLayout.getTag() != newVis)
{
linearLayout.setTag(linearLayout.getVisibility());
//visibility has changed
int newHeight = scrollArea.getHeight();
}
}
});
I need to get the visible height of header in listivew .How to get the height of First item in Listview(Header) or any View.
I Tried method given Below but these are giving me the original height of item not visible height.
view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#SuppressLint("NewApi")
#SuppressWarnings("deprecation")
#Override
public void onGlobalLayout() {
//now we can retrieve the width and height
int width = view.getWidth();
int height = view.getHeight();
//...
//do whatever you want with them
//...
//this is an important step not to keep receiving callbacks:
//we should remove this listener
//I use the function to remove it based on the api level!
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN)
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
else
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
and
view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
int widht = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
and this too
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics); height =
metrics.heightPixels; width = metrics.widthPixels;
But not getting any result.
Thanks in advance
You can try this. Let your layout file is as follows:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rl_container"
android:layout_height="match_parent"
android:layout_width="match_parent">
<ListView
android:id="#+id/sample_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
In your activity java file:
ListView mListView = (ListView) findViewById(R.id.sample_list_view);
mListView.setAdapter(mAdapter);
// add header view.
// Let "mHeaderView" is a header view inflated from some layout file
mListView.addHeaderView(mHeaderView);
// let your listview's parent view (in layout file) is a relative layout
// with id = "rl_container" as shown in above XML layout file
RelativeLayout rlContainer = (RelativeLayout)findViewById(R.id.rl_container);
// To find visible height of the first item (header in this case)
// mListView.getChildAt(i) return view of the ith child from top.
// header is considered to be as 0th child.
// not sure about multiple headers. but it should be same.
View childView = mListView.getChildAt(0);
// visible height is bottom cordinate of the child view - top cordinate of the list view's parent container.
// here I am considering list view as the top child of its parent container.
// code can be modified accordingly to consider margins from top.
int visibleHeight = childView.getBottom() - rlContainer.getTop();
if(visibleHeight < 0) {
//then item is not visible
}
It is working for me as I am using it in my project. comments and suggestions are welcomed.
One of Android samples (FixedGridLayout) extends a ViewGroup to allow for custom transitions when new items are added to a grid. The code works as expected, but doesn't implement scrolling. I thus wrapped the entire layout in a ScrollView expecting that this would solve the issue. However, it appears that the FixedGridLayout view is actually much larger than it should be, leaving a lot of scrollable space after the items.
I suspect the issue is related to the way onMeasure() is implemented. Am I right, and if so, what is wrong with this code?
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int cellWidthSpec = MeasureSpec.makeMeasureSpec(mCellWidth, MeasureSpec.AT_MOST);
int cellHeightSpec = MeasureSpec.makeMeasureSpec(mCellHeight, MeasureSpec.AT_MOST);
int count = getChildCount();
for (int index=0; index<count; index++) {
final View child = getChildAt(index);
child.measure(cellWidthSpec, cellHeightSpec);
}
// Use the size our parents gave us, but default to a minimum size to avoid
// clipping transitioning children
int minCount = count > 3 ? count : 3;
setMeasuredDimension(resolveSize(mCellWidth * minCount, widthMeasureSpec),
resolveSize(mCellHeight * minCount, heightMeasureSpec));
}
ScrollView only cares about the vertical height of the inner child view after measuring it, but it will not scroll unless the inner child sets the height to something larger than the parent.
You could call getHeight() on the inner view to see if it's computed a larger value than you expected. The method is only valid after layout is complete.
The code you posted does appear to have a mistake in it.
int minCount = count > 3 ? count : 3;
setMeasuredDimension(resolveSize(mCellWidth * minCount, widthMeasureSpec),
resolveSize(mCellHeight * minCount, heightMeasureSpec));
The code is setting the width and height based upon the total number of children. If I assume a grid layout pattern, then the width is calculated as mCellWidth * columns and height is calculated as mCellHeight * rows.
If you set the height value using the total number of children, then this would explain why your scrolling beyond the bottom of the layout.
I am developing a custom ViewGroup that contains a number of views. In the constructor, I create a number of FrameLayouts that will each contain two ImageViews. Each Framelayout and the child views are created using the following code.
FrameLayout frame = new FrameLayout(context);
ImageView digitView = new ImageView(context);
digitView.setScaleType(ScaleType.CENTER_CROP);
frame.addView(digitView,
new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
ImageView bezelView = new ImageView(context);
bezelView.setScaleType(ScaleType.CENTER_CROP);
bezelView.setImageResource(R.drawable.bezel);
frame.addView(bezelView);
this.addView(frame, params);
In the onMeasure callback I set the dimensions of the custom ViewGroup
this.setMeasuredDimension(254, 43);
and in the onLayout callback, I calculate the dimensions of each of the FrameLayouts and call the layout method for each
#Override
protected void onLayout (boolean changed, int left, int top, int right, int bottom)
{
if (changed)
{
float width = (float)(right - left) / (float)this.digits;
if ((int)(width/ASPECT_RATIO) > bottom- top)
width = (float)(bottom - top) * ASPECT_RATIO;
this.digitWidth = (int)width;
this.digitHeight = (int)(width/ASPECT_RATIO);
this.xOffset = ((right - left) - (this.digits * this.digitWidth))/2;
this.yOffset = ((bottom - top) - this.digitHeight)/2;
for (int i = this.digits-1; i >=0; i--)
{
int x = xOffset + i * this.digitWidth;
this.placeFrames.get(i).layout(x, this.yOffset, x + this.digitWidth, yOffset + this.digitHeight);
}
}
}
The issue I am having is that the FrameLayouts are being correctly sized and positioned within the custom GroupView, but the ImageViews are not being resized by the FrameLayouts - they have zero width and height. I validated this using the HierarchyViewer.
I think I've missed something - I assumed that the layout method on the FrameLayout would take care of resizing the child ImageViews based on the layout parameters passed in when they were added to the FrameLayout as children, but it seems not.
A pointer in the right direction would be very much appreciated.
Thanks
Andrew
I assumed that the layout method on the FrameLayout would take care of resizing the child ImageViews based on the layout parameters passed in when they were added to the FrameLayout as children, but it seems not.
You are not layout() these ImageView objects yourself nor calling super.onLayout()..