Skip to content

Commit

Permalink
[Backport 10_0_X] fix(android): improve marker detection (#12864)
Browse files Browse the repository at this point in the history
Fixes TIMOB-28462

Co-authored-by: Gary Mathews <contact@garymathews.com>
  • Loading branch information
build and garymathews committed Jun 3, 2021
1 parent 9641945 commit 7ee3fd1
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,6 @@ public void onBindViewHolder(@NonNull ListViewHolder holder, int position)
// Update ListViewHolder with new model data.
// TODO: Optimize `bind()`.
holder.bind(item, selected);

// Handle ListView markers.
final ListViewProxy listViewProxy = item.getListViewProxy();
if (listViewProxy != null) {
listViewProxy.handleMarker(item);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ public void bind(final ListItemProxy proxy, final boolean selected)

// Update model proxy holder.
this.proxy = new WeakReference<>(proxy);
proxy.setHolder(this);

// Obtain ListView proxy for item.
final ListViewProxy listViewProxy = proxy.getListViewProxy();
Expand Down Expand Up @@ -244,8 +245,6 @@ public void bind(final ListItemProxy proxy, final boolean selected)
setHeaderFooter(listViewProxy, sectionProperties, false, true);
}
}

proxy.setHolder(this);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@
import android.app.Activity;
import android.view.View;

import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import ti.modules.titanium.ui.UIModule;
import ti.modules.titanium.ui.widget.TiUIListView;

Expand Down Expand Up @@ -433,67 +430,62 @@ protected TiUIView handleGetView()
}

/**
* Determine if `marker` event should be fired for specified item.
*
* @param item Item to handle for `marker` event.
* Determine if `marker` event should be fired.
*/
public void handleMarker(ListItemProxy item)
public void handleMarkers()
{
if (item != null) {
final Object parent = item.getParent();

if (parent instanceof ListSectionProxy) {
final ListSectionProxy section = (ListSectionProxy) parent;
final int sectionIndex = getIndexOfSection(section);

if (markers.containsKey(sectionIndex)) {

// Found marker for current section.
final Set<Integer> itemIndexSet = markers.get(sectionIndex);

final TiListView listView = getListView();
if (listView == null) {
return;
}
final RecyclerView recyclerView = listView.getRecyclerView();
if (recyclerView == null) {
return;
}
final LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
if (layoutManager == null) {
return;
}

// Loop through markers for current section and determine visibility.
// Some items may not have scrolled into view.
for (Iterator<Integer> i = itemIndexSet.iterator(); i.hasNext();) {
final Integer index = i.next();

final ListItemProxy markedItem = section.getListItemAt(index);
if (markedItem == null) {
continue;
}
final ListViewHolder markedHolder = markedItem.getHolder();
if (markedHolder == null) {
continue;
}
final View markedItemView = markedHolder.itemView;
if (markedItemView == null || markedItemView.getLayoutParams() == null) {
continue;
}
final boolean isVisible =
layoutManager.isViewPartiallyVisible(markedItemView, false, true);

if (isVisible) {
final KrollDict data = new KrollDict();
final TiListView listView = getListView();

// Create and fire marker event.
data.put(TiC.PROPERTY_SECTION_INDEX, sectionIndex);
data.put(TiC.PROPERTY_ITEM_INDEX, index);
fireEvent(TiC.EVENT_MARKER, data, false);
if (markers == null || markers.isEmpty() || listView == null) {
return;
}

// One time event, remove marker.
i.remove();
final ListItemProxy[] items =
new ListItemProxy[] { listView.getFirstVisibleItem(), listView.getLastVisibleItem()};

for (final ListItemProxy item : items) {
if (item != null) {
final Object parent = item.getParent();

if (parent instanceof ListSectionProxy) {
final ListSectionProxy section = (ListSectionProxy) parent;
final int sectionIndex = getIndexOfSection(section);

if (markers.containsKey(sectionIndex)) {

// Found marker for current section.
final Set<Integer> itemIndexSet = markers.get(sectionIndex);

// Loop through markers for current section and determine visibility.
// Some items may not have scrolled into view.
for (Iterator<Integer> i = itemIndexSet.iterator(); i.hasNext(); ) {
final Integer index = i.next();

final ListItemProxy markedItem = section.getListItemAt(index);
if (markedItem == null) {
continue;
}
final TiUIView markedView = markedItem.peekView();
if (markedView == null) {
continue;
}
final View markedNativeView = markedView.getNativeView();
if (markedNativeView == null) {
continue;
}
final boolean isVisible = markedNativeView.isShown();

if (isVisible) {
final KrollDict data = new KrollDict();

// Create and fire marker event.
data.put(TiC.PROPERTY_SECTION_INDEX, sectionIndex);
data.put(TiC.PROPERTY_ITEM_INDEX, index);
fireEvent(TiC.EVENT_MARKER, data, false);

// One time event, remove marker.
i.remove();
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,17 @@ public TiListView(ListViewProxy proxy)
this.recyclerView.setFocusable(true);
this.recyclerView.setFocusableInTouchMode(true);
this.recyclerView.setBackgroundColor(Color.TRANSPARENT);
this.recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
this.recyclerView.setLayoutManager(new LinearLayoutManager(getContext()) {

@Override
public void onLayoutCompleted(RecyclerView.State state)
{
super.onLayoutCompleted(state);

// Process markers after layout.
proxy.handleMarkers();
}
});
this.recyclerView.setFocusableInTouchMode(false);

// Add listener to fire scroll events.
Expand All @@ -79,7 +89,10 @@ public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newStat

if (isScrolling && newState == RecyclerView.SCROLL_STATE_IDLE) {
isScrolling = false;
proxy.fireSyncEvent(TiC.EVENT_SCROLLEND, generateScrollPayload());

if (proxy.hierarchyHasListener(TiC.EVENT_SCROLLEND)) {
proxy.fireSyncEvent(TiC.EVENT_SCROLLEND, generateScrollPayload());
}
}
}

Expand All @@ -96,11 +109,15 @@ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy)

if (!isScrolling) {
isScrolling = true;
proxy.fireSyncEvent(TiC.EVENT_SCROLLSTART, generateScrollPayload());

if (proxy.hierarchyHasListener(TiC.EVENT_SCROLLSTART)) {
proxy.fireSyncEvent(TiC.EVENT_SCROLLSTART, generateScrollPayload());
}
}

// Only fire `scrolling` event upon direction change.
if (lastScrollDeltaY >= 0 && dy <= 0 || lastScrollDeltaY <= 0 && dy >= 0) {
if (proxy.hierarchyHasListener(TiC.EVENT_SCROLLING)
&& (lastScrollDeltaY >= 0 && dy <= 0 || lastScrollDeltaY <= 0 && dy >= 0)) {
final KrollDict payload = generateScrollPayload();

// Determine scroll direction.
Expand All @@ -114,6 +131,9 @@ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy)
}

lastScrollDeltaY = dy;

// Process markers.
proxy.handleMarkers();
}
});

Expand Down Expand Up @@ -250,18 +270,12 @@ public void filterBy(String query)
*/
public KrollDict generateScrollPayload()
{
final KrollDict payload = new KrollDict();
final ListItemProxy firstVisibleProxy = getFirstVisibleItem();
final LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
final KrollDict payload = new KrollDict();

// Obtain first visible list item view.
final View firstVisibleView =
layoutManager.findViewByPosition(layoutManager.findFirstVisibleItemPosition());
if (firstVisibleView != null) {
final ListViewHolder firstVisibleHolder =
(ListViewHolder) recyclerView.getChildViewHolder(firstVisibleView);

// Obtain first visible list item proxy.
final ListItemProxy firstVisibleProxy = (ListItemProxy) firstVisibleHolder.getProxy();
if (firstVisibleProxy != null) {
payload.put(TiC.PROPERTY_FIRST_VISIBLE_ITEM, firstVisibleProxy);

// Obtain first visible list item index in section.
Expand Down Expand Up @@ -356,6 +370,50 @@ public ListItemProxy getAdapterItem(int index)
return this.items.get(index);
}

/**
* Obtain first visible list item proxy.
*
* @return ListItemProxy
*/
public ListItemProxy getFirstVisibleItem()
{
final LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
final View firstVisibleView =
layoutManager.findViewByPosition(layoutManager.findFirstVisibleItemPosition());

if (firstVisibleView != null) {
final ListViewHolder firstVisibleHolder =
(ListViewHolder) recyclerView.getChildViewHolder(firstVisibleView);

// Obtain first visible list item proxy.
return (ListItemProxy) firstVisibleHolder.getProxy();
}

return null;
}

/**
* Obtain last visible list item proxy.
*
* @return ListItemProxy
*/
public ListItemProxy getLastVisibleItem()
{
final LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
final View lastVisibleView =
layoutManager.findViewByPosition(layoutManager.findLastVisibleItemPosition());

if (lastVisibleView != null) {
final ListViewHolder lastVisibleHolder =
(ListViewHolder) recyclerView.getChildViewHolder(lastVisibleView);

// Obtain last visible list item proxy.
return (ListItemProxy) lastVisibleHolder.getProxy();
}

return null;
}

/**
* Determine if table results are filtered by query.
*
Expand Down

0 comments on commit 7ee3fd1

Please sign in to comment.