Android Staggered Grid & Record View.

Create Android Staggered Lib Challenge.

—>  AndroidManifest.xml

values folder

attrs.xml











ClassLoaderSavedState.java

package deal com.android.grid;

import android.os.Parcel;
import android.os.Parcelable;

public summary class ClassLoaderSavedState implements Parcelable {
public static closing ClassLoaderSavedState EMPTY_STATE = new ClassLoaderSavedState() {};

personal Parcelable mSuperState = EMPTY_STATE;
personal ClassLoader mClassLoader;

personal ClassLoaderSavedState() {
mSuperState = null;
mClassLoader = null;
}

protected ClassLoaderSavedState(Parcelable superState, ClassLoader classLoader) {
mClassLoader = classLoader;
if (superState == null) {
throw new IllegalArgumentException(“superState must not be null”);
}
else {
mSuperState = superState != EMPTY_STATE ? superState : null;
}
}

protected ClassLoaderSavedState(Parcel supply) {
// ETSY : we’re utilizing the handed tremendous class loader in contrast to AbsSavedState
Parcelable superState = supply.readParcelable(mClassLoader);
mSuperState = superState != null ? superState : EMPTY_STATE;
}

closing public Parcelable getSuperState() {
return mSuperState;
}

public int describeContents() {
return 0;
}

public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(mSuperState, flags);
}

public static closing Parcelable.Creator CREATOR
= new Parcelable.Creator() {

public ClassLoaderSavedState createFromParcel(Parcel in) {
Parcelable superState = in.readParcelable(null);
if (superState != null) {
throw new IllegalStateException(“superState must be null”);
}
return EMPTY_STATE;
}

public ClassLoaderSavedState[] newArray(int dimension) {
return new ClassLoaderSavedState[size];
}
};
}

ExtendableListView.java

package deal com.android.grid;

import android.annotation.SuppressLint;
import android.content material.Context;
import android.database.DataSetObserver;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Parcel;
import android.os.Parcelable;
import android.help.v4.util.SparseArrayCompat;
import android.help.v4.view.MotionEventCompat;
import android.help.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.*;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.Scroller;
import java.util.ArrayList;

public summary class ExtendableListView extends AbsListView {

personal static closing String TAG = “ExtendableListView”;

personal static closing boolean DBG = false;

personal static closing int TOUCH_MODE_IDLE = 0;
personal static closing int TOUCH_MODE_SCROLLING = 1;
personal static closing int TOUCH_MODE_FLINGING = 2;
personal static closing int TOUCH_MODE_DOWN = 3;
personal static closing int TOUCH_MODE_TAP = 4;
personal static closing int TOUCH_MODE_DONE_WAITING = 5;

personal static closing int INVALID_POINTER = -1;

// Structure utilizing our default current state
personal static closing int LAYOUT_NORMAL = 0;
// Structure from the primary merchandise down
personal static closing int LAYOUT_FORCE_TOP = 1;
// Structure from the saved occasion state knowledge
personal static closing int LAYOUT_SYNC = 2;

personal int mLayoutMode;

personal int mTouchMode;
personal int mScrollState = OnScrollListener.SCROLL_STATE_IDLE;

// Rectangle used for hit testing youngsters
// personal Rect mTouchFrame;
// TODO : ItemClick help from AdapterView

// For managing scrolling
personal VelocityTracker mVelocityTracker = null;

personal int mTouchSlop;
personal int mMaximumVelocity;
personal int mFlingVelocity;

personal boolean mInLayout;

ListAdapter mAdapter;

personal int mMotionY;
personal int mMotionX;
personal int mMotionCorrection;
personal int mMotionPosition;

personal int mLastY;

personal int mActivePointerId = INVALID_POINTER;

protected int mFirstPosition;

// are we connected to a window – we shouldn’t deal with any contact occasions if we’re not!
personal boolean mIsAttached;

personal boolean mBlockLayoutRequests = false;

// has our knowledge modified – and will we react to it
personal boolean mDataChanged;
personal int mItemCount;
personal int mOldItemCount;

closing boolean[] mIsScrap = new boolean[1];

personal RecycleBin mRecycleBin;

personal AdapterDataSetObserver mObserver;
personal int mWidthMeasureSpec;
personal FlingRunnable mFlingRunnable;

protected boolean mClipToPadding;
personal PerformClick mPerformClick;

personal Runnable mPendingCheckForTap;
personal CheckForLongPress mPendingCheckForLongPress;

personal class CheckForLongPress extends WindowRunnnable implements Runnable {
public void run() {
closing int motionPosition = mMotionPosition;
closing View little one = getChildAt(motionPosition);
if (little one != null) {
closing int longPressPosition = mMotionPosition;
closing lengthy longPressId = mAdapter.getItemId(mMotionPosition + mFirstPosition);

boolean dealt with = false;
if (sameWindow() && !mDataChanged) {
dealt with = performLongPress(little one, longPressPosition + mFirstPosition, longPressId);
}
if (dealt with) {
mTouchMode = TOUCH_MODE_IDLE;
setPressed(false);
little one.setPressed(false);
} else {
mTouchMode = TOUCH_MODE_DONE_WAITING;
}

}
}
}

public class FixedViewInfo {

public View view;

public Object knowledge;

public boolean isSelectable;
}

personal ArrayList mHeaderViewInfos;
personal ArrayList mFooterViewInfos;

public ExtendableListView(closing Context context, closing AttributeSet attrs, closing int defStyle) {
tremendous(context, attrs, defStyle);

// setting as much as be a scrollable view group
setWillNotDraw(false);
setClipToPadding(false);
setFocusableInTouchMode(false);

closing ViewConfiguration viewConfiguration = ViewConfiguration.get(context);
mTouchSlop = viewConfiguration.getScaledTouchSlop();
mMaximumVelocity = viewConfiguration.getScaledMaximumFlingVelocity();
mFlingVelocity = viewConfiguration.getScaledMinimumFlingVelocity();

mRecycleBin = new RecycleBin();
mObserver = new AdapterDataSetObserver();

mHeaderViewInfos = new ArrayList();
mFooterViewInfos = new ArrayList();

// begin our structure mode drawing from the highest
mLayoutMode = LAYOUT_NORMAL;
}

@Override
protected void onAttachedToWindow() {
tremendous.onAttachedToWindow();

if (mAdapter != null) {
// Knowledge could have modified whereas we had been indifferent. Refresh.
mDataChanged = true;
mOldItemCount = mItemCount;
mItemCount = mAdapter.getCount();
}
mIsAttached = true;
}

@Override
protected void onDetachedFromWindow() {
tremendous.onDetachedFromWindow();

// Detach any view left within the scrap heap
mRecycleBin.clear();

if (mFlingRunnable != null) {
removeCallbacks(mFlingRunnable);
}

mIsAttached = false;
}

@Override
protected void onFocusChanged(boolean gainFocus, int route, Rect previouslyFocusedRect) {
// TODO : deal with focus and its influence on choice – if we add merchandise choice help
}

@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
// TODO : deal with focus and its influence on choice – if we add merchandise choice help
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
onSizeChanged(w, h);
}

protected void onSizeChanged(int w, int h) {
if (getChildCount() > 0) {
stopFlingRunnable();
mRecycleBin.clear();
mDataChanged = true;
rememberSyncState();
}
}

@Override
public ListAdapter getAdapter() {
return mAdapter;
}

@Override
public void setAdapter(closing ListAdapter adapter) {
if (mAdapter != null) {
mAdapter.unregisterDataSetObserver(mObserver);
}

// use a wrapper record adapter if we now have a header or footer
if (mHeaderViewInfos.dimension() > 0 || mFooterViewInfos.dimension() > 0) {
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
}
else {
mAdapter = adapter;
}

mDataChanged = true;
mItemCount = mAdapter != null ? mAdapter.getCount() : 0;

if (mAdapter != null) {
mAdapter.registerDataSetObserver(mObserver);
mRecycleBin.setViewTypeCount(mAdapter.getViewTypeCount());
}

requestLayout();
}

@Override
public int getCount() {
return mItemCount;
}

@Override
public View getSelectedView() {
if (DBG) Log.e(TAG, “getSelectedView() is not supported in ExtendableListView yet”);
return null;
}

@Override
public void setSelection(closing int place) {
if (place >= 0) {
mLayoutMode = LAYOUT_SYNC;
mSpecificTop = getListPaddingTop();

mFirstPosition = 0;
if (mNeedSync) {
mSyncPosition = place;
mSyncRowId = mAdapter.getItemId(place);
}
requestLayout();
}
}

public void addHeaderView(View v, Object knowledge, boolean isSelectable) {

if (mAdapter != null && !(mAdapter instanceof HeaderViewListAdapter)) {
throw new IllegalStateException(
“Cannot add header view to list — setAdapter has already been called.”);
}

FixedViewInfo information = new FixedViewInfo();
information.view = v;
information.knowledge = knowledge;
information.isSelectable = isSelectable;
mHeaderViewInfos.add(information);

if (mAdapter != null && mObserver != null) {
mObserver.onChanged();
}
}

public void addHeaderView(View v) {
addHeaderView(v, null, true);
}

public int getHeaderViewsCount() {
return mHeaderViewInfos.dimension();
}

boolean removeHeaderView(View v) {
if (mHeaderViewInfos.dimension() > 0) {
boolean outcome = false;
if (mAdapter != null && ((HeaderViewListAdapter) mAdapter).removeHeader(v)) {
if (mObserver != null) {
mObserver.onChanged();
}
outcome = true;
}
removeFixedViewInfo(v, mHeaderViewInfos);
return outcome;
}
return false;
}

personal void removeFixedViewInfo(View v, ArrayList the place) {
int len = the place.dimension();
for (int i = 0; i 0) {
boolean outcome = false;
if (mAdapter != null && ((HeaderViewListAdapter) mAdapter).removeFooter(v)) {
if (mObserver != null) {
mObserver.onChanged();
}
outcome = true;
}
removeFixedViewInfo(v, mFooterViewInfos);
return outcome;
}
return false;
}

@Override
public void setClipToPadding(closing boolean clipToPadding) {
tremendous.setClipToPadding(clipToPadding);
mClipToPadding = clipToPadding;
}

@Override
public void requestLayout() {
if (!mBlockLayoutRequests && !mInLayout) {
tremendous.requestLayout();
}
}

@Override
protected void onLayout(closing boolean modified, closing int l, closing int t, closing int r, closing int b) {
// tremendous.onLayout(modified, l, t, r, b); – skipping base AbsListView implementation on objective
// haven’t set an adapter but? get to it
if (mAdapter == null) {
return;
}

if (modified) {
int childCount = getChildCount();
for (int i = 0; i 0 && mNeedSync) {
mNeedSync = false;
mSyncState = null;

mLayoutMode = LAYOUT_SYNC;
mSyncPosition = Math.min(Math.max(0, mSyncPosition), rely – 1);
return;
}

mLayoutMode = LAYOUT_FORCE_TOP;
mNeedSync = false;
mSyncState = null;

// TODO : add choice dealing with right here
}

public void resetToTop() {
// TO override
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
tremendous.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(widthSize, heightSize);
mWidthMeasureSpec = widthMeasureSpec;
}

@Override
public boolean onTouchEvent(MotionEvent occasion) {

if (!isEnabled())

initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(occasion);

if (!hasChildren()) return false;

boolean dealt with;
closing int motion = occasion.getAction() & MotionEventCompat.ACTION_MASK;
change (motion) {
case MotionEvent.ACTION_DOWN:
dealt with = onTouchDown(occasion);
break;

case MotionEvent.ACTION_MOVE:
dealt with = onTouchMove(occasion);
break;

case MotionEvent.ACTION_CANCEL:
dealt with = onTouchCancel(occasion);
break;

case MotionEvent.ACTION_POINTER_UP:
dealt with = onTouchPointerUp(occasion);
break;

case MotionEvent.ACTION_UP:
dealt with = onTouchUp(occasion);
break;

default:
dealt with = false;
break;
}

notifyTouchMode();

return dealt with;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
int motion = ev.getAction();

if (!mIsAttached) {

return false;
}

change (motion & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
int touchMode = mTouchMode;

closing int x = (int) ev.getX();
closing int y = (int) ev.getY();
mActivePointerId = ev.getPointerId(0);

int motionPosition = findMotionRow(y);
if (touchMode != TOUCH_MODE_FLINGING && motionPosition >= 0) {
// Consumer clicked on an precise view (and was not stopping a fling).
// Bear in mind the place the movement occasion began
mMotionX = x;
mMotionY = y;
mMotionPosition = motionPosition;
mTouchMode = TOUCH_MODE_DOWN;
}
mLastY = Integer.MIN_VALUE;
initOrResetVelocityTracker();
mVelocityTracker.addMovement(ev);
if (touchMode == TOUCH_MODE_FLINGING) {
return true;
}
break;
}

case MotionEvent.ACTION_MOVE: {
change (mTouchMode) {
case TOUCH_MODE_DOWN:
int pointerIndex = ev.findPointerIndex(mActivePointerId);
if (pointerIndex == -1) {
pointerIndex = 0;
mActivePointerId = ev.getPointerId(pointerIndex);
}
closing int y = (int) ev.getY(pointerIndex);
initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(ev);
if (startScrollIfNeeded(y)) {
return true;
}
break;
}
break;
}

case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
mTouchMode = TOUCH_MODE_IDLE;
mActivePointerId = INVALID_POINTER;
recycleVelocityTracker();
reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
break;
}

case MotionEvent.ACTION_POINTER_UP: {
onSecondaryPointerUp(ev);
break;
}
}

return false;
}

@Override
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
if (disallowIntercept) {
recycleVelocityTracker();
}
tremendous.requestDisallowInterceptTouchEvent(disallowIntercept);
}

closing class CheckForTap implements Runnable {
public void run() {
if (mTouchMode == TOUCH_MODE_DOWN) {
mTouchMode = TOUCH_MODE_TAP;
closing View little one = getChildAt(mMotionPosition);
if (little one != null && !little one.hasFocusable()) {
mLayoutMode = LAYOUT_NORMAL;

if (!mDataChanged) {
layoutChildren();
little one.setPressed(true);
setPressed(true);

closing int longPressTimeout = ViewConfiguration.getLongPressTimeout();
closing boolean longClickable = isLongClickable();

if (longClickable) {
if (mPendingCheckForLongPress == null) {
mPendingCheckForLongPress = new CheckForLongPress();
}
mPendingCheckForLongPress.rememberWindowAttachCount();
postDelayed(mPendingCheckForLongPress, longPressTimeout);
} else {
mTouchMode = TOUCH_MODE_DONE_WAITING;
}
} else {
mTouchMode = TOUCH_MODE_DONE_WAITING;
}
}
}
}
}

personal boolean onTouchDown(closing MotionEvent occasion) {
closing int x = (int) occasion.getX();
closing int y = (int) occasion.getY();
int motionPosition = pointToPosition(x, y);

mVelocityTracker.clear();
mActivePointerId = MotionEventCompat.getPointerId(occasion, 0);

if ((mTouchMode != TOUCH_MODE_FLINGING) &&
!mDataChanged &&
motionPosition >= 0 &&
getAdapter().isEnabled(motionPosition)) {
// is it a faucet or a scroll .. we don’t know but!
mTouchMode = TOUCH_MODE_DOWN;

if (mPendingCheckForTap == null) {
mPendingCheckForTap = new CheckForTap();
}
postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());

if (occasion.getEdgeFlags() != 0 && motionPosition = getListPaddingTop() &&
mFirstPosition + getChildCount() mFlingVelocity) {
startFlingRunnable(velocity);
mTouchMode = TOUCH_MODE_FLINGING;
mMotionY = 0;
invalidate();
return true;
}
}
}

stopFlingRunnable();
recycleVelocityTracker();
mTouchMode = TOUCH_MODE_IDLE;
return true;
}

personal boolean onTouchUpTap(closing MotionEvent occasion) {
closing int motionPosition = mMotionPosition;
if (motionPosition >= 0) {
closing View little one = getChildAt(motionPosition);
if (little one != null && !little one.hasFocusable()) {
if (mTouchMode != TOUCH_MODE_DOWN) {
little one.setPressed(false);
}

if (mPerformClick == null) {
invalidate();
mPerformClick = new PerformClick();
}

closing PerformClick performClick = mPerformClick;
performClick.mClickMotionPosition = motionPosition;
performClick.rememberWindowAttachCount();

//            mResurrectToPosition = motionPosition;

if (mTouchMode == TOUCH_MODE_DOWN || mTouchMode == TOUCH_MODE_TAP) {
closing Handler handler = getHandler();
if (handler != null) {
handler.removeCallbacks(mTouchMode == TOUCH_MODE_DOWN ?
mPendingCheckForTap : mPendingCheckForLongPress);
}
mLayoutMode = LAYOUT_NORMAL;
if (!mDataChanged && motionPosition >= 0 && mAdapter.isEnabled(motionPosition)) {
mTouchMode = TOUCH_MODE_TAP;
layoutChildren();
little one.setPressed(true);
setPressed(true);
postDelayed(new Runnable() {
public void run() {
little one.setPressed(false);
setPressed(false);
if (!mDataChanged) {
submit(performClick);
}
mTouchMode = TOUCH_MODE_IDLE;
}
}, ViewConfiguration.getPressedStateDuration());
} else {
mTouchMode = TOUCH_MODE_IDLE;
}
return true;
} else if (!mDataChanged && motionPosition >= 0 && mAdapter.isEnabled(motionPosition)) {
submit(performClick);
}
}
}
mTouchMode = TOUCH_MODE_IDLE;

return true;
}

personal boolean onTouchPointerUp(closing MotionEvent occasion) {
onSecondaryPointerUp(occasion);
closing int x = mMotionX;
closing int y = mMotionY;
closing int motionPosition = pointToPosition(x, y);
if (motionPosition >= 0) {
mMotionPosition = motionPosition;
}
mLastY = y;
return true;
}

personal void onSecondaryPointerUp(MotionEvent occasion) {
closing int pointerIndex = (occasion.getAction() &
MotionEventCompat.ACTION_POINTER_INDEX_MASK) >>
MotionEventCompat.ACTION_POINTER_INDEX_SHIFT;
closing int pointerId = occasion.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our lively pointer going up. Select a brand new
// lively pointer and alter accordingly.
// TODO: Make this choice extra clever.
closing int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mMotionX = (int) occasion.getX(newPointerIndex);
mMotionY = (int) occasion.getY(newPointerIndex);
mActivePointerId = occasion.getPointerId(newPointerIndex);
recycleVelocityTracker();
}
}

personal boolean startScrollIfNeeded(closing int y) {
closing int deltaY = y – mMotionY;
closing int distance = Math.abs(deltaY);
// TODO : Overscroll?
// closing boolean overscroll = mScrollY != 0;
closing boolean overscroll = false;
if (overscroll || distance > mTouchSlop) {
if (overscroll) {
mMotionCorrection = 0;
}
else {
mTouchMode = TOUCH_MODE_SCROLLING;
mMotionCorrection = deltaY > 0 ? mTouchSlop : -mTouchSlop;
}

closing Handler handler = getHandler();
if (handler != null) {
handler.removeCallbacks(mPendingCheckForLongPress);
}
setPressed(false);
View motionView = getChildAt(mMotionPosition – mFirstPosition);
if (motionView != null) {
motionView.setPressed(false);
}
closing ViewParent dad or mum = getParent();
if (dad or mum != null) {
dad or mum.requestDisallowInterceptTouchEvent(true);
}

scrollIfNeeded(y);
return true;
}
return false;
}

personal void scrollIfNeeded(closing int y) {
if (DBG) Log.d(TAG, “scrollIfNeeded y: ” + y);
closing int rawDeltaY = y – mMotionY;
closing int deltaY = rawDeltaY – mMotionCorrection;
int incrementalDeltaY = mLastY != Integer.MIN_VALUE ? y – mLastY : deltaY;

if (mTouchMode == TOUCH_MODE_SCROLLING) {
if (DBG) Log.d(TAG, “scrollIfNeeded TOUCH_MODE_SCROLLING”);
if (y != mLastY) {
// cease our dad or mum
if (Math.abs(rawDeltaY) > mTouchSlop) {
closing ViewParent dad or mum = getParent();
if (dad or mum != null) {
dad or mum.requestDisallowInterceptTouchEvent(true);
}
}

closing int motionIndex;
if (mMotionPosition >= 0) {
motionIndex = mMotionPosition – mFirstPosition;
}
else {

motionIndex = getChildCount() / 2;
}

// No must do all this work if we’re not going to maneuver anyway
boolean atEdge = false;
if (incrementalDeltaY != 0) {
atEdge = moveTheChildren(deltaY, incrementalDeltaY);
}

// Examine to see if we now have ran into the scroll restrict
View motionView = this.getChildAt(motionIndex);
if (motionView != null) {
if (atEdge) {
// TODO : edge impact & overscroll
}
mMotionY = y;
}
mLastY = y;
}

}
// TODO : ELSE SUPPORT OVERSCROLL!
}

personal int findMotionRow(int y) {
int childCount = getChildCount();
if (childCount > 0) {
// all the time from the highest
for (int i = 0; i = maxTop && incrementalDeltaY >= 0);
closing boolean cannotScrollUp = (firstPosition + childCount == mItemCount &&
lastBottom = prime) {
break;
}
else {
rely++;
int place = firstPosition + i;
if (place >= headerViewsCount && place = 0; i–) {
closing View little one = getChildAt(i);
if (little one.getTop() = headerViewsCount && place 0) {
if (DBG) Log.d(TAG, “scrap – detachViewsFromParent start:” + begin + ” rely:” + rely);
detachViewsFromParent(begin, rely);
mRecycleBin.removeSkippedScrap();
onChildrenDetached(begin, rely);
}

if (!awakenScrollBars()) {
invalidate();
}

offsetChildrenTopAndBottom(incrementalDeltaY);

if (isDown) {
mFirstPosition += rely;
}

closing int absIncrementalDeltaY = Math.abs(incrementalDeltaY);
if (spaceAbove finish || hasSpaceUp()) && pos >= 0) {
// TODO : add choice help
makeAndAddView(pos, nextBottom, false, false);
pos–;
nextBottom = getNextChildUpsBottom(pos);
if (DBG) Log.d(TAG, “fillUp next – position:” + pos + ” nextBottom:” + nextBottom);
}

mFirstPosition = pos + 1;
return selectedView;
}

protected boolean hasSpaceUp() {
return false;
}

personal View fillFromTop(int nextTop) {
mFirstPosition = Math.min(mFirstPosition, mItemCount – 1);
if (mFirstPosition 0) {
correctTooHigh(childCount);
}

if (tempIsSelected) {
return temp;
}
else if (above != null) {
return above;
}
else {
return under;
}
}

personal View makeAndAddView(int place, int y, boolean flowDown, boolean chosen) {
View little one;

onChildCreated(place, flowDown);

if (!mDataChanged) {
// Attempt to use an current view for this place
little one = mRecycleBin.getActiveView(place);
if (little one != null) {

// Discovered it — we’re utilizing an current little one
// This simply must be positioned
setupChild(little one, place, y, flowDown, chosen, true);
return little one;
}
}

// Make a brand new view for this place, or convert an unused view if attainable
little one = obtainView(place, mIsScrap);
// This must be positioned and measured
setupChild(little one, place, y, flowDown, chosen, mIsScrap[0]);

return little one;
}

personal void setupChild(View little one, int place, int y, boolean flowDown,
boolean chosen, boolean recycled) {
closing boolean isSelected = false; // TODO : chosen && shouldShowSelector();
closing boolean updateChildSelected = isSelected != little one.isSelected();
closing int mode = mTouchMode;
closing boolean isPressed = mode > TOUCH_MODE_DOWN && mode 0) {
childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
}
else {
childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
little one.measure(childWidthSpec, childHeightSpec);
}

protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT, 0);
}

protected LayoutParams generateHeaderFooterLayoutParams(closing View little one) {
return new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT, 0);
}

personal View obtainView(int place, boolean[] isScrap) {
isScrap[0] = false;
View scrapView;

scrapView = mRecycleBin.getScrapView(place);

View little one;
if (scrapView != null) {
if (DBG) Log.d(TAG, “getView from scrap position:” + place);
little one = mAdapter.getView(place, scrapView, this);

if (little one != scrapView) {
mRecycleBin.addScrapView(scrapView, place);
}
else {
isScrap[0] = true;
}
}
else {
if (DBG) Log.d(TAG, “getView position:” + place);
little one = mAdapter.getView(place, null, this);
}

return little one;
}

personal void correctTooHigh(int childCount) {
// First see if the final merchandise is seen. If it isn’t, it’s OK for the
// prime of the record to be pushed up.
int lastPosition = mFirstPosition + childCount – 1;
if (lastPosition == mItemCount – 1 && childCount > 0) {

// … and its backside edge
closing int lastBottom = getLowestChildBottom();

// That is backside of our drawable space
closing int finish = (getBottom() – getTop()) – getListPaddingBottom();

// That is how far the underside fringe of the final view is from the underside of the
// drawable space
int bottomOffset = finish – lastBottom;

closing int firstTop = getHighestChildTop();

// Ensure we’re 1) Too excessive, and a pair of) Both there are extra rows above the
// first row or the primary row is scrolled off the highest of the drawable space
if (bottomOffset > 0 && (mFirstPosition > 0 || firstTop 0) {
// Fill the hole that was opened above mFirstPosition with extra rows, if
// attainable
int previousPosition = mFirstPosition – 1;
fillUp(previousPosition, getNextChildUpsBottom(previousPosition));
// Shut up the remaining hole
adjustViewsUpOrDown();
}

}
}
}

personal void correctTooLow(int childCount) {
// First see if the primary merchandise is seen. If it isn’t, it’s OK for the
// backside of the record to be pushed down.
if (mFirstPosition == 0 && childCount > 0) {

// … and its prime edge
closing int firstTop = getHighestChildTop();

// That is prime of our drawable space
closing int begin = getListPaddingTop();

// That is backside of our drawable space
closing int finish = (getTop() – getBottom()) – getListPaddingBottom();

// That is how far the highest fringe of the primary view is from the highest of the
// drawable space
int topOffset = firstTop – begin;
closing int lastBottom = getLowestChildBottom();

int lastPosition = mFirstPosition + childCount – 1;

// Ensure we’re 1) Too low, and a pair of) Both there are extra rows under the
// final row or the final row is scrolled off the underside of the drawable space
if (topOffset > 0) {
if (lastPosition finish) {
if (lastPosition == mItemCount – 1) {
// Don’t pull the underside too far up
topOffset = Math.min(topOffset, lastBottom – finish);
}
// Transfer every little thing up
offsetChildrenTopAndBottom(-topOffset);
if (lastPosition 0) {
// Uh-oh — we got here up quick. Slide all views as much as make them
// align with the highest
delta = getHighestChildTop() – getListPaddingTop();
if (delta 0 ? getChildAt(rely – 1).getBottom() : paddingTop;
}

protected int getChildBottom(closing int place) {
int rely = getChildCount();
int paddingBottom = 0;
if (mClipToPadding) {
paddingBottom = getListPaddingBottom();
}
return rely > 0 ? getChildAt(0).getTop() : getHeight() – paddingBottom;
}

protected int getNextChildDownsTop(closing int place) {
closing int rely = getChildCount();
return rely > 0 ? getChildAt(rely – 1).getBottom() : 0;
}

protected int getNextChildUpsBottom(closing int place) {
closing int rely = getChildCount();
if (rely == 0) {
return 0;
}
return rely > 0 ? getChildAt(0).getTop() : 0;
}

protected int getFirstChildTop() {
return hasChildren() ? getChildAt(0).getTop() : 0;
}

protected int getHighestChildTop() {
return hasChildren() ? getChildAt(0).getTop() : 0;
}

protected int getLastChildBottom() {
return hasChildren() ? getChildAt(getChildCount() – 1).getBottom() : 0;
}

protected int getLowestChildBottom() {
return hasChildren() ? getChildAt(getChildCount() – 1).getBottom() : 0;
}

protected boolean hasChildren() {
return getChildCount() > 0;
}

protected void offsetChildrenTopAndBottom(int offset) {
if (DBG) Log.d(TAG, “offsetChildrenTopAndBottom: ” + offset);
closing int rely = getChildCount();
for (int i = 0; i 0) {
// Record is transferring in the direction of the highest. Use first view as mMotionPosition
mMotionPosition = mFirstPosition;
// Don’t fling greater than 1 display screen
delta = Math.min(getHeight() – getPaddingBottom() – getPaddingTop() – 1, delta);
}
else {
// Record is transferring in the direction of the underside. Use final view as mMotionPosition
int offsetToLast = getChildCount() – 1;
mMotionPosition = mFirstPosition + offsetToLast;

// Don’t fling greater than 1 display screen
delta = Math.max(-(getHeight() – getPaddingBottom() – getPaddingTop() – 1), delta);
}

closing boolean atEnd = moveTheChildren(delta, delta);

if (extra && !atEnd) {
invalidate();
mLastFlingY = y;
postOnAnimate(this);
}
else {
endFling();
}
break;
}
}
}

}

personal void postOnAnimate(Runnable runnable) {
ViewCompat.postOnAnimation(this, runnable);
}

public void notifyTouchMode() {
// solely inform the scroll listener about some issues we wish it to know
change (mTouchMode) {
case TOUCH_MODE_SCROLLING:
reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
break;
case TOUCH_MODE_FLINGING:
reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
break;
case TOUCH_MODE_IDLE:
reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
break;
}
}

personal OnScrollListener mOnScrollListener;

public void setOnScrollListener(OnScrollListener scrollListener) {
tremendous.setOnScrollListener(scrollListener);
mOnScrollListener = scrollListener;
}

void reportScrollStateChange(int newState) {
if (newState != mScrollState) {
mScrollState = newState;
if (mOnScrollListener != null) {
mOnScrollListener.onScrollStateChanged(this, newState);
}
}
}

void invokeOnItemScrollListener() {
if (mOnScrollListener != null) {
mOnScrollListener.onScroll(this, mFirstPosition, getChildCount(), mItemCount);
}
}

@SuppressLint(“WrongCall”) personal void updateEmptyStatus() {
boolean empty = getAdapter() == null || getAdapter().isEmpty();
if (isInFilterMode()) {
empty = false;
}

View emptyView = getEmptyView();
if (empty) {
if (emptyView != null) {
emptyView.setVisibility(View.VISIBLE);
setVisibility(View.GONE);
}
else {
// If the caller simply eliminated our empty view, ensure the record view is seen
setVisibility(View.VISIBLE);
}

// We are actually GONE, so pending layouts is not going to be dispatched.
// Drive one right here to guarantee that the state of the record matches
// the state of the adapter.
if (mDataChanged) {
this.onLayout(false, getLeft(), getTop(), getRight(), getBottom());
}
}
else {
if (emptyView != null) {
emptyView.setVisibility(View.GONE);
}
setVisibility(View.VISIBLE);
}
}

// //////////////////////////////////////////////////////////////////////////////////////////
// ADAPTER OBSERVER
//

class AdapterDataSetObserver extends DataSetObserver {

personal Parcelable mInstanceState = null;

@Override
public void onChanged() {
mDataChanged = true;
mOldItemCount = mItemCount;
mItemCount = getAdapter().getCount();

mRecycleBin.clearTransientStateViews();

// Detect the case the place a cursor that was beforehand invalidated has
// been repopulated with new knowledge.
if (ExtendableListView.this.getAdapter().hasStableIds() && mInstanceState != null
&& mOldItemCount == 0 && mItemCount > 0) {
ExtendableListView.this.onRestoreInstanceState(mInstanceState);
mInstanceState = null;
}
else {
rememberSyncState();
}

updateEmptyStatus();
requestLayout();
}

@Override
public void onInvalidated() {
mDataChanged = true;

if (ExtendableListView.this.getAdapter().hasStableIds()) {
// Bear in mind the present state for the case the place our internet hosting exercise is being
// stopped and later restarted
mInstanceState = ExtendableListView.this.onSaveInstanceState();
}

// Knowledge is invalid so we should always reset our state
mOldItemCount = mItemCount;
mItemCount = 0;
mNeedSync = false;

updateEmptyStatus();
requestLayout();
}

public void clearSavedState() {
mInstanceState = null;
}
}

public static class LayoutParams extends AbsListView.LayoutParams {

boolean recycledHeaderFooter;

// Place of the view within the knowledge
int place;

// adapter ID the view represents fetched from the adapter if it’s steady
lengthy itemId = -1;

// adapter view sort
int viewType;

public LayoutParams(Context c, AttributeSet attrs) {
tremendous(c, attrs);
}

public LayoutParams(int w, int h) {
tremendous(w, h);
}

public LayoutParams(int w, int h, int viewType) {
tremendous(w, h);
this.viewType = viewType;
}

public LayoutParams(ViewGroup.LayoutParams supply) {
tremendous(supply);
}

}

class RecycleBin {

personal int mFirstActivePosition;

personal View[] mActiveViews = new View[0];

personal ArrayList[] mScrapViews;

personal int mViewTypeCount;

personal ArrayList mCurrentScrap;

personal ArrayList mSkippedScrap;

personal SparseArrayCompat mTransientStateViews;

public void setViewTypeCount(int viewTypeCount) {
if (viewTypeCount [] scrapViews = new ArrayList[viewTypeCount];
for (int i = 0; i ();
}
mViewTypeCount = viewTypeCount;
mCurrentScrap = scrapViews[0];
mScrapViews = scrapViews;
}

public void markChildrenDirty() {
if (mViewTypeCount == 1) {
closing ArrayList scrap = mCurrentScrap;
closing int scrapCount = scrap.dimension();
for (int i = 0; i scrap = mScrapViews[i];
closing int scrapCount = scrap.dimension();
for (int j = 0; j = 0;
}

void clear() {
if (mViewTypeCount == 1) {
closing ArrayList scrap = mCurrentScrap;
closing int scrapCount = scrap.dimension();
for (int i = 0; i scrap = mScrapViews[i];
closing int scrapCount = scrap.dimension();
for (int j = 0; j = 0 && index = 0 && whichScrap ();
}
mSkippedScrap.add(scrap);
}
if (scrapHasTransientState) {
if (mTransientStateViews == null) {
mTransientStateViews = new SparseArrayCompat();
}
mTransientStateViews.put(place, scrap);
}
return;
}

if (mViewTypeCount == 1) {
mCurrentScrap.add(scrap);
}
else {
mScrapViews[viewType].add(scrap);
}
}

void removeSkippedScrap() {
if (mSkippedScrap == null) {
return;
}
closing int rely = mSkippedScrap.dimension();
for (int i = 0; i 1;

ArrayList scrapViews = mCurrentScrap;
closing int rely = activeViews.size;
for (int i = rely – 1; i >= 0; i–) {
closing View sufferer = activeViews[i];
if (sufferer != null) {
closing LayoutParams lp = (LayoutParams) sufferer.getLayoutParams();
activeViews[i] = null;

closing boolean scrapHasTransientState = ViewCompat.hasTransientState(sufferer);
int viewType = lp.viewType;

if (!shouldRecycleViewType(viewType) || scrapHasTransientState) {
// Don’t transfer views that needs to be ignored
if (viewType != ITEM_VIEW_TYPE_HEADER_OR_FOOTER || scrapHasTransientState) {
removeDetachedView(sufferer, false);
}
if (scrapHasTransientState) {
if (mTransientStateViews == null) {
mTransientStateViews = new SparseArrayCompat();
}
mTransientStateViews.put(mFirstActivePosition + i, sufferer);
}
proceed;
}

if (multipleScraps) {
scrapViews = mScrapViews[viewType];
}
lp.place = mFirstActivePosition + i;
scrapViews.add(sufferer);
}
}

pruneScrapViews();
}

personal void pruneScrapViews() {
closing int maxViews = mActiveViews.size;
closing int viewTypeCount = mViewTypeCount;
closing ArrayList[] scrapViews = mScrapViews;
for (int i = 0; i scrapPile = scrapViews[i];
int dimension = scrapPile.dimension();
closing int extras = dimension – maxViews;
dimension–;
for (int j = 0; j scrap = mCurrentScrap;
closing int scrapCount = scrap.dimension();
for (int i = 0; i scrap = mScrapViews[i];
closing int scrapCount = scrap.dimension();
for (int j = 0; j scrapViews, int place) {
int dimension = scrapViews.dimension();
if (dimension > 0) {
// See if we nonetheless have a view for this place.
for (int i = 0; i 0) {
mNeedSync = true;
mSyncHeight = getHeight();
// Sync the based mostly on the offset of the primary view
View v = getChildAt(0);
ListAdapter adapter = getAdapter();
if (mFirstPosition >= 0 && mFirstPosition infos) {
if (infos == null) return;
for (FixedViewInfo information : infos) {
closing View little one = information.view;
closing ViewGroup.LayoutParams p = little one.getLayoutParams();

if (p instanceof LayoutParams) {
((LayoutParams) p).recycledHeaderFooter = false;
}
}
}

public static class ListSavedState extends ClassLoaderSavedState {
protected lengthy selectedId;
protected lengthy firstId;
protected int viewTop;
protected int place;
protected int top;

public ListSavedState(Parcelable superState) {
tremendous(superState, AbsListView.class.getClassLoader());
}

public ListSavedState(Parcel in) {
tremendous(in);
selectedId = in.readLong();
firstId = in.readLong();
viewTop = in.readInt();
place = in.readInt();
top = in.readInt();
}

@Override
public void writeToParcel(Parcel out, int flags) {
tremendous.writeToParcel(out, flags);
out.writeLong(selectedId);
out.writeLong(firstId);
out.writeInt(viewTop);
out.writeInt(place);
out.writeInt(top);
}

@Override
public String toString() {
return “ExtendableListView.ListSavedState{”
+ Integer.toHexString(System.identityHashCode(this))
+ ” selectedId=” + selectedId
+ ” firstId=” + firstId
+ ” viewTop=” + viewTop
+ ” place=” + place
+ ” top=” + top + “}”;
}

public static closing Creator CREATOR
= new Creator() {
public ListSavedState createFromParcel(Parcel in) {
return new ListSavedState(in);
}

public ListSavedState[] newArray(int dimension) {
return new ListSavedState[size];
}
};
}

@Override
public Parcelable onSaveInstanceState() {

Parcelable superState = tremendous.onSaveInstanceState();
ListSavedState ss = new ListSavedState(superState);

if (mSyncState != null) {
// Simply preserve what we final restored.
ss.selectedId = mSyncState.selectedId;
ss.firstId = mSyncState.firstId;
ss.viewTop = mSyncState.viewTop;
ss.place = mSyncState.place;
ss.top = mSyncState.top;
return ss;
}

boolean haveChildren = getChildCount() > 0 && mItemCount > 0;
ss.selectedId = getSelectedItemId();
ss.top = getHeight();

// TODO : sync choice after we deal with it
if (haveChildren && mFirstPosition > 0) {

View v = getChildAt(0);
ss.viewTop = v.getTop();
int firstPos = mFirstPosition;
if (firstPos >= mItemCount) {
firstPos = mItemCount – 1;
}
ss.place = firstPos;
ss.firstId = mAdapter.getItemId(firstPos);
}
else {
ss.viewTop = 0;
ss.firstId = INVALID_POSITION;
ss.place = 0;
}

return ss;
}

@Override
public void onRestoreInstanceState(Parcelable state) {
ListSavedState ss = (ListSavedState) state;
tremendous.onRestoreInstanceState(ss.getSuperState());
mDataChanged = true;

mSyncHeight = ss.top;

if (ss.firstId >= 0) {
mNeedSync = true;
mSyncState = ss;
mSyncRowId = ss.firstId;
mSyncPosition = ss.place;
mSpecificTop = ss.viewTop;
}
requestLayout();
}

personal class PerformClick extends WindowRunnnable implements Runnable {
int mClickMotionPosition;

public void run() {
if (mDataChanged) return;

closing ListAdapter adapter = mAdapter;
closing int motionPosition = mClickMotionPosition;
if (adapter != null && mItemCount > 0 &&
motionPosition != INVALID_POSITION &&
motionPosition

HeaderViewListAdapter.java

package deal com.android.grid;

import android.database.DataSetObserver;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ListAdapter;
import android.widget.WrapperListAdapter;

import java.util.ArrayList;

public class HeaderViewListAdapter implements WrapperListAdapter, Filterable {

personal closing ListAdapter mAdapter;

// These two ArrayList are assumed to NOT be null.
// They’re certainly created when declared in ListView after which shared.
ArrayList mHeaderViewInfos;
ArrayList mFooterViewInfos;

// Used as a placeholder in case the supplied information views are certainly null.
// At present solely utilized by some CTS exams, which can be eliminated.
static closing ArrayList EMPTY_INFO_LIST =
new ArrayList();

boolean mAreAllFixedViewsSelectable;

personal closing boolean mIsFilterable;

public HeaderViewListAdapter(ArrayList headerViewInfos,
ArrayList footerViewInfos,
ListAdapter adapter) {
mAdapter = adapter;
mIsFilterable = adapter instanceof Filterable;

if (headerViewInfos == null) {
mHeaderViewInfos = EMPTY_INFO_LIST;
} else {
mHeaderViewInfos = headerViewInfos;
}

if (footerViewInfos == null) {
mFooterViewInfos = EMPTY_INFO_LIST;
} else {
mFooterViewInfos = footerViewInfos;
}

mAreAllFixedViewsSelectable =
areAllListInfosSelectable(mHeaderViewInfos)
&& areAllListInfosSelectable(mFooterViewInfos);
}

public int getHeadersCount() {
return mHeaderViewInfos.dimension();
}

public int getFootersCount() {
return mFooterViewInfos.dimension();
}

public boolean isEmpty()

personal boolean areAllListInfosSelectable(ArrayList infos) {
if (infos != null) {
for (StaggeredGridView.FixedViewInfo information : infos) {
if (!information.isSelectable) {
return false;
}
}
}
return true;
}

public boolean removeHeader(View v) {
for (int i = 0; i = numHeaders) {
int adjPosition = place – numHeaders;
int adapterCount = mAdapter.getCount();
if (adjPosition = numHeaders) {
int adjPosition = place – numHeaders;
int adapterCount = mAdapter.getCount();
if (adjPosition

StaggeredGridView.java

package deal com.android.grid;

import android.content material.Context;
import android.content material.res.Configuration;
import android.content material.res.TypedArray;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;

import java.util.Arrays;

public class StaggeredGridView extends ExtendableListView {

personal static closing String TAG = “StaggeredGridView”;
personal static closing boolean DBG = false;

personal static closing int DEFAULT_COLUMNS_PORTRAIT = 2;
personal static closing int DEFAULT_COLUMNS_LANDSCAPE = 3;

personal int mColumnCount;
personal int mItemMargin;
personal int mColumnWidth;
personal boolean mNeedSync;

personal int mColumnCountPortrait = DEFAULT_COLUMNS_PORTRAIT;
personal int mColumnCountLandscape = DEFAULT_COLUMNS_LANDSCAPE;

personal SparseArray mPositionData;
personal int mGridPaddingLeft;
personal int mGridPaddingRight;
personal int mGridPaddingTop;
personal int mGridPaddingBottom;

static class GridItemRecord implements Parcelable {
int column;
double heightRatio;
boolean isHeaderFooter;

GridItemRecord() { }

personal GridItemRecord(Parcel in) {
column = in.readInt();
heightRatio = in.readDouble();
isHeaderFooter = in.readByte() == 1;
}

@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(column);
out.writeDouble(heightRatio);
out.writeByte((byte) (isHeaderFooter ? 1 : 0));
}

@Override
public String toString() {
return “GridItemRecord.ListSavedState{”
+ Integer.toHexString(System.identityHashCode(this))
+ ” column:” + column
+ ” heightRatio:” + heightRatio
+ ” isHeaderFooter:” + isHeaderFooter
+ “}”;
}

public static closing Parcelable.Creator CREATOR
= new Parcelable.Creator() {
public GridItemRecord createFromParcel(Parcel in) {
return new GridItemRecord(in);
}

public GridItemRecord[] newArray(int dimension) {
return new GridItemRecord[size];
}
};
}

personal int[] mColumnTops;

personal int[] mColumnBottoms;

personal int[] mColumnLefts;

personal int mDistanceToTop;

public StaggeredGridView(closing Context context) {
this(context, null);
}

public StaggeredGridView(closing Context context, closing AttributeSet attrs) {
this(context, attrs, 0);
}

public StaggeredGridView(closing Context context, closing AttributeSet attrs, closing int defStyle) {
tremendous(context, attrs, defStyle);

if (attrs != null) {
// get the variety of columns in portrait and panorama
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.StaggeredGridView, defStyle, 0);

mColumnCount = typedArray.getInteger(
R.styleable.StaggeredGridView_column_count, 0);

if (mColumnCount > 0) {
mColumnCountPortrait = mColumnCount;
mColumnCountLandscape = mColumnCount;
}
else {
mColumnCountPortrait = typedArray.getInteger(
R.styleable.StaggeredGridView_column_count_portrait,
DEFAULT_COLUMNS_PORTRAIT);
mColumnCountLandscape = typedArray.getInteger(
R.styleable.StaggeredGridView_column_count_landscape,
DEFAULT_COLUMNS_LANDSCAPE);
}

mItemMargin = typedArray.getDimensionPixelSize(
R.styleable.StaggeredGridView_item_margin, 0);
mGridPaddingLeft = typedArray.getDimensionPixelSize(
R.styleable.StaggeredGridView_grid_paddingLeft, 0);
mGridPaddingRight = typedArray.getDimensionPixelSize(
R.styleable.StaggeredGridView_grid_paddingRight, 0);
mGridPaddingTop = typedArray.getDimensionPixelSize(
R.styleable.StaggeredGridView_grid_paddingTop, 0);
mGridPaddingBottom = typedArray.getDimensionPixelSize(
R.styleable.StaggeredGridView_grid_paddingBottom, 0);

typedArray.recycle();
}

mColumnCount = 0; // decided onMeasure
// Creating these empty arrays to keep away from saving null states
mColumnTops = new int[0];
mColumnBottoms = new int[0];
mColumnLefts = new int[0];
mPositionData = new SparseArray();
}

// //////////////////////////////////////////////////////////////////////////////////////////
// PROPERTIES
//

// Grid padding is utilized to the record merchandise rows however not the header and footer
public int getRowPaddingLeft() {
return getListPaddingLeft() + mGridPaddingLeft;
}

public int getRowPaddingRight() {
return getListPaddingRight() + mGridPaddingRight;
}

public int getRowPaddingTop() {
return getListPaddingTop() + mGridPaddingTop;
}

public int getRowPaddingBottom() {
return getListPaddingBottom() + mGridPaddingBottom;
}

public void setGridPadding(int left, int prime, int proper, int backside) {
mGridPaddingLeft = left;
mGridPaddingTop = prime;
mGridPaddingRight = proper;
mGridPaddingBottom = backside;
}

public void setColumnCountPortrait(int columnCountPortrait) {
mColumnCountPortrait = columnCountPortrait;
onSizeChanged(getWidth(), getHeight());
requestLayoutChildren();
}

public void setColumnCountLandscape(int columnCountLandscape) {
mColumnCountLandscape = columnCountLandscape;
onSizeChanged(getWidth(), getHeight());
requestLayoutChildren();
}

public void setColumnCount(int columnCount) {
mColumnCountPortrait = columnCount;
mColumnCountLandscape = columnCount;
// mColumnCount set onSizeChanged();
onSizeChanged(getWidth(), getHeight());
requestLayoutChildren();
}

// //////////////////////////////////////////////////////////////////////////////////////////
// MEASUREMENT
//
personal boolean isLandscape() {
return getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
}

@Override
protected void onMeasure(closing int widthMeasureSpec, closing int heightMeasureSpec) {
tremendous.onMeasure(widthMeasureSpec, heightMeasureSpec);

if (mColumnCount 0) {
childHeightSpec = MeasureSpec.makeMeasureSpec(layoutParams.top, MeasureSpec.EXACTLY);
}
else {
childHeightSpec = MeasureSpec.makeMeasureSpec(LayoutParams.WRAP_CONTENT, MeasureSpec.UNSPECIFIED);
}
little one.measure(childWidthSpec, childHeightSpec);
}

closing int childHeight = getChildHeight(little one);
setPositionHeightRatio(place, childHeight);

if (DBG) Log.d(TAG, “onMeasureChild AFTER position:” + place +
” h:” + childHeight);
}

public int getColumnWidth() {
return mColumnWidth;
}

public void resetToTop() {
if (mColumnCount > 0) {

if (mColumnTops == null) {
mColumnTops = new int[mColumnCount];
}
if (mColumnBottoms == null) {
mColumnBottoms = new int[mColumnCount];
}
initColumnTopsAndBottoms();

mPositionData.clear();
mNeedSync = false;
mDistanceToTop = 0;
setSelection(0);
}
}

// //////////////////////////////////////////////////////////////////////////////////////////
// POSITIONING
//

@Override
protected void onChildCreated(closing int place, closing boolean flowDown) {
tremendous.onChildCreated(place, flowDown);
if (!isHeaderOrFooter(place)) {
// will we have already got a column for this place?
closing int column = getChildColumn(place, flowDown);
setPositionColumn(place, column);
if (DBG) Log.d(TAG, “onChildCreated position:” + place +
” is in column:” + column);
}
else {
setPositionIsHeaderFooter(place);
}
}

personal void requestLayoutChildren() {
closing int rely = getChildCount();
for (int i = 0; i mColumnBottoms[column]) {
mColumnBottoms[column] = childBottom;
}
}

@Override
protected int getChildLeft(closing int place) {
if (isHeaderOrFooter(place)) {
return tremendous.getChildLeft(place);
}
else {
closing int column = getPositionColumn(place);
return mColumnLefts[column];
}
}

@Override
protected int getChildTop(closing int place) {
if (isHeaderOrFooter(place)) {
return tremendous.getChildTop(place);
}
else {
closing int column = getPositionColumn(place);
if (column == -1) {
return getHighestPositionedBottom();
}
return mColumnBottoms[column];
}
}

@Override
protected int getNextChildDownsTop(closing int place) {
if (isHeaderOrFooter(place)) {
return tremendous.getNextChildDownsTop(place);
}
else {
return getHighestPositionedBottom();
}
}

@Override
protected int getChildBottom(closing int place) {
if (isHeaderOrFooter(place)) {
return tremendous.getChildBottom(place);
}
else {
closing int column = getPositionColumn(place);
if (column == -1) {
return getLowestPositionedTop();
}
return mColumnTops[column];
}
}

@Override
protected int getNextChildUpsBottom(closing int place) {
if (isHeaderOrFooter(place)) {
return tremendous.getNextChildUpsBottom(place);
}
else {
return getLowestPositionedTop();
}
}

@Override
protected int getLastChildBottom() {
closing int lastPosition = mFirstPosition + (getChildCount() – 1);
if (isHeaderOrFooter(lastPosition)) {
return tremendous.getLastChildBottom();
}
return getHighestPositionedBottom();
}

@Override
protected int getFirstChildTop() {
if (isHeaderOrFooter(mFirstPosition)) {
return tremendous.getFirstChildTop();
}
return getLowestPositionedTop();
}

@Override
protected int getHighestChildTop() {
if (isHeaderOrFooter(mFirstPosition)) {
return tremendous.getHighestChildTop();
}
return getHighestPositionedTop();
}

@Override
protected int getLowestChildBottom() {
closing int lastPosition = mFirstPosition + (getChildCount() – 1);
if (isHeaderOrFooter(lastPosition)) {
return tremendous.getLowestChildBottom();
}
return getLowestPositionedBottom();
}

@Override
protected void offsetChildrenTopAndBottom(closing int offset) {
tremendous.offsetChildrenTopAndBottom(offset);
offsetAllColumnsTopAndBottom(offset);
offsetDistanceToTop(offset);
}

protected void offsetChildrenTopAndBottom(closing int offset, closing int column) {
if (DBG) Log.d(TAG, “offsetChildrenTopAndBottom: ” + offset + ” column:” + column);
closing int rely = getChildCount();
for (int i = 0; i 0 && nonHeaderTops[i] != highestTop) {
isAligned = false; // not all of the tops are aligned
}
// what’s the best
if (nonHeaderTops[i] 0) {
for (int i = 0; i mColumnBottoms[column]) {
mColumnBottoms[column] = childBottom + getChildBottomMargin();
}
}
else {
// the header and footer right here
closing int childTop = little one.getTop();
closing int childBottom = little one.getBottom();

for (int col = 0; col mColumnBottoms

) {
mColumnBottoms
= childBottom;
}
}

}
}
}
}

@Override
protected boolean hasSpaceUp() {
int finish = mClipToPadding ? getRowPaddingTop() : 0;
return getLowestPositionedTop() > finish;
}

// //////////////////////////////////////////////////////////////////////////////////////////
// SYNCING ACROSS ROTATION
//

@Override
protected void onSizeChanged(closing int w, closing int h, closing int oldw, closing int oldh) {
tremendous.onSizeChanged(w, h, oldw, oldh);
onSizeChanged(w, h);
}

@Override
protected void onSizeChanged(int w, int h) {
tremendous.onSizeChanged(w, h);
boolean isLandscape = isLandscape();
int newColumnCount = isLandscape ? mColumnCountLandscape : mColumnCountPortrait;
if (mColumnCount != newColumnCount) {
mColumnCount = newColumnCount;

mColumnWidth = calculateColumnWidth(w);

mColumnTops = new int[mColumnCount];
mColumnBottoms = new int[mColumnCount];
mColumnLefts = new int[mColumnCount];

mDistanceToTop = 0;

// rebuild the columns
initColumnTopsAndBottoms();
initColumnLefts();

// if we now have knowledge
if (getCount() > 0 && mPositionData.dimension() > 0) {
onColumnSync();
}

requestLayout();
}
}

personal int calculateColumnWidth(closing int gridWidth) {
closing int listPadding = getRowPaddingLeft() + getRowPaddingRight();
return (gridWidth – listPadding – mItemMargin * (mColumnCount + 1)) / mColumnCount;
}

personal int calculateColumnLeft(closing int colIndex) {
return getRowPaddingLeft() + mItemMargin + ((mItemMargin + mColumnWidth) * colIndex);
}

/***
* Our mColumnTops and mColumnBottoms must be re-built as much as the
* mSyncPosition – the next structure request will then
* structure the that place after which fillUp and fillDown appropriately.
*/
personal void onColumnSync() {
// re-calc tops for brand new column rely!
int syncPosition = Math.min(mSyncPosition, getCount() – 1);

SparseArray positionHeightRatios = new SparseArray(syncPosition);
for (int pos = 0; pos = columnCount) {
// if we’re taking place –
// get the best positioned (lowest worth)
// column backside
if (flowDown) {
column = getHighestPositionedBottomColumn();
}
else {
column = getLowestPositionedTopColumn();

}
}
return column;
}

personal void initColumnTopsAndBottoms() {
initColumnTops();
initColumnBottoms();
}

personal void initColumnTops() {
Arrays.fill(mColumnTops, getPaddingTop() + mGridPaddingTop);
}

personal void initColumnBottoms() {
Arrays.fill(mColumnBottoms, getPaddingTop() + mGridPaddingTop);
}

personal void initColumnLefts() {
for (int i = 0; i lowestPositionedBottom) {
lowestPositionedBottom = backside;
columnFound = i;
}
}
return columnFound;
}

// //////////////////////////////////////////////////////////////////////////////////////////
// TOP
//

personal int getLowestPositionedTop() {
closing int column = getLowestPositionedTopColumn();
return mColumnTops[column];
}

personal int getLowestPositionedTopColumn() {
int columnFound = 0;
// we’ll go backwards by way of because the proper most
// will doubtless be the bottom positioned High
int lowestPositionedTop = Integer.MIN_VALUE;
// the bottom positioned prime is the one with the best worth 😀
for (int i = 0; i lowestPositionedTop) {
lowestPositionedTop = prime;
columnFound = i;
}
}
return columnFound;
}

personal int getHighestPositionedTop() {
closing int column = getHighestPositionedTopColumn();
return mColumnTops[column];
}

personal int getHighestPositionedTopColumn() {
int columnFound = 0;
int highestPositionedTop = Integer.MAX_VALUE;
// the best positioned prime is the one with the bottom worth 😀
for (int i = 0; i = 0 ? columnCount : 0];
in.readIntArray(columnTops);
positionData = in.readSparseArray(GridItemRecord.class.getClassLoader());
}

@Override
public void writeToParcel(Parcel out, int flags) {
tremendous.writeToParcel(out, flags);
out.writeInt(columnCount);
out.writeIntArray(columnTops);
out.writeSparseArray(positionData);
}

@Override
public String toString() {
return “StaggeredGridView.GridListSavedState{”
+ Integer.toHexString(System.identityHashCode(this)) + “}”;
}

public static closing Creator CREATOR
= new Creator() {
public GridListSavedState createFromParcel(Parcel in) {
return new GridListSavedState(in);
}

public GridListSavedState[] newArray(int dimension) {
return new GridListSavedState[size];
}
};
}

@Override
public Parcelable onSaveInstanceState() {
ListSavedState listState = (ListSavedState) tremendous.onSaveInstanceState();
GridListSavedState ss = new GridListSavedState(listState.getSuperState());

// from the record state
ss.selectedId = listState.selectedId;
ss.firstId = listState.firstId;
ss.viewTop = listState.viewTop;
ss.place = listState.place;
ss.top = listState.top;

// our state

boolean haveChildren = getChildCount() > 0 && getCount() > 0;

if (haveChildren && mFirstPosition > 0) {
ss.columnCount = mColumnCount;
ss.columnTops = mColumnTops;
ss.positionData = mPositionData;
}
else {
ss.columnCount = mColumnCount >= 0 ? mColumnCount : 0;
ss.columnTops = new int[ss.columnCount];
ss.positionData = new SparseArray();
}

return ss;
}

@Override
public void onRestoreInstanceState(Parcelable state) {
GridListSavedState ss = (GridListSavedState) state;
mColumnCount = ss.columnCount;
mColumnTops = ss.columnTops;
mColumnBottoms = new int[mColumnCount];
mPositionData = ss.positionData;
mNeedSync = true;
tremendous.onRestoreInstanceState(ss);
}
}

DynamicHeightImageView.java

package deal com.android.grid.util;

import android.content material.Context;
import android.util.AttributeSet;
import android.widget.ImageView;

public class DynamicHeightImageView extends ImageView {

personal double mHeightRatio;

public DynamicHeightImageView(Context context, AttributeSet attrs) {
tremendous(context, attrs);
}

public DynamicHeightImageView(Context context) {
tremendous(context);
}

public void setHeightRatio(double ratio) {
if (ratio != mHeightRatio) {
mHeightRatio = ratio;
requestLayout();
}
}

public double getHeightRatio() {
return mHeightRatio;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mHeightRatio > 0.0) {
// set the picture views dimension
int width = MeasureSpec.getSize(widthMeasureSpec);
int top = (int) (width * mHeightRatio);
setMeasuredDimension(width, top);
}
else {
tremendous.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
}

DynamicHeightTextView.java

package deal com.android.grid.util;

import android.content material.Context;
import android.util.AttributeSet;
import android.widget.TextView;

public class DynamicHeightTextView extends TextView {

personal double mHeightRatio;

public DynamicHeightTextView(Context context, AttributeSet attrs) {
tremendous(context, attrs);
}

public DynamicHeightTextView(Context context) {
tremendous(context);
}

public void setHeightRatio(double ratio) {
if (ratio != mHeightRatio) {
mHeightRatio = ratio;
requestLayout();
}
}

public double getHeightRatio() {
return mHeightRatio;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mHeightRatio > 0.0) {
// set the picture views dimension
int width = MeasureSpec.getSize(widthMeasureSpec);
int top = (int) (width * mHeightRatio);
setMeasuredDimension(width, top);
}
else {
tremendous.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
}

—–> Create Android Staggered Grid Challenge And Hyperlink Above Challenge AS Lib Challenge.

—>  AndroidManifest.xml











In Values Folder

colours.xml



#ffffdc7e#ffd3d3d3#ff8dd304#ff82e0ff#fffffbae#fff10800#1A000000

integers.xml



2

IN Structure Folder

activity_list_view.xml

activity_main.xml

activity_sgv_empy_view.xml

activity_sgv.xml

list_item_header_footer.xml


list_item_sample.xml


IN drawable Folder

list_item_selector.xml











ListViewActivity.java

package deal com.android.pattern;

import android.app.Exercise;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.*;

import java.util.Record;

public class ListViewActivity extends Exercise implements AdapterView.OnItemClickListener {

@Override
protected void onCreate(Bundle savedInstanceState) {
tremendous.onCreate(savedInstanceState);
setContentView(R.structure.activity_list_view);

setTitle(“ListView”);

closing ListView listView = (ListView) findViewById(R.id.list_view);

LayoutInflater layoutInflater = getLayoutInflater();

View header = layoutInflater.inflate(R.structure.list_item_header_footer, null);
View footer = layoutInflater.inflate(R.structure.list_item_header_footer, null);
TextView txtHeaderTitle = (TextView) header.findViewById(R.id.txt_title);
TextView txtFooterTitle =  (TextView) footer.findViewById(R.id.txt_title);
txtHeaderTitle.setText(“THE HEADER!”);
txtFooterTitle.setText(“THE FOOTER!”);

listView.addHeaderView(header);
listView.addFooterView(footer);

closing SampleAdapter adapter = new SampleAdapter(this, R.id.txt_line1);
listView.setAdapter(adapter);
listView.setOnItemClickListener(this);

closing Record sampleData = SampleData.generateSampleData();
for (String knowledge : sampleData) {
adapter.add(knowledge);
}
}

@Override
public void onItemClick(AdapterView> adapterView, View view, int place, lengthy id) {
Toast.makeText(this, “Item Clicked: ” + place, Toast.LENGTH_SHORT).present();
}
}

MainActivity.java

package deal com.android.pattern;

import android.app.Exercise;
import android.content material.Intent;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Exercise implements View.OnClickListener {

@Override
protected void onCreate(Bundle savedInstanceState) {
tremendous.onCreate(savedInstanceState);
setTitle(“SGV Sample”);
setContentView(R.structure.activity_main);

findViewById(R.id.btn_sgv).setOnClickListener(this);
findViewById(R.id.btn_sgv_fragment).setOnClickListener(this);
findViewById(R.id.btn_sgv_empty_view).setOnClickListener(this);
findViewById(R.id.btn_listview).setOnClickListener(this);
}

@Override
public void onClick(closing View v) {
if (v.getId() == R.id.btn_sgv) {
startActivity(new Intent(this, StaggeredGridActivity.class));
}
else if (v.getId() == R.id.btn_sgv_fragment) {
startActivity(new Intent(this, StaggeredGridActivityFragment.class));
}
else if (v.getId() == R.id.btn_sgv_empty_view) {
startActivity(new Intent(this, StaggeredGridEmptyViewActivity.class));
}
else if (v.getId() == R.id.btn_listview) {
startActivity(new Intent(this, ListViewActivity.class));
}
}
}

SampleAdapter.java

package deal com.android.pattern;

import java.util.ArrayList;
import java.util.Random;

import com.android.grid.util.DynamicHeightTextView;

import android.content material.Context;
import android.util.Log;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Toast;

public class SampleAdapter extends ArrayAdapter {

personal static closing String TAG = “SampleAdapter”;

static class ViewHolder {
DynamicHeightTextView txtLineOne;
Button btnGo;
}

personal closing LayoutInflater mLayoutInflater;
personal closing Random mRandom;
personal closing ArrayList mBackgroundColors;

personal static closing SparseArray sPositionHeightRatios = new SparseArray();

public SampleAdapter(closing Context context, closing int textViewResourceId) {
tremendous(context, textViewResourceId);
mLayoutInflater = LayoutInflater.from(context);
mRandom = new Random();
mBackgroundColors = new ArrayList();
mBackgroundColors.add(R.shade.orange);
mBackgroundColors.add(R.shade.inexperienced);
mBackgroundColors.add(R.shade.blue);
mBackgroundColors.add(R.shade.yellow);
mBackgroundColors.add(R.shade.gray);
}

@Override
public View getView(closing int place, View convertView, closing ViewGroup dad or mum) {

ViewHolder vh;
if (convertView == null) {
convertView = mLayoutInflater.inflate(R.structure.list_item_sample, dad or mum, false);
vh = new ViewHolder();
vh.txtLineOne = (DynamicHeightTextView) convertView.findViewById(R.id.txt_line1);
vh.btnGo = (Button) convertView.findViewById(R.id.btn_go);

convertView.setTag(vh);
}
else {
vh = (ViewHolder) convertView.getTag();
}

double positionHeight = getPositionRatio(place);
int backgroundIndex = place >= mBackgroundColors.dimension() ?
place % mBackgroundColors.dimension() : place;

convertView.setBackgroundResource(mBackgroundColors.get(backgroundIndex));

Log.d(TAG, “getView position:” + place + ” h:” + positionHeight);

vh.txtLineOne.setHeightRatio(positionHeight);
vh.txtLineOne.setText(getItem(place) + place);

vh.btnGo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(closing View v) {
Toast.makeText(getContext(), “Button Clicked Position ” +
place, Toast.LENGTH_SHORT).present();
}
});

return convertView;
}

personal double getPositionRatio(closing int place) {
double ratio = sPositionHeightRatios.get(place, 0.0);

if (ratio == 0) {
ratio = getRandomHeightRatio();
sPositionHeightRatios.append(place, ratio);
Log.d(TAG, “getPositionRatio:” + place + ” ratio:” + ratio);
}
return ratio;
}

personal double getRandomHeightRatio() {
return (mRandom.nextDouble() / 2.0) + 1.0; // top will likely be 1.0 – 1.5 the width
}
}

SampleData.java

package deal com.android.pattern;

import java.util.ArrayList;
import java.util.Record;

public class SampleData {

public static closing int SAMPLE_DATA_ITEM_COUNT = 30;

public static ArrayList generateSampleData() {
closing ArrayList knowledge = new ArrayList(SAMPLE_DATA_ITEM_COUNT);

for (int i = 0; i

StaggeredGridActivity.java

package deal com.android.pattern;

import java.util.ArrayList;

import android.app.Exercise;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.TextView;
import android.widget.Toast;

import com.android.grid.StaggeredGridView;

public class StaggeredGridActivity extends Exercise implements AbsListView.OnScrollListener, AbsListView.OnItemClickListener, AdapterView.OnItemLongClickListener {

personal static closing String TAG = “StaggeredGridActivity”;
public static closing String SAVED_DATA_KEY = “SAVED_DATA”;

personal StaggeredGridView mGridView;
personal boolean mHasRequestedMore;
personal SampleAdapter mAdapter;

personal ArrayList mData;

@Override
protected void onCreate(Bundle savedInstanceState) {
tremendous.onCreate(savedInstanceState);
setContentView(R.structure.activity_sgv);

setTitle(“SGV”);
mGridView = (StaggeredGridView) findViewById(R.id.grid_view);

LayoutInflater layoutInflater = getLayoutInflater();

View header = layoutInflater.inflate(R.structure.list_item_header_footer, null);
View footer = layoutInflater.inflate(R.structure.list_item_header_footer, null);
TextView txtHeaderTitle = (TextView) header.findViewById(R.id.txt_title);
TextView txtFooterTitle =  (TextView) footer.findViewById(R.id.txt_title);
txtHeaderTitle.setText(“THE HEADER!”);
txtFooterTitle.setText(“THE FOOTER!”);

mGridView.addHeaderView(header);
mGridView.addFooterView(footer);
mAdapter = new SampleAdapter(this, R.id.txt_line1);

// do we now have saved knowledge?
if (savedInstanceState != null) {
mData = savedInstanceState.getStringArrayList(SAVED_DATA_KEY);
}

if (mData == null) {
mData = SampleData.generateSampleData();
}

for (String knowledge : mData) {
mAdapter.add(knowledge);
}

mGridView.setAdapter(mAdapter);
mGridView.setOnScrollListener(this);
mGridView.setOnItemClickListener(this);
mGridView.setOnItemLongClickListener(this);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_sgv_dynamic, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem merchandise) {
change (merchandise.getItemId()) {
case R.id.col1:
mGridView.setColumnCount(1);
break;
case R.id.col2:
mGridView.setColumnCount(2);
break;
case R.id.col3:
mGridView.setColumnCount(3);
break;
}
return true;
}

@Override
protected void onSaveInstanceState(closing Bundle outState) {
tremendous.onSaveInstanceState(outState);
outState.putStringArrayList(SAVED_DATA_KEY, mData);
}

@Override
public void onScrollStateChanged(closing AbsListView view, closing int scrollState) {
Log.d(TAG, “onScrollStateChanged:” + scrollState);
}

@Override
public void onScroll(closing AbsListView view, closing int firstVisibleItem, closing int visibleItemCount, closing int totalItemCount) {
Log.d(TAG, “onScroll firstVisibleItem:” + firstVisibleItem +
” visibleItemCount:” + visibleItemCount +
” totalItemCount:” + totalItemCount);
// our dealing with
if (!mHasRequestedMore) {
int lastInScreen = firstVisibleItem + visibleItemCount;
if (lastInScreen >= totalItemCount) {
Log.d(TAG, “onScroll lastInScreen – so load more”);
mHasRequestedMore = true;
onLoadMoreItems();
}
}
}

personal void onLoadMoreItems() {
closing ArrayList sampleData = SampleData.generateSampleData();
for (String knowledge : sampleData) {
mAdapter.add(knowledge);
}
// stash all the information in our backing retailer
mData.addAll(sampleData);
// notify the adapter that we will replace now
mAdapter.notifyDataSetChanged();
mHasRequestedMore = false;
}

@Override
public void onItemClick(AdapterView> adapterView, View view, int place, lengthy id) {
Toast.makeText(this, “Item Clicked: ” + place, Toast.LENGTH_SHORT).present();
}

@Override
public boolean onItemLongClick(AdapterView> dad or mum, View view, int place, lengthy id)
{
Toast.makeText(this, “Item Long Clicked: ” + place, Toast.LENGTH_SHORT).present();
return true;
}
}

StaggeredGridActivityFragment.java

package deal com.android.pattern;

import android.os.Bundle;
import android.help.v4.app.Fragment;
import android.help.v4.app.FragmentActivity;
import android.help.v4.app.FragmentManager;
import android.util.Log;
import android.view.*;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.TextView;
import android.widget.Toast;
import com.android.grid.StaggeredGridView;

import java.util.ArrayList;

public class StaggeredGridActivityFragment extends FragmentActivity {

personal static closing String TAG = “StaggeredGridActivityFragment”;

@Override
protected void onCreate(Bundle savedInstanceState) {
tremendous.onCreate(savedInstanceState);

setTitle(“SGV”);

closing FragmentManager fm = getSupportFragmentManager();

// Create the record fragment and add it as our sole content material.
if (fm.findFragmentById(android.R.id.content material) == null) {
closing StaggeredGridFragment fragment = new StaggeredGridFragment();
fm.beginTransaction().add(android.R.id.content material, fragment).commit();
}
}

personal class StaggeredGridFragment extends Fragment implements
AbsListView.OnScrollListener, AbsListView.OnItemClickListener {

personal StaggeredGridView mGridView;
personal boolean mHasRequestedMore;
personal SampleAdapter mAdapter;

personal ArrayList mData;

@Override
public void onCreate(closing Bundle savedInstanceState) {
tremendous.onCreate(savedInstanceState);
setRetainInstance(true);
}

@Override
public View onCreateView(closing LayoutInflater inflater, closing ViewGroup container, closing Bundle savedInstanceState) {
return inflater.inflate(R.structure.activity_sgv, container, false);
}

@Override
public void onActivityCreated(closing Bundle savedInstanceState) {
tremendous.onActivityCreated(savedInstanceState);

mGridView = (StaggeredGridView) getView().findViewById(R.id.grid_view);

if (savedInstanceState == null) {
closing LayoutInflater layoutInflater = getActivity().getLayoutInflater();

View header = layoutInflater.inflate(R.structure.list_item_header_footer, null);
View footer = layoutInflater.inflate(R.structure.list_item_header_footer, null);
TextView txtHeaderTitle = (TextView) header.findViewById(R.id.txt_title);
TextView txtFooterTitle = (TextView) footer.findViewById(R.id.txt_title);
txtHeaderTitle.setText(“THE HEADER!”);
txtFooterTitle.setText(“THE FOOTER!”);

mGridView.addHeaderView(header);
mGridView.addFooterView(footer);
}

if (mAdapter == null) {
mAdapter = new SampleAdapter(getActivity(), R.id.txt_line1);
}

if (mData == null) {
mData = SampleData.generateSampleData();
}

for (String knowledge : mData) {
mAdapter.add(knowledge);
}

mGridView.setAdapter(mAdapter);
mGridView.setOnScrollListener(this);
mGridView.setOnItemClickListener(this);
}

@Override
public void onScrollStateChanged(closing AbsListView view, closing int scrollState) {
Log.d(TAG, “onScrollStateChanged:” + scrollState);
}

@Override
public void onScroll(closing AbsListView view, closing int firstVisibleItem, closing int visibleItemCount, closing int totalItemCount) {
Log.d(TAG, “onScroll firstVisibleItem:” + firstVisibleItem +
” visibleItemCount:” + visibleItemCount +
” totalItemCount:” + totalItemCount);
// our dealing with
if (!mHasRequestedMore) {
int lastInScreen = firstVisibleItem + visibleItemCount;
if (lastInScreen >= totalItemCount) {
Log.d(TAG, “onScroll lastInScreen – so load more”);
mHasRequestedMore = true;
onLoadMoreItems();
}
}
}

personal void onLoadMoreItems() {
closing ArrayList sampleData = SampleData.generateSampleData();
for (String knowledge : sampleData) {
mAdapter.add(knowledge);
}
// stash all the information in our backing retailer
mData.addAll(sampleData);
// notify the adapter that we will replace now
mAdapter.notifyDataSetChanged();
mHasRequestedMore = false;
}

@Override
public void onItemClick(AdapterView> adapterView, View view, int place, lengthy id) {
Toast.makeText(getActivity(), “Item Clicked: ” + place, Toast.LENGTH_SHORT).present();
}
}
}

StaggeredGridEmptyViewActivity.java

package deal com.android.pattern;

import android.app.Exercise;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.TextView;
import android.widget.Toast;

import com.android.grid.StaggeredGridView;

import java.util.ArrayList;

public class StaggeredGridEmptyViewActivity extends Exercise implements AbsListView.OnItemClickListener {

public static closing String SAVED_DATA_KEY = “SAVED_DATA”;
personal static closing int FETCH_DATA_TASK_DURATION = 2000;

personal StaggeredGridView mGridView;
personal SampleAdapter mAdapter;

personal ArrayList mData;

@Override
protected void onCreate(Bundle savedInstanceState) {
tremendous.onCreate(savedInstanceState);
setContentView(R.structure.activity_sgv_empy_view);

setTitle(“SGV”);
mGridView = (StaggeredGridView) findViewById(R.id.grid_view);

LayoutInflater layoutInflater = getLayoutInflater();

View header = layoutInflater.inflate(R.structure.list_item_header_footer, null);
View footer = layoutInflater.inflate(R.structure.list_item_header_footer, null);
TextView txtHeaderTitle = (TextView) header.findViewById(R.id.txt_title);
TextView txtFooterTitle =  (TextView) footer.findViewById(R.id.txt_title);
txtHeaderTitle.setText(“THE HEADER!”);
txtFooterTitle.setText(“THE FOOTER!”);

mGridView.addHeaderView(header);
mGridView.addFooterView(footer);
mGridView.setEmptyView(findViewById(android.R.id.empty));
mAdapter = new SampleAdapter(this, R.id.txt_line1);

// do we now have saved knowledge?
if (savedInstanceState != null) {
mData = savedInstanceState.getStringArrayList(SAVED_DATA_KEY);
fillAdapter();
}

if (mData == null) {
mData = SampleData.generateSampleData();
}

mGridView.setAdapter(mAdapter);

mGridView.setOnItemClickListener(this);

fetchData();
}

personal void fillAdapter() {
for (String knowledge : mData) {
mAdapter.add(knowledge);
}
}

personal void fetchData() {
new AsyncTask() {
@Override
protected Void doInBackground(Void… params) {
SystemClock.sleep(FETCH_DATA_TASK_DURATION);
return null;
}

@Override
protected void onPostExecute(Void aVoid) {
fillAdapter();
}
}.execute();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_sgv_empty_view, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem merchandise) {
mAdapter.clear();
fetchData();
return true;
}

@Override
public void onItemClick(AdapterView> adapterView, View view, int place, lengthy id) {
Toast.makeText(this, “Item Clicked: ” + place, Toast.LENGTH_SHORT).present();
}

@Override
protected void onSaveInstanceState(closing Bundle outState) {
tremendous.onSaveInstanceState(outState);
outState.putStringArrayList(SAVED_DATA_KEY, mData);
}
}

You May Also Like

Calculation Number of Days Between Two Dates

Topic: Delphi Language charlene44 wrote: 18/08/2006 at 15h08 calculation of number of…

World of Warcraft Classic: Some Players Use Illegal Tools to Stay Connected

Earlier this week, Blizzard released World of Warcraft Classic. The launch was,…

Crash Team Racing Bientt Back on Ps4!

Activision seems not to have finished with the remastering of the Playstation…

Top Benefits of Social Media Marketing

We cannot deny the fact that when it comes to marketing, social…