I have an android app with different graphical elements (ImageViews). Some ImageViews can be changed by pressing them, and then they will show another graphic. I have two systems for this, and my problem is the same for both.
In the first case I have layered two ImageViews on top of each other, and then I call each of them and set their visibility programmatically. In the second case I use the function "setImageResource" and change between different drawables.
In both cases I have the problem that the app quite often seems to "hickup" and for a split second show the wrong 'other' graphical element for each element that has a graphical alternative. It shows the wrong graphic for a split second and then jumps back to the correct graphic.
I can not find anything about this online, anyone here that recognizes this issue or have any clues as to what the problem might be?
relevant code:
public void setLight1(int bo) // changes a graphical element by drawable
{
ImageView vw = (ImageView) findViewById(R.id.light_1);
if (bo > 0)
vw.setImageResource(R.drawable.lampaljus);
else
vw.setImageResource(R.drawable.lampaslockn);
}
private void setStickMid(int stick) // changing between two layered imageViews
{
switch (stick)
{
case 1:
ImageView vw_1 = (ImageView) findViewById(R.id.stick_1_up);
vw_1.setVisibility(View.INVISIBLE);
ImageView vw_2 = (ImageView) findViewById(R.id.stick_1);
vw_2.setVisibility(View.VISIBLE);
break;
// the rest of the switch statement omitted, just more of the same
Of the top of my head, try these:
Move all the findViewById code to onCreate of your activity, to avoid calling it multiple times.
How big are the assets R.drawable.lampaljus, R.drawable.lampaslockn and others, dimensions wise. Because trying to load high resolution drawables, especially PNGs, will take a lot of memory.
But I can provide a better solution, if you can post the whole xml and Activity/Fragment code.
Related
Instead of moving views in a current layout, I was wondering if i could instead load a different layout whilst the program is running.
For example in the on create i would use:
setContentView(R.layout.layout1);
and then in an on click listener i would use:
setContentView(R.layout.layout2);
I say this since I am using a custom dialogue which prevents me from producing a dialog to overwrite it. I have attempted it but so far have only received errors. I would really like to know if this is possible.
This is possible, but risky and not recommended for a final product. The problem is, you cannot access already defined views once you have switched views. You need to assign them all again for the new layout. So once you switch the content view, re-initialize all of your views and anything that references the old layout. Calling a view from the old layout will cause a crash or error message.
Like CodeMagic said, it is best to use fragments and the FragmentManager for this. And really, this is not a stable way to produce good code. I recommend using separate fragments and using backstacks and such so that not only will your game work, but you can easily navigate back to the original fragment, rather than use makeshift code that may barely work.
After setContentView(R.id.yourLayout) is called, you need to re-instantiate all of your other views. So like say you used an ImageView view to show the color changes, well you need to instantiate that ImageView after you setContentView(R.id.yourLayout) so that it pulls from the new layout, and does not reference to the original layout.
Example:
ImageView imageView;
public void onCreate(Bundle b){
super.savedInstanceState(b);
setContentView(originalLayout);
//Instatiate all of your original Views.
imageView = (ImageView) R.id.yourImageView;
}
public void onButtonClick(View){
setContentView(newLayout);
imageView = (ImageView) R.id.yourNewImageView;
//All other views
}
If you need an example of the fragment manager solution go here: https://developer.android.com/training/basics/fragments/creating.html
and look through some of their examples on how to properly do what you are trying to do.
I am facing a weird problem using robotium, when i use, solo.getCurrentViews() I get the views in a screen. But for some activities thought the views are loaded, i cannot see the views on the screen, they are hidden and some user actions needed to show them. For example, in Amazon home screen, i have to scroll through the product list, only 3 products are shown in the initial screen. But solo.getCurrentViews() loads all the product views. Now if say I click TextViews other than the three text views that are shown on the screen I get an error and the application exits. So, i think I have to somehow examine whether the textview is currently visible on the screen or not. This goes for all view objects.
Robotium loads all the views, but clicking views which are not currently visible causes error.
The Solo.getCurrentViews() will return all the views.
You can use: RobotiumUtils.removeInvisibleViews(solo.getCurrentViews()) for filtering the visible views.
OR you can filter the visible TextViews by yourself using the following code.
public ArrayList<TextView> getFilteredTextViews()
{
ArrayList<TextView> textViewList = solo.getCurrentViews(TextView.class);
ArrayList<TextView> filteredTextViewList = new ArrayList<TextView>();
for (TextView textview : textViewList ) {
if (textview != null && textview.isShown())
{
filteredTextViewList .add(view);
}
}
return filteredTextViewList;
}
You could cast every view to its class (or to android.view class!) and then check its "VISIBLE" property.
For TextView:
TextView tv = (TextView) solo.getCurrentViews().get(i);
int visible = tv.VISIBLE;
0 - Visible on screen; the default value.
1 - Not displayed, but taken into account during layout (space is left for it).
2 - Completely hidden, as if the view had not been added.
Do the same for all the controls.
just wanted to let you know, I solved the problem by using view.isShown() method check.
I have a very frustrating problem and I don't have an idea what is wrong.
I build simple XML which contains only GridView. This gridview should show images (ImageView) downloaded from specific urls which I retreive with my code.
So the idea of this APP is only to download images from URLS and show those images in GridView. First I must say that I'm using Universal Image Loader library. First please look at my getView code:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView iv;
if(convertView == null) {
iv = new ImageView(MyActivity.this);
iv.setLayoutParams(new GridView.LayoutParams(size,size));
iv.setScaleType(ImageView.ScaleType.CENTER_CROP);
Log.d("APP", "convertView is NULL");
}
else {
iv = (ImageView) convertView;
Log.d("APP", "convertView is NOT null");
}
loader.displayImage(URLS.get(position), iv);
return iv;
}
PROBLEM:
Code above works, and it shows images in GridView. But when I scroll down, I see that:
All images were downloaded (Even those images who are not visible )
When i scroll back up I see that image which was in place 0, is in place 1 and it has been downloaded again. When I scroll back down, images switched positions again. Scrolling back up, I see again images are switching places again ( and downloading again). This goes infinite.
HOW I SOLVED THIS PROBLEM:
I solved this problem by NOT checking if convertView variable is null. Actually I ommited if/else clause.
I used cache in memory = true. So downloading stops and images are in place for ever.
So why I'm asking for help? Mainly because i know that i should not ommit if/else clause for performance reasons. I don't want to mess with users memory and I would like to bring them fast and reliable user experience. Also i would like to know what could be wrong.
Thank you for help. Much appriciated.
Loader needed some time to load picure in ImageView. Because you reuse view for different images you can see a previous image in the view while new image is loading. You can set resetViewBeforeLoading(true) in DisplayImageOptions for avoid this effect.
Also you can use disk cache to avoid downloading images every time from the network. Also limit size of memory cache and set other settings, but I think memory cache is useful, it improves user experience.
And don't forget to use setOnScrollListener(new PauseOnScrollListener(loader, true, true)) to avoid lags on scrolling.
GridView recycles list items for performance purposes. So when you are scrolling, the list items are getting recycled in different places and then your code is re-populating them. Sometimes this lags for images.
I'd recommend using a library that handles this sort of thing like Picasso.
I was having the exactly same problem as you, and didn't want to disable convertView checking either.
My solution was to increase the memory cache size in ImageLoaderConfiguration.
Before, i used to use it like this:
.memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024))
So I changed it to:
.memoryCache(new UsingFreqLimitedMemoryCache(10 * 1024 * 1024))
I don't know if 10*1024*1024 is too much or it will cause any problems, but it seems to have fixed the problem to me and i haven't had any problems until now.
First off, I've been reading this site for years now and it's helped me out of a bind several times, so thank you to the community here who contribute, and hopefully you can help me with a problem of my own.
I'm just starting out with Android development at my company and I'm attempting to port an existing application from Windows Mobile C# to Android Java. Most of it is going smoothly, but one area I'm having some difficulty is the UI.
The Windows Mobile application reads in a survey specification from a file when the WinForm is created. In the case of a closed-ended question (such as multiple choice), I need to populate the screen with either a CheckBox or RadioButton control for each applicable answer in the spec. Creating the layout and controls required is no problem, but we also have a requirement that the screen does not scroll. Because of this our software needs to be able to calculate the best possible fit within the available screen space without overflow (ie. 1-4 columns used for display) before it's displayed
I have written my UI (at least the layout) as both an XML resource or Java code, but because methods like GetWidth() and GetHeight() return 0 in onCreate(), I haven't yet been able to add this required pre-processing.
All of this needs to happen prior to the screen showing. If anyone can point me in the right direction, I would be immensely grateful.
When Android builds the UI from a layout, the root of the layout requests all of it's children to report their desired size by calling onMeasure(). It does this is a recursive fashion bottom up. if necessary, the parent view will then set the size of the children so that they fit. As you have found, this measuring pass is not finished during onCreate().
Try a global layout listener.
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// inflate your main layout here (use RelativeLayout or whatever your root ViewGroup type is
LinearLayout mainLayout = (LinearLayout ) this.getLayoutInflater().inflate(R.layout.main, null);
// set a global layout listener which will be called when the layout pass is completed and the view is drawn
mainLayout.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
// measure your views here
}
}
);
setContentView(mainLayout);
I have a calendar view which is based on a GridView.
It basically a school tests calendar. When you click on one of the cells you can see information about the test. In some phones the TextView containing the information is not shown, or partially shown because the calendar catches the whole screen.
I decided that if the TextView is cut off, I want to show an AlertDialog instead of showing the information on the screen.
The problem is, I don't know how to check if the TextView is cut off.
Here are 2 pictures to show you what I mean:
Thats how it should look:
Thats how it sometimes looks:
Thanks!
You can find out what is screen size category (small, medium ...) see here, and then can have different behavior for different screen sizes. In your case you can show AlertDialog in case of small or medium size screens.
I have found a solution on my own.
I checked the height of the GridView and the height of the TextView.
then,
if (gridViewHeight + textViewHeight >= containingLinearLayoutHeight)
it means that the Text is cut off.