How to adapt coverflow/gallery to fit different screen sizes - android

I'm using this CoverFlow : http://www.inter-fuser.com/2010/02/android-coverflow-widget-v2.html
I want to for the coverflow to adapt to the different screen sizes,
I have modded the coverflow slightly so that I use an XML layout instead.
Here's how the layout should and looks like on my Phone (320x480)
Here's how the layout looks like on a Nexus One (480x720 in emulator)
COVERFLOW CLASS :
public class CoverFlow extends Gallery {
/**
* Graphics Camera used for transforming the matrix of ImageViews
*/
private final Camera mCamera = new Camera();
/**
* The maximum angle the Child ImageView will be rotated by
*/
private int mMaxRotationAngle = 80;
/**
* The maximum zoom on the centre Child
*/
// TODO RENDRE LA VALEUR DYNAMIQUE SUR LA TAILLE DE L'ECRAN
// private int mMaxZoom = -430;
private int mMaxZoom = -370;
/**
* The Centre of the Coverflow
*/
private int mCoveflowCenter;
public CoverFlow(Context context) {
super(context);
this.setStaticTransformationsEnabled(true);
}
public CoverFlow(Context context, AttributeSet attrs) {
super(context, attrs);
this.setStaticTransformationsEnabled(true);
}
public CoverFlow(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.setStaticTransformationsEnabled(true);
}
/**
* Get the max rotational angle of the image
* #return the mMaxRotationAngle
*/
public int getMaxRotationAngle() {
return mMaxRotationAngle;
}
/**
* Set the max rotational angle of each image
* #param maxRotationAngle the mMaxRotationAngle to set
*/
public void setMaxRotationAngle(int maxRotationAngle) {
mMaxRotationAngle = maxRotationAngle;
}
/**
* Get the Max zoom of the centre image
* #return the mMaxZoom
*/
public int getMaxZoom() {
return mMaxZoom;
}
/**
* Set the max zoom of the centre image
* #param maxZoom the mMaxZoom to set
*/
public void setMaxZoom(int maxZoom) {
mMaxZoom = maxZoom;
}
/**
* Get the Centre of the Coverflow
* #return The centre of this Coverflow.
*/
private int getCenterOfCoverflow() {
return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2 + getPaddingLeft();
}
/**
* Get the Centre of the View
* #return The centre of the given view.
*/
private static int getCenterOfView(View view) {
return view.getLeft() + view.getWidth() / 2;
}
/**
* {#inheritDoc}
*
* #see #setStaticTransformationsEnabled(boolean)
*/
#Override
protected boolean getChildStaticTransformation(View child, Transformation t) {
final int childCenter = getCenterOfView(child);
final int childWidth = child.getWidth() ;
int rotationAngle = 0;
t.clear();
t.setTransformationType(Transformation.TYPE_MATRIX);
if (childCenter == mCoveflowCenter) {
transformImageBitmap((ImageView) child, t, 0);
} else {
rotationAngle = (int) (((float) (mCoveflowCenter - childCenter)/ childWidth) * mMaxRotationAngle);
if (Math.abs(rotationAngle) > mMaxRotationAngle) {
rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle : mMaxRotationAngle;
}
transformImageBitmap((ImageView) child, t, rotationAngle);
}
return true;
}
/**
* This is called during layout when the size of this view has changed. If
* you were just added to the view hierarchy, you're called with the old
* values of 0.
*
* #param w Current width of this view.
* #param h Current height of this view.
* #param oldw Old width of this view.
* #param oldh Old height of this view.
*/
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mCoveflowCenter = getCenterOfCoverflow();
super.onSizeChanged(w, h, oldw, oldh);
}
/**
* Transform the Image Bitmap by the Angle passed
*
* #param imageView ImageView the ImageView whose bitmap we want to rotate
* #param t transformation
* #param rotationAngle the Angle by which to rotate the Bitmap
*/
private void transformImageBitmap(ImageView child, Transformation t, int rotationAngle) {
mCamera.save();
final Matrix imageMatrix = t.getMatrix();;
final int imageHeight = child.getLayoutParams().height;;
final int imageWidth = child.getLayoutParams().width;
final int rotation = Math.abs(rotationAngle);
mCamera.translate(0.0f, 0.0f, 100.0f);
//As the angle of the view gets less, zoom in
if ( rotation < mMaxRotationAngle ) {
float zoomAmount = (mMaxZoom + rotation);
mCamera.translate(0.0f, 0.0f, zoomAmount);
}
mCamera.rotateY(rotationAngle);
mCamera.getMatrix(imageMatrix);
imageMatrix.preTranslate(-(imageWidth/2), -(imageHeight/2));
imageMatrix.postTranslate((imageWidth/2), (imageHeight/2));
mCamera.restore();
}
}
HOME ACTIVITY :
public class HomeActivity extends Activity {
private final static String TAG = "HomeActivity";
private TextView pageNameTextView;
private CoverFlow coverFlow;
private ImageAdapter coverImageAdapter;
private int itemSelected = 0;
private Context context;
private SparseArray<String> listeNomIcons;
private int currentImagePosition = 0;
//Info button
private ImageView infoAccueilImageView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home_layout);
//animate Transition
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
context = this;
listeNomIcons = new SparseArray<String>();
listeNomIcons.put(0, "DELAIS D'ATTENTE, RETARD");
listeNomIcons.put(1, "COURRIER SUBSTITUTION");
listeNomIcons.put(2, "IR LC");
listeNomIcons.put(3, "CONTACTS UTILES");
listeNomIcons.put(4, "TEMPS DE PAUSE");
listeNomIcons.put(5, "DISPERTION");
listeNomIcons.put(6, "PRORATA REPOS");
listeNomIcons.put(7, "ALERTE DOMICILE");
listeNomIcons.put(8, "RESERVE DOMICILE");
listeNomIcons.put(9, "RADD");
listeNomIcons.put(10, "JOKER");
coverFlow = (CoverFlow)findViewById(R.id.coverflow);
coverImageAdapter = new ImageAdapter(this);
coverFlow.setAdapter(coverImageAdapter);
coverFlow.setSelection(0, true);
coverFlow.setAnimationDuration(1000);
//cover
pageNameTextView = (TextView)findViewById(R.id.page_nameTextView);
//Info Accueil Image View
infoAccueilImageView = (ImageView)findViewById(R.id.infoImageView);
infoAccueilImageView.setOnClickListener( new OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(context, InfoAccueilActivity.class));
}
} ) ;
coverFlow.setOnItemSelectedListener(new OnItemSelectedListener(){
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
currentImagePosition = position; //this will update your current marker
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
Button goLeft = (Button) findViewById(R.id.select_leftButton);
goLeft.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// go to previous image
coverFlow.onKeyDown(KeyEvent.KEYCODE_DPAD_LEFT, new KeyEvent(0, 0));
}
});
Button goRight = (Button) findViewById(R.id.select_rightButton);
goRight.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// go to next item
coverFlow.onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, new KeyEvent(0, 0));
}
});
coverFlow.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
if(itemSelected == arg2)
{
Log.d(TAG, "arg2 : "+arg2);
switch (arg2) {
case 0:
startActivity(new Intent(context, DelaisAttenteActivity.class));
break;
case 1:
startActivity(new Intent(context, CourrierSubstitutionActivity.class));
break;
case 2:
startActivity(new Intent(context, IRLCActivity.class));
break;
case 3:
startActivity(new Intent(context, ContactsActivity.class));
break;
case 4:
startActivity(new Intent(context, TempsPauseActivity.class));
break;
case 5:
startActivity(new Intent(context, DispertionActivity.class));
break;
case 6:
startActivity(new Intent(context, ProrataReposActivity.class));
break;
case 7:
startActivity(new Intent(context, AlerteDomicileActivity.class));
break;
case 8:
startActivity(new Intent(context, ReserveDomicileActivity.class));
break;
case 9:
startActivity(new Intent(context, ReposAdditionnelActivity.class));
break;
case 10:
startActivity(new Intent(context, JokerActivity.class));
break;
default:
break;
}
}
}
});
coverFlow.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
pageNameTextView.setText(listeNomIcons.get(arg2));
itemSelected = arg2;
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
}
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private final Context mContext;
private final Integer[] mImageIds = {
R.drawable.retard_controller,
R.drawable.courrier_substitution_controller,
R.drawable.irmf_controller,
R.drawable.contacts_controller,
R.drawable.pause_controller,
R.drawable.dispersion_controller,
R.drawable.repos_controller,
R.drawable.alerte_controller,
R.drawable.reserve_domicile_controller,
R.drawable.repos_additionnel_controller,
R.drawable.joker_controller
};
private final ImageView[] mImages;
public ImageAdapter(Context c) {
mContext = c;
mImages = new ImageView[mImageIds.length];
}
#Override
public int getCount() {
return mImageIds.length;
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//Use this code if you want to load from resources
ImageView i = new ImageView(mContext);
i.setImageResource(mImageIds[position]);
i.setLayoutParams(new CoverFlow.LayoutParams(130, 130));
i.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
//Make sure we set anti-aliasing otherwise we get jaggies
BitmapDrawable drawable = (BitmapDrawable) i.getDrawable();
drawable.setAntiAlias(true);
return i;
//return mImages[position];
}
/** Returns the size (0.0f to 1.0f) of the views
* depending on the 'offset' to the center. */
public float getScale(boolean focused, int offset) {
/* Formula: 1 / (2 ^ offset) */
return Math.max(0, 1.0f / (float)Math.pow(2, Math.abs(offset)));
}
}
}

I found a way around, not a great solution but it works pretty well on the devices that I have tested it on...
In the method (in the ImageAdapter in HomeActivity)
#Override
public View getView(int position, View convertView, ViewGroup parent)
there I change the size of the image on this line
i.setLayoutParams(new CoverFlow.LayoutParams(130, 130));
to
int imageSize = calculateSize();
i.setLayoutParams(new CoverFlow.LayoutParams(imageSize, imageSize));
I set imageSize in my onCreate with this method
public int calculateSize()
{
// GET SCREEN SIZE
Display display = getWindowManager().getDefaultDisplay();
// HEIGHT
int height = display.getHeight();
long roundedHeightSize = Math.round((0.2132*height)+27.177);
//WIDTH
int width = display.getWidth();
long roundedWidthSize = Math.round((0.4264*width)-6.9355);
return (int)((roundedHeightSize+roundedWidthSize)/2);
}
TO GET THE FUNCTION :
(0.2132*height)+27.177 & (0.4264*width)-6.9355
I tested manually the height of the image needed on the different devices I had available
Galaxy SIII : 300 (1280x720)
Xperia Mini Pro : 135 (480x320)
Xperia X10 Mini Pro : 95 (320x240)
f(1280)=300
f(480)=135
f(320)=95
f(x) = 0.2132X + 27.177
then I did the same as the width..
I then get the average of the height and width given from these two functions to get the best value for the height and width of the image (seeing as the image is square => width = height)

there is a alphaSpacing kind of int variable, just increase its value . however i can not not remember exact class and variable name as its almost 2 years, when i used this code . but yes, one thing i remember is that i came across very same issue and i had absolutely no idea about stackoverflow. so was trying with different values and eventually succeeded .

I suggested to use values from dimens.xml. As example in the getView method in the adapter:
if (convertView == null) {
convertView = lInflater.inflate(R.layout.item_gallery, null);
((RelativeLayout) convertView.findViewById(R.id.image_issue_layout)).setLayoutParams(new CoverFlowView.LayoutParams(
app.getResources().getDimensionPixelSize(R.dimen.width_coverflow),
app.getResources().getDimensionPixelSize(R.dimen.height_coverflow)));
and in res folder specify different values width_coverflow for the different screens: values-sw600dp-land, values-sw720dp and so on...

Related

animate scaleType="centerCrop" in ImageView

Is there a way to animate scaleType="centerCrop"? I need to scale my image to certerCrop so the image can cover the entire area of the imageView. But I need to animate it to show the user the actual look of the image before it is being scaled I was planning to do it this way
imageView.animate().scaleX(2.0f).setDuration(2000)
but the problem is that I will be doing this on multiple image for a slide show so each image will have a different size and orientation.
I also found this library https://github.com/flavioarfaria/KenBurnsView but still having problems using it.
Any help will be much appreciated thanks.
EDITED
Started working on the KenBurnsView still not able to pan the image to center.
I wrote a custom ImageView to support animation between ScaleTypes, Hope it is helpful for you. And forgive my bad English, It is not my first language.
Usage:
AnimatedImageView animatedImageView = new AnimatedImageView(context) or findViewById(R.id.animated_image_view);
animatedImageView.setAnimatedScaleType(ImageView.ScaleType.CENTER_CROP);
animatedImageView.setAnimDuration(1000); // default is 500
animatedImageView.setStartDelay(500);
animatedImageView.startAnimation;
AnimatedImageView
/**
* Custom ImageView that can animate ScaleType
* Originally created by Wflei on 16/5/31.
* Updated by Mike Miller (https://mikemiller.design) on 6/15/2017.
* Original StackOverflow Post - https://stackoverflow.com/a/37539692/2415921
*/
public class AnimatedImageView extends android.support.v7.widget.AppCompatImageView {
// Listener values;
private ScaleType mFromScaleType, mToScaleType;
private ValueAnimator mValueAnimator;
private int mStartDelay = 0;
private boolean isViewLayedOut = false;
// Constructors
public AnimatedImageView(Context context) {
this(context, null);
}
public AnimatedImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public AnimatedImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// Set default original scale type
mFromScaleType = getScaleType();
// Set default scale type for animation
mToScaleType = getScaleType();
// Init value animator
mValueAnimator = ValueAnimator.ofFloat(0f, 1f);
// Set resource
updateScaleType(mFromScaleType, false);
}
/**
* Sets the scale type we want to animate to
*
* #param toScaleType
*/
public void setAnimatedScaleType(ScaleType toScaleType) {
mToScaleType = toScaleType;
}
/**
* Duration of the animation
*
* #param animationDuration
*/
public void setAnimDuration(int animationDuration) {
mValueAnimator.setDuration(animationDuration);
}
/**
* Set the time delayed for the animation
*
* #param startDelay The delay (in milliseconds) before the animation
*/
public void setStartDelay(Integer startDelay) {
mStartDelay = startDelay == null ? 0 : startDelay;
}
#Override
public void setScaleType(ScaleType scaleType) {
super.setScaleType(scaleType);
mFromScaleType = scaleType;
}
#Override
public void setImageDrawable(Drawable drawable) {
super.setImageDrawable(drawable);
updateScaleType(mFromScaleType, false);
}
#Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
updateScaleType(mFromScaleType, false);
}
#Override
public void setImageResource(int resId) {
super.setImageResource(resId);
updateScaleType(mFromScaleType, false);
}
#Override
public void setImageURI(Uri uri) {
super.setImageURI(uri);
updateScaleType(mFromScaleType, false);
}
/**
* Animates the current view
* and updates it's current asset
*/
public void startAnimation() {
// This will run the animation with a delay (delay is defaulted at 0)
postDelayed(startDelay, mStartDelay);
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
// View has been laid out
isViewLayedOut = true;
// Animate change when bounds are official
if (changed) {
updateScaleType(mToScaleType, false);
}
}
/**
* animate to scaleType
*
* #param toScaleType
*/
private void updateScaleType(final ScaleType toScaleType, boolean animated) {
// Check if view is laid out
if (!isViewLayedOut) {
return;
}
// Cancel value animator if its running
if (mValueAnimator != null && mValueAnimator.isRunning()) {
mValueAnimator.cancel();
mValueAnimator.removeAllUpdateListeners();
}
// Set the scale type
super.setScaleType(mFromScaleType);
// Get values for the current image matrix
setFrame(getLeft(), getTop(), getRight(), getBottom());
Matrix srcMatrix = getImageMatrix();
final float[] srcValues = new float[9], destValues = new float[9];
srcMatrix.getValues(srcValues);
// Set the scale type to the new type
super.setScaleType(toScaleType);
setFrame(getLeft(), getTop(), getRight(), getBottom());
Matrix destMatrix = getImageMatrix();
if (toScaleType == ScaleType.FIT_XY) {
float sX = ((float) getWidth()) / getDrawable().getIntrinsicWidth();
float sY = ((float) getHeight()) / getDrawable().getIntrinsicHeight();
destMatrix.postScale(sX, sY);
}
destMatrix.getValues(destValues);
// Get translation values
final float transX = destValues[2] - srcValues[2];
final float transY = destValues[5] - srcValues[5];
final float scaleX = destValues[0] - srcValues[0];
final float scaleY = destValues[4] - srcValues[4];
// Set the scale type to a matrix
super.setScaleType(ScaleType.MATRIX);
// Listen to value animator changes
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = animation.getAnimatedFraction();
float[] currValues = Arrays.copyOf(srcValues, srcValues.length);
currValues[2] = srcValues[2] + transX * value;
currValues[5] = srcValues[5] + transY * value;
currValues[0] = srcValues[0] + scaleX * value;
currValues[4] = srcValues[4] + scaleY * value;
Matrix matrix = new Matrix();
matrix.setValues(currValues);
setImageMatrix(matrix);
}
});
// Save the newly set scale type after animation completes
mValueAnimator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
// Set the from scale type to the newly used scale type
mFromScaleType = toScaleType;
}
});
// Start the animation
if (animated) {
mValueAnimator.start();
}
}
}

Drag and Drop for listview of views

Hi i am having Listview where each item is having different layout.and i want to perform drag and drop on this listview.i have searched many examples and tried but all works for listview of strings or something like that,none is working on listview of views.finally i decided to go with
DevBytes: ListView Cell Dragging and Rearranging this one.i implemented dynaliclistview but it is crashing as this also using strings in listview.Following is my listview adapter
public class ListViewPagerAdapter extends BaseAdapter {
ViewPagerAdapter mViewPagerAdapter;
private Context context;
private int selectedIndex;
FragmentManager mFragmentManager;
static ViewPager vp;
LayoutInflater inflater;
private ArrayList<Integer> mContent;
public ListViewPagerAdapter(Context context,FragmentManager fg)
{
super();
this.context = context;
mFragmentManager = fg;
}
#Override
public int getCount() {
return 4;
}
public void setSelectedIndex(int position) {
selectedIndex = position;
notifyDataSetChanged();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
if (convertView == null) {
inflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if(position==0)
{
convertView = inflater.inflate(R.layout.titlebar, null);
}
}
if(position==0)
{
convertView = inflater.inflate(R.layout.titlebar, null);
}
if(position==1)
{LayoutInflater inflater1 = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = inflater1.inflate(R.layout.calendarwidget_layout, null);
}
if(position==2)
{
LayoutInflater inflater2 = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = inflater2.inflate(R.layout.view_pager_list_view, null);
vp = (ViewPager) convertView.findViewById(R.id.list_pager);
mViewPagerAdapter = new ViewPagerAdapter(mFragmentManager);
vp.setAdapter(mViewPagerAdapter);
}
if(position==3)
{
LayoutInflater inflater2 = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = inflater2.inflate(R.layout.view_pager_list_view, null);
vp = (ViewPager) convertView.findViewById(R.id.list_pager);
mViewPagerAdapter = new ViewPagerAdapter(mFragmentManager);
vp.setAdapter(mViewPagerAdapter);
mViewPagerAdapter.notifyDataSetChanged();
}
return convertView;
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
}
and following is code for dynamiclisview (same as from mentioned example)
public class DynamicListView extends ListView {
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 items in the listview. When a cell has
* been selected, the hover cell is created and set up.
*/
private AdapterView.OnItemLongClickListener mOnItemLongClickListener =
new AdapterView.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);
ListViewPagerAdapter adapter = ((ListViewPagerAdapter)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();
ListViewPagerAdapter adapter = ((ListViewPagerAdapter)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 items 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();
mobileView.setVisibility(View.VISIBLE);
switchView.setVisibility(View.INVISIBLE);
updateNeighborViewsForID(mMobileItemId);
final ViewTreeObserver observer = getViewTreeObserver();
observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#SuppressLint("NewApi")
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 items.
*/
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 AbsListView.OnScrollListener mScrollListener = new AbsListView.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();
}
}
}
};
}
And following is list.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<com.bin.widget.DynamicListView
android:id="#+id/campaignListView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#0000"
>
</com.bin.widget.DynamicListView>
</RelativeLayout>
please help me out...thanks in advance
HI I finally solved this problem myself,above code works by making few changes in adapter class of listview.In adapter's public long getItemId(int position) make necessary changes so that it will give you id of passed positions view.Dont just return position. Also,in dynamicListview class after swapping position refresh of listview is being done so in listadapter's getview() method,we need to make changes accordingly.
That's it,then it works like charm.Hope this helps somebody else too.

How to make listview empty in android

I am using pulltorefresh in my application.In onRefresh(), I tried to remove all the items by keeping listView.setAdapter(null);
But still my listView.getCount() is returning 1.
listView.setOnRefreshListener(new OnRefreshListener() {
// #Override
public void onRefresh() {
// Your code to refresh the list contents goes here
scroll=true;
pic.clear();
id.clear();
name.clear();
msg.clear();
img.clear();
profimg.clear();
objid.clear();
comment.clear();
weburl.clear();
adapter.clear();
likes.clear();
like_or_unlike.clear();
previousTotal = 0;
adapter.clear();
j=0;
loading = true;
webserv="https://graph.facebook.com/me/home?access_token="+accesstoken;
// listView.setAdapter(null);
System.out.println(listView.getCount());
// doInBack dob=new doInBack();
// dob.execute();
System.out.println(listView.getCount());
doback(webserv);
Log.e("hi","doback called");
}
});
My pulltorefresh class is
package com.beerbro.utils;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.*;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.animation.*;
import android.view.animation.Animation.AnimationListener;
import android.widget.*;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* A generic, customizable Android ListView implementation that has 'Pull to Refresh' functionality.
* <p/>
* This ListView can be used in place of the normal Android android.widget.ListView class.
* <p/>
* Users of this class should implement OnRefreshListener and call setOnRefreshListener(..)
* to get notified on refresh events. The using class should call onRefreshComplete() when
* refreshing is finished.
* <p/>
* The using class can call setRefreshing() to set the state explicitly to refreshing. This
* is useful when you want to show the spinner and 'Refreshing' text when the
* refresh was not triggered by 'Pull to Refresh', for example on start.
* <p/>
* For more information, visit the project page:
* https://github.com/erikwt/PullToRefresh-ListView
*
* #author Erik Wallentinsen <dev+ptr#erikw.eu>
* #version 1.0.0
*/
public class PullToRefreshListView extends ListView{
private static final float PULL_RESISTANCE = 1.7f;
private static final int BOUNCE_ANIMATION_DURATION = 700;
private static final int BOUNCE_ANIMATION_DELAY = 100;
private static final float BOUNCE_OVERSHOOT_TENSION = 1.4f;
private static final int ROTATE_ARROW_ANIMATION_DURATION = 250;
private static enum State{
PULL_TO_REFRESH,
RELEASE_TO_REFRESH,
REFRESHING
}
/**
* Interface to implement when you want to get notified of 'pull to refresh'
* events.
* Call setOnRefreshListener(..) to activate an OnRefreshListener.
*/
public interface OnRefreshListener{
/**
* Method to be called when a refresh is requested
*/
public void onRefresh();
}
private static int measuredHeaderHeight;
private boolean scrollbarEnabled;
private boolean bounceBackHeader;
private boolean lockScrollWhileRefreshing;
private boolean showLastUpdatedText;
private String pullToRefreshText;
private String releaseToRefreshText;
private String refreshingText;
private String lastUpdatedText;
private SimpleDateFormat lastUpdatedDateFormat = new SimpleDateFormat("dd/MM HH:mm");
private float previousY;
private int headerPadding;
private boolean hasResetHeader;
private long lastUpdated = -1;
private State state;
private LinearLayout headerContainer;
private RelativeLayout header;
private RotateAnimation flipAnimation;
private RotateAnimation reverseFlipAnimation;
private ImageView image;
private ProgressBar spinner;
private TextView text;
private TextView lastUpdatedTextView;
private OnItemClickListener onItemClickListener;
private OnItemLongClickListener onItemLongClickListener;
private OnRefreshListener onRefreshListener;
public PullToRefreshListView(Context context){
super(context);
init();
}
public PullToRefreshListView(Context context, AttributeSet attrs){
super(context, attrs);
init();
}
public PullToRefreshListView(Context context, AttributeSet attrs, int defStyle){
super(context, attrs, defStyle);
init();
}
#Override
public void setOnItemClickListener(OnItemClickListener onItemClickListener){
this.onItemClickListener = onItemClickListener;
}
#Override
public void setOnItemLongClickListener(OnItemLongClickListener onItemLongClickListener){
this.onItemLongClickListener = onItemLongClickListener;
}
/**
* Activate an OnRefreshListener to get notified on 'pull to refresh'
* events.
*
* #param onRefreshListener The OnRefreshListener to get notified
*/
public void setOnRefreshListener(OnRefreshListener onRefreshListener){
this.onRefreshListener = onRefreshListener;
}
/**
* #return If the list is in 'Refreshing' state
*/
public boolean isRefreshing(){
return state == State.REFRESHING;
}
/**
* Default is false. When lockScrollWhileRefreshing is set to true, the list
* cannot scroll when in 'refreshing' mode. It's 'locked' on refreshing.
*
* #param lockScrollWhileRefreshing
*/
public void setLockScrollWhileRefreshing(boolean lockScrollWhileRefreshing){
this.lockScrollWhileRefreshing = lockScrollWhileRefreshing;
}
/**
* Default is false. Show the last-updated date/time in the 'Pull ro Refresh'
* header. See 'setLastUpdatedDateFormat' to set the date/time formatting.
*
* #param showLastUpdatedText
*/
public void setShowLastUpdatedText(boolean showLastUpdatedText){
this.showLastUpdatedText = showLastUpdatedText;
if(!showLastUpdatedText) lastUpdatedTextView.setVisibility(View.GONE);
}
/**
* Default: "dd/MM HH:mm". Set the format in which the last-updated
* date/time is shown. Meaningless if 'showLastUpdatedText == false (default)'.
* See 'setShowLastUpdatedText'.
*
* #param lastUpdatedDateFormat
*/
public void setLastUpdatedDateFormat(SimpleDateFormat lastUpdatedDateFormat){
this.lastUpdatedDateFormat = lastUpdatedDateFormat;
}
/**
* Explicitly set the state to refreshing. This
* is useful when you want to show the spinner and 'Refreshing' text when
* the refresh was not triggered by 'pull to refresh', for example on start.
*/
public void setRefreshing(){
state = State.REFRESHING;
scrollTo(0, 0);
setUiRefreshing();
setHeaderPadding(0);
}
/**
* Set the state back to 'pull to refresh'. Call this method when refreshing
* the data is finished.
*/
public void onRefreshComplete(){
state = State.PULL_TO_REFRESH;
resetHeader();
lastUpdated = System.currentTimeMillis();
}
/**
* Change the label text on state 'Pull to Refresh'
*
* #param pullToRefreshText Text
*/
public void setTextPullToRefresh(String pullToRefreshText){
this.pullToRefreshText = pullToRefreshText;
if(state == State.PULL_TO_REFRESH){
text.setText(pullToRefreshText);
}
}
/**
* Change the label text on state 'Release to Refresh'
*
* #param releaseToRefreshText Text
*/
public void setTextReleaseToRefresh(String releaseToRefreshText){
this.releaseToRefreshText = releaseToRefreshText;
if(state == State.RELEASE_TO_REFRESH){
text.setText(releaseToRefreshText);
}
}
/**
* Change the label text on state 'Refreshing'
*
* #param refreshingText Text
*/
public void setTextRefreshing(String refreshingText){
this.refreshingText = refreshingText;
if(state == State.REFRESHING){
text.setText(refreshingText);
}
}
private void init(){
setVerticalFadingEdgeEnabled(false);
headerContainer = (LinearLayout) LayoutInflater.from(getContext()).inflate(R.layout.ptr_header, null);
header = (RelativeLayout) headerContainer.findViewById(R.id.ptr_id_header);
text = (TextView) header.findViewById(R.id.ptr_id_text);
lastUpdatedTextView = (TextView) header.findViewById(R.id.ptr_id_last_updated);
image = (ImageView) header.findViewById(R.id.ptr_id_image);
spinner = (ProgressBar) header.findViewById(R.id.ptr_id_spinner);
pullToRefreshText = getContext().getString(R.string.ptr_pull_to_refresh);
releaseToRefreshText = getContext().getString(R.string.ptr_release_to_refresh);
refreshingText = getContext().getString(R.string.ptr_refreshing);
lastUpdatedText = getContext().getString(R.string.ptr_last_updated);
flipAnimation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
flipAnimation.setInterpolator(new LinearInterpolator());
flipAnimation.setDuration(ROTATE_ARROW_ANIMATION_DURATION);
flipAnimation.setFillAfter(true);
reverseFlipAnimation = new RotateAnimation(-180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
reverseFlipAnimation.setInterpolator(new LinearInterpolator());
reverseFlipAnimation.setDuration(ROTATE_ARROW_ANIMATION_DURATION);
reverseFlipAnimation.setFillAfter(true);
addHeaderView(headerContainer);
setState(State.PULL_TO_REFRESH);
scrollbarEnabled = isVerticalScrollBarEnabled();
ViewTreeObserver vto = header.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new PTROnGlobalLayoutListener());
super.setOnItemClickListener(new PTROnItemClickListener());
super.setOnItemLongClickListener(new PTROnItemLongClickListener());
}
private void setHeaderPadding(int padding){
headerPadding = padding;
MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) header.getLayoutParams();
mlp.setMargins(0, Math.round(padding), 0, 0);
header.setLayoutParams(mlp);
}
#Override
public boolean onTouchEvent(MotionEvent event){
if(lockScrollWhileRefreshing
&& (state == State.REFRESHING || getAnimation() != null && !getAnimation().hasEnded())){
return true;
}
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
if(getFirstVisiblePosition() == 0) previousY = event.getY();
else previousY = -1;
break;
case MotionEvent.ACTION_UP:
if(previousY != -1 && (state == State.RELEASE_TO_REFRESH || getFirstVisiblePosition() == 0)){
switch(state){
case RELEASE_TO_REFRESH:
setState(State.REFRESHING);
bounceBackHeader();
break;
case PULL_TO_REFRESH:
resetHeader();
break;
}
}
break;
case MotionEvent.ACTION_MOVE:
if(previousY != -1){
float y = event.getY();
float diff = y - previousY;
if(diff > 0) diff /= PULL_RESISTANCE;
previousY = y;
int newHeaderPadding = Math.max(Math.round(headerPadding + diff), -header.getHeight());
if(newHeaderPadding != headerPadding && state != State.REFRESHING){
setHeaderPadding(newHeaderPadding);
if(state == State.PULL_TO_REFRESH && headerPadding > 0){
setState(State.RELEASE_TO_REFRESH);
image.clearAnimation();
image.startAnimation(flipAnimation);
}else if(state == State.RELEASE_TO_REFRESH && headerPadding < 0){
setState(State.PULL_TO_REFRESH);
image.clearAnimation();
image.startAnimation(reverseFlipAnimation);
}
return true;
}
}
break;
}
return super.onTouchEvent(event);
}
private void bounceBackHeader(){
int yTranslate = state == State.REFRESHING ?
header.getHeight() - headerContainer.getHeight() :
-headerContainer.getHeight() - headerContainer.getTop();
TranslateAnimation bounceAnimation = new TranslateAnimation(
TranslateAnimation.ABSOLUTE, 0,
TranslateAnimation.ABSOLUTE, 0,
TranslateAnimation.ABSOLUTE, 0,
TranslateAnimation.ABSOLUTE, yTranslate);
bounceAnimation.setDuration(BOUNCE_ANIMATION_DURATION);
bounceAnimation.setFillEnabled(true);
bounceAnimation.setFillAfter(false);
bounceAnimation.setFillBefore(true);
bounceAnimation.setInterpolator(new OvershootInterpolator(BOUNCE_OVERSHOOT_TENSION));
bounceAnimation.setAnimationListener(new HeaderAnimationListener(yTranslate));
startAnimation(bounceAnimation);
}
private void resetHeader(){
if(getFirstVisiblePosition() > 0){
setHeaderPadding(-header.getHeight());
setState(State.PULL_TO_REFRESH);
return;
}
if(getAnimation() != null && !getAnimation().hasEnded()){
bounceBackHeader = true;
}else{
bounceBackHeader();
}
}
private void setUiRefreshing(){
spinner.setVisibility(View.VISIBLE);
image.clearAnimation();
image.setVisibility(View.INVISIBLE);
text.setText(refreshingText);
}
private void setState(State state){
this.state = state;
switch(state){
case PULL_TO_REFRESH:
spinner.setVisibility(View.INVISIBLE);
image.setVisibility(View.VISIBLE);
text.setText(pullToRefreshText);
if(showLastUpdatedText && lastUpdated != -1){
lastUpdatedTextView.setVisibility(View.VISIBLE);
lastUpdatedTextView.setText(String.format(lastUpdatedText, lastUpdatedDateFormat.format(new Date(lastUpdated))));
}
break;
case RELEASE_TO_REFRESH:
spinner.setVisibility(View.INVISIBLE);
image.setVisibility(View.VISIBLE);
text.setText(releaseToRefreshText);
break;
case REFRESHING:
setUiRefreshing();
lastUpdated = System.currentTimeMillis();
if(onRefreshListener == null){
setState(State.PULL_TO_REFRESH);
}else{
onRefreshListener.onRefresh();
}
break;
}
}
#Override
protected void onScrollChanged(int l, int t, int oldl, int oldt){
super.onScrollChanged(l, t, oldl, oldt);
if(!hasResetHeader){
if(measuredHeaderHeight > 0 && state != State.REFRESHING){
setHeaderPadding(-measuredHeaderHeight);
}
hasResetHeader = true;
}
}
private class HeaderAnimationListener implements AnimationListener{
private int height, translation;
private State stateAtAnimationStart;
public HeaderAnimationListener(int translation){
this.translation = translation;
}
public void onAnimationStart(Animation animation){
stateAtAnimationStart = state;
android.view.ViewGroup.LayoutParams lp = getLayoutParams();
height = lp.height;
lp.height = getHeight() - translation;
setLayoutParams(lp);
if(scrollbarEnabled){
setVerticalScrollBarEnabled(false);
}
}
// #Override
public void onAnimationEnd(Animation animation){
setHeaderPadding(stateAtAnimationStart == State.REFRESHING ? 0 : -measuredHeaderHeight - headerContainer.getTop());
setSelection(0);
android.view.ViewGroup.LayoutParams lp = getLayoutParams();
lp.height = height;
setLayoutParams(lp);
if(scrollbarEnabled){
setVerticalScrollBarEnabled(true);
}
if(bounceBackHeader){
bounceBackHeader = false;
postDelayed(new Runnable(){
// #Override
public void run(){
resetHeader();
}
}, BOUNCE_ANIMATION_DELAY);
}else if(stateAtAnimationStart != State.REFRESHING){
setState(State.PULL_TO_REFRESH);
}
}
// #Override
public void onAnimationRepeat(Animation animation){}
}
private class PTROnGlobalLayoutListener implements OnGlobalLayoutListener{
// #Override
public void onGlobalLayout(){
int initialHeaderHeight = header.getHeight();
if(initialHeaderHeight > 0){
measuredHeaderHeight = initialHeaderHeight;
if(measuredHeaderHeight > 0 && state != State.REFRESHING){
setHeaderPadding(-measuredHeaderHeight);
requestLayout();
}
}
getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
private class PTROnItemClickListener implements OnItemClickListener{
//
// #Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id){
hasResetHeader = false;
if(onItemClickListener != null && state == State.PULL_TO_REFRESH){
// Passing up onItemClick. Correct position with the number of header views
onItemClickListener.onItemClick(adapterView, view, position - getHeaderViewsCount(), id);
}
}
}
private class PTROnItemLongClickListener implements OnItemLongClickListener{
// #Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int position, long id){
hasResetHeader = false;
if(onItemLongClickListener != null && state == State.PULL_TO_REFRESH){
// Passing up onItemLongClick. Correct position with the number of header views
return onItemLongClickListener.onItemLongClick(adapterView, view, position - getHeaderViewsCount(), id);
}
return false;
}
}
}
I really didnt understand why it is returning 1 instead of 0.
Have you tried to clear the list and the notify the adapter?
I mean, If I use an String array to make the list:
ArrayList<String> names=new ArrayList<String>();
ArrayAdapter<String> adapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, names);
ListView listView = (ListView) findViewById(android.R.id.list);
listView.setAdapter(adapter);
If I want to clear it, I make:
names.clear();
adapter.notifyDataSetChanged();

Android Gallery zoom in/out

Hi I am using the Gallery widget to show images downloaded from the internet.
to show several images and I would like to have a gradual zoom while people slide up and down on the screen. I know how to implement the touch event the only thing I don't know how to make the whole gallery view grow gradually. I don't want to zoom in on one image I want the whole gallery to zoom in/out gradually.
EDIT3: I manage to zoom the visible part of the gallery but the problem is I need to find a way for the gallery to find out about it and update it's other children too.
What happens is if 3 images are visible then you start zooming and the gallery does get smaller, so do the images but what I would like in this case is more images to be visible but I don't know how to reach this desired effect. Here's the entire code:
public class Gallery1 extends Activity implements OnTouchListener {
private static final String TAG = "GalleryTest";
private float zoom=0.0f;
// Remember some things for zooming
PointF start = new PointF();
PointF mid = new PointF();
Gallery g;
LinearLayout layout2;
private ImageAdapter ad;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gallery_1);
layout2=(LinearLayout) findViewById(R.id.layout2);
// Reference the Gallery view
g = (Gallery) findViewById(R.id.gallery);
// Set the adapter to our custom adapter (below)
ad=new ImageAdapter(this);
g.setAdapter(ad);
layout2.setOnTouchListener(this);
}
public void zoomList(boolean increase) {
Log.i(TAG, "startig animation");
AnimatorSet set = new AnimatorSet();
set.playTogether(
ObjectAnimator.ofFloat(g, "scaleX", zoom),
ObjectAnimator.ofFloat(g, "scaleY", zoom)
);
set.addListener(new AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animator animation) {
}
#Override
public void onAnimationCancel(Animator animation) {
// TODO Auto-generated method stub
}
});
set.setDuration(100).start();
}
public class ImageAdapter extends BaseAdapter {
private static final int ITEM_WIDTH = 136;
private static final int ITEM_HEIGHT = 88;
private final int mGalleryItemBackground;
private final Context mContext;
private final Integer[] mImageIds = {
R.drawable.gallery_photo_1,
R.drawable.gallery_photo_2,
R.drawable.gallery_photo_3,
R.drawable.gallery_photo_4,
R.drawable.gallery_photo_5,
R.drawable.gallery_photo_6,
R.drawable.gallery_photo_7,
R.drawable.gallery_photo_8
};
private final float mDensity;
public ImageAdapter(Context c) {
mContext = c;
// See res/values/attrs.xml for the <declare-styleable> that defines
// Gallery1.
TypedArray a = obtainStyledAttributes(R.styleable.Gallery1);
mGalleryItemBackground = a.getResourceId(
R.styleable.Gallery1_android_galleryItemBackground, 1);
a.recycle();
mDensity = c.getResources().getDisplayMetrics().density;
}
public int getCount() {
return mImageIds.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
convertView = new ImageView(mContext);
imageView = (ImageView) convertView;
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setLayoutParams(new Gallery.LayoutParams(
(int) (ITEM_WIDTH * mDensity + 0.5f),
(int) (ITEM_HEIGHT * mDensity + 0.5f)));
} else {
imageView = (ImageView) convertView;
}
imageView.setImageResource(mImageIds[position]);
return imageView;
}
}
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_MOVE
&& event.getPointerCount() > 1) {
midPoint(mid, event);
if(mid.y > start.y){
Log.i(TAG, "Going down (Math.abs(mid.y - start.y)= "+(Math.abs(mid.y - start.y))+" and zoom="+zoom); // going down so increase
if ((Math.abs(mid.y - start.y) > 10) && (zoom<2.5f)){
zoom=zoom+0.1f;
midPoint(start, event);
zoomList(true);
}
return true;
}else if(mid.y < start.y){
Log.i(TAG, "Going up (Math.abs(mid.y - start.y)= "+(Math.abs(mid.y - start.y))+" and zoom="+zoom); //smaller
if ((Math.abs(mid.y - start.y) > 10) &&(zoom>0.1)){
midPoint(start, event);
zoom=zoom-0.1f;
zoomList(false);
}
return true;
}
}
else if (event.getAction() == MotionEvent.ACTION_POINTER_DOWN) {
Log.e(TAG, "Pointer went down: " + event.getPointerCount());
return true;
}
else if (event.getAction() == MotionEvent.ACTION_UP) {
Log.i(TAG, "Pointer going up");
return true;
}
else if (event.getAction() == MotionEvent.ACTION_DOWN) {
Log.i(TAG, "Pointer going down");
start.set(event.getX(), event.getY());
return true;
}
return false;
// indicate event was handled or not
}
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
I realise I will probably have to extend the Gallery or even another View group or create my own class but I don't know where to start: which method use the one responsible for scaling...
EDIT4: I don't know if he question is clear enough. Here is an example of states:
State one: initial state, we have 3 images in view
State 2: we detect vertical touches going up with 2 fingers = we have to zoom out
state 3: we start zooming = animation on the gallery or on the children???
state 4: gallery detects that it's 3 children are smaller
state 5: gallery adds 1 /more children according to the new available space
LAST UPDATE:
Thanks to all that have posted but I have finally reached a conclusion and that is to not use Gallery at all:
1. It's deprecated
2. It's not customizable enough for my case
If you want to animate several images at once you may want to consider using OpenGl, I am using libgdx library:
https://github.com/libgdx/libgdx
The following ScalingGallery implementation might be of help.
This gallery subclass overrides the getChildStaticTransformation(View child, Transformation t) method in which the scaling is performed. You can further customize the scaling parameters to fit your own needs.
Please note the ScalingGalleryItemLayout.java class. This is necessary because after you have performed the scaling operationg on the child views, their hit boxes are no longer valid so they must be updated from with the getChildStaticTransformation(View child, Transformation t) method.
This is done by wrapping each gallery item in a ScalingGalleryItemLayout which extends a LinearLayout. Again, you can customize this to fit your own needs if a LinearLayout does not meet your needs for layout out your gallery items.
File : /src/com/example/ScalingGallery.java
/**
* A Customized Gallery component which alters the size and position of its items based on their position in the Gallery.
*/
public class ScalingGallery extends Gallery {
public static final int ITEM_SPACING = -20;
private static final float SIZE_SCALE_MULTIPLIER = 0.25f;
private static final float ALPHA_SCALE_MULTIPLIER = 0.5f;
private static final float X_OFFSET = 20.0f;
/**
* Implemented by child view to adjust the boundaries after it has been matrix transformed.
*/
public interface SetHitRectInterface {
public void setHitRect(RectF newRect);
}
/**
* #param context
* Context that this Gallery will be used in.
* #param attrs
* Attributes for this Gallery (via either xml or in-code)
*/
public ScalingGallery(Context context, AttributeSet attrs) {
super(context, attrs);
setStaticTransformationsEnabled(true);
setChildrenDrawingOrderEnabled(true);
}
/**
* {#inheritDoc}
*
* #see #setStaticTransformationsEnabled(boolean)
*
* This is where the scaling happens.
*/
protected boolean getChildStaticTransformation(View child, Transformation t) {
child.invalidate();
t.clear();
t.setTransformationType(Transformation.TYPE_BOTH);
// Position of the child in the Gallery (... +2 +1 0 -1 -2 ... 0 being the middle)
final int childPosition = getSelectedItemPosition() - getPositionForView(child);
final int childPositionAbs = (int) Math.abs(childPosition);
final float left = child.getLeft();
final float top = child.getTop();
final float right = child.getRight();
final float bottom = child.getBottom();
Matrix matrix = t.getMatrix();
RectF modifiedHitBox = new RectF();
// Change alpha, scale and translate non-middle child views.
if (childPosition != 0) {
final int height = child.getMeasuredHeight();
final int width = child.getMeasuredWidth();
// Scale the size.
float scaledSize = 1.0f - (childPositionAbs * SIZE_SCALE_MULTIPLIER);
if (scaledSize < 0) {
scaledSize = 0;
}
matrix.setScale(scaledSize, scaledSize);
float moveX = 0;
float moveY = 0;
// Moving from right to left -- linear move since the scaling is done with respect to top-left corner of the view.
if (childPosition < 0) {
moveX = ((childPositionAbs - 1) * SIZE_SCALE_MULTIPLIER * width) + X_OFFSET;
moveX *= -1;
} else { // Moving from left to right -- sum of the previous positions' x displacements.
// X(n) = X(0) + X(1) + X(2) + ... + X(n-1)
for (int i = childPositionAbs; i > 0; i--) {
moveX += (i * SIZE_SCALE_MULTIPLIER * width);
}
moveX += X_OFFSET;
}
// Moving down y-axis is linear.
moveY = ((childPositionAbs * SIZE_SCALE_MULTIPLIER * height) / 2);
matrix.postTranslate(moveX, moveY);
// Scale alpha value.
final float alpha = (1.0f / childPositionAbs) * ALPHA_SCALE_MULTIPLIER;
t.setAlpha(alpha);
// Calculate new hit box. Since we moved the child, the hitbox is no longer lined up with the new child position.
final float newLeft = left + moveX;
final float newTop = top + moveY;
final float newRight = newLeft + (width * scaledSize);
final float newBottom = newTop + (height * scaledSize);
modifiedHitBox = new RectF(newLeft, newTop, newRight, newBottom);
} else {
modifiedHitBox = new RectF(left, top, right, bottom);
}
// update child hit box so you can tap within the child's boundary
((SetHitRectInterface) child).setHitRect(modifiedHitBox);
return true;
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// Helps to smooth out jittering during scrolling.
// read more - http://www.unwesen.de/2011/04/17/android-jittery-scrolling-gallery/
final int viewsOnScreen = getLastVisiblePosition() - getFirstVisiblePosition();
if (viewsOnScreen <= 0) {
super.onLayout(changed, l, t, r, b);
}
}
private int mLastDrawnPosition;
#Override
protected int getChildDrawingOrder(int childCount, int i) {
//Reset the last position variable every time we are starting a new drawing loop
if (i == 0) {
mLastDrawnPosition = 0;
}
final int centerPosition = getSelectedItemPosition() - getFirstVisiblePosition();
if (i == childCount - 1) {
return centerPosition;
} else if (i >= centerPosition) {
mLastDrawnPosition++;
return childCount - mLastDrawnPosition;
} else {
return i;
}
}
}
File : /src/com/example/ScalingGalleryItemLayout.java
public class ScalingGalleryItemLayout extends LinearLayout implements SetHitRectInterface {
public ScalingGalleryItemLayout(Context context) {
super(context);
}
public ScalingGalleryItemLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScalingGalleryItemLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
private Rect mTransformedRect;
#Override
public void setHitRect(RectF newRect) {
if (newRect == null) {
return;
}
if (mTransformedRect == null) {
mTransformedRect = new Rect();
}
newRect.round(mTransformedRect);
}
#Override
public void getHitRect(Rect outRect) {
if (mTransformedRect == null) {
super.getHitRect(outRect);
} else {
outRect.set(mTransformedRect);
}
}
}
File : /res/layout/ScaledGalleryItemLayout.xml
<?xml version="1.0" encoding="utf-8"?>
<com.example.ScalingGalleryItemLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gallery_item_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical"
android:padding="5dp" >
<ImageView
android:id="#+id/gallery_item_image"
android:layout_width="360px"
android:layout_height="210px"
android:layout_gravity="center"
android:antialias="true"
android:background="#drawable/gallery_item_button_selector"
android:cropToPadding="true"
android:padding="35dp"
android:scaleType="centerInside" />
<TextView
android:id="#+id/gallery_item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="#drawable/white"
android:textSize="30sp" />
</com.example.ScalingGalleryItemLayout>
To keep the state of the animation after it is done, just do this on your animation:
youranim.setFillAfter(true);
Edit :
In my project, I use this method and i think, it's help you :
http://developer.sonymobile.com/wp/2011/04/12/how-to-take-advantage-of-the-pinch-to-zoom-feature-in-your-xperia%E2%84%A2-10-apps-part-1/
U can do Image Zoom pinch option for gallery also.
by using below code lines:
you can download the example.
https://github.com/alvinsj/android-image-gallery/downloads
I hope this example will help to u..if u have any queries ask me.....
This is solution
integrate gallery component in android with gesture-image library
gesture-imageView
And here is full sample code
SampleCode

Android: fadeIn selected row

I have listview similar to this:
Add code, it isn't much, but maybe helpful:
CustomAdapter:
public class MyAdapter extends BaseAdapter{
private LayoutInflater mInflater;
private Animation fadeIn;
private Animation fadeOut;
public MyAdapter(Activity c) {
mInflater = c.getLayoutInflater();
fadeIn = AnimationUtils.loadAnimation(c.getApplicationContext(), R.anim.alpha_show);
fadeIn.setFillAfter(true);
fadeOut = AnimationUtils.loadAnimation(c.getApplicationContext(), R.anim.alpha_dissappear);
fadeOut.setFillAfter(true);
}
public int getCount() {
return MainButtonsList.getList().getSize() +
GlobalPrefs.getEmptyRowsAtEnd() +
GlobalPrefs.getEmptyRowsAtStart();
}
public View getView(int position, View v, ViewGroup parent) {
View convertView = v;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.main_list_item, null);
}
ImageView iv = (ImageView) convertView.findViewById(R.id.image);
if ((position > GlobalPrefs.getEmptyRowsAtStart() - 1) && (position < getCount() - GlobalPrefs.getEmptyRowsAtEnd())) {
iv.setImageResource(MainButtonsList.getList().getListImageResource(position - GlobalPrefs.getEmptyRowsAtStart()));
iv.setAlpha(255);
iv.setTag(MainButtonsList.UNPRESSED_BUTTON_TAG);
} else {
iv.setTag(MainButtonsList.UNUSED_BUTTON_TAG);
iv.setAlpha(0);
iv.setVisibility(0);
iv.setClickable(false);
iv.setImageResource(R.drawable.logo_list_null);
}
iv.setMaxHeight(GlobalPrefs.getRowHeight());
iv.setMaxWidth(GlobalPrefs.getRowWidth());
iv.setBackgroundResource(0);
return convertView;
}
public Object getItem(int position) {
return MainButtonsList.getList().getObject(position);
}
public long getItemId(int position) {
return position;
}
}
Custom ListView:
public class CopyOfListView3d extends ListView{
private final Camera mCamera = new Camera();
private final Matrix mMatrix = new Matrix();
private Context context;
private Paint mPaint;
public CopyOfListView3d(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
this.setChildrenDrawingOrderEnabled(true);
}
#Override
protected int getChildDrawingOrder (int childCount, int i) {
//sets order number to each child, so makes overlap and center is always on top
}
#Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
// get top left coordinates
boolean isCenter = false;
final int top = child.getTop();
final int bottom = child.getBottom();
Bitmap bitmap = child.getDrawingCache();
if (bitmap == null) {
child.setDrawingCacheEnabled(true);
child.buildDrawingCache();
bitmap = child.getDrawingCache();
}
final int centerY = child.getHeight() / 2;
final int centerX = child.getWidth() / 2;
final int radius = getHeight() / 2;
final int absParentCenterY = getTop() + getHeight() / 2;
final int absChildCenterY = child.getTop() + centerY;
final int distanceY = (absParentCenterY - absChildCenterY) / 2;
final int absDistance = Math.min(radius, Math.abs(distanceY));
final float translateZ = (float) Math.sqrt((radius * radius) - (absDistance * absDistance));
mCamera.save();
float myTranslateX = (float) (translateZ * (1.5f));
int density = GlobalPrefs.getDensity();
if (density < DisplayMetrics.DENSITY_LOW) {
myTranslateX = (float) myTranslateX - 80;
} else if (density == DisplayMetrics.DENSITY_LOW) {
myTranslateX = (float) myTranslateX - GlobalPrefs.getScreenWidth() + density + 40;
} else if (density <= DisplayMetrics.DENSITY_MEDIUM) {
myTranslateX = (float) myTranslateX - ((float)(GlobalPrefs.getScreenWidth()*0.75)) + density/2;
} else
if (density <= DisplayMetrics.DENSITY_HIGH) {
myTranslateX = (float) myTranslateX - 320;
} else
if (density > DisplayMetrics.DENSITY_HIGH) {
//Log.i("density", "this is more than high");
myTranslateX = (float) myTranslateX;
}
if ((top < absParentCenterY) && (bottom > absParentCenterY)) {
//make center row bigger
isCenter = true;
mCamera.translate((float) myTranslateX, 0, (float) -160);//130
child.setPressed(true);
child.setTag(MainButtonsList.PRESSED_BUTTON_TAG);
}
else {
//top
child.setTag(MainButtonsList.UNPRESSED_BUTTON_TAG);
child.setPressed(false);
mCamera.translate((float) myTranslateX, 0, -150);//120;
};
mCamera.getMatrix(mMatrix);
mCamera.restore();
// create and initialize the paint object
if (mPaint == null) {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setFilterBitmap(true);
}
//calculates alpha for each row, so far from center, rows are barely visible
mPaint.setAlpha(calculateAlpha(absChildCenterY));
mMatrix.postTranslate((float) (-centerX * 1.5f), top);
canvas.drawBitmap(bitmap, mMatrix, mPaint);
return false;
}
}
They are made of ImageViews where white color is selected state and blue color is unselected state and I change selected/unselected by screen coordinates, so center always is selected.
I have custom 3dListView which extends ListView and made custom adapter, where i set imageviews to rows. Code is too much to show, but there are pretty simple
One of these could be helpfull:
1) How can I make fade in (maybe also fade out) for center row (I can find which row is center when giving parent or childCount)? (Better)
2) It also could be helpfull if there is any OnStateChange listener, which listens to view's presses. Then I could fade in anytime when view becomes pressed and fadeout, when looses press.
I found an answer myself. Added this code piece to my custom ListView in drawChild method end:
final ImageView iv = (ImageView) child.findViewById(R.id.image);
child.setTag(MainButtonsList.PRESSED_BUTTON_TAG);
Animation anim = fadeOut();
anim.setAnimationListener(new Animation.AnimationListener() {
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
public void onAnimationEnd(Animation animation) {
child.setPressed(true);
iv.startAnimation(fadeIn());
}
});
iv.clearAnimation();
iv.startAnimation(anim);
In list item layout, added another image, which put under item and now it looks prety nice.
You'll want to do the fading in the adapter for the listview.
In your adapter
private List<YourListObject> deleteItems;
// Constructor to init list and other vars
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Draw stuff
// including your object
for(YourListObject obj : deleteItems){
if(currentObj.equals(obj)){
Animation fadeOutAnimation = new AlphaAnimation(1.0f, 0.0f);
fadeOutAnimation.setDuration(300);
DeleteAnimationListener listener = new DeleteAnimationListener(currentObj);
fadeOutAnimation.setAnimationListener(listener);
someView.startAnimation(fadeOutAnimation);
}
}
return someView;
}
public void remove(YourListObject obj){
deleteItems.add(obj);
notifyDataSetChanged();
}
protected class DeleteAnimationListener extends EndAnimationListener {
private final YourListObject obj;
public DeleteAnimationListener(YourListObject obj) {
this.obj = obj;
}
#Override
public void onAnimationEnd(Animation animation) {
yourObjects.remove(obj);
deleteItems.remove(obj);
notifyDataSetChanged();
}
};
currentObj is the view in the list your currently manipulating
yourObjects is the list you are storing the data in.
deleteItems is a new list.
You call .remove(obj) on your adapter to remove one.
The getView will then remove it from the list (with a fade out animation) once this animation is finished the AnimationListener will remove the actual object from your dataset.

Categories

Resources