View.getTop() always returns 0 - android

So View.getTop() is, as per the docs:
Top position of this view relative to its parent.
I have the following layout:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/root"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.scrollviewtest1.MainActivity">
<LinearLayout
android:id="#+id/scroll_container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.example.scrollviewtest1.MyTextView
android:id="#+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/large_text" />
<TextView
android:id="#+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
</LinearLayout>
</ScrollView>
I am checking for getTop() for LinearLayout as I scroll up and down and getTop() always returns 0. Shouldn't it change as it moves up and down relative to its parent?.
How I checked it?
I stored reference to the LinearLayout inside the child TextView and called invalidate() every time there was scrolling:
ScrollView root = ((ScrollView) findViewById(R.id.root));
root.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
#Override
public void onScrollChanged() {
textView.invalidate();
}
});
and checked inside the onDraw() call of the child TextView

Try this way :
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
int top = view.getTop();
}
}, 300);// delay times in milliseconds
You can set delay time as per your requirement.

To get the LinearLayout scrolled position call myScrollView.getScrollY();
getTop(); returns what you entered as marginTop in your xml layout and it not varies when the thing is scrolled, to know the actual current position you need to take in account getScrollY(); too

Related

ImageView AlignParentBottom

In my application I have an ImageView that gets with buttom alignment, in a RelativeLayout which is the root view of the Layout:
The problem is that when the keyboard is opened, it goes up together:
I tried to fix it by putting it in Manifest: `android:windowSoftInputMode="stateVisible|adjustPan",
It works, the problem is that the FloatingButton stops scrolling too, is there any way to make ImageView only "locked" down when the keyboard opens?
The xml looks like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:layout_alignParentBottom="true"
app:srcCompat="#drawable/ic_rodape"/>
<ScrollView........../>
<android.support.design.widget.FloatingActionButton
android:id="#+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_margin="8dp"
app:backgroundTint="#color/colorPrimary"
app:srcCompat="#drawable/back"/>
</RelativeLayout>
Instead of using android:windowSoftInputMode="stateVisible|adjustPan" use this to hide specific views RelativeLayout rootView = (RelativeLayout) findViewById(R.id.root)
rootView is just a view pointing to your root view in this case a relative layout(give an id to your Relative layout)
rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Rect r = new Rect();
rootView.getWindowVisibleDisplayFrame(r);
int heightDiff = rootView.getRootView().getHeight() - (r.bottom - r.top);
if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
//when the keyboard is up...
view_one.setVisibility(View.GONE);
}else{
//when the keyboard is down...
view_one.setVisibility(View.VISIBLE);
}
}
});
Thanks to answers here and here

Text jumps right to center when keyboard toggled

I have a RecycleView in which I visualize some text. The text is entered through an EditText view in the bottom. The RecycleView contains a TextView which is has the text centered.
I have also a function that detects if the keyboard is visualised. When the keyboard is visualised, then some layout parameters are changed so that the EditText looks good. I also have a smooth scroll to the last position of the RecycleView.
When I reopen the keyboard again, the text is first drawn to the left of the screen. If I swipe, the text is re-aligned to center. That is very disturbing and I always want the text to be centered. I probably miss something when changing the parameters of the layouts.
KeyBoard openedListener:
// Function to see of keyboard is opened or not.
private void detectKeyBoard(){
final ConstraintLayout rootView = findViewById(R.id.activity_root);
rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
float heightDiff = rootView.getRootView().getHeight() - rootView.getChildAt(0).getHeight();
if (!isRefSet){
refDiff = heightDiff;
isRefSet = true;
}
if (heightDiff > refDiff) {
LinearLayout.LayoutParams params = new
LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
0);
params.weight = wRSmall;
mRecyclerView.setLayoutParams(params);
LinearLayout.LayoutParams eParams = new
LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
0);
eParams.weight = wESmall;
mLinearInput.setLayoutParams(eParams);
if (mAdapter.getItemCount() > 0) {
mRecyclerView.smoothScrollToPosition(mAdapter.getItemCount() - 1);
}
} else {
LinearLayout.LayoutParams params = new
LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
0);
params.weight = wRStart;
mRecyclerView.setLayoutParams(params);
LinearLayout.LayoutParams eParams = new
LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
0);
eParams.weight = wEStart;
mLinearInput.setLayoutParams(eParams);
if (mAdapter.getItemCount() > 0) {
mRecyclerView.smoothScrollToPosition(mAdapter.getItemCount() - 1);
}
}
}
});
}
xml for RecycleView:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/activity_root"
tools:context="com.example.erikbylow.autoflash.TranslateActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/translate_linear"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.9"
android:scrollbars="vertical"
android:layout_gravity="center_horizontal"
android:id="#+id/translate_recycle"
android:background="#android:color/holo_blue_bright" />
<LinearLayout
android:layout_width="match_parent"
android:id="#+id/linear_input"
android:layout_height="0dp"
android:layout_weight="0.1"
android:orientation="horizontal">
<EditText
android:layout_width="0dp"
android:layout_weight="0.75"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:singleLine="true"
android:id="#+id/source_input"
android:hint="Type text to translate"/>
<Button
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_weight="0.25"
android:layout_alignRight="#+id/source_input"
android:text="Translate"
android:clickable="true"
android:onClick="startTranslate"
android:background="#android:color/holo_green_dark"/>
</LinearLayout>
</LinearLayout>
TextView for Adapter:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:textSize="#dimen/active_text_size"
android:id="#+id/adapter_textview"/>
After swiping it is re-aligned:
EDIT: It did not work to remove android:layout_gravity="center_horizontal" in the recycle xml part.
Further, if the screen is full without the keyboard being opened, the text is moved to the right:
Can you comment the detectKeyBoard() function? Just to check if the same problem exists or not?
Just a guess -
I see that you are creating a new LayoutParams object and assign it to your mRecyclerView and mLinearInput.
As far as I know, this new LayoutParam object will replace what you have set in XML, including layout_gravity, layout_weight, etc.
Try getting existing LayoutParams from mRecyclerView and mLinearInput, and modify their values instead.
Cannot advise much because I do not really understand the reason behind resetting layout params in your case.

relativelayout wrap_content not working

this is my xml code
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:id="#+id/tt">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/trashParent"
android:visibility="visible"
android:orientation="horizontal"
android:layout_alignParentBottom="true">
<LinearLayout
android:background="#drawable/bgtrash"
android:layout_width="match_parent"
android:layout_height="140dp"
android:baselineAligned="false"
android:orientation="horizontal">
</LinearLayout>
</RelativeLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="#+id/parentTrash"
android:layout_marginBottom="30dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true">
<
</LinearLayout>
as we can see the parent View with id android:id="#+id/tt"
its height and width its wrap_content i know if some child have android:layout_alignParentBottom="true" so the wrap_conent not work its will be like match_parent
but now i do this in java i have to method will hide and show the child
private void hide(){
trashParent.setVisibility(View.GONE);
parentTrash.setVisibility(View.GONE);
}
private void show(){
trashParent.setVisibility(View.VISIBLE);
parentTrash.setVisibility(View.VISIBLE);
}
now when i hide the child and make it wrap_content its still match parent this the run code
hide();
RelativeLayout.LayoutParams chatHeadParentParamst = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
tt.setLayoutParams(chatHeadParentParamst);
tt.setBackgroundColor(Color.YELLOW);
change tt height to wrap_content because its be match parent some time
but after change to wrap_conent is still like match_parent
i think the child still not Gone and i set it to wrap_conent
because when i use delay its work this the delay
hide();
Handler handler = new Handler(Looper.getMainLooper());
Runnable runnable = new Runnable() {
#Override
public void run() {
hide(); // i dont no must i call it again to work
RelativeLayout.LayoutParams chatHeadParentParamst = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
tt.setLayoutParams(chatHeadParentParamst);
tt.setBackgroundColor(Color.YELLOW);
Log.d("called now delay","wwwwwwwww");
}
};
handler.postDelayed(runnable, 1100);
with delay now its size chnage to wrap_conent without delay it be same like match_parent but all child visibility was gone any solotio without delay i cant use LinerLayout i must use RaltiveLayout becuase i need child one over one

Does getMeasuredHeight() and getMeasuredWidth() work on nested views, and when do I use it?

I've been trying to measure the pixel dimensions of a view within a RelativeLayout that's within another RelativeLayout:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="60"
>
...
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/labels_placeholder"
android:id="#+id/player_section_layout"
>
<LinearLayout
android:id="#+id/player_section_background"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="horizontal"
android:weightSum="100">
<!--The view above is what I'm trying to measure-->
<LinearLayout
android:id="#+id/player_section_background_left"
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_weight="50"
android:background="#AAAAAA"
android:orientation="horizontal" />
<LinearLayout
android:id="#+id/player_section_background_right"
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_weight="50"
android:background="#DD0000"
android:orientation="horizontal" />
</LinearLayout>
<HorizontalScrollView
android:id="#+id/player_section"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_alignTop="#id/player_section_background">
<ImageView
android:id="#+id/waveform_placeholder"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:scaleType="centerInside"
/>
</HorizontalScrollView>
</RelativeLayout>
</RelativeLayout>
I tried calling getMeasuredHeight() and getMeasuredWidth() right after referring to it in onCreateView() of the fragment:
waveformBackground = (LinearLayout)result.findViewById(R.id.player_section_background);
waveformBackground.post(new Runnable() {
#Override
public void run() {
Log.i("bckg_layout_dims", waveformBackground.getMeasuredWidth()+" "+waveformBackground.getMeasuredHeight());
}
});
And it returns 0 for both.
I did hear something about it not working before the view is being drawn, but I don't know when exactly it finishes drawing. Is it after OnCreateView, and if so, can I call it in OnActivityResult?
The problem you are facing is because the view is being drawn after you ask for the height and width. I used a ViewTreeObserver which constantly listens for changes in the views, and can access the measurements after the views has been drawn. Im not sure this is the best solution for your problem but you should look into it. Here's an example:
mTitleContainer.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int toolBarHeight = mTitle.getHeight() + mSubtitle.getHeight() + (int) TOOLBARPADDING;
if (toolBarHeight != mLastTitleHeight) {
CollapsingToolbarLayout.LayoutParams layoutParams = (CollapsingToolbarLayout.LayoutParams) mTitleToolbar.getLayoutParams();
layoutParams.height = toolBarHeight;
mTitleToolbar.setLayoutParams(layoutParams);
mLastTitleHeight = toolBarHeight;
}
}
}
);

Detect if view is scrolled out of the screen

I have layout with scrollView as below :
<ScrollView
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="#+id/transparentLayout"
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="#android:color/transparent"
android:orientation="vertical" >
</LinearLayout>
... other views
</ScrollView>
I want to detect if the transparentLayout (LinearLayout) is scrolled out of the screen.
I solved it in this fashion:
scrollView.getViewTreeObserver().addOnScrollChangedListener(new OnScrollChangedListener() {
#Override
public void onScrollChanged() {
Rect scrollBounds = new Rect();
scrollView.getHitRect(scrollBounds);
if (layout.getLocalVisibleRect(scrollBounds)) {
// if layout even a single pixel, is within the visible area do something
} else {
// if layout goes out or scrolled out of the visible area do something
}
}
});

Categories

Resources