Android getting the view tree - android

I want to get all views inside of an activity. like;
ArrayList<View> views = new Arraylist<>();
views.addAll(getAllViewsFromActivity());
what I want is "getAllViewsFromActivity()" function. I clearly want to get all the views even a single button. But I couldn't find any clear answer.
For the progress, it must be like this:
MainView : getWindow().getDecorView()
- -
RelativeLayout
- -
Button LinearLayout
-
TextView
How can I get this tree in Android programmatically? and also lets assume that I got this tree, Can I also identify the types of them like: view instanceof Button ?

the view you want to get is clear. so you can use the parent view(such as LinerarLayout) to get the children. so you can try this:
int count = parent.getChildCount();
for(int i =0; i< count;i++){
View child = parent.getChildAt(i);
//here you can to chage the view some proper.
//if you only want to change the background color, it belongs to view, don't
// need to cast.
}

Related

Check If a view is completely hidden by other views (not window)

I have two views A and B. View B is completely covered view A which means the bounding rect of view B is more than bounding rect of view A.
The best example I can give is, I have a fixed bottom tabs layout and a RecyclerView with multiple linear layouts. When I scroll, one of the linear layout will be behind the bottom tabs layout.
So, How can I programatically check If view A is completely covered by other views (other views might not be known upfront)?
Is there any possible way to identify this?
Update:
I have tried the solution mentioned here. But it didn't solve my problem. In my case, the view bounds are exactly matching and I want which view is on top.
After lot of struggle, I have found a way to identify if view is overlapped by other views in the following way.
AccessibilityNodeInfo nodeInfo = AccessibilityNodeInfo.obtain();
viewA.onInitializeAccessibilityNodeInfo(nodeInfo);
if (!nodeInfo.isVisibleToUser()) {
// View is not visible to user. This also validates if viewA is overlapped by other views
}
nodeInfo.recycle();
Use the following method it will help you to find view overlapping:-
private boolean isYourViewOverlapping(View firstView, View secondView) {
int[] firstPosition = new int[2];
int[] secondPosition = new int[2];
firstView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
firstView.getLocationOnScreen(firstPosition);
secondView.getLocationOnScreen(secondPosition);
int r = firstView.getMeasuredWidth() + firstPosition[0];
int l = secondPosition[0];
return r >= l && (r != 0 && l != 0);
}

Xamarin dynamically added views using inflater inside loop adding only one entry

I followed the below link to dynamically add a layout multiple times using inflater and AddView()
Is there a way to programmatically create copies of a layout in android?
I used a loop to create multiple entries. But only one entry is comming up which is the result of last loop index
Below is my C# code
I can see only one child inside the parent which is the result of last loop.
What I missed?
var parent = FindViewById<RelativeLayout>(Resource.Id.ParentLayoutWrapper);
for (int i = 0; i < 4; i++)
{
var view = LayoutInflater.Inflate(Resource.Layout.RepeatingLayout, parent, false);
var txtView = view.FindViewById<TextView>(Resource.Id.textViewSample);
txtView.Text = i.ToString()+ " Android application is debugging";
txtView.Id = i;
parent.AddView(view, i);
}
The original post you worked from had a LinearLayout as the parent layout, not a RelativeLayout like you have. When you add a view (or another layout) to a LinearLayout, it gets positioned below (when LinearLayout has vertical orientation) any existing elements in the layout. However, the elements in a RelativeLayout need to use positioning properties to determine where they will be in the RelativeLayout, so every time you add the new layout, RepeatingLayout, since you are not changing the layout options, the view/layout is added over the existing view/layout. So change the parent layout to a LinearLayout in your layout file and then this should work:
LinearLayout parent = FindViewById<LinearLayout>(Resource.Id.parentLayout);
for (int i = 0; i < 4; i++)
{
var view = LayoutInflater.Inflate(Resource.Layout.RepeatingLayout, null);
var tv = view.FindViewById<TextView>(Resource.Id.textViewSample);
tv.Text = i.ToString() + " Android application is debugging";
parent.AddView(view);
}
Trying to do the same with a RelativeLayout as the parent layout highly complicates things unnecessarily.

Compare Drawables on ImageViews

I'm trying to create a One-armed Bandit app.
I have created an animation xml file to go through multiple images. When a button is clicked, the animation stops.
My question is how to compare the picture that one animation stopped on with that of another? So far I've tried something like this:
if(wheel1.getBackground().getConstantState().equals(wheel2.getBackground().getConstantState())) matches++;
Any help is appreciated.
you must be starting the animation with .animationStart()
just use .onAnimationStop() and it will trigger the event automatically.
A View should not maintain application logic, the controller (your hosting Activity or Fragment) should.
That said, to achieve what you want use View.setTag() to apply a logical description of each View to it.
Then when stopping animation, loop through all Views you have and get their position on screen, get the Views mostly visible in each column of your bandit machine and compare their tags (View.getTag())
for example, if the items animate vertically use below method to determine where the bandit stopped.
//the area where to compare views
int BOUND_TOP, BOUNT_DOWN;
//your content view
ViewGroup rootLayout;
//method to get information about what is visible
public List<Object> getVisibleViewTags() {
List<Object> list = new LinkedList<>();
int count = rootLayout.getChildCount();
for (int pos = 0; pos < count; pos++) {
View child = rootLayout.getChildAt(pos);
float translationY = child.getTranslationY();
if (translationY > BOUND_TOP && translationY < BOUND_DOWN) {
list.add(child.getTag());
}
}
return list;
}
Now you just need to attach information about a view as tag to it.
example:
view.setTag("view_apples");
or
view.setTag("view_bananas");

How to make a set of views invisible in android

I'm trying to make a set of views (that include several textviews and buttons - all in different parent layouts, but in the same activity) invisible if a particular condition is evaluated to false.
The conventional way to do that would be:
findViewById(R.id.myview).setVisibility(View.INVISIBLE);
My question is, will I have to do this for all the views one by one that I want to be invisible, And then toggle them back when I want them visible?
Or, is there a way to avoid the code-repetition?
If the Views are in different parents , you can't do it directly, but you can implement a method to change the visibility of a bunch of Views if you want to keep your code clean:
List<View> relatedViews = new ArrayList<>();
// ...
relatedViews.add(view1);
relatedViews.add(view2);
relatedViews.add(view3);
// ...
changeVisibility(relatedViews, View.INVISIBLE);
// ...
private void changeVisibility(List<View> views, int visibility) {
for (View view : views) {
view.setVisibility(visibility);
}
}
As a side note, you may want to change the visibility to View.GONE instead of View.INVISIBLE so it doesn't take any space in the layout.
you can use something like this. It's not the most elegant solution but works.
The idea is give to each view that you want to hide a same content description, because in the same layout you can not use same id for multiple view. With the same content description you can find all views in your layout and hide them.
That's an example considering the first layout as Linear. You can change obviously ;)
public class TestActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
LinearLayout rootLayout = (LinearLayout)findViewById(R.id.rootLayout);
int childcount = rootLayout.getChildCount();
for (int i=0; i < childcount; i++){
View v = rootLayout.getChildAt(i);
if(v.getContentDescription() != null && v.getContentDescription().equals("invisibleView")){
v.setVisibility(View.INVISIBLE);
//I suggest you to use GONE instead of INVISIBLE to remove the space of the view
}
}
}
}
in your xml give to the object that you want to hide this property
android:contentDescription="invisibleView"
Use varargs method for show or hide multiple views.
for example if you have views like view1, view2.....etc
then just call setVisibility(View.VISIBLE,view1,view2)
public static void setVisibility(int visibility, View... views){
for (View view : views){
view.setVisibility(visibility);
}
}

Successive ImageViews in a loop

I am working on an app where I have to set up a number of drawables. The number depends on the user input.
I therefore need to use a loop there I set up as many successive images as the user have chosen in one or several rows.
I can not find out how. I know how to put the images in an array and use
(ImageView) findViewById(R.id.img)
to set them up. But I want to create this successive ImageViews in the loop.
try to make a combinatino of LinearLayout and LayoutInflater (to inflate custom views)
LinearLayout layout = (LinearLayout) findViewById(R.id.linear);
for (int i = 0; i < userChoice; i++)
{
LayoutInflater li = LayoutInflater.from(yourContext);
View customView = li.inflate(R.layout.image_holder, this);
// (In case you need to use the image) ImageView yourImage = (ImageView)customView.findViewById(R.id.image_view);
layout.addView(customView);
}
where:
userChoice is the number the user has choose
layout is linear layout inside your main.xml (or the root element itself)
image_holder is an xml with ImageView inside it

Categories

Resources