Titanium add multiple views to a scrollview at once? - android

Is it possible to add multiple views to a ScrollView in titanium? So lets say I have the following:
var scrollView = Titanium.UI.createScrollView();
var views = [];
var view1 = Titanium.UI.createView();
views.push(view1);
var view2 = Titanium.UI.createView();
views.push(view2);
scrollView.add(views);
window.add(scrollView);
Would the above work? If not what needs to be done in order for it to work?

According to their documentation this shouldn't work. (Never tried before.) But you could do something like this:
views.forEach(function(view) {
scrollView.add(view);
});

I know this is a bit late, but its the solution I used to this problem, hopefully its still helpful. Basically, it involves setting the opacity of the scrollView to 0 until you are done loading. This means that rather than the rows appearing 1 at a time, they all appear simultaneously, and that this can be run in the background while your program/user does other stuff. Please note that it only works if the scrollView is empty - its not a good solution for adding rows to a scrollView that already has stuff in it:
var sView = Titanium.UI.createScrollView({
//Whatever properties you need for your scrollView
opacity: 0,
});
//childViews is an array of all the stuff you'd like to add to sView
childCount = childViews.length
//Add a postlayout event to the last childView - this will automatically set the opacity to 1 when the last child is loaded
childViews[childCount - 1].addEventListener('postlayout', function showScrollView(e){
this.parent.setOpacity(1);
this.removeEventListener(showScrollView);
});
//Iteratively add each view in the array to the sView
for (var x = 0; x < childCount; x++) {
sView.add(childViews[x]);
}
window.add(sView);

Related

Android getting the view tree

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.
}

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.

Flow textview around image

I've spent hours looking for answer and have really no idea how to solve it. So let's get down to business:
There is an image and a TextView and I need to flow the TextView around the ImageView like this:
First possible solution woult be to use https://github.com/deano2390/FlowTextView but it's not extending TextView so this library is not suitable for me for number of reasons.
Second solution would be to use LeadingMarginSpan.LeadingMarginSpan2 span but it affects on each paragraph for each n lines inside the text (like in this answer -> How to layout text to flow around an image), so I get smth like this:
But I wanted to set margin only for first n lines! Then I decided to implement LeadingMarginSpan.Standart and create a counter and increment it in getLeadingMargin(first: Boolean): Int function invocation. When the counter reach the desirable value, the function returns 0 as a margin width. And there is a fail again! Instead of filling the TextView lines, the text just moved left and didn't spread to the end of the view!
UPD: Yes, I've used onGlobalLayoutListener in here
Well, googling for another solution I found this answer https://stackoverflow.com/a/27064368/7218592
Ok, I've done everything as described and implemented the code:
//set left margin of desirable width
val params: RelativeLayout.LayoutParams = RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
params.leftMargin = holder.imageContainerHeight!!
params.addRule(RelativeLayout.BELOW, holder.mNumberAndTimeInfo!!.id)
holder.mCommentTextView!!.layoutParams = params
if (holder.commentTextViewOnGlobalLayoutListener != null)
holder.mCommentTextView!!.viewTreeObserver.removeOnGlobalLayoutListener(
holder.commentTextViewOnGlobalLayoutListener)
//add onGlobalLayoutListener
holder.mCommentTextView!!.viewTreeObserver.addOnGlobalLayoutListener(
if (holder.commentTextViewOnGlobalLayoutListener != null)
holder.commentTextViewOnGlobalLayoutListener
else CommentTextViewOnGlobalLayoutListener(holder,
SpannableString(HtmlCompat.fromHtml(
mView.getActivity(), commentDocument.html(), 0,
null, SpanTagHandlerCompat(mView.getActivity())))))`
My OnGlobalLayoutListener looks like this: `
class CommentTextViewOnGlobalLayoutListener(
val holder: CommentAndFilesListViewViewHolder, val commentSpannable: Spannable) :
ViewTreeObserver.OnGlobalLayoutListener {
val LOG_TAG: String = CommentTextViewOnGlobalLayoutListener::class.java.simpleName
override fun onGlobalLayout() {
holder.mCommentTextView!!.viewTreeObserver.removeGlobalOnLayoutListener(this)
//when textview layout is drawn, get the line end to spanify only the needed text
val charCount = holder.mCommentTextView!!.layout.getLineEnd(Math.min(
holder.mCommentTextView!!.layout.lineCount - 1,
CommentLeadingMarginSpan.computeLinesToBeSpanned(holder)))
if (charCount <= commentSpannable.length) {
commentSpannable.setSpan(CommentLeadingMarginSpan(holder),
0, charCount, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}
//set the left margin back to zero
(holder.mCommentTextView!!.layoutParams as RelativeLayout.LayoutParams).leftMargin = 0
holder.mCommentTextView!!.text = commentSpannable
}
}
`
Well, it works. But how terrible it works! As I'm using view holder pattern I have to hold a variable to the listener and remove if it is not been called and successfully removed because onGlobalLayout function wasn't called in time! And it is called too late, so you need to wait about 300 ms and then watch all the "reconstruction" of the TextView and it looks disgustingly!
So, my question is:
How to make margins for first n lines in TextView, before it's been drawn on UI?
This is more a suggestion that will only work with a little trial and error
This code uses a multi line Edit Text
btnPrint.setOnClickListener {
val str = """
One
Two
Three
Now click Action Button Custom SB
""".trimIndent()
etNews.setText(str)
}
Play with the One Two values indent and trimIndent has other properties available

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");

Creating and removing views in java

I am creating lots of view dynamically and adding them to my RelativeLayout. I need to keep track of all of these views so I can remove them later, so I add them is an ArrayList. But when I try to remove them all from the layout, they are not all removed.
ArrayList<LineView> lineChain = new ArrayList<LineView>();
LineView linkLine;
RelativeLayout wrapper; // Removed params etc.
// Later on in code
// This occurs many times
linkLine = new LineView(getApplicationContext());
wrapper.addView(linkLine, rlp);
lineChain.add(linkLine);
This is what I do when I try to remove all of the views. This only happens once:
for (int i = 0; i <= lineChain.size() -1; i++) {
LineView lv = lineChain.get(i);
wrapper.removeView(lv);
lineChain.remove(i);
}
As I said, the problem is that not all the lines are removed - I havn't managed to work out the pattern for which are deleted and which aren't.
You have a bug in your remove code.
for (int i = 0; i <= lineChain.size() -1; i++) {
LineView lv = lineChain.get(i);
wrapper.removeView(lv);
lineChain.remove(i);
}
The documentation for ArrayList.remove(int) function says:
Removes the element at the specified position in this list. Shifts any
subsequent elements to the left (subtracts one from their indices).
When you remove an item at an index i, all the remaining elements are shifted to the left. So for example if you remove an element at position 0. The element at position 1 is shifted to position 0 and is never removed (because you are incrementing i).
The your code to this:
while (!lineChain.isEmpty()) {
LineView lv = lineChain.get(0);
wrapper.removeView(lv);
lineChain.remove(0);
}
I think that the problem is while removing the element from the List after the cycle.
You should do something like this:
for (LineView lv : lineChain) {
((RelativeLayout) namebar.getParent()).removeView(namebar);
}
If you want to get rid of all the elements, just reset the list
lineChain = new ArrayList<LineView>()

Categories

Resources