How to check if TextView is within the Visible Screen Android - android

I wanted to know if my textview is within the visible screen region or not..
I have looked at links as:
Android - Get the visible area of a view?
Android: how to check if a View inside of ScrollView is visible?
But nothing seems to work for me.
Code that i used to check is
Rect rect = new Rect();
//textview intialized in onCreate as text1
text1.getHitRect(rect);
text1.measure(0, 0);
//layout is the parent layout (linear) in which i am adding the text view
Rect acctualView = new Rect(Math.round(layout.getX()), Math.round(layout.getY()),
Math.round(layout.getX() + layout.getWidth()), Math.round(layout.getY() +layout.getHeight()));
if(Rect.intersects(acctualView, rect))
{
Toast.makeText(context, "visible", Toast.LENGTH_LONG).show();
}else {
Toast.makeText(context, "Not visible ", Toast.LENGTH_LONG).show();
}
Every width and height of textview and layout is giving me 0 "zero",
Please let me know how to fix this and know whether a view is inside the visible region or not
Here is my complete activity code
public class MainActivity extends Activity {
private TextView text1, text2, text3, text4, text5, text6;
private Context context;
private LinearLayout layout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = getLayoutInflater().getContext();
layout = (LinearLayout) findViewById(R.id.parentLayout);
setTextViews();
checkViewAndUpdate();
}
private void checkViewAndUpdate() {
Rect rect = new Rect();
layout.getHitRect(rect);
if (text1.getLocalVisibleRect(rect)) {
Toast.makeText(context, "visible", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context, "Not visible", Toast.LENGTH_LONG).show();
}
}
private void setTextViews() {
text1 = new TextView(context);
text2 = new TextView(context);
text3 = new TextView(context);
text4 = new TextView(context);
text5 = new TextView(context);
text6 = new TextView(context);
text1.setText("text1");
text2.setText("text2");
text3.setText("text3");
text4.setText("text4");
text5.setText("text5");
text6.setText("text6");
text1.setTextSize(30);
text2.setTextSize(30);
text3.setTextSize(30);
text4.setTextSize(30);
text5.setTextSize(30);
text6.setTextSize(30);
//layout.removeAllViews();
layout.addView(text1);
layout.addView(text2);
layout.addView(text3);
layout.addView(text4);
layout.addView(text5);
layout.addView(text6);
}
}
and my layout only contains LinearLayout (empty)

as i wrote on comment, checking visible rect at onCreate won't work.
Try this code at end of onCreate (instead of call checkAndUpdate() directly).
layout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
checkViewAndUpdate();
}
});
View layout does not finish though if you added view at onCreate. yes, this time user cannot see the actual activity and view's actual size are not set.
onGlobalLayout will call when view layout is ended (and activity is visible).
at that timing, we can now get size and position of them!
FYI, you can remove this listener by calling layout.getViewTreeObserver().removeOnGlobalLayoutListener(this) in onGlobalLayout()

try with this:
if (yourView.getParent().getVisibility() == View.VISIBLE) {
// visible
} else{
// hiden
}
Or this:
Rect rect = new Rect();
parentView.getHitRect(rect);
if (imageView.getLocalVisibleRect(rect)) {
// imageView is within the visible window
} else {
// imageView is not within the visible window
}

Why don't you use the for method?
for(int i = 0; i < 6; i++){
TextView tv = new TextView(context);
tv.setTextSize(30);
layout.addView(tv);
//Maybe set some listeners...
}

Related

Get Element Positions after adding to layout in Android

I'm trying to get the postions of an ImageView after i added it to a relative Layout.
I'm adding ImageViews randomly within the relative layout by clicking on a button. So far this works very good. But why does getLeft, getRight, getTop, getBottom return 0? The Thing is, that the values are all available on the next buttonclick. So when ImageView 1 has everything 0 on the creation, it has the information if i click the button again.
So to make it clear:
Buttonclick-1 -> ImageView-1 added (outputs 0 on getLeft,Top,Right,Bottom)
Buttonclick-2 -> ImageView-2 added (ImageView-1 outputs coordinates, but ImageView-2 outputs 0)
I'm sure this has to do with the drawing of the ImageView. Surely it is not ready drawn on the view when i iterate over the children and ask for the actual positions.
Here is my code so far:
final ConstraintLayout cl = (ConstraintLayout) findViewById(R.id.constraintLayout);
final ScrollView sc=(ScrollView) findViewById(R.id.scrollView);
final Button btnButton = (Button) findViewById(R.id.buttontest);
final LinearLayout ll = (LinearLayout) findViewById(R.id.linearLayout);
final RelativeLayout rl = (RelativeLayout) findViewById(R.id.rLayout);
btnButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ImageView im= new ImageView(UserAreaActivity.this);
im.setImageResource(R.mipmap.ic_launcher);
im.setScaleType(ImageView.ScaleType.FIT_XY);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(150, 150);
Random r = new Random();
Random r2 = new Random();
int x = r.nextInt(rl.getWidth());
int y = r2.nextInt(rl.getHeight());
if(x+(layoutParams.width) >= rl.getWidth()){
x=x-layoutParams.width;
}
if(y+(layoutParams.height) >= rl.getHeight()){
y=y-layoutParams.height;
}
layoutParams.leftMargin=x;
layoutParams.topMargin=y;
im.setLayoutParams(layoutParams);
TextView tv = new TextView(UserAreaActivity.this);
tv.setText("my text");
rl.addView(im);
ll.addView(tv);
System.out.println("ID "+im.getId());
System.out.println("Left "+im.getLeft());
System.out.println("Right "+im.getRight());
System.out.println("Top "+im.getTop());
System.out.println("Bottom "+im.getBottom());
for (int i = 0; i < rl.getChildCount(); i++) {
View subView = rl.getChildAt(i);
if (subView instanceof ImageView) {
ImageView imageView = (ImageView) subView;
System.out.println("ID "+i);
System.out.println("Left "+imageView.getLeft());
System.out.println("Right "+imageView.getRight());
System.out.println("Top "+imageView.getTop());
System.out.println("Bottom "+imageView.getBottom());
}
}
}
});
When you call rl.addView(im); you are kicking off a process that will eventually involve a "layout pass" for your RelativeLayout and your ImageView. It is only after this layout pass completes that you will be able to get valid coordinates for your ImageView.
Unfortunately, there's no one-liner for "give me the coordinates after the layout pass". All the best options are asynchronous (i.e. you register some code to run once the ImageView has been laid out). I recommend ViewTreeObserver.OnGlobalLayoutListener.
Something like this:
im.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
System.out.println("ID "+im.getId());
System.out.println("Left "+im.getLeft());
System.out.println("Right "+im.getRight());
System.out.println("Top "+im.getTop());
System.out.println("Bottom "+im.getBottom());
im.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});

HorizontalScrollView - Adding Item at specific position

I want that the user can scroll throw my HorizontalScrollView and if he press my Button, a TextView will be shown on the current position of my HorizontalScrollView.
So far I already know how to present a TextView, but not on a specific position...
TextView textView;
textView = new TextView(MainActivity.this);
textView.setText(editText.getText().toString());
linearLayout.addView(textView);
Any help is welcomed!
Do some thing like this ,
final HorizontalScrollView scrollView = (HorizontalScrollView) findViewById(R.id.scroller);
final RelativeLayout container = (RelativeLayout) findViewById(R.id.container);
findViewById(R.id.addButton).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
TextView iv = new TextView(Act2.this);
iv.setText(new Date().toString());
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(300, 400);
params.leftMargin = scrollView.getScrollX();
params.topMargin = scrollView.getScrollY();
container.addView(iv, params);
}
});
And the relative layout should be inside the HorizontalScrollView. This will add a textview exactly in the current position , but you should also write code for avoiding the overlapping the TextViews.

move image from outside left screen to outside right screen Android

I have a cutstom DialogFragment to show a loading message to the user. For the loading message image, I created an animation that goes from the left part of the screen (starting from outside the screen) to the right of the screen (finishing outside the screen). To do so, I thought of starting the animation on y=-imageWith and finish in y=imageWith+dialogWith:
public class MensajeDialogFragment extends DialogFragment {
TextView mTvMensaje;
TextView mTvTitulo;
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
ImageView loadingImage = (ImageView) dialogView.findViewById(R.id.ivBus);
View dialogView = inflater.inflate(R.layout.layout_mensaje_dialog, null);
TextView mTvTitulo = (TextView) dialogView.findViewById(R.id.tvTitulo);
TextView mTvMensaje = (TextView) dialogView.findViewById(R.id.tvMensaje);
mTvTitulo.setText(getArguments().getString(getString(R.string.bundle_titulo), ""));
mTvMensaje.setText(getArguments().getString(getString(R.string.bundle_mensaje), ""));
builder.setView(dialogView);
TranslateAnimation izqADerAnimacion = new TranslateAnimation(-loadingImage.getWidth(), dialogView.getWidth()+loadingImage.getWidth(), 0, 0);
izqADerAnimacion.setDuration(3500);
izqADerAnimacion.setRepeatCount(Animation.INFINITE);
loadingImage.startAnimation(izqADerAnimacion);
return builder.create();
}
}
But for some reason, the loadingImage.getWidth() and dialogView.getWidth() are returning 0. What can I do to solve this without hardcoding the starting and finishing positions?
loadingImage.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT > 16)
loadingImage.getViewTreeObserver().removeOnGlobalLayoutListener(this);
else
loadingImage.getViewTreeObserver().removeGlobalOnLayoutListener(this);
//do animation
}
});
hope this works
TranslateAnimation izqADerAnimacion =
new TranslateAnimation(-loadingImage.getWidth(),
dialogView.getWidth()+loadingImage.getWidth(), 0, 0);
In your code above mentioned you can directly give some value like
TranslateAnimation animation = new TranslateAnimation(-970.0f, 2000.0f, 0.0f, 0.0f);
It works nicely in Nexus 9 tab.

Adding image to Toast?

Is it possible to programmatically add an image to a toast popup?
Yes, you can add imageview or any view into the toast notification by using setView() method, using this method you can customize the Toast as per your requirement.
Here i have created a Custom layout file to be inflated into the Toast notification, and then i have used this layout in Toast notification by using setView() method.
cust_toast_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/relativeLayout1"
android:background="#android:color/white">
<TextView
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="#+id/textView1" android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:text="PM is here"
android:gravity="center"
android:textColor="#android:color/black">
</TextView>
<ImageView
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:src="#drawable/new_logo"
android:layout_below="#+id/textView1"
android:layout_margin="5dip"
android:id="#+id/imageView1">
</ImageView>
<TextView
android:id="#+id/textView2"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:text="This is the demo of Custom Toast Notification"
android:gravity="center"
android:layout_below="#+id/imageView1"
android:textColor="#android:color/black">
</TextView>
</RelativeLayout>
CustomToastDemoActivity.java
LayoutInflater inflater = getLayoutInflater();
View view = inflater.inflate(R.layout.cust_toast_layout,
(ViewGroup)findViewById(R.id.relativeLayout1));
Toast toast = new Toast(this);
toast.setView(view);
toast.show();
Simply, Use the following:
Toast toast = new Toast(myContext);
ImageView view = new ImageView(myContext);
view.setImageResource(R.drawable.image_icon);
toast.setView(view);
toast.show();
You can create any view programmatically (since I am assuming you are asking on how to do this WITHOUT using a LayoutInflater) and call setView on the Toast you made.
//Create a view here
LinearLayout v = new LinearLayout(this);
//populate layout with your image and text or whatever you want to put in here
Toast toast = new Toast(getApplicationContext());
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast.setDuration(Toast.LENGTH_LONG);
toast.setView(v);
toast.show();
Knickedi's solution is good, but if you only need an icon next to the text you can make use of the fact that the Toast has a pre-defined TextView with the same ID and set the icon on the TextView:
Toast toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
TextView tv = (TextView) toast.getView().findViewById(android.R.id.message);
if (null!=tv) {
tv.setCompoundDrawablesWithIntrinsicBounds(icon, 0, 0, 0);
tv.setCompoundDrawablePadding(context.getResources().getDimensionPixelSize(R.dimen.padding_toast));
I think this is better that we show text of Toast on the image which we pass to the makeImageToast function...
so I shades Knickedi codes and :
public class utility {
public static Toast makeImageToast(Context context, int imageResId, CharSequence text, int length) {
Toast toast = Toast.makeText(context, text, length);
View rootView = toast.getView();
LinearLayout linearLayout = null;
View messageTextView = null;
// check (expected) toast layout
if (rootView instanceof LinearLayout) {
linearLayout = (LinearLayout) rootView;
if (linearLayout.getChildCount() == 1) {
View child = linearLayout.getChildAt(0);
if (child instanceof TextView) {
messageTextView = (TextView) child;
((TextView) child).setGravity(Gravity.CENTER);
}
}
}
// cancel modification because toast layout is not what we expected
if (linearLayout == null || messageTextView == null) {
return toast;
}
ViewGroup.LayoutParams textParams = messageTextView.getLayoutParams();
((LinearLayout.LayoutParams) textParams).gravity = Gravity.CENTER;
// convert dip dimension
float density = context.getResources().getDisplayMetrics().density;
int imageSize = (int) (density * 25 + 0.5f);
int imageMargin = (int) (density * 15 + 0.5f);
// setup image view layout parameters
LinearLayout.LayoutParams imageParams = new LinearLayout.LayoutParams(imageSize, imageSize);
imageParams.setMargins(0, 0, imageMargin, 0);
imageParams.gravity = Gravity.CENTER;
// setup image view
ImageView imageView = new ImageView(context);
imageView.setImageResource(imageResId);
imageView.setLayoutParams(imageParams);
// modify root layout
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
linearLayout.setBackgroundResource(imageResId);
linearLayout.setGravity(Gravity.CENTER);
linearLayout.setHorizontalGravity(Gravity.CENTER);
linearLayout.setHorizontalGravity(Gravity.CENTER);
//addView(imageView, 0);
return toast;
}
}
and this is use of it:
utility.makeImageToast(getApplicationContext(),
R.drawable.your_image,"your_text",Toast.LENGTH_LONG).show();
There's always the possibility to create a custom layout. There was one fact which I disliked about that: It breaks the system default toast UI. This could differ on different platforms and implementations. There's no simple way to use the system default resource so I decided to hack the toast and force an image into it.
Hint: You can get the default resource like this:
Toast.makeToast(context, "", 0).getView().getBackground()
Here's a helper which will display an image in front of the toast message:
Helper.makeImageToast(context, R.drawable.my_image, "Toast with image", Toast.LENGTH_SHORT).show()
I use that to indicate success, info or error. Makes a toast information nicer and more expressive...
(It's worth mentioning that the hack bases on the fact that the internal toast is using a LinearLayout so isn't system and implementation independent. See comments.)
public static Toast makeImageToast(Context context, int imageResId, CharSequence text, int length) {
Toast toast = Toast.makeText(context, text, length);
View rootView = toast.getView();
LinearLayout linearLayout = null;
View messageTextView = null;
// check (expected) toast layout
if (rootView instanceof LinearLayout) {
linearLayout = (LinearLayout) rootView;
if (linearLayout.getChildCount() == 1) {
View child = linearLayout.getChildAt(0);
if (child instanceof TextView) {
messageTextView = (TextView) child;
}
}
}
// cancel modification because toast layout is not what we expected
if (linearLayout == null || messageTextView == null) {
return toast;
}
ViewGroup.LayoutParams textParams = messageTextView.getLayoutParams();
((LinearLayout.LayoutParams) textParams).gravity = Gravity.CENTER_VERTICAL;
// convert dip dimension
float density = context.getResources().getDisplayMetrics().density;
int imageSize = (int) (density * 25 + 0.5f);
int imageMargin = (int) (density * 15 + 0.5f);
// setup image view layout parameters
LinearLayout.LayoutParams imageParams = new LinearLayout.LayoutParams(imageSize, imageSize);
imageParams.setMargins(0, 0, imageMargin, 0);
imageParams.gravity = Gravity.CENTER_VERTICAL;
// setup image view
ImageView imageView = new ImageView(context);
imageView.setImageResource(imageResId);
imageView.setLayoutParams(imageParams);
// modify root layout
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
linearLayout.addView(imageView, 0);
return toast;
}
Toast aa = Toast.makeText(getBaseContext(), "OPEN",Toast.LENGTH_SHORT);
ImageView cc = new ImageView(getBaseContext());
cc.setImageResource(R.drawable.a);
aa.setView(cc);
aa.show();
class CustomToast extends AppCompatActivity {
Button custom_toast;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_toast);
custom_toast = (Button) findViewById(R.id.customToast);
custom_toast.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
LayoutInflater inflater=getLayoutInflater();
View layout=inflater.inflate(R.layout.custom_toast_layout, (ViewGroup) findViewById(R.id.toast_layout_root));
TextView toastTextView=(TextView) findViewById(R.id.toastTextView);
ImageView toastimageview=(ImageView) findViewById(R.id.toastImageView);
toastTextView.setText("Custom toast in android");
toastimageview.setImageResource(R.drawable.ic_launcher_background);
Toast toast=new Toast(CustomToast.this);
toast.setDuration(Toast.LENGTH_SHORT);
toast.setView(layout);
toast.show();
}
});
}
}

When Extending LinearLayout Child Views are not visible

Alright. So I start my activity in Main, grab the FragmentManager and instantiate a Fragment which needs to return a View. OK. So I extended a LinearLayout in order to have something to return. My Activity and Fragment are happy but I am not.
Three LinearLayouts which I create in the parent ViewGroup are there (code below). I have verified this by counting children and by setting the background colors to contrast one another. The parent also changes size depending on how tall I make the children (when I don't declare any LayoutParams on the parent).
public class Mainmenu extends LinearLayout {
private ArrayList<LinearLayout> panes = new ArrayList<LinearLayout>();
private Context context;
private final int
LEFT = 0, CENTER = 1, RIGHT = 2;
public Mainmenu(Context c) {
super(c);
context = c;
setBackgroundColor(Color.WHITE);
setOrientation(HORIZONTAL);
setLayoutParams(
new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT));
for(int i=0;i<=RIGHT;i++){ //Create the (3) Panes
LinearLayout ll = new LinearLayout(context);
ll.setLayoutParams(
new LinearLayout.LayoutParams(300,
LinearLayout.LayoutParams.FILL_PARENT));
switch(i){
case LEFT | RIGHT:
ll.setBackgroundColor(Color.DKGRAY);
default:
ll.setBackgroundColor(Color.BLACK);
}
ll.setOrientation(LinearLayout.VERTICAL);
ll.setVisibility(VISIBLE);
ll.setWillNotDraw(false);
panes.add(i, ll);
addView(ll);
}
LinearLayout.LayoutParams buttons =
new LinearLayout.LayoutParams(100, 50);
buttons.setMargins(15, 5, 5, 0);
TextView tv1 = new TextView(context);
tv1.setText("hello");
tv1.setTextColor(Color.RED);
panes.get(LEFT).addView(tv1, buttons);
Button button = new Button(context);
button.setText("Launch Editor");
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v){
}
});
panes.get(CENTER).addView(button);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
}
}
Nothing is null, all my elements (3 ViewGroups and 2 Views) are present in the tree but not visible. I've tried bringing children to the front through the parent and the children, creating them in different super.methods and invalidating the view in a similarly shotgunned fashion. What's going on? Is it as simple as not having any idea what I'm doing?
The problem is simply because you are overriding onLayout and doing nothing with it. You only need to override this if you want to layout the children yourself (ie, you were designing some unique custom layout). In this case just remove that method, or call super.onLayout.

Categories

Resources