Unable to hide IndexScroll from listview - java

I have a custom listview which is having a custom inexscroller which draws itself when you scroll through the list. Now that doesnt look nice when my listview is not having too many items. So what I want to do is to hide the IndexScroller when the items are less than a particular number to be scrollable. I have done everything but I am not able to hide the list view. Please help:
Here are the classes used:
IndexableListViewActivity
public class IndexableListViewActivity extends Activity implements OnClickListener
{
private ArrayList<String> mItems;
private IndexableListView mListView;
TextView MyTasks, TeamTasks, username, fullusername;
RelativeLayout listlay;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mItems = new ArrayList<String>();
mItems.add("Diary of a Wimpy Kid 6: Cabin Fever");
mItems.add("Steve Jobs");
mItems.add("Inheritance (The Inheritance Cycle)");
mItems.add("11/22/63: A Novel");
mItems.add("The Hunger Games");
mItems.add("The LEGO Ideas Book");
mItems.add("Explosive Eighteen: A Stephanie Plum Novel");
mItems.add("Catching Fire (The Second Book of the Hunger Games)");
mItems.add("Elder Scrolls V: Skyrim: Prima Official Game Guide");
mItems.add("Death Comes to Pemberley");
mItems.add("Diary of a Wimpy Kid 6: Cabin Fever");
mItems.add("Steve Jobs");
mItems.add("Inheritance (The Inheritance Cycle)");
mItems.add("11/22/63: A Novel");
mItems.add("The Hunger Games");
mItems.add("The LEGO Ideas Book");
mItems.add("Explosive Eighteen: A Stephanie Plum Novel");
mItems.add("Catching Fire (The Second Book of the Hunger Games)");
mItems.add("Elder Scrolls V: Skyrim: Prima Official Game Guide");
mItems.add("Death Comes to Pemberley");
mItems.add("Make this list longer");
mItems.add("A");
mItems.add("B");
// mItems.add("C");
// mItems.add("D");
// mItems.add("E");
// mItems.add("F");
// mItems.add("H");
// mItems.add("I");
// mItems.add("J");
// mItems.add("K");
// mItems.add("L");
// mItems.add("M");
// mItems.add("N");
// mItems.add("O");
// mItems.add("P");
// mItems.add("Q");
// mItems.add("R");
// mItems.add("S");
// mItems.add("T");
// mItems.add("U");
// mItems.add("V");
// mItems.add("W");
// mItems.add("X");
// mItems.add("Y");
// mItems.add("Z");
Collections.sort(mItems);
ContentAdapter adapter = new ContentAdapter(this,
android.R.layout.simple_list_item_1, mItems);
mListView = (IndexableListView) findViewById(R.id.listview);
mListView.setAdapter(adapter);
mListView.setFastScrollEnabled(true);
MyTasks = (TextView)findViewById(R.id.myTasks);
MyTasks.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
MyTasks.setBackgroundResource(R.drawable.rectangle_selected);
TeamTasks.setBackgroundResource(R.drawable.rectangle);
if(mListView.getLastVisiblePosition() + 1 == mListView.getCount()) {
Toast.makeText(getBaseContext(), "No need to scroll", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(getBaseContext(), "Need to scroll", Toast.LENGTH_SHORT).show();
}
}
});
TeamTasks = (TextView)findViewById(R.id.teamTasks);
TeamTasks.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
TeamTasks.setBackgroundResource(R.drawable.rectangle_selected);
MyTasks.setBackgroundResource(R.drawable.rectangle);
}
});
}
private class ContentAdapter extends ArrayAdapter<String> implements SectionIndexer {
private String mSections = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public ContentAdapter(Context context, int textViewResourceId,
List<String> objects) {
super(context, textViewResourceId, objects);
}
#Override
public int getPositionForSection(int section) {
// If there is no item for current section, previous section will be selected
for (int i = section; i >= 0; i--) {
for (int j = 0; j < getCount(); j++) {
if (i == 0) {
// For numeric section
for (int k = 0; k <= 9; k++) {
if (StringMatcher.match(String.valueOf(getItem(j).charAt(0)), String.valueOf(k)))
return j;
}
} else {
if (StringMatcher.match(String.valueOf(getItem(j).charAt(0)), String.valueOf(mSections.charAt(i))))
return j;
}
}
}
return 0;
}
#Override
public int getSectionForPosition(int position) {
return 0;
}
#Override
public Object[] getSections() {
String[] sections = new String[mSections.length()];
for (int i = 0; i < mSections.length(); i++)
sections[i] = String.valueOf(mSections.charAt(i));
return sections;
}
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
}
StrngMatcher.java
public class StringMatcher {
public static boolean match(String value, String keyword) {
if (value == null || keyword == null)
return false;
if (keyword.length() > value.length())
return false;
int i = 0, j = 0;
do {
int vi = value.charAt(i);
int kj = keyword.charAt(j);
if (isKorean(vi) && isInitialSound(kj)) {
} else {
if (vi == kj) {
i++;
j++;
} else if (j > 0)
break;
else
i++;
}
} while (i < value.length() && j < keyword.length());
return (j == keyword.length())? true : false;
}
private static boolean isKorean(int i) {
return false;
}
private static boolean isInitialSound(int i) {
return false;
}
}
IndexableListView.java
public class IndexableListView extends ListView {
private boolean mIsFastScrollEnabled = false;
private IndexScroller mScroller = null;
private GestureDetector mGestureDetector = null;
public IndexableListView(Context context) {
super(context);
}
public IndexableListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public IndexableListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public boolean isFastScrollEnabled() {
return mIsFastScrollEnabled;
}
#Override
public void setFastScrollEnabled(boolean enabled) {
mIsFastScrollEnabled = enabled;
if (mIsFastScrollEnabled) {
if (mScroller == null)
mScroller = new IndexScroller(getContext(), this);
}
else {
if (mScroller != null) {
mScroller.hide();
mScroller = null;
}
}
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
// Overlay index bar
if (mScroller != null)
mScroller.draw(canvas);
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
// Intercept ListView's touch event
if (mScroller != null && mScroller.onTouchEvent(ev))
return true;
if (mGestureDetector == null) {
mGestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2,
float velocityX, float velocityY) {
// If fling happens, index bar shows
if(mScroller!=null)
mScroller.show();
return super.onFling(e1, e2, velocityX, velocityY);
}
});
}
mGestureDetector.onTouchEvent(ev);
return super.onTouchEvent(ev);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
}
#Override
public void setAdapter(ListAdapter adapter) {
super.setAdapter(adapter);
if (mScroller != null)
mScroller.setAdapter(adapter);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (mScroller != null)
mScroller.onSizeChanged(w, h, oldw, oldh);
}
}
IndexScroller.java
public class IndexScroller {
private float mIndexbarWidth;
private float mIndexbarMargin;
private float mPreviewPadding;
private float mDensity;
private float mScaledDensity;
private float mAlphaRate;
private int mState = STATE_HIDDEN;
private int mListViewWidth;
private int mListViewHeight;
private int mCurrentSection = -1;
private boolean mIsIndexing = false;
private ListView mListView = null;
private SectionIndexer mIndexer = null;
private String[] mSections = null;
private RectF mIndexbarRect;
private static final int STATE_HIDDEN = 0;
private static final int STATE_SHOWING = 1;
private static final int STATE_SHOWN = 2;
private static final int STATE_HIDING = 3;
public IndexScroller(Context context, ListView lv) {
mDensity = context.getResources().getDisplayMetrics().density;
mScaledDensity = context.getResources().getDisplayMetrics().scaledDensity;
mListView = lv;
setAdapter(mListView.getAdapter());
mIndexbarWidth = 20 * mDensity;
mIndexbarMargin = 2 * mDensity;
mPreviewPadding = 5 * mDensity;
}
public void draw(Canvas canvas) {
if (mState == STATE_HIDDEN)
return;
// mAlphaRate determines the rate of opacity
Paint indexbarPaint = new Paint();
indexbarPaint.setColor(Color.BLACK);
indexbarPaint.setAlpha((int) (64 * mAlphaRate));
indexbarPaint.setAntiAlias(true);
canvas.drawRoundRect(mIndexbarRect, 5 * mDensity, 5 * mDensity, indexbarPaint);
if (mSections != null && mSections.length > 0) {
// Preview is shown when mCurrentSection is set
if (mCurrentSection >= 0) {
Paint previewPaint = new Paint();
previewPaint.setColor(Color.BLACK);
previewPaint.setAlpha(96);
previewPaint.setAntiAlias(true);
previewPaint.setShadowLayer(3, 0, 0, Color.argb(64, 0, 0, 0));
Paint previewTextPaint = new Paint();
previewTextPaint.setColor(Color.WHITE);
previewTextPaint.setAntiAlias(true);
previewTextPaint.setTextSize(50 * mScaledDensity);
float previewTextWidth = previewTextPaint.measureText(mSections[mCurrentSection]);
float previewSize = 2 * mPreviewPadding + previewTextPaint.descent() - previewTextPaint.ascent();
RectF previewRect = new RectF((mListViewWidth - previewSize) / 2
, (mListViewHeight - previewSize) / 2
, (mListViewWidth - previewSize) / 2 + previewSize
, (mListViewHeight - previewSize) / 2 + previewSize);
canvas.drawRoundRect(previewRect, 5 * mDensity, 5 * mDensity, previewPaint);
canvas.drawText(mSections[mCurrentSection], previewRect.left + (previewSize - previewTextWidth) / 2 - 1
, previewRect.top + mPreviewPadding - previewTextPaint.ascent() + 1, previewTextPaint);
}
Paint indexPaint = new Paint();
indexPaint.setColor(Color.WHITE);
indexPaint.setAlpha((int) (255 * mAlphaRate));
indexPaint.setAntiAlias(true);
indexPaint.setTextSize(12 * mScaledDensity);
float sectionHeight = (mIndexbarRect.height() - 2 * mIndexbarMargin) / mSections.length;
float paddingTop = (sectionHeight - (indexPaint.descent() - indexPaint.ascent())) / 2;
for (int i = 0; i < mSections.length; i++) {
float paddingLeft = (mIndexbarWidth - indexPaint.measureText(mSections[i])) / 2;
canvas.drawText(mSections[i], mIndexbarRect.left + paddingLeft
, mIndexbarRect.top + mIndexbarMargin + sectionHeight * i + paddingTop - indexPaint.ascent(), indexPaint);
}
}
}
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
// If down event occurs inside index bar region, start indexing
if (mState != STATE_HIDDEN && contains(ev.getX(), ev.getY())) {
setState(STATE_SHOWN);
// It demonstrates that the motion event started from index bar
mIsIndexing = true;
// Determine which section the point is in, and move the list to that section
mCurrentSection = getSectionByPoint(ev.getY());
mListView.setSelection(mIndexer.getPositionForSection(mCurrentSection));
return true;
}
break;
case MotionEvent.ACTION_MOVE:
if (mIsIndexing) {
// If this event moves inside index bar
if (contains(ev.getX(), ev.getY())) {
// Determine which section the point is in, and move the list to that section
mCurrentSection = getSectionByPoint(ev.getY());
mListView.setSelection(mIndexer.getPositionForSection(mCurrentSection));
}
return true;
}
break;
case MotionEvent.ACTION_UP:
if (mIsIndexing) {
mIsIndexing = false;
mCurrentSection = -1;
}
if (mState == STATE_SHOWN)
setState(STATE_HIDING);
break;
}
return false;
}
public void onSizeChanged(int w, int h, int oldw, int oldh) {
mListViewWidth = w;
mListViewHeight = h;
mIndexbarRect = new RectF(w - mIndexbarMargin - mIndexbarWidth
, mIndexbarMargin
, w - mIndexbarMargin
, h - mIndexbarMargin);
}
public void show() {
if (mState == STATE_HIDDEN)
setState(STATE_SHOWING);
else if (mState == STATE_HIDING)
setState(STATE_HIDING);
}
public void hide() {
if (mState == STATE_SHOWN)
setState(STATE_HIDING);
}
public void setAdapter(Adapter adapter) {
if (adapter instanceof SectionIndexer) {
mIndexer = (SectionIndexer) adapter;
mSections = (String[]) mIndexer.getSections();
}
}
private void setState(int state) {
if (state < STATE_HIDDEN || state > STATE_HIDING)
return;
mState = state;
switch (mState) {
case STATE_HIDDEN:
// Cancel any fade effect
mHandler.removeMessages(0);
break;
case STATE_SHOWING:
// Start to fade in
mAlphaRate = 0;
fade(0);
break;
case STATE_SHOWN:
// Cancel any fade effect
mHandler.removeMessages(0);
break;
case STATE_HIDING:
// Start to fade out after three seconds
mAlphaRate = 1;
fade(3000);
break;
}
}
private boolean contains(float x, float y) {
// Determine if the point is in index bar region, which includes the right margin of the bar
return (x >= mIndexbarRect.left && y >= mIndexbarRect.top && y <= mIndexbarRect.top + mIndexbarRect.height());
}
private int getSectionByPoint(float y) {
if (mSections == null || mSections.length == 0)
return 0;
if (y < mIndexbarRect.top + mIndexbarMargin)
return 0;
if (y >= mIndexbarRect.top + mIndexbarRect.height() - mIndexbarMargin)
return mSections.length - 1;
return (int) ((y - mIndexbarRect.top - mIndexbarMargin) / ((mIndexbarRect.height() - 2 * mIndexbarMargin) / mSections.length));
}
private void fade(long delay) {
mHandler.removeMessages(0);
mHandler.sendEmptyMessageAtTime(0, SystemClock.uptimeMillis() + delay);
}
private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (mState) {
case STATE_SHOWING:
// Fade in effect
mAlphaRate += (1 - mAlphaRate) * 0.2;
if (mAlphaRate > 0.9) {
mAlphaRate = 1;
setState(STATE_SHOWN);
}
mListView.invalidate();
fade(10);
break;
case STATE_SHOWN:
// If no action, hide automatically
setState(STATE_HIDING);
break;
case STATE_HIDING:
// Fade out effect
mAlphaRate -= mAlphaRate * 0.2;
if (mAlphaRate < 0.1) {
mAlphaRate = 0;
setState(STATE_HIDDEN);
}
mListView.invalidate();
fade(10);
break;
}
}
};
}
In this, IndexableListView and IndexScroller are in same package and other 2 classes are in 2 different packages.
Please help how to just hide the IndexScroller so that it doesnt show up on touches.

Since no one bothered to answer, here is the thing to be done.,
For all lines where state is set as shown in IndexScroller.java, enclose them in:
isTrue = mListView.getLastVisiblePosition() + 1 == mListView.getCount();
if(!isTrue)
{
//State Shown
}

Related

Android not getting getApplicationContext on service

When i using on touch listener. Inside the touch listener i have called a method. The method parameters want activity and view. When i using getApplicationContext() in my service it shows
Wrong 1st argument type. Found: 'android.content.Context', required: 'android.app.Activity'
My code is given below
MyService.java
chatHead.setOnTouchListener(new View.OnTouchListener() {
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
initialX = params.x;
initialY = params.y;
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
startX = event.getX();
startY = event.getY();
return false;
case MotionEvent.ACTION_UP:
float endX = event.getX();
float endY = event.getY();
if (isAClick(startX, endX, startY, endY)) {
Log.d("LockView", "clicked2");
CircularAnim.fullActivity(getApplicationContext(), v)
.colorOrImageRes(R.color.color1)
.go(new CircularAnim.OnAnimationEndListener() {
#Override
public void onAnimationEnd() {
startActivity(new Intent(getApplicationContext(), BrowserActivity.class));
}
});
}
return true;
case MotionEvent.ACTION_MOVE:
params.x = initialX
+ (int) (event.getRawX() - initialTouchX);
params.y = initialY
+ (int) (event.getRawY() - initialTouchY);
windowManager.updateViewLayout(chatHead, params);
return false;
}
return true;
}
});
windowManager.addView(chatHead, params);
private boolean isAClick(float startX, float endX, float startY, float endY) {
float differenceX = Math.abs(startX - endX);
float differenceY = Math.abs(startY - endY);
if (differenceX > CLICK_ACTION_THRESHHOLD/* =5 */ || differenceY > CLICK_ACTION_THRESHHOLD) {
return false;
}
return true;
}
CircularAnim.java
public static FullActivityBuilder fullActivity(Activity activity, View triggerView) {
return new FullActivityBuilder(activity, triggerView);
}
public static void init(long perfectMills, long fullActivityPerfectMills, int colorOrImageRes) {
sPerfectMills = perfectMills;
sFullActivityPerfectMills = fullActivityPerfectMills;
sColorOrImageRes = colorOrImageRes;
}
The getApplicationContext() is getting in CircularAnim.fullActivity(MainActivity.this, view) but it is not in CircularAnim.fullActivity
How to solve problem of getApplicationContext in CircularAnim.fullActivity(getApplicationContext(), v)
Please help me.
Full code of CircularAnim
public class CircularAnim {
public static final long PERFECT_MILLS = 618;
public static final int MINI_RADIUS = 0;
private static Long sPerfectMills;
private static Long sFullActivityPerfectMills;
private static Integer sColorOrImageRes;
private static long getPerfectMills() {
if (sPerfectMills != null)
return sPerfectMills;
else
return PERFECT_MILLS;
}
private static long getFullActivityMills() {
if (sFullActivityPerfectMills != null)
return sFullActivityPerfectMills;
else
return PERFECT_MILLS;
}
private static int getColorOrImageRes() {
if (sColorOrImageRes != null)
return sColorOrImageRes;
else
return android.R.color.white;
}
public interface OnAnimationEndListener {
void onAnimationEnd();
}
#SuppressLint("NewApi")
public static class VisibleBuilder {
private View mAnimView, mTriggerView;
private Float mStartRadius, mEndRadius;
private long mDurationMills = getPerfectMills();
private boolean isShow;
private OnAnimationEndListener mOnAnimationEndListener;
public VisibleBuilder(View animView, boolean isShow) {
mAnimView = animView;
this.isShow = isShow;
if (isShow) {
mStartRadius = MINI_RADIUS + 0F;
} else {
mEndRadius = MINI_RADIUS + 0F;
}
}
public VisibleBuilder triggerView(View triggerView) {
mTriggerView = triggerView;
return this;
}
public VisibleBuilder startRadius(float startRadius) {
mStartRadius = startRadius;
return this;
}
public VisibleBuilder endRadius(float endRadius) {
mEndRadius = endRadius;
return this;
}
public VisibleBuilder duration(long durationMills) {
mDurationMills = durationMills;
return this;
}
#Deprecated //You can use method - go(OnAnimationEndListener onAnimationEndListener).
public VisibleBuilder onAnimationEndListener(OnAnimationEndListener onAnimationEndListener) {
mOnAnimationEndListener = onAnimationEndListener;
return this;
}
public void go() {
go(null);
}
public void go(OnAnimationEndListener onAnimationEndListener) {
mOnAnimationEndListener = onAnimationEndListener;
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
doOnEnd();
return;
}
int rippleCX, rippleCY, maxRadius;
if (mTriggerView != null) {
int[] tvLocation = new int[2];
mTriggerView.getLocationInWindow(tvLocation);
final int tvCX = tvLocation[0] + mTriggerView.getWidth() / 2;
final int tvCY = tvLocation[1] + mTriggerView.getHeight() / 2;
int[] avLocation = new int[2];
mAnimView.getLocationInWindow(avLocation);
final int avLX = avLocation[0];
final int avTY = avLocation[1];
int triggerX = Math.max(avLX, tvCX);
triggerX = Math.min(triggerX, avLX + mAnimView.getWidth());
int triggerY = Math.max(avTY, tvCY);
triggerY = Math.min(triggerY, avTY + mAnimView.getHeight());
int avW = mAnimView.getWidth();
int avH = mAnimView.getHeight();
rippleCX = triggerX - avLX;
rippleCY = triggerY - avTY;
int maxW = Math.max(rippleCX, avW - rippleCX);
int maxH = Math.max(rippleCY, avH - rippleCY);
maxRadius = (int) Math.sqrt(maxW * maxW + maxH * maxH) + 1;
} else {
rippleCX = (mAnimView.getLeft() + mAnimView.getRight()) / 2;
rippleCY = (mAnimView.getTop() + mAnimView.getBottom()) / 2;
int w = mAnimView.getWidth();
int h = mAnimView.getHeight();
maxRadius = (int) Math.sqrt(w * w + h * h) + 1;
}
if (isShow && mEndRadius == null)
mEndRadius = maxRadius + 0F;
else if (!isShow && mStartRadius == null)
mStartRadius = maxRadius + 0F;
try {
Animator anim = ViewAnimationUtils.createCircularReveal(
mAnimView, rippleCX, rippleCY, mStartRadius, mEndRadius);
mAnimView.setVisibility(View.VISIBLE);
anim.setDuration(mDurationMills);
anim.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
doOnEnd();
}
});
anim.start();
} catch (Exception e) {
e.printStackTrace();
doOnEnd();
}
}
private void doOnEnd() {
if (isShow)
mAnimView.setVisibility(View.VISIBLE);
else
mAnimView.setVisibility(View.INVISIBLE);
if (mOnAnimationEndListener != null)
mOnAnimationEndListener.onAnimationEnd();
}
}
#SuppressLint("NewApi")
public static class FullActivityBuilder {
private Activity mActivity;
private View mTriggerView;
private float mStartRadius = MINI_RADIUS;
private int mColorOrImageRes = getColorOrImageRes();
private Long mDurationMills;
private OnAnimationEndListener mOnAnimationEndListener;
private int mEnterAnim = android.R.anim.fade_in, mExitAnim = android.R.anim.fade_out;
public FullActivityBuilder(Activity activity, View triggerView) {
mActivity = activity;
mTriggerView = triggerView;
}
public FullActivityBuilder startRadius(float startRadius) {
mStartRadius = startRadius;
return this;
}
public FullActivityBuilder colorOrImageRes(int colorOrImageRes) {
mColorOrImageRes = colorOrImageRes;
return this;
}
public FullActivityBuilder duration(long durationMills) {
mDurationMills = durationMills;
return this;
}
public FullActivityBuilder overridePendingTransition(int enterAnim, int exitAnim) {
mEnterAnim = enterAnim;
mExitAnim = exitAnim;
return this;
}
public void go(OnAnimationEndListener onAnimationEndListener) {
mOnAnimationEndListener = onAnimationEndListener;
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
doOnEnd();
return;
}
int[] location = new int[2];
mTriggerView.getLocationInWindow(location);
final int cx = location[0] + mTriggerView.getWidth() / 2;
final int cy = location[1] + mTriggerView.getHeight() / 2;
final ImageView view = new ImageView(mActivity);
view.setScaleType(ImageView.ScaleType.CENTER_CROP);
view.setImageResource(mColorOrImageRes);
final ViewGroup decorView = (ViewGroup) mActivity.getWindow().getDecorView();
int w = decorView.getWidth();
int h = decorView.getHeight();
decorView.addView(view, w, h);
int maxW = Math.max(cx, w - cx);
int maxH = Math.max(cy, h - cy);
final int finalRadius = (int) Math.sqrt(maxW * maxW + maxH * maxH) + 1;
try {
Animator anim = ViewAnimationUtils.createCircularReveal(view, cx, cy, mStartRadius, finalRadius);
int maxRadius = (int) Math.sqrt(w * w + h * h) + 1;
if (mDurationMills == null) {
double rate = 1d * finalRadius / maxRadius;
mDurationMills = (long) (getFullActivityMills() * Math.sqrt(rate));
}
final long finalDuration = mDurationMills;
anim.setDuration((long) (finalDuration * 0.9));
anim.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
doOnEnd();
mActivity.overridePendingTransition(mEnterAnim, mExitAnim);
mTriggerView.postDelayed(new Runnable() {
#Override
public void run() {
if (mActivity.isFinishing()) return;
try {
Animator anim = ViewAnimationUtils.createCircularReveal(view, cx, cy,
finalRadius, mStartRadius);
anim.setDuration(finalDuration);
anim.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
try {
decorView.removeView(view);
} catch (Exception e) {
e.printStackTrace();
}
}
});
anim.start();
} catch (Exception e) {
e.printStackTrace();
try {
decorView.removeView(view);
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
}, 1000);
}
});
anim.start();
} catch (Exception e) {
e.printStackTrace();
doOnEnd();
}
}
private void doOnEnd() {
mOnAnimationEndListener.onAnimationEnd();
}
}
public static VisibleBuilder show(View animView) {
return new VisibleBuilder(animView, true);
}
public static VisibleBuilder hide(View animView) {
return new VisibleBuilder(animView, false);
}
public static FullActivityBuilder fullActivity(Activity activity, View triggerView) {
return new FullActivityBuilder(activity, triggerView);
}
public static void init(long perfectMills, long fullActivityPerfectMills, int colorOrImageRes) {
sPerfectMills = perfectMills;
sFullActivityPerfectMills = fullActivityPerfectMills;
sColorOrImageRes = colorOrImageRes;
}
}
Do it this way...
public class BaseService extends Service {
public Context mContext;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
mContext = getApplicationContext();
} }
getApplicationContext() is Related to application and not to activity hence you should use activityname.this or getBaseContext() and you are trying to perform UI Thread operation using Application Context ,Activity UI related operation shold be perform using Activity Context ,not Application Context
If what you need is to access the Context of your activity from your service, another thing you can try to pass the Activity context in the constructor of the Service. For example:
Activity
public class BT_Client extends Activity{
private BtService mBTService;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
mBtService = new BtService(this, ...);
}
}
Service
public class BtService {
Context myActivityContext;
public BtService(Context context, ...) {
myActivityContext = context;
...
}
}

Android - NullPointerException SimpleAdapter - Pinned section ListView?

I created a ListView with pinned which works well once. But when I arrive latest item of ListView crashes on me and says NullPointerException.
I need that when I arrive latest item get next 5 of items .
MainActivity.java :
public class PinnedSectionListActivity extends ListActivity implements OnClickListener {
public static Context context;
public static Context _context;
public static SQLiteDatabase sql;
public Cursor cursor;
public Cursor cursorA;
public boolean flag = false;
public Integer count = 0;
public List<Items> result;
public List<ItemsT> resultT;
static class SimpleAdapter extends ArrayAdapter<Item> implements PinnedSectionListView.PinnedSectionListAdapter {
private List<Items> Results;
private List<ItemsT> ResultsT;
private Integer counts;
private static final int[] COLORS = new int[] {
R.color.green_light, R.color.orange_light,
R.color.blue_light, R.color.red_light };
public SimpleAdapter(Context context,List<Items> MResults,List<ItemsT> MresultT,Integer count , int resource, int textViewResourceId) {
super(context, resource, textViewResourceId);
this.Results = MResults;
this.ResultsT = MresultT;
this.counts = count;
generateDataset(false);
}
public void generateDataset(boolean clear) {
int y = 0;
if (clear) clear();
prepareSections(counts);
int sectionPosition = 0, listPosition = 0;
for (char i=0; i<counts; i++) {
final Items ci = Results.get(i);
Item section = new Item(Item.SECTION, ci.WTitleO);
section.sectionPosition = sectionPosition;
section.listPosition = listPosition++;
onSectionAdded(section, sectionPosition);
add(section);
for (int j=0;j<ci.count;j++) {
final ItemsT xx = ResultsT.get(y);
Item item = new Item(Item.ITEM, xx.WTitleT);
item.sectionPosition = sectionPosition;
item.listPosition = listPosition++;
y++;
add(item);
}
sectionPosition++;
}
}
protected void prepareSections(int sectionsNumber) { }
protected void onSectionAdded(Item section, int sectionPosition) { }
#Override public View getView(int position, View convertView, ViewGroup parent) {
TextView view = (TextView) super.getView(position, convertView, parent);
view.setTextColor(Color.DKGRAY);
view.setTag("" + position);
Item item = getItem(position);
if (item.type == Item.SECTION) {
view.setBackgroundColor(parent.getResources().getColor(COLORS[item.sectionPosition % COLORS.length]));
}
return view;
}
#Override public int getViewTypeCount() {
return 2;
}
#Override public int getItemViewType(int position) {
return getItem(position).type;
}
#Override
public boolean isItemViewTypePinned(int viewType) {
return viewType == Item.SECTION;
}
}
static class Items {
public int conO ;
public String WTitleO;
public int count;
}
static class ItemsT {
public String WTitleT;
}
static class Item {
public static final int ITEM = 0;
public static final int SECTION = 1;
public final int type;
public final String text;
public int sectionPosition;
public int listPosition;
public Item(int type, String text) {
this.type = type;
this.text = text;
}
#Override public String toString() {
return text;
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = getApplicationContext();
_context = this;
DB db = new DB(context);
db.CreateFile();
try {
db.CreateandOpenDataBase();
} catch (IOException e) {
e.printStackTrace();
}
sql = db.openDataBase();
test();
}
public void test(){
result = new ArrayList<Items>();
resultT = new ArrayList<ItemsT>();
try {
cursor = sql.rawQuery("SELECT (select count() as number from WebSite_BookPageDB22 as b where b.ParentID = a.ContentID) as count" +
" ,ContentID,Title" +
" FROM WebSite_BookPageDB22 as a" +
" WHERE ArticleID = '" + 61799 + "' AND ParentID = '" + 0 + "'order by PageID ASC LIMIT 5", null);
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
Items ci = new Items();
ci.conO = cursor.getInt(cursor.getColumnIndex("ContentID"));
ci.WTitleO = cursor.getString(cursor.getColumnIndex("Title"));
ci.count = cursor.getInt(cursor.getColumnIndex("count"));
if(flag == false) {
count = cursor.getCount();
flag = true;
}
cursorA = sql.rawQuery("select Title from WebSite_BookPageDB22 where ParentID = '" + ci.conO +"' order by PageID ASC", null);
try {
if (cursorA != null && cursorA.moveToFirst()) {
do {
ItemsT cty = new ItemsT();
cty.WTitleT = cursorA.getString(cursorA.getColumnIndex("Title"));
resultT.add(cty);
} while (cursorA.moveToNext());
}
}catch (Exception e){
Log.i("xxx", "You have an error");
}finally {
if (cursorA != null) {
cursorA.close();
}
}
result.add(ci);
} while (cursor.moveToNext());
}
}
} catch (Exception e) {
} finally {
cursor.close();
}
SimpleAdapter adapt = new SimpleAdapter(_context, result, resultT, count, android.R.layout.simple_list_item_1, android.R.id.text1);
setListAdapter(adapt);
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Item item = (Item) getListView().getAdapter().getItem(position);
if (item != null) {
Toast.makeText(this, "Item " + position + ": " + item.text, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Item " + position, Toast.LENGTH_SHORT).show();
}
}
#Override
public void onClick(View v) {
Toast.makeText(this, "Item: " + v.getTag() , Toast.LENGTH_SHORT).show();
}
}
And PinnedSectionListView.java :
public class PinnedSectionListView extends ListView {
//-- inner classes
/** List adapter to be implemented for being used with PinnedSectionListView adapter. */
public static interface PinnedSectionListAdapter extends ListAdapter {
/** This method shall return 'true' if views of given type has to be pinned. */
boolean isItemViewTypePinned(int viewType);
}
/** Wrapper class for pinned section view and its position in the list. */
static class PinnedSection {
public View view;
public int position;
public long id;
}
//-- class fields
// fields used for handling touch events
private final Rect mTouchRect = new Rect();
private final PointF mTouchPoint = new PointF();
private int mTouchSlop;
private View mTouchTarget;
private MotionEvent mDownEvent;
// fields used for drawing shadow under a pinned section
private GradientDrawable mShadowDrawable;
private int mSectionsDistanceY;
private int mShadowHeight;
/** Delegating listener, can be null. */
OnScrollListener mDelegateOnScrollListener;
/** Shadow for being recycled, can be null. */
PinnedSection mRecycleSection;
/** shadow instance with a pinned view, can be null. */
PinnedSection mPinnedSection;
/** Pinned view Y-translation. We use it to stick pinned view to the next section. */
int mTranslateY;
/** Scroll listener which does the magic */
private final OnScrollListener mOnScrollListener = new OnScrollListener() {
#Override public void onScrollStateChanged(AbsListView view, int scrollState) {
if (mDelegateOnScrollListener != null) { // delegate
mDelegateOnScrollListener.onScrollStateChanged(view, scrollState);
}
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (mDelegateOnScrollListener != null) { // delegate
mDelegateOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
}
if(firstVisibleItem+visibleItemCount == totalItemCount && totalItemCount!=0)
{
PinnedSectionListActivity xx = new PinnedSectionListActivity();
xx.flag = false;
xx.test();
/*Intent refresh = new Intent(PinnedSectionListActivity._context, PinnedSectionListActivity.class);
PinnedSectionListActivity._context.startActivity(refresh);*/
}
// get expected adapter or fail fast
ListAdapter adapter = getAdapter();
if (adapter == null || visibleItemCount == 0) return; // nothing to do
final boolean isFirstVisibleItemSection =
isItemViewTypePinned(adapter, adapter.getItemViewType(firstVisibleItem));
if (isFirstVisibleItemSection) {
View sectionView = getChildAt(0);
if (sectionView.getTop() == getPaddingTop()) { // view sticks to the top, no need for pinned shadow
destroyPinnedShadow();
} else { // section doesn't stick to the top, make sure we have a pinned shadow
ensureShadowForPosition(firstVisibleItem, firstVisibleItem, visibleItemCount);
}
} else { // section is not at the first visible position
int sectionPosition = findCurrentSectionPosition(firstVisibleItem);
if (sectionPosition > -1) { // we have section position
ensureShadowForPosition(sectionPosition, firstVisibleItem, visibleItemCount);
} else { // there is no section for the first visible item, destroy shadow
destroyPinnedShadow();
}
}
};
};
/** Default change observer. */
private final DataSetObserver mDataSetObserver = new DataSetObserver() {
#Override public void onChanged() {
recreatePinnedShadow();
};
#Override public void onInvalidated() {
recreatePinnedShadow();
}
};
//-- constructors
public PinnedSectionListView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public PinnedSectionListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initView();
}
private void initView() {
setOnScrollListener(mOnScrollListener);
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
initShadow(true);
}
//-- public API methods
public void setShadowVisible(boolean visible) {
initShadow(visible);
if (mPinnedSection != null) {
View v = mPinnedSection.view;
invalidate(v.getLeft(), v.getTop(), v.getRight(), v.getBottom() + mShadowHeight);
}
}
//-- pinned section drawing methods
public void initShadow(boolean visible) {
if (visible) {
if (mShadowDrawable == null) {
mShadowDrawable = new GradientDrawable(Orientation.TOP_BOTTOM,
new int[] { Color.parseColor("#ffa0a0a0"), Color.parseColor("#50a0a0a0"), Color.parseColor("#00a0a0a0")});
mShadowHeight = (int) (8 * getResources().getDisplayMetrics().density);
}
} else {
if (mShadowDrawable != null) {
mShadowDrawable = null;
mShadowHeight = 0;
}
}
}
/** Create shadow wrapper with a pinned view for a view at given position */
void createPinnedShadow(int position) {
// try to recycle shadow
PinnedSection pinnedShadow = mRecycleSection;
mRecycleSection = null;
// create new shadow, if needed
if (pinnedShadow == null) pinnedShadow = new PinnedSection();
// request new view using recycled view, if such
View pinnedView = getAdapter().getView(position, pinnedShadow.view, PinnedSectionListView.this);
// read layout parameters
LayoutParams layoutParams = (LayoutParams) pinnedView.getLayoutParams();
if (layoutParams == null) {
layoutParams = (LayoutParams) generateDefaultLayoutParams();
pinnedView.setLayoutParams(layoutParams);
}
int heightMode = MeasureSpec.getMode(layoutParams.height);
int heightSize = MeasureSpec.getSize(layoutParams.height);
if (heightMode == MeasureSpec.UNSPECIFIED) heightMode = MeasureSpec.EXACTLY;
int maxHeight = getHeight() - getListPaddingTop() - getListPaddingBottom();
if (heightSize > maxHeight) heightSize = maxHeight;
// measure & layout
int ws = MeasureSpec.makeMeasureSpec(getWidth() - getListPaddingLeft() - getListPaddingRight(), MeasureSpec.EXACTLY);
int hs = MeasureSpec.makeMeasureSpec(heightSize, heightMode);
pinnedView.measure(ws, hs);
pinnedView.layout(0, 0, pinnedView.getMeasuredWidth(), pinnedView.getMeasuredHeight());
mTranslateY = 0;
// initialize pinned shadow
pinnedShadow.view = pinnedView;
pinnedShadow.position = position;
pinnedShadow.id = getAdapter().getItemId(position);
// store pinned shadow
mPinnedSection = pinnedShadow;
}
/** Destroy shadow wrapper for currently pinned view */
void destroyPinnedShadow() {
if (mPinnedSection != null) {
// keep shadow for being recycled later
mRecycleSection = mPinnedSection;
mPinnedSection = null;
}
}
/** Makes sure we have an actual pinned shadow for given position. */
void ensureShadowForPosition(int sectionPosition, int firstVisibleItem, int visibleItemCount) {
if (visibleItemCount < 2) { // no need for creating shadow at all, we have a single visible item
destroyPinnedShadow();
return;
}
if (mPinnedSection != null
&& mPinnedSection.position != sectionPosition) { // invalidate shadow, if required
destroyPinnedShadow();
}
if (mPinnedSection == null) { // create shadow, if empty
createPinnedShadow(sectionPosition);
}
// align shadow according to next section position, if needed
int nextPosition = sectionPosition + 1;
if (nextPosition < getCount()) {
int nextSectionPosition = findFirstVisibleSectionPosition(nextPosition,
visibleItemCount - (nextPosition - firstVisibleItem));
if (nextSectionPosition > -1) {
View nextSectionView = getChildAt(nextSectionPosition - firstVisibleItem);
final int bottom = mPinnedSection.view.getBottom() + getPaddingTop();
mSectionsDistanceY = nextSectionView.getTop() - bottom;
if (mSectionsDistanceY < 0) {
// next section overlaps pinned shadow, move it up
mTranslateY = mSectionsDistanceY;
} else {
// next section does not overlap with pinned, stick to top
mTranslateY = 0;
}
} else {
// no other sections are visible, stick to top
mTranslateY = 0;
mSectionsDistanceY = Integer.MAX_VALUE;
}
}
}
int findFirstVisibleSectionPosition(int firstVisibleItem, int visibleItemCount) {
ListAdapter adapter = getAdapter();
int adapterDataCount = adapter.getCount();
if (getLastVisiblePosition() >= adapterDataCount) return -1; // dataset has changed, no candidate
if (firstVisibleItem+visibleItemCount >= adapterDataCount){//added to prevent index Outofbound (in case)
visibleItemCount = adapterDataCount-firstVisibleItem;
}
for (int childIndex = 0; childIndex < visibleItemCount; childIndex++) {
int position = firstVisibleItem + childIndex;
int viewType = adapter.getItemViewType(position);
if (isItemViewTypePinned(adapter, viewType)) return position;
}
return -1;
}
int findCurrentSectionPosition(int fromPosition) {
ListAdapter adapter = getAdapter();
if (fromPosition >= adapter.getCount()) return -1; // dataset has changed, no candidate
if (adapter instanceof SectionIndexer) {
// try fast way by asking section indexer
SectionIndexer indexer = (SectionIndexer) adapter;
int sectionPosition = indexer.getSectionForPosition(fromPosition);
int itemPosition = indexer.getPositionForSection(sectionPosition);
int typeView = adapter.getItemViewType(itemPosition);
if (isItemViewTypePinned(adapter, typeView)) {
return itemPosition;
} // else, no luck
}
// try slow way by looking through to the next section item above
for (int position=fromPosition; position>=0; position--) {
int viewType = adapter.getItemViewType(position);
if (isItemViewTypePinned(adapter, viewType)) return position;
}
return -1; // no candidate found
}
void recreatePinnedShadow() {
destroyPinnedShadow();
ListAdapter adapter = getAdapter();
if (adapter != null && adapter.getCount() > 0) {
int firstVisiblePosition = getFirstVisiblePosition();
int sectionPosition = findCurrentSectionPosition(firstVisiblePosition);
if (sectionPosition == -1) return; // no views to pin, exit
ensureShadowForPosition(sectionPosition,
firstVisiblePosition, getLastVisiblePosition() - firstVisiblePosition);
}
}
#Override
public void setOnScrollListener(OnScrollListener listener) {
if (listener == mOnScrollListener) {
super.setOnScrollListener(listener);
} else {
mDelegateOnScrollListener = listener;
}
}
#Override
public void onRestoreInstanceState(Parcelable state) {
super.onRestoreInstanceState(state);
post(new Runnable() {
#Override public void run() { // restore pinned view after configuration change
recreatePinnedShadow();
}
});
}
#Override
public void setAdapter(ListAdapter adapter) {
// assert adapter in debug mode
if (BuildConfig.DEBUG && adapter != null) {
if (!(adapter instanceof PinnedSectionListAdapter))
throw new IllegalArgumentException("Does your adapter implement PinnedSectionListAdapter?");
if (adapter.getViewTypeCount() < 2)
throw new IllegalArgumentException("Does your adapter handle at least two types" +
" of views in getViewTypeCount() method: items and sections?");
}
// unregister observer at old adapter and register on new one
ListAdapter oldAdapter = getAdapter();
if (oldAdapter != null) oldAdapter.unregisterDataSetObserver(mDataSetObserver);
if (adapter != null) adapter.registerDataSetObserver(mDataSetObserver);
// destroy pinned shadow, if new adapter is not same as old one
if (oldAdapter != adapter) destroyPinnedShadow();
super.setAdapter(adapter);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (mPinnedSection != null) {
int parentWidth = r - l - getPaddingLeft() - getPaddingRight();
int shadowWidth = mPinnedSection.view.getWidth();
if (parentWidth != shadowWidth) {
recreatePinnedShadow();
}
}
}
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (mPinnedSection != null) {
// prepare variables
int pLeft = getListPaddingLeft();
int pTop = getListPaddingTop();
View view = mPinnedSection.view;
// draw child
canvas.save();
int clipHeight = view.getHeight() +
(mShadowDrawable == null ? 0 : Math.min(mShadowHeight, mSectionsDistanceY));
canvas.clipRect(pLeft, pTop, pLeft + view.getWidth(), pTop + clipHeight);
canvas.translate(pLeft, pTop + mTranslateY);
drawChild(canvas, mPinnedSection.view, getDrawingTime());
if (mShadowDrawable != null && mSectionsDistanceY > 0) {
mShadowDrawable.setBounds(mPinnedSection.view.getLeft(),
mPinnedSection.view.getBottom(),
mPinnedSection.view.getRight(),
mPinnedSection.view.getBottom() + mShadowHeight);
mShadowDrawable.draw(canvas);
}
canvas.restore();
}
}
//-- touch handling methods
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
final float x = ev.getX();
final float y = ev.getY();
final int action = ev.getAction();
if (action == MotionEvent.ACTION_DOWN
&& mTouchTarget == null
&& mPinnedSection != null
&& isPinnedViewTouched(mPinnedSection.view, x, y)) { // create touch target
// user touched pinned view
mTouchTarget = mPinnedSection.view;
mTouchPoint.x = x;
mTouchPoint.y = y;
// copy down event for eventually be used later
mDownEvent = MotionEvent.obtain(ev);
}
if (mTouchTarget != null) {
if (isPinnedViewTouched(mTouchTarget, x, y)) { // forward event to pinned view
mTouchTarget.dispatchTouchEvent(ev);
}
if (action == MotionEvent.ACTION_UP) { // perform onClick on pinned view
super.dispatchTouchEvent(ev);
performPinnedItemClick();
clearTouchTarget();
} else if (action == MotionEvent.ACTION_CANCEL) { // cancel
clearTouchTarget();
} else if (action == MotionEvent.ACTION_MOVE) {
if (Math.abs(y - mTouchPoint.y) > mTouchSlop) {
// cancel sequence on touch target
MotionEvent event = MotionEvent.obtain(ev);
event.setAction(MotionEvent.ACTION_CANCEL);
mTouchTarget.dispatchTouchEvent(event);
event.recycle();
// provide correct sequence to super class for further handling
super.dispatchTouchEvent(mDownEvent);
super.dispatchTouchEvent(ev);
clearTouchTarget();
}
}
return true;
}
// call super if this was not our pinned view
return super.dispatchTouchEvent(ev);
}
private boolean isPinnedViewTouched(View view, float x, float y) {
view.getHitRect(mTouchRect);
// by taping top or bottom padding, the list performs on click on a border item.
// we don't add top padding here to keep behavior consistent.
mTouchRect.top += mTranslateY;
mTouchRect.bottom += mTranslateY + getPaddingTop();
mTouchRect.left += getPaddingLeft();
mTouchRect.right -= getPaddingRight();
return mTouchRect.contains((int)x, (int)y);
}
private void clearTouchTarget() {
mTouchTarget = null;
if (mDownEvent != null) {
mDownEvent.recycle();
mDownEvent = null;
}
}
private boolean performPinnedItemClick() {
if (mPinnedSection == null) return false;
OnItemClickListener listener = getOnItemClickListener();
if (listener != null && getAdapter().isEnabled(mPinnedSection.position)) {
View view = mPinnedSection.view;
playSoundEffect(SoundEffectConstants.CLICK);
if (view != null) {
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
}
listener.onItemClick(this, view, mPinnedSection.position, mPinnedSection.id);
return true;
}
return false;
}
public static boolean isItemViewTypePinned(ListAdapter adapter, int viewType) {
if (adapter instanceof HeaderViewListAdapter) {
adapter = ((HeaderViewListAdapter)adapter).getWrappedAdapter();
}
return ((PinnedSectionListAdapter) adapter).isItemViewTypePinned(viewType);
}
}
For second time get me error here :
SimpleAdapter adapt = new SimpleAdapter(_context, result, resultT, count, android.R.layout.simple_list_item_1, android.R.id.text1);
setListAdapter(adapt);
Your not using PinnedSectionListActivity current reference properly,If you wan to access your current public function inside any other class then you have to pass your current activity reference :
Declaration
private Context context;
Get current activity reference
public PinnedSectionListView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
initView();
}
public PinnedSectionListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
initView();
}
Use current activity reference in onScroll() :
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (mDelegateOnScrollListener != null) { // delegate
mDelegateOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
}
if(firstVisibleItem+visibleItemCount == totalItemCount && totalItemCount!=0)
{
if(context!=null){
((PinnedSectionListActivity)context).cleans();
}
}else {
// get expected adapter or fail fast
ListAdapter adapter = getAdapter();
if (adapter == null || visibleItemCount == 0) return; // nothing to do
final boolean isFirstVisibleItemSection = isItemViewTypePinned(adapter, adapter.getItemViewType(firstVisibleItem));
if (isFirstVisibleItemSection) {
View sectionView = getChildAt(0);
if (sectionView.getTop() == getPaddingTop()) { // view sticks to the top, no need for pinned shadow
destroyPinnedShadow();
} else { // section doesn't stick to the top, make sure we have a pinned shadow
ensureShadowForPosition(firstVisibleItem, firstVisibleItem, visibleItemCount);
}
} else { // section is not at the first visible position
int sectionPosition = findCurrentSectionPosition(firstVisibleItem);
if (sectionPosition > -1) { // we have section position
ensureShadowForPosition(sectionPosition, firstVisibleItem, visibleItemCount);
} else { // there is no section for the first visible item, destroy shadow
destroyPinnedShadow();
}
}
}
};
PinnedSectionListView full activity code :
public class PinnedSectionListView extends ListView {
//-- inner classes
/** List adapter to be implemented for being used with PinnedSectionListView adapter. */
public static interface PinnedSectionListAdapter extends ListAdapter {
/** This method shall return 'true' if views of given type has to be pinned. */
boolean isItemViewTypePinned(int viewType);
}
/** Wrapper class for pinned section view and its position in the list. */
static class PinnedSection {
public View view;
public int position;
public long id;
}
//-- class fields
// fields used for handling touch events
private final Rect mTouchRect = new Rect();
private final PointF mTouchPoint = new PointF();
private int mTouchSlop;
private View mTouchTarget;
private MotionEvent mDownEvent;
// fields used for drawing shadow under a pinned section
private GradientDrawable mShadowDrawable;
private int mSectionsDistanceY;
private int mShadowHeight;
/** Delegating listener, can be null. */
OnScrollListener mDelegateOnScrollListener;
/** Shadow for being recycled, can be null. */
PinnedSection mRecycleSection;
/** shadow instance with a pinned view, can be null. */
PinnedSection mPinnedSection;
/** Pinned view Y-translation. We use it to stick pinned view to the next section. */
int mTranslateY;
private Context context;
/** Scroll listener which does the magic */
private final OnScrollListener mOnScrollListener = new OnScrollListener() {
#Override public void onScrollStateChanged(AbsListView view, int scrollState) {
if (mDelegateOnScrollListener != null) { // delegate
mDelegateOnScrollListener.onScrollStateChanged(view, scrollState);
}
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (mDelegateOnScrollListener != null) { // delegate
mDelegateOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
}
if(firstVisibleItem+visibleItemCount == totalItemCount && totalItemCount!=0)
{
if(context!=null){
((PinnedSectionListActivity)context).cleans();
}
}else {
// get expected adapter or fail fast
ListAdapter adapter = getAdapter();
if (adapter == null || visibleItemCount == 0) return; // nothing to do
final boolean isFirstVisibleItemSection = isItemViewTypePinned(adapter, adapter.getItemViewType(firstVisibleItem));
if (isFirstVisibleItemSection) {
View sectionView = getChildAt(0);
if (sectionView.getTop() == getPaddingTop()) { // view sticks to the top, no need for pinned shadow
destroyPinnedShadow();
} else { // section doesn't stick to the top, make sure we have a pinned shadow
ensureShadowForPosition(firstVisibleItem, firstVisibleItem, visibleItemCount);
}
} else { // section is not at the first visible position
int sectionPosition = findCurrentSectionPosition(firstVisibleItem);
if (sectionPosition > -1) { // we have section position
ensureShadowForPosition(sectionPosition, firstVisibleItem, visibleItemCount);
} else { // there is no section for the first visible item, destroy shadow
destroyPinnedShadow();
}
}
}
};
};
/** Default change observer. */
private final DataSetObserver mDataSetObserver = new DataSetObserver() {
#Override public void onChanged() {
recreatePinnedShadow();
};
#Override public void onInvalidated() {
recreatePinnedShadow();
}
};
//-- constructors
public PinnedSectionListView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
initView();
}
public PinnedSectionListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
initView();
}
private void initView() {
setOnScrollListener(mOnScrollListener);
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
initShadow(true);
}
//-- public API methods
public void setShadowVisible(boolean visible) {
initShadow(visible);
if (mPinnedSection != null) {
View v = mPinnedSection.view;
invalidate(v.getLeft(), v.getTop(), v.getRight(), v.getBottom() + mShadowHeight);
}
}
//-- pinned section drawing methods
public void initShadow(boolean visible) {
if (visible) {
if (mShadowDrawable == null) {
mShadowDrawable = new GradientDrawable(Orientation.TOP_BOTTOM,
new int[] { Color.parseColor("#ffa0a0a0"), Color.parseColor("#50a0a0a0"), Color.parseColor("#00a0a0a0")});
mShadowHeight = (int) (8 * getResources().getDisplayMetrics().density);
}
} else {
if (mShadowDrawable != null) {
mShadowDrawable = null;
mShadowHeight = 0;
}
}
}
/** Create shadow wrapper with a pinned view for a view at given position */
void createPinnedShadow(int position) {
// try to recycle shadow
PinnedSection pinnedShadow = mRecycleSection;
mRecycleSection = null;
// create new shadow, if needed
if (pinnedShadow == null) pinnedShadow = new PinnedSection();
// request new view using recycled view, if such
View pinnedView = getAdapter().getView(position, pinnedShadow.view, PinnedSectionListView.this);
// read layout parameters
LayoutParams layoutParams = (LayoutParams) pinnedView.getLayoutParams();
if (layoutParams == null) {
layoutParams = (LayoutParams) generateDefaultLayoutParams();
pinnedView.setLayoutParams(layoutParams);
}
int heightMode = MeasureSpec.getMode(layoutParams.height);
int heightSize = MeasureSpec.getSize(layoutParams.height);
if (heightMode == MeasureSpec.UNSPECIFIED) heightMode = MeasureSpec.EXACTLY;
int maxHeight = getHeight() - getListPaddingTop() - getListPaddingBottom();
if (heightSize > maxHeight) heightSize = maxHeight;
// measure & layout
int ws = MeasureSpec.makeMeasureSpec(getWidth() - getListPaddingLeft() - getListPaddingRight(), MeasureSpec.EXACTLY);
int hs = MeasureSpec.makeMeasureSpec(heightSize, heightMode);
pinnedView.measure(ws, hs);
pinnedView.layout(0, 0, pinnedView.getMeasuredWidth(), pinnedView.getMeasuredHeight());
mTranslateY = 0;
// initialize pinned shadow
pinnedShadow.view = pinnedView;
pinnedShadow.position = position;
pinnedShadow.id = getAdapter().getItemId(position);
// store pinned shadow
mPinnedSection = pinnedShadow;
}
/** Destroy shadow wrapper for currently pinned view */
void destroyPinnedShadow() {
if (mPinnedSection != null) {
// keep shadow for being recycled later
mRecycleSection = mPinnedSection;
mPinnedSection = null;
}
}
/** Makes sure we have an actual pinned shadow for given position. */
void ensureShadowForPosition(int sectionPosition, int firstVisibleItem, int visibleItemCount) {
if (visibleItemCount < 2) { // no need for creating shadow at all, we have a single visible item
destroyPinnedShadow();
return;
}
if (mPinnedSection != null
&& mPinnedSection.position != sectionPosition) { // invalidate shadow, if required
destroyPinnedShadow();
}
if (mPinnedSection == null) { // create shadow, if empty
createPinnedShadow(sectionPosition);
}
// align shadow according to next section position, if needed
int nextPosition = sectionPosition + 1;
if (nextPosition < getCount()) {
int nextSectionPosition = findFirstVisibleSectionPosition(nextPosition,
visibleItemCount - (nextPosition - firstVisibleItem));
if (nextSectionPosition > -1) {
View nextSectionView = getChildAt(nextSectionPosition - firstVisibleItem);
final int bottom = mPinnedSection.view.getBottom() + getPaddingTop();
mSectionsDistanceY = nextSectionView.getTop() - bottom;
if (mSectionsDistanceY < 0) {
// next section overlaps pinned shadow, move it up
mTranslateY = mSectionsDistanceY;
} else {
// next section does not overlap with pinned, stick to top
mTranslateY = 0;
}
} else {
// no other sections are visible, stick to top
mTranslateY = 0;
mSectionsDistanceY = Integer.MAX_VALUE;
}
}
}
int findFirstVisibleSectionPosition(int firstVisibleItem, int visibleItemCount) {
ListAdapter adapter = getAdapter();
int adapterDataCount = adapter.getCount();
if (getLastVisiblePosition() >= adapterDataCount) return -1; // dataset has changed, no candidate
if (firstVisibleItem+visibleItemCount >= adapterDataCount){//added to prevent index Outofbound (in case)
visibleItemCount = adapterDataCount-firstVisibleItem;
}
for (int childIndex = 0; childIndex < visibleItemCount; childIndex++) {
int position = firstVisibleItem + childIndex;
int viewType = adapter.getItemViewType(position);
if (isItemViewTypePinned(adapter, viewType)) return position;
}
return -1;
}
int findCurrentSectionPosition(int fromPosition) {
ListAdapter adapter = getAdapter();
if (fromPosition >= adapter.getCount()) return -1; // dataset has changed, no candidate
if (adapter instanceof SectionIndexer) {
// try fast way by asking section indexer
SectionIndexer indexer = (SectionIndexer) adapter;
int sectionPosition = indexer.getSectionForPosition(fromPosition);
int itemPosition = indexer.getPositionForSection(sectionPosition);
int typeView = adapter.getItemViewType(itemPosition);
if (isItemViewTypePinned(adapter, typeView)) {
return itemPosition;
} // else, no luck
}
// try slow way by looking through to the next section item above
for (int position=fromPosition; position>=0; position--) {
int viewType = adapter.getItemViewType(position);
if (isItemViewTypePinned(adapter, viewType)) return position;
}
return -1; // no candidate found
}
void recreatePinnedShadow() {
destroyPinnedShadow();
ListAdapter adapter = getAdapter();
if (adapter != null && adapter.getCount() > 0) {
int firstVisiblePosition = getFirstVisiblePosition();
int sectionPosition = findCurrentSectionPosition(firstVisiblePosition);
if (sectionPosition == -1) return; // no views to pin, exit
ensureShadowForPosition(sectionPosition,
firstVisiblePosition, getLastVisiblePosition() - firstVisiblePosition);
}
}
#Override
public void setOnScrollListener(OnScrollListener listener) {
if (listener == mOnScrollListener) {
super.setOnScrollListener(listener);
} else {
mDelegateOnScrollListener = listener;
}
}
#Override
public void onRestoreInstanceState(Parcelable state) {
super.onRestoreInstanceState(state);
post(new Runnable() {
#Override public void run() { // restore pinned view after configuration change
recreatePinnedShadow();
}
});
}
#Override
public void setAdapter(ListAdapter adapter) {
// assert adapter in debug mode
if (BuildConfig.DEBUG && adapter != null) {
if (!(adapter instanceof PinnedSectionListAdapter))
throw new IllegalArgumentException("Does your adapter implement PinnedSectionListAdapter?");
if (adapter.getViewTypeCount() < 2)
throw new IllegalArgumentException("Does your adapter handle at least two types" +
" of views in getViewTypeCount() method: items and sections?");
}
// unregister observer at old adapter and register on new one
ListAdapter oldAdapter = getAdapter();
if (oldAdapter != null) oldAdapter.unregisterDataSetObserver(mDataSetObserver);
if (adapter != null) adapter.registerDataSetObserver(mDataSetObserver);
// destroy pinned shadow, if new adapter is not same as old one
if (oldAdapter != adapter) destroyPinnedShadow();
super.setAdapter(adapter);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (mPinnedSection != null) {
int parentWidth = r - l - getPaddingLeft() - getPaddingRight();
int shadowWidth = mPinnedSection.view.getWidth();
if (parentWidth != shadowWidth) {
recreatePinnedShadow();
}
}
}
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (mPinnedSection != null) {
// prepare variables
int pLeft = getListPaddingLeft();
int pTop = getListPaddingTop();
View view = mPinnedSection.view;
// draw child
canvas.save();
int clipHeight = view.getHeight() +
(mShadowDrawable == null ? 0 : Math.min(mShadowHeight, mSectionsDistanceY));
canvas.clipRect(pLeft, pTop, pLeft + view.getWidth(), pTop + clipHeight);
canvas.translate(pLeft, pTop + mTranslateY);
drawChild(canvas, mPinnedSection.view, getDrawingTime());
if (mShadowDrawable != null && mSectionsDistanceY > 0) {
mShadowDrawable.setBounds(mPinnedSection.view.getLeft(),
mPinnedSection.view.getBottom(),
mPinnedSection.view.getRight(),
mPinnedSection.view.getBottom() + mShadowHeight);
mShadowDrawable.draw(canvas);
}
canvas.restore();
}
}
//-- touch handling methods
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
final float x = ev.getX();
final float y = ev.getY();
final int action = ev.getAction();
if (action == MotionEvent.ACTION_DOWN
&& mTouchTarget == null
&& mPinnedSection != null
&& isPinnedViewTouched(mPinnedSection.view, x, y)) { // create touch target
// user touched pinned view
mTouchTarget = mPinnedSection.view;
mTouchPoint.x = x;
mTouchPoint.y = y;
// copy down event for eventually be used later
mDownEvent = MotionEvent.obtain(ev);
}
if (mTouchTarget != null) {
if (isPinnedViewTouched(mTouchTarget, x, y)) { // forward event to pinned view
mTouchTarget.dispatchTouchEvent(ev);
}
if (action == MotionEvent.ACTION_UP) { // perform onClick on pinned view
super.dispatchTouchEvent(ev);
performPinnedItemClick();
clearTouchTarget();
} else if (action == MotionEvent.ACTION_CANCEL) { // cancel
clearTouchTarget();
} else if (action == MotionEvent.ACTION_MOVE) {
if (Math.abs(y - mTouchPoint.y) > mTouchSlop) {
// cancel sequence on touch target
MotionEvent event = MotionEvent.obtain(ev);
event.setAction(MotionEvent.ACTION_CANCEL);
mTouchTarget.dispatchTouchEvent(event);
event.recycle();
// provide correct sequence to super class for further handling
super.dispatchTouchEvent(mDownEvent);
super.dispatchTouchEvent(ev);
clearTouchTarget();
}
}
return true;
}
// call super if this was not our pinned view
return super.dispatchTouchEvent(ev);
}
private boolean isPinnedViewTouched(View view, float x, float y) {
view.getHitRect(mTouchRect);
// by taping top or bottom padding, the list performs on click on a border item.
// we don't add top padding here to keep behavior consistent.
mTouchRect.top += mTranslateY;
mTouchRect.bottom += mTranslateY + getPaddingTop();
mTouchRect.left += getPaddingLeft();
mTouchRect.right -= getPaddingRight();
return mTouchRect.contains((int)x, (int)y);
}
private void clearTouchTarget() {
mTouchTarget = null;
if (mDownEvent != null) {
mDownEvent.recycle();
mDownEvent = null;
}
}
private boolean performPinnedItemClick() {
if (mPinnedSection == null) return false;
OnItemClickListener listener = getOnItemClickListener();
if (listener != null && getAdapter().isEnabled(mPinnedSection.position)) {
View view = mPinnedSection.view;
playSoundEffect(SoundEffectConstants.CLICK);
if (view != null) {
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
}
listener.onItemClick(this, view, mPinnedSection.position, mPinnedSection.id);
return true;
}
return false;
}
public static boolean isItemViewTypePinned(ListAdapter adapter, int viewType) {
if (adapter instanceof HeaderViewListAdapter) {
adapter = ((HeaderViewListAdapter)adapter).getWrappedAdapter();
}
return ((PinnedSectionListAdapter) adapter).isItemViewTypePinned(viewType);
}
}

Is it possible to make Imageview with checked and unchecked like radiobutton?

I am having nearly 500+ images in Imageview inside Horizontalscrollview. If i am selecting an image then I am marking it as selected. If I am selecting any other images in the view, it should be un-select and newly clicked image should have to be selected. How could I can achieve it?
for (int i = 0; i < Home.arr_category_item_list.size(); i++) {
ImageView circleImageView = new ImageView(getActivity());
imageLoader.get(Home.arr_category_item_list.get(i).get(Variables.EST_CATEGORY_ITEM_IMAGE), ImageLoader.getImageListener(circleImageView, R.drawable.defaultimage, R.drawable.defaultimage));
circleImageView.setTag(Integer.parseInt(Home.arr_category_item_list.get(i).get(Variables.EST_CATEGORY_ITEM_ID)));
circleImageView.setLayoutParams(params);
lnr_category_item.addView(circleImageView);
}
Please check the image attached. At the bottom of the screen there is an Image view. So user will have option to select only one image at a time.
Now this is some really old code, hope it still works.
Note: there may be a thing or two missing, but you can get the idea from this implementation
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import yourpackage.R;
//Creataed by Bojan Kseneman on 14.8.2013
public class CustomCheckBox extends ImageView {
private boolean isChecked;
private boolean isImageShown;
private boolean useCustomClickListener;
//private String android_xmlns = "http://schemas.android.com/apk/res/android";
private String app_xmlns;
private int checkboxOnResID;
private int checkboxOffResID;
private int checkboxDisabledOnResID;
private int checkboxDisabledOffResID;
//private int imageHeight;
//private int imageWidth;
public CustomCheckBox(Context context, AttributeSet attrs) {
super(context, attrs);
app_xmlns = new StringBuilder("http://schemas.android.com/apk/res/" + context.getPackageName()).toString();
init(attrs);
}
private void init(AttributeSet attrs) {
checkboxOnResID = attrs.getAttributeResourceValue(app_xmlns, "resourceChecked", R.drawable.round_checkbox_on);
checkboxOffResID = attrs.getAttributeResourceValue(app_xmlns, "resourceNotChecked", R.drawable.round_checkbox_off);
checkboxDisabledOnResID = attrs.getAttributeResourceValue(app_xmlns, "resourceDisabledOn", R.drawable.round_checkbox_off);
checkboxDisabledOffResID = attrs.getAttributeResourceValue(app_xmlns, "resourceDisabledOff", R.drawable.round_checkbox_off);
useCustomClickListener = attrs.getAttributeBooleanValue(app_xmlns, "customClickEvent", false);
if (useCustomClickListener)
this.setOnTouchListener(new CboxTouchListener());
else {
this.setOnTouchListener(new NormalClickListener());
}
if (!hasOnClickListener()) {
/**
* assign a new onClick listener so we get desired onClick sound
* effect (because we call it) this is opposite to how android
* behaves, where you don't hear the sound if there is not
* onClickListener assigned
*/
this.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
}
private boolean hasOnClickListener() {
try {
if (android.os.Build.VERSION.SDK_INT >= 14) {
//the information is inside ListenerInfo
java.lang.reflect.Field listenerInfoField = null;
listenerInfoField = Class.forName("android.view.View").getDeclaredField("mListenerInfo");
if (listenerInfoField != null)
listenerInfoField.setAccessible(true);
Object mOnClickListener = null;
mOnClickListener = listenerInfoField.get(this); //get from view object, in this case this is this
// get the field mOnClickListener, that holds the listener and cast it to a listener
java.lang.reflect.Field listenerField = null;
listenerField = Class.forName("android.view.View$ListenerInfo").getDeclaredField("mOnClickListener");
//View.OnClickListener myListener = (View.OnClickListener) listenerField.get(myLiObject);
return (listenerField.get(mOnClickListener) != null);
}
else {
//directly in View
java.lang.reflect.Field f = Class.forName("android.view.View").getDeclaredField("mOnClickListener");
return (f.get(this) != null);
}
}
catch (Exception e) {
return false;
}
}
// private void setScaledDownImage(int resID) {
// this.setImageBitmap(CommonMethods.decodeSampledBitmapFromResource(getContext(), resID, imageWidth, imageHeight));
// }
public boolean isChecked() {
return (isChecked && this.isEnabled());
}
public void setChecked(boolean isChecked) {
if (this.isEnabled())
setCheckedIgnoreEnabled(isChecked);
else
this.setEnabled(false);
}
public void setCheckedIgnoreEnabled(boolean isChecked) {
if ((this.isChecked != isChecked) || !isImageShown) {
this.isChecked = isChecked;
if (isChecked)
setImageResource(checkboxOnResID);
else
setImageResource(checkboxOffResID);
}
}
#Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
if (enabled)
setChecked(isChecked);
else {
int resID = isChecked ? checkboxDisabledOnResID : checkboxDisabledOffResID;
setImageResource(resID);
}
}
public void setCheckedAndEnabled(boolean isChecked, boolean isEnabled) {
setCheckedIgnoreEnabled(isChecked);
setEnabled(isEnabled);
}
public void toggle() {
setChecked(!isChecked);
}
public void toggleWithClick() {
toggle();
this.performClick();
}
public void toggleWithSilentClick() {
//v.playSoundEffect(android.view.SoundEffectConstants.CLICK);
boolean currentState = this.isSoundEffectsEnabled();
this.setSoundEffectsEnabled(false);
toggleWithClick();
this.setSoundEffectsEnabled(currentState);
}
private class CboxTouchListener extends ImageBoundClickListener {
#Override
public void doSomething() {
super.doSomething();
setChecked(!isChecked);
CustomCheckBox.this.performClick();
}
}
private class NormalClickListener extends MyOnClickListener {
#Override
public void doSomething() {
super.doSomething();
setChecked(!isChecked);
CustomCheckBox.this.performClick();
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//this.imageWidth = MeasureSpec.getSize(widthMeasureSpec);
//this.imageHeight = MeasureSpec.getSize(heightMeasureSpec);
if (!isImageShown) {
setChecked(isChecked);
isImageShown = !isImageShown;
}
}
}
I used this click listener, since I was using some round images and I didn't want to trigger the click events when the user clicked on the transparent part of the image.
public abstract class ImageBoundClickListener implements android.view.View.OnTouchListener {
private String TAG = "ImageBoundsTouchListener";
private boolean shouldTriggerAction = false;
Rect allowedArea;
#Override
public boolean onTouch(View v, MotionEvent event) {
//let's us detect only clicks on the part where actual image is and not where the ImageView is
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
float[] eventXY = new float[] { event.getX(), event.getY() };
allowedArea = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
android.graphics.Matrix invertMatrix = new android.graphics.Matrix();
ImageView iv = (ImageView) v;
iv.getImageMatrix().invert(invertMatrix);
invertMatrix.mapPoints(eventXY);
int x = (int) eventXY[0];
int y = (int) eventXY[1];
Drawable imgDrawable = iv.getDrawable();
Bitmap bitmap = ((BitmapDrawable) imgDrawable).getBitmap();
//Limit x,y within the bitmap
if (x < 0)
x = 0;
else if (x > (bitmap.getWidth() - 1))
x = bitmap.getWidth() - 1;
if (y < 0)
y = 0;
else if (y > bitmap.getHeight() - 1)
y = bitmap.getHeight() - 1;
int touchedRGB = bitmap.getPixel(x, y);
//is transparent?
shouldTriggerAction = (touchedRGB == 0) ? false : true;
return true;
case MotionEvent.ACTION_MOVE:
if (!allowedArea.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY()))
//the user went out of the user area
shouldTriggerAction = false;
return true;
case MotionEvent.ACTION_UP:
//finger is no longer on screen
if (shouldTriggerAction)
doSomething();
return true;
default:
return false;
}
}
public void doSomething() {
}
}

Drag and Drop ListView Rows Disappearing Android

I have a listview in my app that uses the drag and drop functionality from this Google video: https://www.youtube.com/watch?v=_BZIvjMgH-Q . It works just fine when the app loads items from the database, but when I trying adding an item to the listview it breaks. Here is what that looks like: https://www.youtube.com/watch?v=_BZIvjMgH-Q
I think the problem is with my getItemId method inside my ItemsArrayAdapter.java class:
#Override
public long getItemId(int position) {
Long idToReturn = (long) INVALID_ID;
if (position >= 0 && position <= mIdMap.size()-1) {
try {
String item = getItem(position);
idToReturn = (long) mIdMap.get(item);
}
catch(Exception e){}
}
return idToReturn;
}
Here is what the DynamicListView.java looks like:
public class DynamicListView extends ListView {
final static String TAG = DynamicListView.class.getSimpleName();
private final int SMOOTH_SCROLL_AMOUNT_AT_EDGE = 15;
private final int MOVE_DURATION = 150;
private final int LINE_THICKNESS = 15;
public ArrayList<String> mCheeseList;
private int mLastEventY = -1;
private int mDownY = -1;
private int mDownX = -1;
private int mTotalOffset = 0;
private boolean mCellIsMobile = false;
private boolean mIsMobileScrolling = false;
private int mSmoothScrollAmountAtEdge = 0;
private final int INVALID_ID = -1;
private long mAboveItemId = INVALID_ID;
private long mMobileItemId = INVALID_ID;
private long mBelowItemId = INVALID_ID;
private BitmapDrawable mHoverCell;
private Rect mHoverCellCurrentBounds;
private Rect mHoverCellOriginalBounds;
private final int INVALID_POINTER_ID = -1;
private int mActivePointerId = INVALID_POINTER_ID;
private boolean mIsWaitingForScrollFinish = false;
private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE;
public DynamicListView(Context context) {
super(context);
init(context);
}
public DynamicListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public DynamicListView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public void init(Context context) {
setOnItemLongClickListener(mOnItemLongClickListener);
setOnScrollListener(mScrollListener);
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
mSmoothScrollAmountAtEdge = (int)(SMOOTH_SCROLL_AMOUNT_AT_EDGE / metrics.density);
}
/**
* Listens for long clicks on any mItems in the listview. When a cell has
* been selected, the hover cell is created and set up.
*/
private OnItemLongClickListener mOnItemLongClickListener =
new OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int pos, long id) {
mTotalOffset = 0;
int position = pointToPosition(mDownX, mDownY);
int itemNum = position - getFirstVisiblePosition();
View selectedView = getChildAt(itemNum);
mMobileItemId = getAdapter().getItemId(position);
mHoverCell = getAndAddHoverView(selectedView);
selectedView.setVisibility(INVISIBLE);
mCellIsMobile = true;
updateNeighborViewsForID(mMobileItemId);
return true;
}
};
/**
* Creates the hover cell with the appropriate bitmap and of appropriate
* size. The hover cell's BitmapDrawable is drawn on top of the bitmap every
* single time an invalidate call is made.
*/
private BitmapDrawable getAndAddHoverView(View v) {
int w = v.getWidth();
int h = v.getHeight();
int top = v.getTop();
int left = v.getLeft();
Bitmap b = getBitmapWithBorder(v);
BitmapDrawable drawable = new BitmapDrawable(getResources(), b);
mHoverCellOriginalBounds = new Rect(left, top, left + w, top + h);
mHoverCellCurrentBounds = new Rect(mHoverCellOriginalBounds);
drawable.setBounds(mHoverCellCurrentBounds);
return drawable;
}
/** Draws a black border over the screenshot of the view passed in. */
private Bitmap getBitmapWithBorder(View v) {
Bitmap bitmap = getBitmapFromView(v);
Canvas can = new Canvas(bitmap);
Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(LINE_THICKNESS);
paint.setColor(Color.BLACK);
can.drawBitmap(bitmap, 0, 0, null);
can.drawRect(rect, paint);
return bitmap;
}
/** Returns a bitmap showing a screenshot of the view passed in. */
private Bitmap getBitmapFromView(View v) {
Bitmap bitmap = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas (bitmap);
v.draw(canvas);
return bitmap;
}
/**
* Stores a reference to the views above and below the item currently
* corresponding to the hover cell. It is important to note that if this
* item is either at the top or bottom of the list, mAboveItemId or mBelowItemId
* may be invalid.
*/
private void updateNeighborViewsForID(long itemID) {
int position = getPositionForID(itemID);
ItemsArrayAdapter adapter = ((ItemsArrayAdapter)getAdapter());
mAboveItemId = adapter.getItemId(position - 1);
mBelowItemId = adapter.getItemId(position + 1);
}
/** Retrieves the view in the list corresponding to itemID */
public View getViewForID (long itemID) {
int firstVisiblePosition = getFirstVisiblePosition();
ItemsArrayAdapter adapter = ((ItemsArrayAdapter)getAdapter());
for(int i = 0; i < getChildCount(); i++) {
View v = getChildAt(i);
int position = firstVisiblePosition + i;
long id = adapter.getItemId(position);
if (id == itemID) {
return v;
}
}
return null;
}
/** Retrieves the position in the list corresponding to itemID */
public int getPositionForID (long itemID) {
View v = getViewForID(itemID);
if (v == null) {
return -1;
} else {
return getPositionForView(v);
}
}
/**
* dispatchDraw gets invoked when all the child views are about to be drawn.
* By overriding this method, the hover cell (BitmapDrawable) can be drawn
* over the listview's mItems whenever the listview is redrawn.
*/
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (mHoverCell != null) {
mHoverCell.draw(canvas);
}
}
#Override
public boolean onTouchEvent (MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mDownX = (int)event.getX();
mDownY = (int)event.getY();
mActivePointerId = event.getPointerId(0);
break;
case MotionEvent.ACTION_MOVE:
if (mActivePointerId == INVALID_POINTER_ID) {
break;
}
int pointerIndex = event.findPointerIndex(mActivePointerId);
mLastEventY = (int) event.getY(pointerIndex);
int deltaY = mLastEventY - mDownY;
if (mCellIsMobile) {
mHoverCellCurrentBounds.offsetTo(mHoverCellOriginalBounds.left,
mHoverCellOriginalBounds.top + deltaY + mTotalOffset);
mHoverCell.setBounds(mHoverCellCurrentBounds);
invalidate();
handleCellSwitch();
mIsMobileScrolling = false;
handleMobileCellScroll();
return false;
}
break;
case MotionEvent.ACTION_UP:
touchEventsEnded();
break;
case MotionEvent.ACTION_CANCEL:
touchEventsCancelled();
break;
case MotionEvent.ACTION_POINTER_UP:
/* If a multitouch event took place and the original touch dictating
* the movement of the hover cell has ended, then the dragging event
* ends and the hover cell is animated to its corresponding position
* in the listview. */
pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = event.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
touchEventsEnded();
}
break;
default:
break;
}
return super.onTouchEvent(event);
}
/**
* This method determines whether the hover cell has been shifted far enough
* to invoke a cell swap. If so, then the respective cell swap candidate is
* determined and the data set is changed. Upon posting a notification of the
* data set change, a layout is invoked to place the cells in the right place.
* Using a ViewTreeObserver and a corresponding OnPreDrawListener, we can
* offset the cell being swapped to where it previously was and then animate it to
* its new position.
*/
private void handleCellSwitch() {
final int deltaY = mLastEventY - mDownY;
int deltaYTotal = mHoverCellOriginalBounds.top + mTotalOffset + deltaY;
View belowView = getViewForID(mBelowItemId);
View mobileView = getViewForID(mMobileItemId);
View aboveView = getViewForID(mAboveItemId);
boolean isBelow = (belowView != null) && (deltaYTotal > belowView.getTop());
boolean isAbove = (aboveView != null) && (deltaYTotal < aboveView.getTop());
if (isBelow || isAbove) {
final long switchItemID = isBelow ? mBelowItemId : mAboveItemId;
View switchView = isBelow ? belowView : aboveView;
final int originalItem = getPositionForView(mobileView);
if (switchView == null) {
updateNeighborViewsForID(mMobileItemId);
return;
}
swapElements(mCheeseList, originalItem, getPositionForView(switchView));
((BaseAdapter) getAdapter()).notifyDataSetChanged();
mDownY = mLastEventY;
final int switchViewStartTop = switchView.getTop();
if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.KITKAT){
mobileView.setVisibility(View.VISIBLE);
switchView.setVisibility(View.INVISIBLE);
} else{
mobileView.setVisibility(View.INVISIBLE);
switchView.setVisibility(View.VISIBLE);
}
updateNeighborViewsForID(mMobileItemId);
final ViewTreeObserver observer = getViewTreeObserver();
observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
observer.removeOnPreDrawListener(this);
View switchView = getViewForID(switchItemID);
mTotalOffset += deltaY;
int switchViewNewTop = switchView.getTop();
int delta = switchViewStartTop - switchViewNewTop;
switchView.setTranslationY(delta);
ObjectAnimator animator = ObjectAnimator.ofFloat(switchView,
View.TRANSLATION_Y, 0);
animator.setDuration(MOVE_DURATION);
animator.start();
return true;
}
});
}
}
private void swapElements(ArrayList arrayList, int indexOne, int indexTwo) {
Object temp = arrayList.get(indexOne);
arrayList.set(indexOne, arrayList.get(indexTwo));
arrayList.set(indexTwo, temp);
}
/**
* Resets all the appropriate fields to a default state while also animating
* the hover cell back to its correct location.
*/
private void touchEventsEnded () {
final View mobileView = getViewForID(mMobileItemId);
if (mCellIsMobile|| mIsWaitingForScrollFinish) {
mCellIsMobile = false;
mIsWaitingForScrollFinish = false;
mIsMobileScrolling = false;
mActivePointerId = INVALID_POINTER_ID;
// If the autoscroller has not completed scrolling, we need to wait for it to
// finish in order to determine the final location of where the hover cell
// should be animated to.
if (mScrollState != OnScrollListener.SCROLL_STATE_IDLE) {
mIsWaitingForScrollFinish = true;
return;
}
mHoverCellCurrentBounds.offsetTo(mHoverCellOriginalBounds.left, mobileView.getTop());
ObjectAnimator hoverViewAnimator = ObjectAnimator.ofObject(mHoverCell, "bounds",
sBoundEvaluator, mHoverCellCurrentBounds);
hoverViewAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
invalidate();
}
});
hoverViewAnimator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationStart(Animator animation) {
setEnabled(false);
}
#Override
public void onAnimationEnd(Animator animation) {
mAboveItemId = INVALID_ID;
mMobileItemId = INVALID_ID;
mBelowItemId = INVALID_ID;
mobileView.setVisibility(VISIBLE);
mHoverCell = null;
setEnabled(true);
invalidate();
}
});
hoverViewAnimator.start();
} else {
touchEventsCancelled();
}
}
/**
* Resets all the appropriate fields to a default state.
*/
private void touchEventsCancelled () {
View mobileView = getViewForID(mMobileItemId);
if (mCellIsMobile) {
mAboveItemId = INVALID_ID;
mMobileItemId = INVALID_ID;
mBelowItemId = INVALID_ID;
mobileView.setVisibility(VISIBLE);
mHoverCell = null;
invalidate();
}
mCellIsMobile = false;
mIsMobileScrolling = false;
mActivePointerId = INVALID_POINTER_ID;
}
/**
* This TypeEvaluator is used to animate the BitmapDrawable back to its
* final location when the user lifts his finger by modifying the
* BitmapDrawable's bounds.
*/
private final static TypeEvaluator<Rect> sBoundEvaluator = new TypeEvaluator<Rect>() {
public Rect evaluate(float fraction, Rect startValue, Rect endValue) {
return new Rect(interpolate(startValue.left, endValue.left, fraction),
interpolate(startValue.top, endValue.top, fraction),
interpolate(startValue.right, endValue.right, fraction),
interpolate(startValue.bottom, endValue.bottom, fraction));
}
public int interpolate(int start, int end, float fraction) {
return (int)(start + fraction * (end - start));
}
};
/**
* Determines whether this listview is in a scrolling state invoked
* by the fact that the hover cell is out of the bounds of the listview;
*/
private void handleMobileCellScroll() {
mIsMobileScrolling = handleMobileCellScroll(mHoverCellCurrentBounds);
}
/**
* This method is in charge of determining if the hover cell is above
* or below the bounds of the listview. If so, the listview does an appropriate
* upward or downward smooth scroll so as to reveal new mItems.
*/
public boolean handleMobileCellScroll(Rect r) {
int offset = computeVerticalScrollOffset();
int height = getHeight();
int extent = computeVerticalScrollExtent();
int range = computeVerticalScrollRange();
int hoverViewTop = r.top;
int hoverHeight = r.height();
if (hoverViewTop <= 0 && offset > 0) {
smoothScrollBy(-mSmoothScrollAmountAtEdge, 0);
return true;
}
if (hoverViewTop + hoverHeight >= height && (offset + extent) < range) {
smoothScrollBy(mSmoothScrollAmountAtEdge, 0);
return true;
}
return false;
}
public void setCheeseList(ArrayList<String> cheeseList) {
mCheeseList = cheeseList;
}
/**
* This scroll listener is added to the listview in order to handle cell swapping
* when the cell is either at the top or bottom edge of the listview. If the hover
* cell is at either edge of the listview, the listview will begin scrolling. As
* scrolling takes place, the listview continuously checks if new cells became visible
* and determines whether they are potential candidates for a cell swap.
*/
private OnScrollListener mScrollListener = new OnScrollListener () {
private int mPreviousFirstVisibleItem = -1;
private int mPreviousVisibleItemCount = -1;
private int mCurrentFirstVisibleItem;
private int mCurrentVisibleItemCount;
private int mCurrentScrollState;
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
mCurrentFirstVisibleItem = firstVisibleItem;
mCurrentVisibleItemCount = visibleItemCount;
mPreviousFirstVisibleItem = (mPreviousFirstVisibleItem == -1) ? mCurrentFirstVisibleItem
: mPreviousFirstVisibleItem;
mPreviousVisibleItemCount = (mPreviousVisibleItemCount == -1) ? mCurrentVisibleItemCount
: mPreviousVisibleItemCount;
checkAndHandleFirstVisibleCellChange();
checkAndHandleLastVisibleCellChange();
mPreviousFirstVisibleItem = mCurrentFirstVisibleItem;
mPreviousVisibleItemCount = mCurrentVisibleItemCount;
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
mCurrentScrollState = scrollState;
mScrollState = scrollState;
isScrollCompleted();
}
/**
* This method is in charge of invoking 1 of 2 actions. Firstly, if the listview
* is in a state of scrolling invoked by the hover cell being outside the bounds
* of the listview, then this scrolling event is continued. Secondly, if the hover
* cell has already been released, this invokes the animation for the hover cell
* to return to its correct position after the listview has entered an idle scroll
* state.
*/
private void isScrollCompleted() {
if (mCurrentVisibleItemCount > 0 && mCurrentScrollState == SCROLL_STATE_IDLE) {
if (mCellIsMobile && mIsMobileScrolling) {
handleMobileCellScroll();
} else if (mIsWaitingForScrollFinish) {
touchEventsEnded();
}
}
}
/**
* Determines if the listview scrolled up enough to reveal a new cell at the
* top of the list. If so, then the appropriate parameters are updated.
*/
public void checkAndHandleFirstVisibleCellChange() {
if (mCurrentFirstVisibleItem != mPreviousFirstVisibleItem) {
if (mCellIsMobile && mMobileItemId != INVALID_ID) {
updateNeighborViewsForID(mMobileItemId);
handleCellSwitch();
}
}
}
/**
* Determines if the listview scrolled down enough to reveal a new cell at the
* bottom of the list. If so, then the appropriate parameters are updated.
*/
public void checkAndHandleLastVisibleCellChange() {
int currentLastVisibleItem = mCurrentFirstVisibleItem + mCurrentVisibleItemCount;
int previousLastVisibleItem = mPreviousFirstVisibleItem + mPreviousVisibleItemCount;
if (currentLastVisibleItem != previousLastVisibleItem) {
if (mCellIsMobile && mMobileItemId != INVALID_ID) {
updateNeighborViewsForID(mMobileItemId);
handleCellSwitch();
}
}
}
};
}
Here is how I add an item to the listview:
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String text = mNewItemText.getText().toString();
if (!mItems.contains(text) && !text.isEmpty()) {
mItems.add(text);
mItemsArrayAdapter.update();
mItemsArrayAdapter.notifyDataSetChanged();
}
else{
Toast.makeText(NoteActivity.this, text + " is already added.", Toast.LENGTH_LONG).show();
}
}
});
Here is the update method:
public void update(){
for (int i = 0; i < mArrayList.size(); ++i) {
mIdMap.put(mArrayList.get(i), i);
}
}
Thanks in advance.

kikoso/swipeable cards android

hey i tried the kikose/swipeable-cards library but its performance isnt good(lags even on nexus 5 ). i tried to change the mMaxVisible in the cardContainer class from 3 to 2 the performance improved a little but still lags so i changes it to 1 and the performance looked very card on the first. after i swiped the first card the second isnt swipeable . the mTopCard in the cardcontainer class is null . how can i fix this or improve performance in others way maybe ?
here is the cardcontainer class :
public class CardContainer extends AdapterView<ListAdapter> {
public static final int INVALID_POINTER_ID = -1;
private int mActivePointerId = INVALID_POINTER_ID;
private static final double DISORDERED_MAX_ROTATION_RADIANS = Math.PI / 64;
private int mNumberOfCards = -1;
Context context;
private final DataSetObserver mDataSetObserver = new DataSetObserver() {
#Override
public void onChanged() {
super.onChanged();
clearStack();
ensureFull();
}
#Override
public void onInvalidated() {
super.onInvalidated();
clearStack();
}
};
private final Random mRandom = new Random();
private final Rect boundsRect = new Rect();
private final Rect childRect = new Rect();
private final Matrix mMatrix = new Matrix();
//TODO: determine max dynamically based on device speed
private int mMaxVisible =2;
private GestureDetector mGestureDetector;
private int mFlingSlop;
private Orientation mOrientation;
private ListAdapter mListAdapter;
private float mLastTouchX;
private float mLastTouchY;
private View mTopCard;
private int mTouchSlop;
private int mGravity;
private int mNextAdapterPosition;
private boolean mDragging;
private boolean animating;
int index;
Profile cardModel;
public CardContainer(Context context) {
super(context);
this.context = context;
setOrientation(Orientation.Disordered);
setGravity(Gravity.TOP);
init();
animating = false;
}
public CardContainer(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
initFromXml(attrs);
init();
}
public CardContainer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
initFromXml(attrs);
init();
}
private void init() {
ViewConfiguration viewConfiguration = ViewConfiguration
.get(getContext());
mFlingSlop = viewConfiguration.getScaledMinimumFlingVelocity();
mTouchSlop = viewConfiguration.getScaledTouchSlop();
mGestureDetector = new GestureDetector(getContext(),
new GestureListener());
}
private void initFromXml(AttributeSet attr) {
TypedArray a = getContext().obtainStyledAttributes(attr,
R.styleable.CardContainer);
setGravity(a.getInteger(R.styleable.CardContainer_android_gravity,
Gravity.TOP));
int orientation = a
.getInteger(R.styleable.CardContainer_orientation, 1);
setOrientation(Orientation.fromIndex(orientation));
index = 0;
a.recycle();
}
#Override
public ListAdapter getAdapter() {
return mListAdapter;
}
#Override
public void setAdapter(ListAdapter adapter) {
index = 0;
if (mListAdapter != null)
mListAdapter.unregisterDataSetObserver(mDataSetObserver);
clearStack();
mTopCard = null;
mListAdapter = adapter;
mNextAdapterPosition = 0;
adapter.registerDataSetObserver(mDataSetObserver);
ensureFull();
Log.e("GETCHILD CARD CONT","getChildAt(getChildCount() - 1)==================="+getChildAt(getChildCount() - 1));
Log.e("GETCHILD CARD CONT","getChildCount()==================="+getChildCount());
if (getChildCount() != 0) {
mTopCard = getChildAt(getChildCount() - 1);
mTopCard.setLayerType(LAYER_TYPE_HARDWARE, null);
}
mNumberOfCards = getAdapter().getCount();
requestLayout();
((Profile)adapter.getItem(0)).getOnCardDimissedListener().initialiseCard();
}
private void ensureFull() {
while (mNextAdapterPosition < mListAdapter.getCount() && getChildCount() < mMaxVisible) {
View view = mListAdapter.getView(mNextAdapterPosition, null, this);
view.setLayerType(LAYER_TYPE_SOFTWARE, null);
if(mOrientation == Orientation.Disordered) {
view.setRotation(getDisorderedRotation());
}
addViewInLayout(view, 0, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
mListAdapter.getItemViewType(mNextAdapterPosition)), false);
requestLayout();
mNextAdapterPosition += 1;
}
}
private void clearStack() {
removeAllViewsInLayout();
mNextAdapterPosition = 0;
mTopCard = null;
}
public Orientation getOrientation() {
return mOrientation;
}
public void setOrientation(Orientation orientation) {
if (orientation == null)
throw new NullPointerException("Orientation may not be null");
if(mOrientation != orientation) {
this.mOrientation = orientation;
if(orientation == Orientation.Disordered) {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.setRotation(getDisorderedRotation());
}
}
else {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.setRotation(0);
}
}
requestLayout();
}
}
private float getDisorderedRotation() {
return (float) Math.toDegrees(mRandom.nextGaussian() * DISORDERED_MAX_ROTATION_RADIANS);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int requestedWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
int requestedHeight = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
int childWidth, childHeight;
if (mOrientation == Orientation.Disordered) {
int R1, R2;
if (requestedWidth >= requestedHeight) {
R1 = requestedHeight;
R2 = requestedWidth;
} else {
R1 = requestedWidth;
R2 = requestedHeight;
}
childWidth = (int) ((R1 * Math.cos(DISORDERED_MAX_ROTATION_RADIANS) - R2 * Math.sin(DISORDERED_MAX_ROTATION_RADIANS)) / Math.cos(2 * DISORDERED_MAX_ROTATION_RADIANS));
childHeight = (int) ((R2 * Math.cos(DISORDERED_MAX_ROTATION_RADIANS) - R1 * Math.sin(DISORDERED_MAX_ROTATION_RADIANS)) / Math.cos(2 * DISORDERED_MAX_ROTATION_RADIANS));
} else {
childWidth = requestedWidth;
childHeight = requestedHeight;
}
int childWidthMeasureSpec, childHeightMeasureSpec;
childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.AT_MOST);
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.AT_MOST);
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
assert child != null;
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
for (int i = 0; i < getChildCount(); i++) {
boundsRect.set(0, 0, getWidth(), getHeight());
View view = getChildAt(i);
int w, h;
w = view.getMeasuredWidth();
h = view.getMeasuredHeight();
Gravity.apply(mGravity, w, h, boundsRect, childRect);
view.layout(childRect.left, childRect.top, childRect.right, childRect.bottom);
}
}
int holdingCard;
View likeImage, dislikeImage;
#Override
public boolean onTouchEvent(MotionEvent event) {
if (mTopCard == null || animating) {
return false;
}
if (mGestureDetector.onTouchEvent(event)) {
return true;
}
final int pointerIndex;
final float x, y;
final float dx, dy;
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
getHitRect(mTopCard,childRect);
pointerIndex = event.getActionIndex();
x = event.getX(pointerIndex);
y = event.getY(pointerIndex);
if (!childRect.contains((int) x, (int) y)) {
return false;
}
mLastTouchX = x;
mLastTouchY = y;
mActivePointerId = event.getPointerId(pointerIndex);
float[] points = new float[]{x - mTopCard.getLeft(), y - mTopCard.getTop()};
mTopCard.getMatrix().invert(mMatrix);
mMatrix.mapPoints(points);
mTopCard.setPivotX(points[0]);
mTopCard.setPivotY(points[1]);
break;
case MotionEvent.ACTION_MOVE:
pointerIndex = event.findPointerIndex(mActivePointerId);
x = event.getX(pointerIndex);
y = event.getY(pointerIndex);
dx = x - mLastTouchX;
dy = y - mLastTouchY;
Profile profile = (Profile) getAdapter().getItem(0);
likeImage = mTopCard.findViewById(R.id.like_text_image);
dislikeImage = mTopCard.findViewById(R.id.dislike_text_image);
if (mTopCard.getTranslationX() + dx > 30) {
profile.getOnCardDimissedListener().tendToLike();
dislikeImage.setVisibility(View.INVISIBLE);
likeImage.setVisibility(View.VISIBLE);
}
else if (mTopCard.getTranslationX() + dx < 30) {
profile.getOnCardDimissedListener().tendToDislike();
likeImage.setVisibility(View.INVISIBLE);
dislikeImage.setVisibility(View.VISIBLE);
} else {
likeImage.setVisibility(View.INVISIBLE);
dislikeImage.setVisibility(View.INVISIBLE);
}
if (Math.abs(dx) > mTouchSlop || Math.abs(dy) > mTouchSlop) {
mDragging = true;
}
if(!mDragging) {
return true;
}
mTopCard.setTranslationX(mTopCard.getTranslationX() + dx);
mTopCard.setTranslationY(mTopCard.getTranslationY() + dy);
mTopCard.setRotation(40 * mTopCard.getTranslationX() / (getWidth() / 2.f));
mLastTouchX = x;
mLastTouchY = y;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (!mDragging) {
return true;
}
mDragging = false;
mActivePointerId = INVALID_POINTER_ID;
ValueAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mTopCard,
PropertyValuesHolder.ofFloat("translationX", 0),
PropertyValuesHolder.ofFloat("translationY", 0),
PropertyValuesHolder.ofFloat("rotation", (float) Math.toDegrees(mRandom.nextGaussian() * DISORDERED_MAX_ROTATION_RADIANS)),
PropertyValuesHolder.ofFloat("pivotX", mTopCard.getWidth() / 2.f),
PropertyValuesHolder.ofFloat("pivotY", mTopCard.getHeight() / 2.f)
).setDuration(250);
animator.setInterpolator(new AccelerateInterpolator());
animator.addListener(new AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
animating = true;
}
#Override
public void onAnimationRepeat(Animator animation) {
animating = true;
}
#Override
public void onAnimationEnd(Animator animation) {
animating = false;
dislikeImage.setVisibility(View.INVISIBLE);
likeImage.setVisibility(View.INVISIBLE);
((Profile) getAdapter().getItem(0)).getOnCardDimissedListener().cancelCard();
}
#Override
public void onAnimationCancel(Animator animation) {
animating = false;
}
});
animator.start();
break;
case MotionEvent.ACTION_POINTER_UP:
pointerIndex = event.getActionIndex();
final int pointerId = event.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = event.getX(newPointerIndex);
mLastTouchY = event.getY(newPointerIndex);
mActivePointerId = event.getPointerId(newPointerIndex);
}
break;
}
return true;
}
private void getHitRect(View v, Rect rect) {
rect.left = (int) (v.getLeft() + v.getTranslationX());
rect.top = (int) (v.getTop() + v.getTranslationY());
rect.right = rect.left + v.getWidth();
rect.bottom = rect.top + v.getHeight();
}
public boolean isAnimating()
{
return animating;
}
public Profile getCurrentCard() {
if(index + 1 > getAdapter().getCount())
return null;
Profile profile = (Profile) getAdapter().getItem(index);
if (index + 1 == getAdapter().getCount())
profile.setLast(true);
return profile;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
try {
Log.e("CARD CONTAINER","MTOPCARD =====================+++++++++ "+mTopCard);
if (mTopCard == null) {
return false;
}
if (mGestureDetector.onTouchEvent(event)) {
return true;
}
final int pointerIndex;
final float x, y;
final float dx, dy;
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
getHitRect(mTopCard,childRect);
Profile Profile = (Profile) getAdapter().getItem(0);
if (Profile.getOnClickListener() != null) {
Profile.getOnClickListener().OnClickListener();
}
pointerIndex = event.getActionIndex();
x = event.getX(pointerIndex);
y = event.getY(pointerIndex);
if (!childRect.contains((int) x, (int) y)) {
return false;
}
mLastTouchX = x;
mLastTouchY = y;
mActivePointerId = event.getPointerId(pointerIndex);
break;
case MotionEvent.ACTION_MOVE:
pointerIndex = event.findPointerIndex(mActivePointerId);
x = event.getX(pointerIndex);
y = event.getY(pointerIndex);
if (Math.abs(x - mLastTouchX) > mTouchSlop || Math.abs(y - mLastTouchY) > mTouchSlop) {
float[] points = new float[]{x - mTopCard.getLeft(), y - mTopCard.getTop()};
mTopCard.getMatrix().invert(mMatrix);
mMatrix.mapPoints(points);
mTopCard.setPivotX(points[0]);
mTopCard.setPivotY(points[1]);
return true;
}
}
return false;
} catch (Exception e) {
// TODO Auto-generated catch block
return super.onInterceptTouchEvent(event);
}
}
#Override
public View getSelectedView() {
throw new UnsupportedOperationException();
}
#Override
public void setSelection(int position) {
throw new UnsupportedOperationException();
}
public int getGravity() {
return mGravity;
}
public void setGravity(int gravity) {
mGravity = gravity;
}
public static class LayoutParams extends ViewGroup.LayoutParams {
int viewType;
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
}
public LayoutParams(int width, int height) {
super(width, height);
}
public LayoutParams(ViewGroup.LayoutParams source) {
super(source);
}
public LayoutParams(int w, int h, int viewType) {
super(w, h);
this.viewType = viewType;
}
}
private class GestureListener extends SimpleOnGestureListener {
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
final View topCard = mTopCard;
float dx = e2.getX() - e1.getX();
if (Math.abs(dx) > mTouchSlop &&
Math.abs(velocityX) > Math.abs(velocityY) &&
Math.abs(velocityX) > mFlingSlop * 3) {
float targetX = topCard.getX();
float targetY = topCard.getY();
long duration = 0;
boundsRect.set(0 - topCard.getWidth() - 100, 0 - topCard.getHeight() - 100, getWidth() + 100, getHeight() + 100);
while (boundsRect.contains((int) targetX, (int) targetY)) {
targetX += velocityX / 10;
targetY += velocityY / 10;
duration += 100;
}
duration = Math.min(400, duration);
cardModel = (Profile) getAdapter().getItem(0);
if (cardModel.getOnCardDimissedListener() != null) {
if ( targetX > 0 ) {
{
if(MyUser.getInstance((Activity)context).getVip().equals("1") || (Float.valueOf((getCurrentCard()).getScore())>MyGenericApp.getInstance((Activity)context).getMinScoreMatch()))
{
mTopCard = getChildAt(getChildCount() - 2);
if (mTopCard != null)
mTopCard.setLayerType(LAYER_TYPE_HARDWARE, null);
cardModel.getOnCardDimissedListener().onLike();
}
else
{
cardModel.getOnCardDimissedListener().forcedToDislike();
return super.onFling(e1, e2, velocityX, velocityY);
}
}
} else {
mTopCard = getChildAt(getChildCount() - 2);
if (mTopCard != null)
mTopCard.setLayerType(LAYER_TYPE_HARDWARE, null);
cardModel.getOnCardDimissedListener().onDislike();
}
index++;
}
animating = true;
topCard.animate()
.setDuration(duration)
.alpha(.75f)
.setInterpolator(new LinearInterpolator())
.x(targetX)
.y(targetY)
.rotation(Math.copySign(45, velocityX))
.setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
removeViewInLayout(topCard);
ensureFull();
if(getCurrentCard()!=null)
cardModel.getOnCardDimissedListener().initialiseCard();
animating = false;
}
#Override
public void onAnimationCancel(Animator animation) {
onAnimationEnd(animation);
}
});
return true;
} else
return false;
}
}
public void dislike(){
final View topCard = mTopCard;
View likeImage = mTopCard.findViewById(R.id.like_text_image);
View dislikeImage = mTopCard.findViewById(R.id.dislike_text_image);
dislikeImage.setVisibility(View.VISIBLE);
likeImage.setVisibility(View.INVISIBLE);
mTopCard = getChildAt(getChildCount() - 2);
Profile cardModel = (Profile)getAdapter().getItem(0);
if(mTopCard != null)
mTopCard.setLayerType(LAYER_TYPE_HARDWARE, null);
animating = true;
topCard.animate()
.setDuration(400)
.alpha(.75f)
.setInterpolator(new LinearInterpolator())
.x(-GlobalFunctions.getScreenWidth(context))
.y(topCard.getY())
.rotation(-45)
.setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
removeViewInLayout(topCard);
ensureFull();
animating = false;
}
#Override
public void onAnimationCancel(Animator animation) {
onAnimationEnd(animation);
}
});
if(cardModel.getOnCardDimissedListener() != null){
cardModel.getOnCardDimissedListener().onDislike();
}
index++;
if(index < getAdapter().getCount())
((Profile)getAdapter().getItem(0)).getOnCardDimissedListener().initialiseCard();
}
public void like(){
final View topCard = mTopCard;
View likeImage = mTopCard.findViewById(R.id.like_text_image);
View dislikeImage = mTopCard.findViewById(R.id.dislike_text_image);
likeImage.setVisibility(View.VISIBLE);
dislikeImage.setVisibility(View.INVISIBLE);
mTopCard = getChildAt(getChildCount() - 2);
Profile cardModel = (Profile)getAdapter().getItem(0);
if(mTopCard != null)
mTopCard.setLayerType(LAYER_TYPE_HARDWARE, null);
animating = true;
topCard.animate()
.setDuration(400)
.alpha(.75f)
.setInterpolator(new LinearInterpolator())
.x(GlobalFunctions.getScreenWidth(context))
.y(topCard.getY())
.rotation(45)
.setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
removeViewInLayout(topCard);
ensureFull();
animating = false;
}
#Override
public void onAnimationCancel(Animator animation) {
onAnimationEnd(animation);
}
});
if(cardModel.getOnCardDimissedListener() != null){
cardModel.getOnCardDimissedListener().onLike();
}
index++;
if(index < getAdapter().getCount())
((Profile)getAdapter().getItem(0)).getOnCardDimissedListener().initialiseCard();
}
}

Categories