Indeterminate progressbar in listview - android

I'm trying to create a list that shows an indeterminate progress bar as the last entry while it's fetching more data. I can show the bar and get/add the data, but scrolling up and down while it's loading causes multiple progress bars to show up.
I have a ListActivity that uses an ArrayAdapter. Each row has a layout as follows.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:background="#drawable/textlines" android:padding="2dip">
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content" android:id="#+id/rowContent">
<TextView android:height="20sp" android:text=""
android:id="#+id/search_display" android:layout_width="fill_parent"
android:textSize="16sp" android:layout_height="20sp" android:gravity="left" />
</LinearLayout>
<LinearLayout android:layout_height="wrap_content"
android:layout_width="fill_parent" android:id="#+id/rowSpinner"
android:padding="3px" android:gravity="center" android:visibility="gone">
<ProgressBar android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="#+id/progress"
android:indeterminate="true" />
</LinearLayout>
</RelativeLayout>
The ListView has an OnScrollListener with the following onScroll method.
public void onScroll(final AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
// detect if last item is visible
if ((visibleItemCount < totalItemCount)
&& (firstVisibleItem + visibleItemCount == totalItemCount))
{
if (false == scrollTaskRunning)
{
scrollTaskRunning = true;
getMoreData(totalItemCount);
}
}
}
getMoreData invokes an AsyncTask that gets some more data to add to adapter. In its onPreExecute I call showSpinner() --
private void showSpinner()
{
// nothing to do if there's already a spinner visible
if (isSpinVisible == true) return;
// hide the progress spinner
if (0 < lvList.getChildCount())
{
View vRow = lvList.getChildAt(lvList.getChildCount() - 1);
vRow.findViewById(R.id.rowContent).setVisibility(View.GONE);
vRow.findViewById(R.id.rowSpinner).setVisibility(View.VISIBLE);
}
isSpinVisible = true;
}
and in its onPostExecute/onCancelled I call hideSpinner() which is the same code, except checking the isSpinVisible flag the other way, and GONE and VISIBLE swapped. The swapping code, so far as I can tell, only gets called once, but multiple entries in the last show up with the progress bar visible if you scroll up and down.
I tried doing this instead for hideSpinner() --
private void hideSpinner()
{
// nothing to do if there's no spinner visible
if (isSpinVisible == false) return;
// show the progress spinner
int iChildCount = lvList.getChildCount();
if (0 < lvList.getChildCount())
{
for (int i = 0; i < iChildCount; i++)
{
View vRow = lvList.getChildAt(iChildCount);
if (null != vRow)
{
vRow.findViewById(R.id.rowContent).setVisibility(View.VISIBLE);
vRow.findViewById(R.id.rowSpinner).setVisibility(View.GONE);
}
}
}
else if (null != pbSearch)
{
pbSearch.setVisibility(View.GONE);
}
isSpinVisible = false;
}
but vRow is null, and some of the progress bars still show up. How do I fix this? Alternatively, is there a better way to do this? (I thought I might be able to do something with my ArrayAdapter's getView() method, but I couldn't work it out.)
ETA: this answer seems to explain the problem I'm having, but knowing that hasn't helped me find a way around it.
ETA2: I tried doing this:
final LayoutInflater mInflater = (LayoutInflater)
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
aapSearchResults = new ArrayAdapter<ParsedXML>(this, R.layout.search_row, saData)
{
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
View row;
// get the view
if (null == convertView)
{
row = mInflater.inflate(R.layout.search_row, null);
}
else
{
row = convertView;
}
// bind the data to the view
TextView tv = (TextView) row.findViewById(R.id.search_display);
tv.setText(getItem(position).name);
// show data, hide spinner
row.findViewById(R.id.rowContent).setVisibility(View.VISIBLE);
row.findViewById(R.id.rowSpinner).setVisibility(View.GONE);
// if the current position is the last, and a task is running,
// show the progress bar
if (taskRunning && (position == this.getCount()-1))
{
row.findViewById(R.id.rowContent).setVisibility(View.GONE);
row.findViewById(R.id.rowSpinner).setVisibility(View.VISIBLE);
}
return row;
}
};
lvList.setAdapter(aapSearchResults);
but I'm clearly making a logic error still, because sometimes scrolling up and down now gets me blank entries. (Is it because the count has changed?)

Generally speaking you should never touch the children of a ListView directly. In fact, after they leave your adapter's getView() nest, you should consider them to be fully independent and entirely divorced from your direct control. The only way you can control them is by calling notifyDataSetChanged() and letting the ListView make new ones.
To get around your problem, do something like:
public class MyAdapter extends ArrayAdapter[…]{
//[…]
private boolean mIsLoading = false;
public void setIsLoading(boolean isLoading){
if (mIsLoading != isLoading){
mIsLoading = isLoading;
notifyDataSetChanged();
}
}
#Override
public int getCount(){
return super.getCount() + (isLoading ? 1 : 0);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (mIsLoading && position == (getCount() - 1)){
//return your progress view goes here. Ensure that it has the ID R.id.progress;
}else{
if (convertView != null && convertView.getId() == R.id.progress){
convertView = null;
}
return super.getView(position, convertView, parent);
}
}
}

I would suggest you use a BaseAdapter instead. It automatically loads more elements when the last one on the list is shown.

Related

Difference between tinting a child View and the containing ViewGroup

I'm trying to better understand the following situation that arose while refactoring some "selection highlighting" code (to take advantage of tinting).
There's a list that's populated with an adapter, CodebookAdapter, where each item's defined as:
CodebookAdapter List Item Layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#FFFFFFFF">
<ImageView
android:id="#+id/item_icon_iv"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_gravity="center_vertical" />
<TextView
android:id="#+id/item_header_tv"
android:layout_width="match_parent"
android:layout_height="20dp"
android:textColor="#FF000000"
android:textSize="14dp"/>
<!--android:background="#FFFFFFFF"-->
</LinearLayout>
The method below, HiliteCodeItem(), sets the TextView, item_header_tv, to selected.
I've set the background-tint first on the list-item itself, and then just on the enclosed TextView (to avoid undesired highlighting of the entire layout):
// option 1 - item_header_tv's background can be omitted/null, highlights ok
/////////////////////////////////////////////////////////////
v.Background.SetTintList(_csl);
// option 2 - item_header_tv's background cannot be omitted/null
/////////////////////////////////////////////////////////////
tv.Background.SetTintList(_csl);
Why if in option 2 the background must be explicitly set (or else tv.Background.SetTintList(_csl); throws null ex), but in option 1 item_header_tv's background get's highlighted?
Is the enclosing list item's LinearLayout doing a null check on the background of TextView and instantiating one?
public class Codebook : LinearLayout
{
protected virtual void HiliteCodeItem(TextView codeDesc, Code code)
{
_codebookAdapter.SelectedCode = code;
//codeDesc.SetBackgroundColor(SelectedCodeListItemBgColor);
codeDesc.Selected = true;
_codebookAdapter.NotifyDataSetChanged();
}
protected class CodebookAdapter : ArrayAdapter<Code>
{
private Codebook _; // explicit outer object ref
private int _listItemRes;
private List<Code> _items;
private Android.Content.Res.ColorStateList _csl;
public Code SelectedCode { get; set; }
public CodebookAdapter(Context context, int listItemRes, List<Code> items, Codebook outer)
: base(context, listItemRes.Layout, items)
{
_ = outer;
_listItemRes = listItemRes;
_items = items;
_csl = _._context.Resources.GetColorStateList(Resource.Color.codebook_code_list_item_color_state_list);
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View v = convertView;
TextView tv;
if (v == null)
{
v = _._inflater.Inflate(_listItemRes, parent, false);
tv = v.FindViewById<TextView>(Resource.Id.item_header_tv);
// option 1 - item_header_tv's background can be omitted/null, highlights ok
/////////////////////////////////////////////////////////////
v.Background.SetTintList(_csl);
// option 2 - item_header_tv's background cannot be omitted/null
/////////////////////////////////////////////////////////////
tv.Background.SetTintList(_csl);
}
else
tv = v.FindViewById<TextView>(Resource.Id.item_header_tv);
if (_items == null || _items.Count == 0)
{
return v;
}
Code code = _items[position];
if (code != null)
{
if (code == SelectedCode)
{
//tvCodeHeader.SetBackgroundColor(_.SelectedCodeListItemBgColor);
tvCodeHeader.Selected = true;
}
else
{
//tvCodeHeader.SetBackgroundColor(_.UnselectedCodeListItemBgColor);
tvCodeHeader.Selected = false;
}
}
}
}
}
Why if in option 2 the background must be explicitly set (or else tv.Background.SetTintList(_csl); throws null ex), but in option 1 item_header_tv's background get's highlighted?
The first works because you've set android:background="#FFFFFFFF" to the LinearLayout, the code v = _._inflater.Inflate(_listItemRes, parent, false); points to the this LinearLayout. So it's background is not omitted/null.
The Background cannot be null if you want to SetTintList, the second line doesn't work because Background of your TextView v is null.
By the way, controls like Button has Background set by default, you don't need to specify the Background property for them to use SetTintList.

Multiple EditText in ListView, tap to focus on one EditText and focus jumps to the first

I've got EditTexts in my rows in a ListView. When I tap on one of the EditTexts the soft keyboard appears and the focus jumps to the first EditText in the list instead of staying in the field where I tapped.
Here is a video of it:
https://youtu.be/ZwuFrX-WWBo
I created a completely stripped down app to demonstrate the problem. The full code is here: https://pastebin.com/YT8rxqKa
I'm not doing anything to alter the focus in my code:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.cell_textfield, parent, false);
}
TextView label = (TextView) convertView.findViewById(R.id.textview1);
EditText textfield = (EditText) convertView.findViewById(R.id.textview2);
String text = String.format("Row %d", position);
label.setText(text);
textfield.setText(text);
return convertView;
}
I found another post on StackOverflow giving a workaround for this dumb Android behavior, which involves putting an OnFocusChangedListener on all of the textfields so they can retake focus if it's taken from them improperly.
That worked to regain focus, but then I discovered that when a textfield retakes focus the cursor ends up at the start of the text instead of end, which is unnatural and annoying to my users.
Here is a video of that:
https://youtu.be/A35wLqbuIac
Here's the code for that OnFocusChangeListener. It works to fight the stupid Android behavior of moving focus, but the cursor is misplaced after it regains focus.
View.OnFocusChangeListener onFocusChangeListener = new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean hasFocus) {
long t = System.currentTimeMillis();
long delta = t - focusTime;
if (hasFocus) { // gained focus
if (delta > minDeltaForReFocus) {
focusTime = t;
focusTarget = view;
}
}
else { // lost focus
if (delta <= minDeltaForReFocus && view == focusTarget) {
focusTarget.post(new Runnable() { // reset focus to target
public void run() {
Log.d("BA", "requesting focus");
focusTarget.requestFocus();
}
});
}
}
}
};
I hate having to put a bandaid on a bandaid on a bandaid to try to get Android to just behave as it would naturally be expected to behave, but I'll take what I can get.
1) Is there something I can do to fix this problem at the source and not have to have the OnFocusChangeListener at all?
2) If (1) isn't possible, then how can I make sure that when I force focus back to the correct field that I make sure the cursor is placed at the end? I tried using setSelection() right after requestFocus() but since the textfield wasn't yet focused the selection is ignored.
Here was my "solution." In short: ListViews are stupid and will always be a total nightmare when EditTexts are involved, so I changed my Fragment/Adapter code to be able to adapt to either a ListView layout or a ScrollView layout. It only works if you have a small number of rows, because the scrollview implementation isn't able to take advantage of lazy-loading and view recycling. Thankfully, any situation wherein I want EditTexts in a ListView, I rarely have more than 20 rows or so.
When inflating my view in my BaseListFragment, I get my layout id via a method that relies on a hasTextFields() method:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(getLayoutId(), container, false);
return view;
}
public boolean hasTextfields() {
return false;
}
public int getLayoutId() {
if (hasTextfields()) {
return R.layout.scrollfragment;
} else {
return R.layout.listfragment;
}
}
In my various subclasses of my BaseListFragment, if I need to have an EditText in one of my fields, I just override the hasTextFields() method to return true and then my fragment/adapter switchs over to using the basic scrollview implementation.
From there, it's a matter of making sure that the Adapter handles the standard ListView actions for both the ListView and the ScrollView scenarios. Like this:
public void notifyDataSetChanged() {
// If scrollContainer is not null, that means we're in a ScrollView setup
if (this.scrollContainer != null) {
// intentionally not calling super
this.scrollContainer.removeAllViews();
this.setupRows();
} else {
// use the real ListView
super.notifyDataSetChanged();
}
}
public void setupRows() {
for (int i = 0; i < this.getCount(); i++) {
View view = this.getView(i, null, this.scrollContainer);
view.setOnClickListener(myItemClickListener);
this.scrollContainer.addView(view);
}
}
One issue that the click listener presented is that a ListView wants an AdapterView.OnItemClickListener, but arbitrary Views inside a ScrollView want a simple View.OnClickListener. So, I made my ItemClickListener also implement View.OnClickListener and then just dispatched the OnClick to the OnItemClick method:
public class MyItemClickListener implements AdapterView.OnItemClickListener, View.OnClickListener {
#Override
public void onClick(View v) {
// You can either have your Adapter set the tag on the View to be its position
// or you could have your click listener use v.getParent() and iterate through
// the children to find the position. I find its faster and easier to have my
// adapter set the Tag on the view.
int position = v.getTag();
this.onItemClick(null, v, config.getPosition(), 0);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// ...
}
}
Then in MyEditTextListFragment, I create the adapter like this:
listener = createClickListener();
adapter = createListAdapter();
if (scrollContainer != null) {
adapter.setScrollContainer(scrollContainer);
adapter.setMenuItemClickListener(listener);
adapter.setupRows();
} else {
getListView().setOnItemClickListener(listener);
getListView().setAdapter(adapter);
}
Here is my scrollfragment.xml for reference:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
android:clickable="true"
>
<!--
The following LinearLayout as a focus catcher that won't cause the keyboard to
show without it, the virtual keyboard shows up immediately/always which means we
never get to the enjoy the full size of our screen while scrolling, and
that sucks.
-->
<LinearLayout
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_width="0px"
android:layout_height="0px"/>
<!--
This ListView is still included in the layout but set to visibility=gone. List
fragments require a standard ListView in the layout, so this gets us past that
check and allows us to use the same adapter code in both listview and scrollview
situations.
-->
<ListView android:id="#id/android:list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:drawSelectorOnTop="false"
android:background="#null"
android:layout_alignParentTop="true"
android:descendantFocusability="afterDescendants"
android:visibility="gone"
/>
<!--
This scrollview will act as our fake listview so that we don't have to deal with
all the stupid crap that comes along with having EditTexts inside a ListView.
-->
<ScrollView
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="afterDescendants"
>
<LinearLayout
android:id="#+id/scrollContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
</LinearLayout>
</ScrollView>
</RelativeLayout>
Try this once, it worked for me:
public void setCursorPosition() {
focusTarget.requestFocus();
focusTarget.setCursorVisible(true);
other.setCursorVisible(false);
} else {
other.setCursorVisible(true);
focusTarget.setCursorVisible(false);
}
}

How to add load more button in android listview for offline content?

I have a listview and an array of say 30 items in it, now I want to show first 10 items only when I open it, and then as I scroll to bottom I want to show a load more button which when clicked will add next 10 items to the listview and again on scrolling to bottom it should show load more button. I just don't know how to handle this, any help would be appreciated.
We can add Load More button to list view using listview.addFooterView(btnLoadMore) then, we can ada a click event listener to load more button and call a background thread which will append more data to listview.
here is the complete tutorial on listview with load more button
hope this helps :)
listv.setOnScrollListener(new OnScrollListener() {
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if(firstVisibleItem+visibleItemCount == totalItemCount && totalItemCount!=0)
{
if(flag_loading == false)
{
flag_loading = true;
addmoreitems();
}
}
}
});
and then you can add next ten items in addmoreitems(). it will work.
If you want to add button at footer of listview just add yourlistview.addFooterView. Just try this code
Make following changes to ListAdapter class
#Override
public View getView(int position, View convertView, ViewGroup parent) {
....
if (mTotalPages > mData.size()) {
if ((position + 1) == getCount()) {
holder.sLoadingView.setVisibility(View.VISIBLE);
} else {
holder.sLoadingView.setVisibility(View.GONE);
}
}
....
}
Where mTotalPages = 30 in your case.
In adapter layout add load more view at the bottom like this,
<TextView
android:id="#+id/loading_more_items"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/content_wrapper"
android:layout_centerHorizontal="true"
android:layout_margin="#dimen/space"
android:clickable="false"
android:gravity="start"
android:singleLine="false"
android:text="Loading..."
android:textColor="#color/dark_grey"
android:textSize="#dimen/text_size_small"
android:visibility="gone" />

onListItemClick stops working after one click

LAST EDIT
I found the problem with solution here: http://code.google.com/p/android/issues/detail?id=3414#c27
ORIGINAL POST
I have a ListView (actually a ListFragment) where I want to expand a object when I click on it, and collaps it again on a second click.
This is my onListItemClick
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
//mAdapter.toggleItem(id); // removed this
ListView list = getListView();
int start = list.getFirstVisiblePosition();
for (int i = start, j = list.getLastVisiblePosition(); i <= j; i++) {
Cursor item = (Cursor) list.getItemAtPosition(i);
if (id == item.getLong(item.getColumnIndex(ItemColumns._ID))) {
View view = list.getChildAt(i - start);
ViewStub stub = (ViewStub) view.findViewById(R.id.stub);
// View inflated;
if (stub.getVisibility() == View.VISIBLE)
stub.setVisibility(View.GONE);
else
stub.inflate();
// list.getAdapter().getView(i, view, list);
// break;
}
}
}
It works, but it only fires once. Once the ListItem has expanded the onListItemClick wont get fired again. Any idea why?
best
Marcus
EDIT: It's the actual line: stub.inflate(); which disables the click event
EDIT2: I foudn the problem was due to the ViewStub
it look like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#CC0000"
android:orientation="vertical">
<SeekBar android:id="#+id/progress"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
The LinearLayout does not shadow the original listItem. But if I remove the seekbar it works great.
If your listview contains a control that can steal the focus (Seekbar in your situation), you just need to make it not focusable
<SeekBar
android:focusable="false" />

ListView receives touches, but onItemClickListener does not receive clicks after a pause and resume

We generate several ListViews that hold info for a user to filter information in another fragment. It works fine, unless you pause and resume the app (say, backgrounding it, or locking the screen). Once you do that, the list can be scrolled, but not clicked.
List generating code:
private View addList(LayoutInflater inflater, ViewGroup container, final FilterValue.SearchCategory type, final String[] labels) {
ArrayAdapter<String> adapter = generateArrayAdapter(inflater, labels, type);
if(adapter == null) {
return null;
}
filterAdapters.add(adapter);
ListView list = (ListView) inflater.inflate(R.layout.on_demand_filter_list, container, false);
list.setAdapter(adapter);
list.setItemsCanFocus(false);
list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
list.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
list.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(final View view, final MotionEvent motionEvent) {
LOG.d(TAG, "NO TOUCHING!");
return false; //To change body of implemented methods use File | Settings | File Templates.
}
});
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
LOG.d(TAG, "onItemClick!");
CheckedTextView textView = (CheckedTextView) view.findViewById(R.id.title);
textView.toggle();
if (textView.isChecked()) {
filterValue.addToSelectedList(labels[i], type);
} else {
filterValue.removeFromSelectedList(labels[i], type);
}
}
});
list.setAdapter(adapter);
list.setVisibility(View.GONE);
filterListContainer.addView(list);
return list;
}
The onTouch listener only exists to ensure the Touch is received. (It is.) The DescendantFocusability appears to have no effect, this bug exists before and after it was added.
Each is tied to a button that shows or hides the list.
titleHeader.setOnClickListener(new View.OnClickListener() {
public void onClick(View clickedView) {
closeNetworkList();
closeGenreList();
titlesOpen = !titlesOpen;
ImageView indicator = (ImageView) clickedView.findViewById(R.id.filter_expansion_indicator_icon);
if (indicator != null) {
if (titlesOpen) {
indicator.setImageResource(R.drawable.arrow_filter_up);
} else {
indicator.setImageResource(R.drawable.arrow_filter_down);
}
}
if (titlesOpen) {
titlesListView.setVisibility(View.VISIBLE);
} else {
titlesListView.setVisibility(View.GONE);
}
}
});
Tapping this button to hide and then show the listView (which was generated with addList) resets something, and the items can be clicked again.
XML for an item row:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:focusableInTouchMode="false"
android:padding="8dp"
android:orientation="horizontal">
<CheckedTextView
android:id="#+id/title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#drawable/on_demand_filter_checked_text_sel"
android:gravity="center_vertical"
android:paddingLeft="76dp"
android:focusable="false"
android:focusableInTouchMode="false"
android:drawableLeft="#drawable/checkbox_sel"
android:drawablePadding="14dp"
style="#style/LargeRegular"/>
</LinearLayout>
The focusables are new additions, but neither worked. The problem occurred before they were added.
The ListView itself:
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/list"
android:layout_width="fill_parent"
android:layout_height="275dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:divider="#color/Transparent"
android:descendantFocusability="blocksDescendants"
android:cacheColorHint="#ffffff"/>
I am at my absolute wits' end. No one on my team has a sensible solution to this. It works fine, right up until you pause and resume. We do absolutely nothing that touches the views in resume or pause. Can anyone help? I can provide more detail as needed.
I had similar problem with my app (extended SurfaceView which lost touch events after resume) and resolved it by calling the setFocusable( true ) in the onResume() implementation. Apparently the view didn't get the focus and therefore did not receive the touch events. Not sure whether this is the case here, but worth trying.
Remembered that I had had a similar problem with fragment activities. I had a case when layout requests were blocked, they did not cause actual layout traverse.
I've fixed it in Enroscar library (BaseFragment class) with the following snippet of code in a fragment class:
#Override
public void onStart() {
// ... other staff ...
super.onStart();
/*
XXX I don't know the reason but sometimes after coming back here from other activity all layout requests are blocked. :(
It looks like some concurrency issue or a views tree traversal bug
*/
final View contentView = getActivity().findViewById(android.R.id.content);
if (contentView != null) {
final ViewParent root = contentView.getParent();
if (contentView.isLayoutRequested() && !root.isLayoutRequested()) {
if (DebugFlags.DEBUG_GUI) { Log.i("View", "fix layout request"); }
root.requestLayout();
}
}
}

Categories

Resources