How to detect when TextView exits/enters screen on Android? - java

I have this LinearLayout with few elements in it. Since there are many elements I have wrap it inside ScrollView. Inside this LinearLayout I have one TextView element and I won't to detect when it is not longer visible on screen while scrolling.
The thing that I am trying to do is to show this Activity with LinearLayout and make title of toolbar empty, then when user scrolls down, and this TextView exits screen, I want to set title in the toolbar to content of that TextView. And similar when this text view enters screen again to set title in toolbar to be empty.
I have no idea how to implement this and what listeners to use...
EDIT:
This is what I want to create: detect when text view exits or enters screen and update title in toolbar accordingly.

This will work for API23 or higher, but it gives you the basic idea.
ScrollView scroll = (ScrollView) findViewById(R.id.yourScrollView);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
scroll.setOnScrollChangeListener(new View.OnScrollChangeListener() {
#Override
public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
Log.e(TAG, "SCROLL = " + scrollY);
if(scrollY > txtView_Y){
setTitle("Hello");
}
else{
setTitle("I'm not there yet");
}
}
});
}
The value txtView_Y is the y position of your TextView. You will have to get that after the Activity has positioned all the views. You will probably need ViewTreeObserver.OnGlobalLayoutListener for that.

Related

Recyclerview / Picasso not re-rendering or re-fitting image upon height change

I am using Viewpager2 which displays a different instance of the same fragment in each page.
each fragment has a recyclerview, whose items are made of a (Constraint)layout with a couple edittext and an ImageView
I am calculating height of the element (layout) of a recyclerview in order to have exactly N items displayed. For the width I am simply setting colSpan of recyclerview GridLayoutManager and it works.
When setting the number of rows (of the layout of the single view in OnBindViewHolder of the Adapter), the height is updated, but the picture loaded with Picasso is not refitted to stretch the whole height, until when I change viewpager page and come back... adding/removing elements to the adapter does NOT trigger any update of the image.
The problem is more visible when decreasing the rows number, as the previously fitted image is kept the same, thus not covering the whole ImageView.
placing the image like this, in debug I can see that the if is entered when changing N rows:
String drPath = localData[position].getDrawablePath();
if (!drPath.equals(""))
{
var f = new File(filesDir, drPath);
try
{
Picasso.get()
.load(f)
.fit()
.centerCrop()
.into(holder.itemImage);
}
catch (Exception e)
{
e.printStackTrace();
}
}
I tried:
after changing N rows, notifyDataSetChanged()
in OnBindViewHolder:
public void onBindViewHolder(#NonNull ViewHolder holder, int position)
{
if (holder.heightChanged(parentHeight / numberRows))
{
holder.updateLayoutHeight(parentHeight / numberRows);
}
holder.itemLayout.requestLayout();
holder.itemLayout.invalidate();
holder.itemLayout.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
holder.itemImage.requestLayout();
holder.itemImage.invalidate();
holder.itemImage.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
// ...picasso loading
and debugging I see the height of layout and imageView has been actually recalculated.
Since gLM.setSpanCount(nCols) works, seeing that it calls requestLayout(), I am calling the same on recyclerview after the I called updateHeight on the adapter:
cmdEditVM.getnRowsRecyView().observe(
getViewLifecycleOwner(), (nRows) ->
{
if (!firstUpdRows)
{
cmdObjectsAdapter.updateNRows(nRows);
**recyView.requestLayout();**
}
firstUpdRows = false;
});
I don't have any more ideas, so any suggestion would be appreciated :)

How to refresh layout/context from list adapter (I think this is what i need)

Im having a bug that i cant understand the reason and how to resolve it. I belive that is a problem of layout/view/context refresh but i dont know.
I have a cell from a listView(I prefer recyclerView but the project has years) and in the corner of the cell i have a button to show more options. Programatically it just make an element View.GONE and another element View.VISIBLE.
I will attach code in a moment
To this button i setted too a listener that when i tap on it it do the opposite of below mentioned. It shows some elements and hide an entire LinearLayout from the cell. The elements are showed BUT the LinearLayout keeps on the screen like bugged. If i tap anywhere it disappears and if i try to tap on it it disappears too. Its like the view of that linear got bugged and keep in there like a ghost view. I will shop some pictures.
The cell normally at the beginning: https://imgur.com/1BjK0KP
The cell after i press the entire view to show the LinearLayout at the bottom of the cell: https://imgur.com/eONSptW
The cell after i press the arrow of the corner to hide the LinearLayout. Here it shows the view bugged https://imgur.com/jrT0qxV
The cell after i tap anywhere else https://imgur.com/XD1jN7U
public void expandView(View view){
final View cellView = view;
final LinearLayout editLinear = (LinearLayout) view.findViewById(R.id.cart_edit);
editLinear.setVisibility(View.VISIBLE);
final TextViewFont countText = (TextViewFont) view.findViewById(R.id.itemCount);
countText.setVisibility(View.GONE);
final TextViewFont total = (TextViewFont) view.findViewById(R.id.itemTotal);
final ImageView imageViewArrow = (ImageView) view.findViewById(R.id.cart_edit_image);
imageViewArrow.setImageDrawable(context.getResources().getDrawable(R.drawable.icon_arrow_up));
//notifyDataSetChanged();
imageViewArrow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
countText.setVisibility(View.VISIBLE);
editLinear.setVisibility(View.GONE);
imageViewArrow.setImageDrawable(context.getResources().getDrawable(R.drawable.icon_arrow_down));
}
});
First of all, you don't need to store context because in View you have the method view.getContext().
I recommend this article:
https://possiblemobile.com/2013/06/context/
On the other hand, ensure that you don't have a ghost view that is overlapping your image view.

Android gridview change background by position

I have Gridview with images. above the image I have text(hello) and I can to show images(without text) to my gridview .now I want if I click gridview's 5th element I want to hide 5th image's text.meybe problem solution is gridview.setOnItemClickListener but I do not know how I can do this
I wrote some code witch can to show toast message by position, but I do not know how I can to hide text by position
gridview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
Toast.makeText(getApplicationContext(), "Cliked" + position,
Toast.LENGTH_SHORT).show();
}
});
You could try setVisibility along with an array to sort through the GUI identifiers:
int textId = this.getResources().getIdentifier(position, "id", this.getPackageName());
TextView picText = (TextView) findViewById (R.id.TextID);
picText.setVisibility(TextView.INVISIBLE);
Or something like that. INVISIBLE makes it invisible, but take up the same space - GONE will make the space disappear too - so depending on what you want.
That should at least get you in the right direction.
For more: http://developer.android.com/reference/android/view/View.html#setVisibility(int)
First Find the textView that you want INVISIBLE.
Then set it INVISIBLE.
By below Code
((TextView) v).setVisibility(TextView.INVISIBLE);
if above Line dont work use below
TextView textview=(TextView)v.findViewById(R.id.id_of_textview);
textview.setVisibility(TextView.INVISIBLE);

How can I make a drop down hidden menu

I want to make a drop down menu, like a status menu, that is hidden when the activity starts, and when it's pressed or slid it opens like the image below..
http://i.stack.imgur.com/jeq5z.png
My layout currently has a RelativeLayout for the top bar and a ScrollView for the text.. between those, i'd like to put the menu..
I'm not doing this app on phonegap or anything like that, just java and xml..
Thanks in advance
Edit:
Thank you all for your help! I end up doing a FrameLayout that was set off the screen with the translationY and then, when clicked, just slide up and down.. Here's the snipped.. I'll just leave it here in case someone else needs it.
on layout.xml
<FrameLayout
android:id="#+id/layout_FrameLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#00ffffff" >
<!-- stuf -->
</FrameLayout>
on activity.java
private FrameLayout statusDrawer = null;
private int statusDrawerHeight; // height of the FrameLayout (generated automatically)
private int statusDrawerDragButtonHeight = 30 + 5; //height of the DragButton + height of the border
private boolean statusDrawerOpened = false;
private int statusDrawerDuration = 750; //time in milliseconds
private TimeInterpolator interpolator = null; //type of animation see#developer.android.com/reference/android/animation/TimeInterpolator.html
#Override
protected void onCreated(Bundle savedInstanceState){
statusDrawer = (FrameLayout) findViewById(R.id.layout_FrameLayout);
interpolator = new AccelerateDecelerateInterpolator();
statusDrawer.post(new Runnable() {
#Override
public void run() {
statusDrawerHeight = statusDrawer.getHeight();
statusDrawer.setTranslationY(-statusDrawerHeight+statusDrawerDragButtonHeight);
}
});
statusDrawer.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v){
if(statusDrawerOpened) {
statusDrawer.animate()
.translationY(-statusDrawerHeight+statusDrawerDragButtonHeight)
.setDuration(statusDrawerDuration)
.setInterpolator(interpolator)
.start();
} else {
statusDrawer.animate()
.translationY(0)
.setDuration(statusDrawerDuration)
.setInterpolator(interpolator)
.start();
}
statusDrawerOpened = !statusDrawerOpened;
}
});
}
Use a FrameLayout as the root layout. Add the drop menu layout as in the right side of your picture. Call
menuView.setTranslationY(-view.getHeight);
on this view to initially hide the drop down menu when the activity is started. Make sure menuView only refers to the drop down view part without the small tab button. When the user touches the tab animate translationY to 0 so that the layout will slide down
ObjectAnimator.ofFloat(dropDownView, "translationY", -view.getHeight, 0).setDuration(200).start();
whereby dropDownView refers to the complete drop down menu.
Using ObjectAnimator requires API level 11. If you need to support older API levels, use http://developer.android.com/reference/android/view/animation/TranslateAnimation.html (which has some down sides).
If you instead want add a sliding effect, e.g. the sliding menu is moving with together with the finger, install a OnTouchListener:
dropDownTab.setOnTouchListener(new OnTouchListener() {
public void onTouch(View v, MotionEvent e) {
// Make the drop down menu finger follow the finger position.
// Use again dropDownView.setTranslationY(...) to move the view.
// If the drop down menu has been dragged a certain distance, make it move out by itself using the animation as above.
}
});

Android - TranslateAnimation update dynamically the size of the Layout

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 :)

Categories

Resources