Strange XML layout bug when targeting Android 4.3 - android

I'm experiencing a really peculiar bug with an XML layout file when building my application while targeting API level 18. It doesn't happen with API level 17. I'm running the application on Android 4.3 devices, and the bug persists on all three devices.
Here's what it looks like:
API 17 (correct):
API 18 (incorrect):
I'm using the StickyGridHeaders library, and the following is my getHeaderView() method:
#Override
public View getHeaderView(int position, View convertView, ViewGroup parent) {
RowItem holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.seasons_row_header, parent, false);
holder = new RowItem();
holder.title = (TextView) convertView.findViewById(R.id.seasonTitle);
holder.episodeCount = (TextView) convertView.findViewById(R.id.episodeCount);
convertView.setTag(holder);
} else {
holder = (RowItem) convertView.getTag();
}
if (seasons.get(position).equals("00")) {
holder.title.setText(R.string.stringSpecials);
} else {
holder.title.setText(getString(R.string.showSeason) + " " + seasons.get(position));
}
int size = seasonEpisodeCount.get(Integer.valueOf(seasons.get(position)));
holder.episodeCount.setText(size + " " + getResources().getQuantityString(R.plurals.episodes, size, size));
convertView.setClickable(false);
convertView.setFocusable(false);
return convertView;
}
Here's the layout XML file:
<?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="wrap_content"
android:background="#80000000"
android:padding="#dimen/list_padding" >
<TextView
android:id="#+id/seasonTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginRight="#dimen/list_padding"
android:layout_toLeftOf="#+id/episodeCount"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textIsSelectable="false"
android:textStyle="bold" />
<TextView
android:id="#+id/episodeCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/seasonTitle"
android:layout_alignParentRight="true"
android:layout_alignTop="#+id/seasonTitle"
android:gravity="bottom"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textIsSelectable="false" />
</RelativeLayout>
Does anyone else have a clue as to what's going on here? I find it really strange that it's working when targeting API level 17 and not working when targeting the latest API level (18).
Update:
This is what it looks like in the visual layout editor with Android 4.3 as the target:

I managed to solve the issue myself.
Like I said, I am using the StickyGridHeaders library and referencing it in my application. It appears that the library was targeting API level 17. I changed it to level 18, compiled and ran the application - great success!
In conclusion: Make sure your application and libraries target the same API level.

I have the same issue, too.
My experiences have shown that crossed alignments are the reason of the problem (TextView #+id/seasonTitle has the property android:layout_toLeftOf="#+id/episodeCount"; TextView #+id/episodeCount has the properties android:layout_alignBottom="#+id/seasonTitle" and layout_alignTop="#+id/seasonTitle". One of the Layouts won't refresh its childs correct.
Changing the Layout-XML that crossed alignments are prevented, you no longer have this problem.

I have the same issue :
a ListView with a white background
each child has a View with a gray background and width and height to match_parent, within a RelativeLayout
on API 17, every is OK
on API 18+, the ListView is white
instead of setting a fixed height, I put a min_height to the View, and the problem is (temporary) solved!
hope it helps

Related

ConstrainLayout ConstraintSet - not working properly with Start/End constrains

Looks like ConstraintSet is finding hard to cope up with Start/End constrains.
This example is taken from Google samples.
Github: android-ConstraintLayoutExamples
When you replace Left & Right constrains with Start & End, ConstraintSet - not working properly, It's working with Left/Right constrains only.
For example replace
layout_constraintStart_toStartOf with layout_constraintLeft_toLeftOf & replace
layout_constraintEnd_toEndOf with layout_constraintRight_toRightOf
in following files:
constraintset_example_main.xml
constraintset_example_big.xml
Behaviour:
onClick of image:
private ConstraintSet mConstraintSetNormal = new ConstraintSet();
private ConstraintSet mConstraintSetBig = new ConstraintSet();
public void toggleMode(View v) {
TransitionManager.beginDelayedTransition(mRootLayout);
mShowBigImage = !mShowBigImage;
applyConfig();
}
private void applyConfig() {
if (mShowBigImage) {
mConstraintSetBig.applyTo(mRootLayout);
} else {
mConstraintSetNormal.applyTo(mRootLayout);
}
}
By default Android studio uses start/ end constrains hence it's I want to know root cause and possible fix.
Or Is this a bug with ConstrainSet itself?
This does look like a problem with ConstraintSet, but let's see. The following analysis is based upon the sample project with the link that you supplied.
In the sample project, I have updated ConstraintLayout to the most recent version:
compile 'com.android.support.constraint:constraint-layout:1.1.0-beta5'
I did this in case we are trying to track down an issue that has already been addressed. I also updated the layout constraintset_example_big and replaced all left/right constraints with start/end constraints as follows:
constraintset_example_big.xml
<android.support.constraint.ConstraintLayout
android:id="#+id/activity_constraintset_example"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="#+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="24dp"
android:layout_marginStart="24dp"
android:layout_marginTop="24dp"
android:onClick="toggleMode"
android:scaleType="centerCrop"
android:src="#drawable/lake"
app:layout_constraintDimensionRatio="h,16:9"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:contentDescription="#string/lake_tahoe_image" />
<TextView
android:id="#+id/textView9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/lake_tahoe_title"
android:textSize="30sp"
app:layout_constraintStart_toStartOf="#+id/imageView"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="#+id/imageView" />
<TextView
android:id="#+id/textView11"
android:layout_width="0dp"
android:layout_height="0dp"
android:text="#string/lake_discription"
app:layout_constraintStart_toStartOf="#+id/textView9"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="#+id/textView9"
app:layout_constraintEnd_toEndOf="#+id/imageView"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="16dp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintVertical_bias="0.0" />
</android.support.constraint.ConstraintLayout>
With these changes in place, this is what we see.
This is clearly not right. It is supposed to look like this after the transition.
After some debugging, I tracked the issue down to this line in ConstraintSetExampleActivity.java:
mConstraintSetBig.load(this, R.layout.constraintset_example_big);
ConstraintSet#load() seems to be straightforward, but if we replace the code above with an explicit inflation of the layout followed by a clone of the ConstraintSet on the inflated layout as follows:
// mConstraintSetBig.load(this, R.layout.constraintset_example_big);
ConstraintLayout cl = (ConstraintLayout) getLayoutInflater().inflate(R.layout.constraintset_example_big,null);
mConstraintSetBig.clone(cl);
We see this behavior in the app which is much better.
So my takeaway is that ConstraintSet#load() has a problem with start/end constraints. The workaround is to inflate the ConstraintLayout then do a clone.
ConstraintSetExampleActivity#onCreate()
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.constraintset_example_main);
mRootLayout = (ConstraintLayout) findViewById(R.id.activity_constraintset_example);
// Note that this can also be achieved by calling
// `mConstraintSetNormal.load(this, R.layout.constraintset_example_main);`
// Since we already have an inflated ConstraintLayout in `mRootLayout`, clone() is
// faster and considered the best practice.
mConstraintSetNormal.clone(mRootLayout);
// Load the constraints from the layout where ImageView is enlarged.
// Toggle the comment status on the following three lines to fix/break.
// mConstraintSetBig.load(this, R.layout.constraintset_example_big);
ConstraintLayout cl = (ConstraintLayout) getLayoutInflater().inflate(R.layout.constraintset_example_big,null);
mConstraintSetBig.clone(cl);
if (savedInstanceState != null) {
boolean previous = savedInstanceState.getBoolean(SHOW_BIG_IMAGE);
if (previous != mShowBigImage) {
mShowBigImage = previous;
applyConfig();
}
}
}
This issue is known and will be fixed in the 1.1 beta 6 release
https://issuetracker.google.com/issues/74253269
For those who faces issues like constraint set clone not working properly, my layout was not updating to new constraints when i called clone and applyTo methods after an api call, turns out it was due to a loading dialog i showed before the change that caused the error.

Android data binding on android 4.1 doesn't work

https://developer.android.com/topic/libraries/data-binding/index.html:
The Data Binding Library offers both flexibility and broad
compatibility — it's a support library, so you can use it with all
Android platform versions back to Android 2.1 (API level 7+).
But when I'm trying to use data binding in my project it just doesn't work, there's no reaction for that, TextViews are empty, onClick bindings just desn't workx, please help me I need support for android 4.1, google tells that it should to be possible even for 2.1, I don't think they're lying :/
Example code:
<FrameLayout
android:layout_width="130dp"
android:layout_height="0dp"
android:layout_weight="15"
android:layout_gravity="center"
android:background="#color/colorSecondary"
android:clickable="true"
android:onClick="#{ () -> view.save() }" <!-- binding -->
android:layout_margin="15dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="#string/save"
android:textAllCaps="true"
android:textColor="#color/colorForeground"/>
</FrameLayout>
Code behind:
public void save()
{
if(viewModel.car.save() != 0) //If you put breakpoint here it won't be hit
getLayoutRoot().goBack();
}
Code works fine on API level 19+
I found the problem, I was returning false on PreBind event when SDK_INT < KITKAT in my automatic transitions function:
binding.addOnRebindCallback(new OnRebindCallback()
{
#Override
public boolean onPreBind(ViewDataBinding binding)
{
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
return false; //should be true, that's it
ViewGroup sceneRoot = (ViewGroup) binding.getRoot();
TransitionManager.beginDelayedTransition(sceneRoot, transition);
return true;
}
});

TextInputLayout disable animation

I am using the TextInputLayout to implement the floating label pattern. However, when I set the text programmatically on the EditText, I still get the animation of the label moving from the control to the label - the same as if the user had clicked it.
I don't want this animation though if I set it programmatically, is this possible? Here is my code:
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/root">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/editText1" />
</android.support.design.widget.TextInputLayout>
And in the onResume I do:
TextInputLayout root = (TextInputLayout)findViewById(R.id.root);
EditText et = (EditText)root.findViewById(R.id.editText1);
et.setText("Actual text");
root.setHint("Hint");
As of v23 of the support libs, a setHintAnimationEnabled method has been added. Here are the docs. So you can set this new attribute to false in the XML and then programmatically set it to true after you've finished populating the editText. OR simply handle it all programmatically, as needed.
So in your example, that would become something like:
TextInputLayout root = (TextInputLayout)findViewById(R.id.root);
root.setHintAnimationEnabled(false);
root.setHint("Hint");
EditText et = (EditText)root.findViewById(R.id.editText1);
et.setText("Actual text");
// later...
root.setHintAnimationEnabled(true);
Of course, be sure to open your Android SDK Manager and update your Android Support Library to rev. 23 and Android Support Repository to rev. 17 first and then add that to build.gradle via:
compile 'com.android.support:design:23.0.0'
Note that as the Design library depends on the Support v4 and AppCompat Support Libraries, those will be included automatically when you add the Design library dependency.
Put this attribute app:hintEnabled="false" here:
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:hintEnabled="false">
It works for me
I have found an (unwieldy) way to do that. Looking into the source code of the TextInputLayout, I've discovered that the only occasion when the class doesn't update it's hint with animation is when the EditText is added to it. The only obstacle is that you can only add it once to the layout, once it is there, it will permanently be tied to it, and there's no way to remove it.
So here's the solution:
Create a TextInputLayout without the EditText. Programmatically or via XML inflation - doesn't matter, but it has to be empty.
Create the EditText and set its text to whatever you need.
Add the EditText to the TextInputLayout.
Here's an example:
TextInputLayout hintView = (TextInputLayout) findViewById(R.id.hint_view);
hintView.setHint(R.string.hint);
EditText fieldView = new EditText(hintView.getContext());
fieldView.setText(value);
hintView.addView(fieldView);
Unfortunately, if you want to set the text to something else without the animation, you will have to repeat all these steps, except for the creation of a new EditText (the last one can be reused). I hope Google can fix this, because it is really inconvenient, but for now that's what we have.
Update: this is, thankfully, fixed in the design library 23.0.0, so just update to that version, and you won't have to do all this crazy stuff.
You can disable it by using
app:hintAnimationEnabled="false"
I will give you simple code and you don't have to make all programmatically just add xlm attribute and that's all.
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:hintAnimationEnabled="true"
app:passwordToggleEnabled="true">
<EditText
android:id="#+id/password_field_activity_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:hint="#string/password"
android:inputType="textPassword"
android:padding="10dp"
android:textColor="#color/color_holo_light_gray"
android:textColorHint="#color/color_holo_light_gray"
android:textCursorDrawable="#drawable/cursor_drawable" />
</android.support.design.widget.TextInputLayout>
Hope it will help
I wrote a small method to run after loading the view hierarchy that disables animation on initial display but enables it after wards. Add this to your Base Activity/Fragment/View and it will solve it issue.
private void setTextInputLayoutAnimation(View view) {
if (view instanceof TextInputLayout) {
TextInputLayout til = (TextInputLayout) view;
til.setHintAnimationEnabled(false);
til.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override public boolean onPreDraw() {
til.getViewTreeObserver().removeOnPreDrawListener(this);
til.setHintAnimationEnabled(true);
return false;
}
});
return;
}
if (view instanceof ViewGroup) {
ViewGroup group = (ViewGroup) view;
for (int i = 0; i < group.getChildCount(); i++) {
View child = group.getChildAt(i);
setTextInputLayoutAnimation(child);
}
}
}
I check out ideas about support library v23 - it's does not work yet :( Programmatically inserting of EditText is unusable if you wish to use databinding labrary
In result of research I found solution without full disabling of animation:
layout.xml
<android.support.design.widget.TextInputLayout
android:id="#+id/text_til"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/product_title_placeholder">
<android.support.design.widget.TextInputEditText
android:id="#+id/text_tiet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#={bindingText}"/>
</android.support.design.widget.TextInputLayout>
Activity.java
final TextInputLayout textLayout = (TextInputLayout) findViewById(R.id.text_til);
if(binding.getText() != null) {
// disable animation
textLayout.setHintAnimationEnabled(false);
final TextInputEditText editText = (TextInputEditText) titleLayout.findViewById(R.id.text_tiet);
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean b) {
// enable animation after layout inflated
textLayout.setHintAnimationEnabled(true);
editText.setOnFocusChangeListener(null);
}
});
}
// manage focus for new binding object
((View)textLayout .getParent()).setFocusableInTouchMode(binding.getText() == null);
It's looks not prettily, but it works :)

Android: requestLayout() improperly called

The following error occurs when I attempt to inflate a layout within a ListView:
requestLayout() improperly called by android.widget.TextView{...} during layout: running second layout pass
I am attempting to inflate a layout within a ListView as follows:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
LayoutInflater inflater = (LayoutInflater) musicActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_item, parent, false);
...
}else{...}
}
The layout being inflated can look as simple as the following, and will still produce the error
<TextView
android:id="#+id/txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="#dimen/txt_size"/>
I have looked into similar questions, and no solutions found seem to work Question 1, Question 2, Question 3.
Does anyone know what causes this type of error? Any troubleshooting advice? For more context, this ListView is displayed within a Fragment within a ViewPager
UPDATE
Here is the full XML Layout (minus a bunch of attributes), that still results in the problem
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/txt1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/txt2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/txt3"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/txt4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
Based on this, I would think the XML itself is not a problem, unless it has to do with the fact that I am using a ViewPager and Fragments
This issue seems to be a bug in the android implementation, please see: https://code.google.com/p/android/issues/detail?id=75516
Activating the fast scroll feature of a ListView in your code via ListView.setFastScrollEnabled(true) will trigger this bug and you'll start seeing the
requestLayout() improperly called by android.widget.TextView{...}
during layout: running second layout pass
message in your console.
This bug must have been introduced in one of the KitKat (4.4.x) updates, as I've not seen it with the initial KitKat (4.4.0) release. Apart from the ugly console spamming with the debug message from above, there seem to be no other impacts (maybe performance in some cases, which I haven't tested).
Cheers
PS: it's not the first time that the fast scroll feature is bugged, e.g. https://code.google.com/p/android/issues/detail?id=63545, 63545 was fixed in KitKat 4.4.3 but 75516 poped up thereafter --> seems to be a vexed subject for google ;-)
EDIT May 12 2015:
I updated my Nexus 7 to Android 5.1 some minutes ago (was Running 5.0 before) and stopped seeing this issue in this new version. As the appearance of the FastScroll indicator also changed in 5.1, I assume that google fixed this issue or at least commented out those ugly lines that spammed the console...
75516 & 82461 are still 'unresolved', but I guess that those refer to the same issue, that's now resolved in 5.1.
The problem is that while the method getView() of your adapter is displaying your layout some other code is trying to access this view to display it, resulting in a collision.
Note that some methods, that maybe you don't take care of (like setScale(), setTypeFace()) indeed call requestLayout(), so it would be interesting what you are doing after your inflate statement.
For me this issue was occurring upon a setLayoutParams() call. The solution was posting a runnable on the looper:
// java
imageView.post(new Runnable() {
#Override public void run() {
imageView.setLayoutParams(params);
}
});
// kotlin
post(Runnable { imageView.setLayoutParams(params) })
I fixed this issue by disabling fastScroll on the ListView in the XML.
<ListView
android:id="#+id/mListview"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:fastScrollEnabled="false"
/>
In my case (Samsung Galaxy S4, API 21) this happened in ListView with EditTexts. I have a listener for field validation. Something like:
edit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
error.setVisibility(View.INVISIBLE);
error.setText("");
} else {
String s = edit.getText().toString();
if (s.isEmpty()) {
error.setText("Error 1");
} else if (s.length() < 2 || s.length() > 100) {
error.setText("Error 2");
}
error.setVisibility(View.VISIBLE);
}
}
});
After settinging focus in one of these EditTexts an above check is called. After that a TextView will change (the TextView contains an error message and lies over the EditText).
Setting focus to the second or the third EditText led to permanent request of the first EditText and return to current. An applications runs in infinite loop of requests (focus edittext 1, unfocus edittext 1, focus 3, unfocus 3, focus 1, etc).
I tried to set listView.setFastScrollEnabled(false). Also I tried a requestLayout() of some elements like in https://github.com/sephiroth74/HorizontalVariableListView/issues/93 with no chances.
Currently I made that TextView of fixed width and height in XML:
<TextView
android:id="#+id/error"
android:layout_width="match_parent" (or "200dp", but not "wrap_content")
android:layout_height="20dp"
.../>
After some experiments I noticed that a height of 20dp can be replaced with "wrap_content". But if a text is too long that divides into 2 lines, the application again catches in the infinite loop. So, android:singleLine="true" will help. It is deprecated, but amazingly android:maxLines="1" with android:lines="1" don't help as they again request layout.
Eventually we have:
<TextView
android:id="#+id/error"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:textColor="#f00"
android:textSize="20sp"
tools:text="Error message"/>
That's not a good solution, but at least it breaks the infinite loop.
This might happen if you are using some 3rd party extension of ListView. Replace that with standard ListView and check if it still throws the error.
I had similar problem. Please check Android layout: running second layout pass and my answer.
I had the same issue with Kitkat 4.4.4 on Motorola X with Genymotion. In my case the list item is a simple CheckedTextView and the error occurred in AppCompatCheckedTextView.
As a normal implementation I inflated the item from XML layout file like below:
if (convertView == null) {
convertView = inflater.inflate(R.layout.checkable_list_entry, parent, false);
}
After some trying I found out that this has something to do with XML inflation. I don't know the root cause, but as a solution I decided to inflate the list item by code and set all the properties by code too.
It ended up like this:
CheckedTextView view;
if (convertView == null) {
view = new CheckedTextView(parent.getContext());
view.setMinHeight(getResources().getDimensionPixelSize(R.dimen.default_touch_height));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
view.setTextAppearance(R.style.SectionEntry);
} else {
view.setTextAppearance(parent.getContext(), R.style.SectionEntry);
}
view.setBackgroundResource(R.drawable.form_element);
view.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
view.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT));
} else {
view = (CheckedTextView) convertView;
}
I had a problem with the same warning log :
requestLayout() improperly called by android.support.v7.widget.AppCompatTextView {...} during layout: running second layout pass
I was working with recylcerview and going to update it with new data.
The only solution that worked for me is as below :
Step(1). Remove current data :
public void removeAll() {
items.clear(); //clear list
notifyDataSetChanged();
}
Step(2). When you want to populate the recyclerview with new data, first set a new LayoutManager to recyclerview again:
private void initRecycleView() {
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false));
}
Step(3). Update the recyclerview with new data. for example :
public void refreshData(List newItems) {
this.items = newItems;
notifyItemRangeChanged(0, items.size());
}
Try taking off the textSize from the xml and setting it in Java code. I think that's causing it to be laid out twice.
In my case this warning prevented a button from showing up in API 21 devices. The button visibility was previously set to GONE.
The only workaround I got it was setting to INVISIBLE instead of GONE for API 21. It wasn't a real solution but it was acceptable for me.
I only post this because it can be useful from somebody.
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
theButton.setVisibility(View.INVISIBLE);
}
else {
theButton.setVisibility(View.GONE);
}
Sometimes you maybe already fixed the issue but it still keeps same error, so you need to close visual studio then delete all bin and obj folders from your projects, then uninstall the app from the emulator. then walah!! everything will works fine
I solved the problem like this:
mHolder.txt_fword.setTextSize(22);
mHolder.txt_farth.setTextSize(22);
mHolder.txt_fdef.setTextSize(22);
mHolder.txt_fdef2.setTextSize(22);
mHolder.txt_frem.setTextSize(22);
//if (fdef2.get(pos).equals("")) mHolder.txt_fdef2.setVisibility(View.GONE);
//if (frem.get(pos).equals("")) mHolder.txt_frem.setVisibility(View.GONE);
issue is .setVisibility(View.GONE); , change to .setVisibility(View.VISIBLE);

App lags with android:layerType="software"

I am making a really simple app (basically a listview with only a few images). It generally performs really well on my testing device (a Motorola Moto G with the stock android that comes with it).
However, I want my ListView to have dotted dividers. Therefore I made a list_divider.xml file defining the divider and set this to be the divider to be used in the ListView. I have tried that out on my Moto G, but it didn't display the line dotted.
So I've googled around and found here a solution to the problem. Disabling hw acceleration for the view solved the error and displayed the divider correctly.
However, now I have another problem: Since disabling hw acceleration the app began to lag when scrolling.
Is there a solution to having a dotted divider and not disabling hw acceleration or at least have the performance nearly as good as before disabling it?
Edit: Here is the adapter code I use:
public class AstronautArrayAdapter extends ArrayAdapter<Astronaut> {
public static final String TAG = "AstronautArrayAdapter";
public AstronautArrayAdapter(Context context, List<Astronaut> objects) {
super(context, R.layout.astronauts_list_row, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
RowViewHolder holder = null;
if (convertView == null) {
LayoutInflater inflater = ((Activity) getContext()).getLayoutInflater();
convertView = inflater.inflate(R.layout.astronauts_list_row, parent, false);
holder = new RowViewHolder();
holder.name = (TextView) convertView.findViewById(R.id.nameOfAustronaut);
holder.daysInSpace = (TextView) convertView.findViewById(R.id.numberOfDaysInSpace);
holder.country = (ImageView) convertView.findViewById(R.id.countryImage);
holder.title = (TextView) convertView.findViewById(R.id.titleOfAstronaut);
convertView.setTag(holder);
} else {
holder = (RowViewHolder) convertView.getTag();
}
Astronaut astronaut = getItem(position);
holder.name.setText(astronaut.getName());
holder.daysInSpace.setText(Integer.toString(astronaut.getDaysInSpace()));
holder.country.setImageBitmap(astronaut.getCountryImage(getContext()));
holder.title.setText(astronaut.getTitle());
return convertView;
}
private static class RowViewHolder {
TextView name;
TextView daysInSpace;
ImageView country;
TextView title;
}
}
Edit 2: Here are the two layout files in question:
activity_main.xml
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/astronautsList"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="16dp"
android:dividerHeight="3dp"
android:divider="#drawable/list_divider"
android:layerType="software" />
list_divider.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="line" >
<stroke
android:width="1px"
android:color="#android:color/black"
android:dashWidth="5px"
android:dashGap="1px" />
<size android:height="3dp" />
</shape>
possible answer for the lag you're seeing is:
add this line inside the dependencies section to your build.gradle
compile 'com.squareup.picasso:picasso:2.3.2'
and replace this line
holder.country.setImageBitmap(astronaut.getCountryImage(getContext()));
with
Picasso.with(context).load(/* insert the URL here */).into(holder.country);
and remove the code that is downloading all the images and saving locally. Picasso automagically download/decode the bitmaps and manage disk and ram cache for you.
ps.:
if you're not using Gradle:
You should change to Android-Studio and use Gradle
forget what I said about adding the line to the gradle file and just download the jar file from their website, put into the libs folder and make sure to mess on the project settings to make sure that jar goes inside your APK (I honestly do not remember how those settings work because I abandoned Eclipse long time ago)
As you did not mentioned it, have you implemented the ViewHolder pattern?
As the ListView recycles views it has to inflate a layout and insert any text and images in. You normally call findViewById in this section of code which is quite expensive. The ViewHolder pattern solves this and is easy to implement.
See here for a great tutorial by Google
http://developer.android.com/training/improving-layouts/smooth-scrolling.html

Categories

Resources