Skip to content

Commit

Permalink
Optimize example.
Browse files Browse the repository at this point in the history
  • Loading branch information
Kenber committed Sep 11, 2016
1 parent 904153c commit e6f4dce
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,37 @@
import android.os.Bundle;
import android.view.View;
import android.widget.ListView;
import android.widget.Toast;

import com.kenber.doublestickyheaderslist.R;
import com.kenber.doublestickyheaderslist.data.ListItem;
import com.kenber.doublestickyheaderslist.ui.ListAdapter;

/**
* @author Kenber
*/
public class DoubleStickyHeadersListActivity extends ListActivity implements View.OnClickListener {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_double_sticky_headers_list);
setListAdapter(new ListAdapter(this, R.layout.view_list_item, R.id.text1));
}

@Override
protected void onListItemClick(ListView l, View v, int position, long id) {

ListItem item = (ListItem) getListView().getAdapter().getItem(position);
if (item != null) {
Toast.makeText(getApplicationContext(), "Item " + position + ": level " + item.level + ", text: " + item.text, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "Item " + position + ": not exist", Toast.LENGTH_SHORT).show();
}
}

@Override
public void onClick(View view) {

Toast.makeText(this, "Item: " + view.getTag(), Toast.LENGTH_SHORT).show();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,18 @@ public class ListAdapter extends ArrayAdapter<ListItem> implements DoubleStickHe
private static final int LEVEL1_HEADERS_NUMBER = 4;
private static final int LEVEL2_HEADERS_NUMBER = 5;

private static final int[] BG_COLORS = {
android.R.color.holo_blue_dark, android.R.color.holo_red_dark,
android.R.color.holo_orange_dark, android.R.color.holo_green_dark};

public ListAdapter(Context context, int resource) {
super(context, resource);
private static final int BG_COLOR_LEVEL_0 = android.R.color.holo_purple;
private static final int BG_COLOR_LEVEL_1 = android.R.color.holo_green_light;
private static final int BG_COLOR_LEVEL_2 = android.R.color.white;
public ListAdapter(Context context, int resource, int textViewResourceId) {
super(context, resource, textViewResourceId);
genListData();
}

public void genListData() {

int listPosition = 0;
for (char i = 0; i < LEVEL0_HEADERS_NUMBER; i++) {
ListItem level0Header = new ListItem(DoubleStickyHeaderListView.HEADER_LEVEL_0, String.valueOf((char)('A' + i)));
level0Header.listPosition = listPosition++;
add(level0Header);

for (char j = 0; j < LEVEL1_HEADERS_NUMBER; j++) {
Expand All @@ -45,7 +42,6 @@ public void genListData() {

for (int k = 0; k < LEVEL2_HEADERS_NUMBER; k++) {
ListItem level2Header = new ListItem(DoubleStickyHeaderListView.HEADER_LEVEL_2, level1Header.text + " - " + k);
level2Header.listPosition = listPosition++;
add(level2Header);
}
}
Expand All @@ -58,10 +54,13 @@ public View getView(int position, View convertView, ViewGroup parent) {
TextView view = (TextView) super.getView(position, convertView, parent);
view.setTextColor(Color.BLACK);
view.setTag("" + position);
ListItem item = getItem(position);
if (item.level == DoubleStickyHeaderListView.HEADER_LEVEL_0 ||
item.level == DoubleStickyHeaderListView.HEADER_LEVEL_1) {
view.setBackgroundColor(parent.getResources().getColor(BG_COLORS[item.listPosition % BG_COLORS.length]));
int level = getHeaderLevel(position);
if (level == DoubleStickyHeaderListView.HEADER_LEVEL_0) {
view.setBackgroundColor(parent.getResources().getColor(BG_COLOR_LEVEL_0));
} else if (level == DoubleStickyHeaderListView.HEADER_LEVEL_1) {
view.setBackgroundColor(parent.getResources().getColor(BG_COLOR_LEVEL_1));
} else {
view.setBackgroundColor(parent.getResources().getColor(BG_COLOR_LEVEL_2));
}
return view;
}
Expand Down
5 changes: 5 additions & 0 deletions example/src/main/res/drawable/bg_list_item.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@color/pressed"/>
<item android:drawable="@color/normal"/>
</selector>
10 changes: 10 additions & 0 deletions example/src/main/res/layout/view_list_item.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:minHeight="50dp"/>
2 changes: 2 additions & 0 deletions example/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
<color name="normal">#fff</color>
<color name="pressed">#666</color>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public static class StickyHeader {
private final Rect mTouchRect = new Rect();
private final PointF mTouchPoint = new PointF();
private View mTouchTarget;
private int mTouchTargetType;
private int mTouchTargetLevel;

private int mHeadersDistanceY0;
private int mHeadersDistanceY1;
Expand Down Expand Up @@ -92,14 +92,13 @@ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCoun
destroyPinnedShadow(HEADER_LEVEL_1);
} else {
int stickyHeaderPosition1;
if (adapter.getItemViewType(firstVisibleItem + 1) == HEADER_LEVEL_0) {
if (((DoubleStickHeadersListAdapter)adapter).getHeaderLevel(firstVisibleItem + 1) == HEADER_LEVEL_0) {
stickyHeaderPosition1 = -1;
} else {
stickyHeaderPosition1 = isLevel1HeaderSticky(firstVisibleItem + 1) ? (firstVisibleItem + 1) : -1;
}
ensureShadowForPosition(firstVisibleItem, stickyHeaderPosition1, firstVisibleItem, visibleItemCount);
}

} else {
int stickyHeaderPosition0 = findCurrentStickyHeaderPosition(firstVisibleItem, HEADER_LEVEL_0);
int stickyHeaderPosition1 = findCurrentLevel2StickyHeaderPosition(firstVisibleItem);
Expand Down Expand Up @@ -139,10 +138,10 @@ private void initView() {
setOnScrollListener(mOnScrollListener);
}

void createPinnedShadow(int stickyHeaderPosition, int type) {
void createPinnedShadow(int stickyHeaderPosition, int level) {

StickyHeader pinnedShadow = type == HEADER_LEVEL_0 ? mRecycleHeader0 : mRecycleHeader1;
if (type == HEADER_LEVEL_0) {
StickyHeader pinnedShadow = level == HEADER_LEVEL_0 ? mRecycleHeader0 : mRecycleHeader1;
if (level == HEADER_LEVEL_0) {
mRecycleHeader0 = null;
} else {
mRecycleHeader1 = null;
Expand All @@ -152,9 +151,9 @@ void createPinnedShadow(int stickyHeaderPosition, int type) {

View pinnedView = getAdapter().getView(stickyHeaderPosition, pinnedShadow.view, DoubleStickyHeaderListView.this);

ViewGroup.LayoutParams layoutParams = (ViewGroup.LayoutParams) pinnedView.getLayoutParams();
ViewGroup.LayoutParams layoutParams = pinnedView.getLayoutParams();
if (layoutParams == null) {
layoutParams = (ViewGroup.LayoutParams) generateDefaultLayoutParams();
layoutParams = generateDefaultLayoutParams();
pinnedView.setLayoutParams(layoutParams);
}

Expand All @@ -170,30 +169,30 @@ void createPinnedShadow(int stickyHeaderPosition, int type) {
int hs = MeasureSpec.makeMeasureSpec(heightSize, heightMode);
pinnedView.measure(ws, hs);
pinnedView.layout(0, 0, pinnedView.getMeasuredWidth(), pinnedView.getMeasuredHeight());
if (type == HEADER_LEVEL_0) {
if (level == HEADER_LEVEL_0) {
mTranslateY0 = 0;
} else if (type == HEADER_LEVEL_1) {
} else if (level == HEADER_LEVEL_1) {
mTranslateY1 = 0;
}

pinnedShadow.view = pinnedView;
pinnedShadow.position = stickyHeaderPosition;
pinnedShadow.id = getAdapter().getItemId(stickyHeaderPosition);

if (type == HEADER_LEVEL_0) {
if (level == HEADER_LEVEL_0) {
mStickyHeader0 = pinnedShadow;
} else {
mStickyHeader1 = pinnedShadow;
}
}

void destroyPinnedShadow(int type) {
if (type == HEADER_LEVEL_0) {
void destroyPinnedShadow(int level) {
if (level == HEADER_LEVEL_0) {
if (mStickyHeader0 != null) {
mRecycleHeader0 = mStickyHeader0;
mStickyHeader0 = null;
}
} else if (type == HEADER_LEVEL_1) {
} else if (level == HEADER_LEVEL_1) {
if (mStickyHeader1 != null) {
mRecycleHeader1 = mStickyHeader1;
mStickyHeader1 = null;
Expand Down Expand Up @@ -271,10 +270,13 @@ void ensureShadowForPosition(int stickyHeader0Position, int stickyHeader1Positio
}

boolean isLevel1HeaderSticky(int position) {
return getAdapter().getItemViewType(position + 1) == HEADER_LEVEL_2;
if (position + 1 >= getAdapter().getCount()) {
return false;
}
return ((DoubleStickHeadersListAdapter)getAdapter()).getHeaderLevel(position + 1) == HEADER_LEVEL_2;
}

int findFirstVisibleStickyHeaderPosition(int firstVisibleItem, int visibleItemCount, int type) {
int findFirstVisibleStickyHeaderPosition(int firstVisibleItem, int visibleItemCount, int level) {
ListAdapter adapter = getAdapter();

int adapterDataCount = adapter.getCount();
Expand All @@ -287,20 +289,20 @@ int findFirstVisibleStickyHeaderPosition(int firstVisibleItem, int visibleItemCo

for (int childIndex = 0; childIndex < visibleItemCount; childIndex++) {
int position = firstVisibleItem + childIndex;
int viewType = adapter.getItemViewType(position);
if (type == HEADER_LEVEL_0 && viewType == type)
int headerLevel = ((DoubleStickHeadersListAdapter)getAdapter()).getHeaderLevel(position);
if (level == HEADER_LEVEL_0 && headerLevel == level)
return position;
if (type == HEADER_LEVEL_1 && viewType == type) return position;
if (level == HEADER_LEVEL_1 && headerLevel == level) return position;
}
return -1;
}

int findCurrentLevel2StickyHeaderPosition(int firstVisibleItem) {
int viewType = getAdapter().getItemViewType(firstVisibleItem + 1);
int headerLevel = ((DoubleStickHeadersListAdapter)getAdapter()).getHeaderLevel(firstVisibleItem + 1);
int stickyHeaderPosition1;
if (viewType == HEADER_LEVEL_2) {
if (headerLevel == HEADER_LEVEL_2) {
stickyHeaderPosition1 = findCurrentStickyHeaderPosition(firstVisibleItem + 1, 1);
} else if (viewType == HEADER_LEVEL_1) {
} else if (headerLevel == HEADER_LEVEL_1) {
if (isLevel1HeaderSticky(firstVisibleItem + 1)) {
stickyHeaderPosition1 = firstVisibleItem + 1;
} else {
Expand All @@ -312,16 +314,16 @@ int findCurrentLevel2StickyHeaderPosition(int firstVisibleItem) {
return stickyHeaderPosition1;
}

int findCurrentStickyHeaderPosition(int fromPosition, int type) {
int findCurrentStickyHeaderPosition(int fromPosition, int level) {
ListAdapter adapter = getAdapter();

if (fromPosition >= adapter.getCount()) return -1;

for (int position = fromPosition; position >= 0; position--) {
int viewType = adapter.getItemViewType(position);
if (type == HEADER_LEVEL_0 && viewType == type)
int headerLevel = ((DoubleStickHeadersListAdapter)getAdapter()).getHeaderLevel(position);
if (level == HEADER_LEVEL_0 && headerLevel == level)
return position;
if (type == HEADER_LEVEL_1 && viewType == type) return position;
if (level == HEADER_LEVEL_1 && headerLevel == level) return position;
}
return -1;
}
Expand Down Expand Up @@ -431,14 +433,14 @@ public boolean dispatchTouchEvent(MotionEvent ev) {
if (mStickyHeader0 != null && isStickyHeaderTouched(mStickyHeader0.view, x, y, HEADER_LEVEL_0)) {
mTouchTarget = mStickyHeader0.view;
mStickyCatchTouch = true;
mTouchTargetType = HEADER_LEVEL_0;
mTouchTargetLevel = HEADER_LEVEL_0;
mTouchPoint.x = x;
mTouchPoint.y = y;
}
if (mStickyHeader1 != null && isStickyHeaderTouched(mStickyHeader1.view, x, y - mStickyHeader0.view.getHeight(), HEADER_LEVEL_1)) {
mTouchTarget = mStickyHeader1.view;
mStickyCatchTouch = true;
mTouchTargetType = HEADER_LEVEL_1;
mTouchTargetLevel = HEADER_LEVEL_1;
mTouchPoint.x = x;
mTouchPoint.y = y;
ev.setLocation(x, y - mStickyHeader0.view.getHeight());
Expand Down Expand Up @@ -471,7 +473,7 @@ public boolean dispatchTouchEvent(MotionEvent ev) {
mTouchTarget.setPressed(false);
invalidate();
}
int postion = mTouchTargetType == HEADER_LEVEL_0 ? mStickyHeader0.position : mStickyHeader1.position;
int postion = mTouchTargetLevel == HEADER_LEVEL_0 ? mStickyHeader0.position : mStickyHeader1.position;
performItemClick(mTouchTarget, postion, postion);
}
}
Expand All @@ -482,10 +484,10 @@ public boolean dispatchTouchEvent(MotionEvent ev) {
return super.dispatchTouchEvent(ev);
}

private boolean isStickyHeaderTouched(View view, float x, float y, int type) {
private boolean isStickyHeaderTouched(View view, float x, float y, int level) {
view.getHitRect(mTouchRect);

int translateY = type == HEADER_LEVEL_0 ? mTranslateY0 : mTranslateY1;
int translateY = level == HEADER_LEVEL_0 ? mTranslateY0 : mTranslateY1;
mTouchRect.top += translateY;
mTouchRect.bottom += translateY + getPaddingTop();
mTouchRect.left += getPaddingLeft();
Expand Down

0 comments on commit e6f4dce

Please sign in to comment.