I am working with swipelistview in android where i need to implement onClick in a listview to swipe out the list item. I used openanimate method in OnclickfrontView. But my output result is reverse. I am getting view from right to left instead of left to right. The library which i used is https://github.com/47deg/android-swipelistview. The xml layout for swipelistview is
android:id="#+id/search_screen_listview_sharedData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="0dp"
android:layout_marginTop="0dp"
android:cacheColorHint="#00000000"
android:background="#color/white"
android:divider="#color/sliding_menu_listview_divider"
android:dividerHeight="0.2dp"
android:fadingEdgeLength="0dp"
android:focusable="false"
android:focusableInTouchMode="false"
android:listSelector="#color/transparent"
swipe:swipeFrontView="#+id/front"
swipe:swipeBackView="#+id/back"
swipe:swipeOpenOnLongPress="false"
swipe:swipeActionLeft="reveal"
swipe:swipeActionRight="reveal"
swipe:swipeCloseAllItemsWhenMoveList="true"
swipe:swipeDrawableChecked="#color/sliding_menu_selection_blue"
swipe:swipeDrawableUnchecked="#color/white"
swipe:swipeOffsetLeft="200dp"
swipe:swipeOffsetRight="70dp"
swipe:swipeMode="right" />
The sample code for your reference is
swipeListView = (SwipeListView) view
.findViewById(R.id.listview_sharedData);
swipeFrontView = (View) view.findViewById(R.id.front);
if (Build.VERSION.SDK_INT >= 11) {
swipeListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
swipeListView
.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
#Override
public void onItemCheckedStateChanged(ActionMode mode,
int position, long id, boolean checked) {
mode.setTitle("Selected ("
+ swipeListView.getCountSelected() + ")");
}
#Override
public void onDestroyActionMode(ActionMode mode) {
swipeListView.unselectedChoiceStates();
}
#Override
public boolean onActionItemClicked(ActionMode mode,
android.view.MenuItem item) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean onCreateActionMode(ActionMode mode,
android.view.Menu menu) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean onPrepareActionMode(ActionMode mode,
android.view.Menu menu) {
// TODO Auto-generated method stub
return false;
}
});
}
swipeListView.setSwipeListViewListener(new BaseSwipeListViewListener() {
#Override
public void onOpened(int position, boolean toRight) {
}
#Override
public void onClosed(int position, boolean fromRight) {
}
#Override
public void onListChanged() {
}
#Override
public void onMove(int position, float x) {
}
#Override
public void onStartOpen(int position, int action, boolean right) {
Log.d("swipe", String.format("onStartOpen %d - action %d",
position, action));
}
#Override
public void onStartClose(int position, boolean right) {
Log.d("swipe", String.format("onStartClose %d", position));
}
#Override
public void onClickFrontView(int position) {
Log.d("swipe", String.format("onClickFrontView %d", position));
swipeListView.openAnimate(position);
}
#Override
public void onClickBackView(int position) {
Log.d("swipe", String.format("onClickBackView %d", position));
//swipeListView.closeAnimate(position);
}
#Override
public void onDismiss(int[] reverseSortedPositions) {
/*
* for (int position : reverseSortedPositions) {
* data.remove(position); } adapter.notifyDataSetChanged();
*/
}
});
if (Constant.List != null) {
if (Constant.List.size() > 0) {
swipeListView.setAdapter(new CustomContentListAdapter(
getActivity(), Constant.List, true));
}
}
return view;
}
Please help me how to achieve left to right swipview while i click the listview item. I am struggling with this for a week but still didnt get good solution for it.
public void openAnimate(int position) {
touchListener.openAnimate(position);
}
protected void openAnimate(int position) {
openAnimate(
swipeListView.getChildAt(
position - swipeListView.getFirstVisiblePosition())
.findViewById(swipeFrontView), position);
}
private void openAnimate(View view, int position) {
if (!opened.get(position)) {
generateRevealAnimate(view, true, false, position);
}
}
private void generateRevealAnimate(final View view, final boolean swap,
final boolean swapRight, final int position) {
int moveTo = 0;
if (opened.get(position)) {
if (!swap) {
moveTo = openedRight.get(position) ? (int) (viewWidth - rightOffset)
: (int) (-viewWidth + leftOffset);
}
} else {
if (swap) {
moveTo = swapRight ? (int) (viewWidth - rightOffset)
: (int) (-viewWidth + leftOffset);
}
}
animate(view).translationX(moveTo).setDuration(animationTime)
.setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
swipeListView.resetScrolling();
if (swap) {
boolean aux = !opened.get(position);
opened.set(position, aux);
if (aux) {
swipeListView.onOpened(position, swapRight);
openedRight.set(position, swapRight);
} else {
swipeListView.onClosed(position,
openedRight.get(position));
}
}
resetCell();
}
});
}
private void resetCell() {
if (downPosition != ListView.INVALID_POSITION) {
if (swipeCurrentAction == SwipeListView.SWIPE_ACTION_CHOICE) {
backView.setVisibility(View.VISIBLE);
}
frontView.setClickable(opened.get(downPosition));
frontView.setLongClickable(opened.get(downPosition));
frontView = null;
backView = null;
downPosition = ListView.INVALID_POSITION;
}
}
Edit the openAnimate() method in the source code of the library you downloaded to make it move the other way (assuming the source code is included)
Edit:
Below is the code that determines where to move the view to
int moveTo = 0;
if (opened.get(position)) {
if (!swap) {
moveTo = openedRight.get(position) ? (int) (viewWidth - rightOffset)
: (int) (-viewWidth + leftOffset);
}
} else {
if (swap) {
moveTo = swapRight ? (int) (viewWidth - rightOffset)
: (int) (-viewWidth + leftOffset);
}
}
Because i dont have the full code i dont know what viewWidth or rightOffset and leftOffset are defined as.
I suggest you try something like this:
: (int) (-viewWidth + leftOffset);
to
: (int) (viewWidth - leftOffset);
And do that for both cases. I cant guarantee that will work but try playing around with those values if it doesnt.
You need add some code for:
SwipeListView.java
public void openAnimateRight(int position) {
touchListener.openAnimateRight(position);
}
public void closeAnimateRight(int position) {
touchListener.closeAnimateRight(position);
}
SwipeListViewTouchListener.java
protected void openAnimateRight(int position) {
openAnimateRight(swipeListView.getChildAt(position - swipeListView.getFirstVisiblePosition()).findViewById(swipeFrontView), position);
}
protected void closeAnimateRight(int position) {
closeAnimateRight(swipeListView.getChildAt(position - swipeListView.getFirstVisiblePosition()).findViewById(swipeFrontView), position);
}
private void openAnimateRight(View view, int position) {
if (!opened.get(position)) {
generateRevealAnimate(view, true, true, position);
}
}
private void closeAnimateRight(View view, int position) {
if (opened.get(position)) {
generateRevealAnimate(view, true, true, position);
}
}
and then you can call:
#Override
public void onClickFrontView(int position) {
Log.d("swipe", String.format("onClickFrontView %d", position));
swipe_list_view.openAnimateRight(position);
}
This working for me :)
The same way like in OnclickBackView you have to write swipeListView.closeanimate(postion);
On searching the repositry you provided. the library itself providing the support for swipetoright mode.
public final static int SWIPE_MODE_RIGHT = 2;
https://github.com/47deg/android-swipelistview/blob/20dbffdf3417a7ad0cbba06cc6f1caa7ffb3808d/swipelistview/src/com/fortysevendeg/swipelistview/SwipeListView.java
try that option to do your task...
All the best..
Related
I have to build animation like This.
Sorry I don't have too much reputation to upload image. you can find gif file from the above link.
I have done all this and it works fine on KitKat and LollyPop only but not on the other API version. I am using this library. Can any one please figure out the actual problem
Here is my code. Thanks in advance
public abstract class AbstractSlideExpandableListAdapter extends WrapperListAdapterImpl
{
private View lastOpnUpperView = null;
ArrayList<View> upperViewsList = new ArrayList<View>();
ArrayList<View> lowerViewsList = new ArrayList<View>();
ArrayList<View> circleViewsList = new ArrayList<View>();
private View lastOpen = null;
private int lastOpenPosition = -1;
private int lastOpenItemIndex = 0;
private int animationDuration = 800;
private BitSet openItems = new BitSet();
private final SparseIntArray viewHeights = new SparseIntArray(10);
private ViewGroup parent;
public AbstractSlideExpandableListAdapter(ListAdapter wrapped)
{
super(wrapped);
lastOpenPosition = 0;
openItems.set(lastOpenPosition, true);
}
private OnItemExpandCollapseListener expandCollapseListener;
public void setItemExpandCollapseListener(OnItemExpandCollapseListener listener)
{
expandCollapseListener = listener;
}
public void removeItemExpandCollapseListener()
{
expandCollapseListener = null;
}
public interface OnItemExpandCollapseListener
{
public void onExpand(View itemView, int position);
public void onCollapse(View itemView, int position);
}
private void notifiyExpandCollapseListener(int type, View view, int position)
{
if (expandCollapseListener != null)
{
if (type == ExpandCollapseAnimation.EXPAND)
{
expandCollapseListener.onExpand(view, position);
}
else if (type == ExpandCollapseAnimation.COLLAPSE)
{
expandCollapseListener.onCollapse(view, position);
}
}
}
#Override
public View getView(int position, View view, ViewGroup viewGroup)
{
this.parent = viewGroup;
view = wrapped.getView(position, view, viewGroup);
enableFor(view, position);
return view;
}
public abstract View getExpandToggleButton(View parent);
public abstract View getExpandableView(View parent);
// upperView to expand animation for sequeeze
public abstract View getUpperView(View upperView);
// Lower view to expand and collapse
public abstract View getLowerView(View upperView);
// Get the circle view to hide and show
public abstract View getCircleView(View circleView);
/**
* Gets the duration of the collapse animation in ms. Default is 330ms. Override this method to change the default.
*
* #return the duration of the anim in ms
*/
public int getAnimationDuration()
{
return animationDuration;
}
/**
* Set's the Animation duration for the Expandable animation
*
* #param duration
* The duration as an integer in MS (duration > 0)
* #exception IllegalArgumentException
* if parameter is less than zero
*/
public void setAnimationDuration(int duration)
{
if (duration < 0)
{
throw new IllegalArgumentException("Duration is less than zero");
}
animationDuration = duration;
}
/**
* Check's if any position is currently Expanded To collapse the open item #see collapseLastOpen
*
* #return boolean True if there is currently an item expanded, otherwise false
*/
public boolean isAnyItemExpanded()
{
return (lastOpenPosition != -1) ? true : false;
}
public void enableFor(View parent, int position)
{
View more = getExpandToggleButton(parent);
View itemToolbar = getExpandableView(parent);
View upperView = getUpperView(parent);
View circleView = getCircleView(parent);
View lowerView = getLowerView(parent);
itemToolbar.measure(parent.getWidth(), parent.getHeight());
upperViewsList.add(upperView);
circleViewsList.add(circleView);
lowerViewsList.add(lowerView);
if (position == 0)
{
// lastopenUpperViewTemporary = upperView;
lastOpnUpperView = upperView;
upperView.setVisibility(View.GONE);
lowerView.setVisibility(View.GONE);
}
enableFor(more, upperView, itemToolbar, position);
itemToolbar.requestLayout();
}
private void animateListExpand(final View button, final View target, final int position)
{
target.setAnimation(null);
int type;
if (target.getVisibility() == View.VISIBLE)
{
type = ExpandCollapseAnimation.COLLAPSE;
}
else
{
type = ExpandCollapseAnimation.EXPAND;
}
// remember the state
if (type == ExpandCollapseAnimation.EXPAND)
{
openItems.set(position, true);
}
else
{
openItems.set(position, false);
}
// check if we need to collapse a different view
if (type == ExpandCollapseAnimation.EXPAND)
{
if (lastOpenPosition != -1 && lastOpenPosition != position)
{
if (lastOpen != null)
{
animateWithUpperView(lastOpen, ExpandCollapseAnimation.COLLAPSE, position);
// animateView(lastOpen, ExpandCollapseAnimation.COLLAPSE);
notifiyExpandCollapseListener(ExpandCollapseAnimation.COLLAPSE, lastOpen, lastOpenPosition);
}
openItems.set(lastOpenPosition, false);
}
lastOpen = target;
lastOpenPosition = position;
}
else if (lastOpenPosition == position)
{
lastOpenPosition = -1;
}
// animateView(target, type);
// Expand the view which was collapse
Animation anim = new ExpandCollapseAnimation(target, type);
anim.setDuration(getAnimationDuration());
target.startAnimation(anim);
this.notifiyExpandCollapseListener(type, target, position);
// }
}
private void enableFor(final View button, final View upperView, final View target, final int position)
{
// lastopenUpperViewTemporary = upperView;
if (target == lastOpen && position != lastOpenPosition)
{
// lastOpen is recycled, so its reference is false
lastOpen = null;
}
if (position == lastOpenPosition)
{
// re reference to the last view
// so when can animate it when collapsed
// lastOpen = target;
lastOpen = target;
lastOpnUpperView = upperView;
}
int height = viewHeights.get(position, -1);
if (height == -1)
{
viewHeights.put(position, target.getMeasuredHeight());
updateExpandable(target, position);
}
else
{
updateExpandable(target, position);
}
button.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(final View view)
{
System.out.println("Position: " + position);
if (lastOpenPosition == position)
{
return;
}
System.out.println("Upper View: " + upperView);
Animation anim = new ExpandCollapseUpperViewAnimation(upperViewsList.get(position), ExpandCollapseUpperViewAnimation.COLLAPSE);
anim.setDuration(800);
anim.setAnimationListener(new AnimationListener()
{
#Override
public void onAnimationStart(Animation animation)
{
circleViewsList.get(position).setVisibility(View.GONE);
}
#Override
public void onAnimationRepeat(Animation animation)
{
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animation animation)
{
// TODO Auto-generated method stub
// upperViewsList.get(position).setVisibility(View.VISIBLE);
animateListExpand(button, target, position);
}
});
upperViewsList.get(position).startAnimation(anim);
// Lower animation
Animation lowerAnim = new ExpandCollapseUpperViewAnimation(lowerViewsList.get(position), ExpandCollapseUpperViewAnimation.COLLAPSE);
lowerAnim.setDuration(800);
lowerViewsList.get(position).startAnimation(lowerAnim);
}
});
}
private void updateExpandable(View target, int position)
{
final LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) target.getLayoutParams();
if (openItems.get(position))
{
target.setVisibility(View.VISIBLE);
params.bottomMargin = 0;
}
else
{
target.setVisibility(View.GONE);
params.bottomMargin = 0 - viewHeights.get(position);
}
}
/**
* Performs either COLLAPSE or EXPAND animation on the target view
*
* #param target
* the view to animate
* #param type
* the animation type, either ExpandCollapseAnimation.COLLAPSE or ExpandCollapseAnimation.EXPAND
*/
private void animateView(final View target, final int type)
{
Animation anim = new ExpandCollapseAnimation(target, type);
anim.setDuration(getAnimationDuration());
anim.setAnimationListener(new AnimationListener()
{
#Override
public void onAnimationStart(Animation animation)
{
}
#Override
public void onAnimationRepeat(Animation animation)
{
}
#Override
public void onAnimationEnd(Animation animation)
{
System.out.println("Animation End");
if (type == ExpandCollapseAnimation.EXPAND)
{
if (parent instanceof ListView)
{
ListView listView = (ListView) parent;
int movement = target.getBottom();
Rect r = new Rect();
boolean visible = target.getGlobalVisibleRect(r);
Rect r2 = new Rect();
listView.getGlobalVisibleRect(r2);
if (!visible)
{
listView.smoothScrollBy(movement, getAnimationDuration());
}
else
{
if (r2.bottom == r.bottom)
{
listView.smoothScrollBy(movement, getAnimationDuration());
}
}
}
}
}
});
target.startAnimation(anim);
}
private void animateWithUpperView(final View target, final int type, final int position)
{
Animation anim = new ExpandCollapseAnimation(target, type);
anim.setDuration(getAnimationDuration());
anim.setAnimationListener(new AnimationListener()
{
#Override
public void onAnimationStart(Animation animation)
{
}
#Override
public void onAnimationRepeat(Animation animation)
{
}
#Override
public void onAnimationEnd(Animation animation)
{
// upperViewsList.get(lastOpenItemForUpperView).setVisibility(View.VISIBLE);
// lastOpenItemForUpperView = position;
Animation expandItemAniamtion = new ExpandCollapseLowerViewAnimation(upperViewsList.get(lastOpenItemIndex), ExpandCollapseUpperViewAnimation.EXPAND);
expandItemAniamtion.setDuration(800);
expandItemAniamtion.setAnimationListener(new AnimationListener()
{
#Override
public void onAnimationStart(Animation animation)
{
}
#Override
public void onAnimationRepeat(Animation animation)
{
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animation animation)
{
circleViewsList.get(lastOpenItemIndex).setVisibility(View.VISIBLE);
lastOpenItemIndex = position;
}
});
// Lower view animation
Animation lowerAnim = new ExpandCollapseLowerViewAnimation(lowerViewsList.get(lastOpenItemIndex), ExpandCollapseUpperViewAnimation.EXPAND);
lowerAnim.setDuration(800);
upperViewsList.get(lastOpenItemIndex).startAnimation(expandItemAniamtion);
lowerViewsList.get(lastOpenItemIndex).startAnimation(lowerAnim);
}
});
target.startAnimation(anim);
}
/**
* Closes the current open item. If it is current visible it will be closed with an animation.
*
* #return true if an item was closed, false otherwise
*/
public boolean collapseLastOpen()
{
if (isAnyItemExpanded())
{
// if visible animate it out
if (lastOpen != null)
{
animateView(lastOpen, ExpandCollapseAnimation.COLLAPSE);
}
openItems.set(lastOpenPosition, false);
lastOpenPosition = -1;
return true;
}
return false;
}
public Parcelable onSaveInstanceState(Parcelable parcelable)
{
SavedState ss = new SavedState(parcelable);
ss.lastOpenPosition = this.lastOpenPosition;
ss.openItems = this.openItems;
return ss;
}
public void onRestoreInstanceState(SavedState state)
{
if (state != null)
{
this.lastOpenPosition = state.lastOpenPosition;
this.openItems = state.openItems;
}
}
/**
* Utility methods to read and write a bitset from and to a Parcel
*/
private static BitSet readBitSet(Parcel src)
{
BitSet set = new BitSet();
if (src == null)
{
return set;
}
int cardinality = src.readInt();
for (int i = 0; i < cardinality; i++)
{
set.set(src.readInt());
}
return set;
}
private static void writeBitSet(Parcel dest, BitSet set)
{
int nextSetBit = -1;
if (dest == null || set == null)
{
return; // at least dont crash
}
dest.writeInt(set.cardinality());
while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1)
{
dest.writeInt(nextSetBit);
}
}
/**
* The actual state class
*/
static class SavedState extends View.BaseSavedState
{
public BitSet openItems = null;
public int lastOpenPosition = -1;
SavedState(Parcelable superState)
{
super(superState);
}
private SavedState(Parcel in)
{
super(in);
lastOpenPosition = in.readInt();
openItems = readBitSet(in);
}
#Override
public void writeToParcel(Parcel out, int flags)
{
super.writeToParcel(out, flags);
out.writeInt(lastOpenPosition);
writeBitSet(out, openItems);
}
// required field that makes Parcelables from a Parcel
public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>()
{
public SavedState createFromParcel(Parcel in)
{
return new SavedState(in);
}
public SavedState[] newArray(int size)
{
return new SavedState[size];
}
};
}
public static Animation ExpandOrCollapseView(final View v, final boolean expand)
{
try
{
Method m = v.getClass().getDeclaredMethod("onMeasure", int.class, int.class);
m.setAccessible(true);
m.invoke(v, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(((View) v.getParent()).getMeasuredWidth(), MeasureSpec.AT_MOST));
}
catch (Exception e)
{
e.printStackTrace();
}
final int initialHeight = v.getMeasuredHeight();
if (expand)
{
v.getLayoutParams().height = 0;
}
else
{
v.getLayoutParams().height = initialHeight;
}
v.setVisibility(View.VISIBLE);
Animation a = new Animation()
{
#Override
protected void applyTransformation(float interpolatedTime, Transformation t)
{
int newHeight = 0;
if (expand)
{
newHeight = (int) (initialHeight * interpolatedTime);
}
else
{
newHeight = (int) (initialHeight * (1 - interpolatedTime));
}
v.getLayoutParams().height = newHeight;
v.requestLayout();
if (interpolatedTime == 1 && !expand)
v.setVisibility(View.GONE);
}
#Override
public boolean willChangeBounds()
{
return true;
}
};
a.setDuration(1000);
return a;
}}
Luckily I have found the solution. On pre-kitkat the upperView on list item which was gone does not forcelly animate but on kitkat and so on it forcelly animate from gone to visible.
So as the solution we must give a layer of view between of list item and upper view (Which we have to animate).
In this way it will work like charm.
im used this libarary https://github.com/47deg/android-swipelistview
in project im want row only swipe to left and not allow swipe rows
with wiche other and when clicked row not swipeing and open new Activity
public class Aragh extends Activity {
SwipeListView swipelistview;
ItemAdapter adapter;
List<ItemRow> itemData;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.aragh);
swipelistview=(SwipeListView)findViewById(R.id.example_swipe_lv_list);
itemData=new ArrayList<ItemRow>();
adapter=new ItemAdapter(this,R.layout.custom_row,itemData);
swipelistview.setSwipeListViewListener(new BaseSwipeListViewListener() {
#Override
public void onOpened(int position, boolean toRight) {
}
#Override
public void onClosed(int position, boolean fromRight) {
}
#Override
public void onListChanged() {
}
#Override
public void onMove(int position, float x) {
}
#Override
public void onStartOpen(int position, int action, boolean right) {
Log.d("swipe", String.format("onStartOpen %d - action %d", position, action));
}
#Override
public void onStartClose(int position, boolean right) {
Log.d("swipe", String.format("onStartClose %d", position));
}
#Override
public void onClickFrontView(int position) {
Log.d("swipe", String.format("onClickFrontView %d", position));
swipelistview.openAnimate(position); //when you touch front view it will open
}
#Override
public void onClickBackView(int position) {
Log.d("swipe", String.format("onClickBackView %d", position));
swipelistview.closeAnimate(position);//when you touch back view it will close
}
#Override
public void onDismiss(int[] reverseSortedPositions) {
}
});
//These are the swipe listview settings. you can change these
//setting as your requirement
swipelistview.setSwipeMode(SwipeListView.SWIPE_MODE_RIGHT); // there are five swiping modes
swipelistview.setSwipeActionLeft(SwipeListView.SWIPE_ACTION_DISMISS); //there are four swipe actions
swipelistview.setSwipeActionRight(SwipeListView.SWIPE_ACTION_DISMISS);
swipelistview.setOffsetLeft(convertDpToPixel(0f)); // left side offset
swipelistview.setOffsetRight(convertDpToPixel(80f)); // right side offset
swipelistview.setAnimationTime(500); // Animation time
swipelistview.setSwipeOpenOnLongPress(false); // enable or disable SwipeOpenOnLongPress
swipelistview.setAdapter(adapter);
for(int i=0;i<10;i++)
{
itemData.add(new ItemRow("Swipe Item"+i,getResources().getDrawable(R.drawable.ic_launcher) ));
}
adapter.notifyDataSetChanged();
}
public int convertDpToPixel(float dp) {
DisplayMetrics metrics = getResources().getDisplayMetrics();
float px = dp * (metrics.densityDpi / 160f);
return (int) px;
}
}
I recommend doing it in XML.
in your SwipeListView tag add
swipe:swipeMode="left"
it locks your swipe mode to the left.
you can choose - left / right / both .
You just need to put swipe:swipeMode="left" inside <....SwipeListView /> in your xml layout to allow swiping only in left direction
I am using touch listener for an imageview in the listview item .It is working fine when I just do that like an sample application(I mean I have that Listview item as an sample one). But when I put this in a listview it is really becoming very slow.
I just wants to drag the image only horizantally,for that purpose I used ConstrainedDragandDrop View class which I got from the Github.
In my sample application:
public class HorizontalScroll extends Activity {
ImageView full_left,heart;
RelativeLayout rlMainLayout,rlImages,Cartoon_image,half_left,play_btn,centre,centre_leftanimate;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.inflated_bloops);
half_left=(RelativeLayout)findViewById(R.id.half_left);
Cartoon_image=(RelativeLayout)findViewById(R.id.cartoon_image);
play_btn=(RelativeLayout)findViewById(R.id.play_btn);
heart=(ImageView)findViewById(R.id.ivheart);
ConstrainedDragAndDropView dndView = (ConstrainedDragAndDropView) findViewById(R.id.dndView);
dndView.setDragHandle(findViewById(R.id.cartoon_image),findViewById(R.id.half_left),heart);
dndView.setAllowVerticalDrag(false,HorizontalScroll.this);
}
}
When I used in my Listview:
public class Cars extends BaseAdapter
{
public View getView(int position, View convertView, ViewGroup parent)
{
View v = convertView;
LayoutInflater inflator = getLayoutInflater();
v= inflator.inflate(R.layout.inflated_bloops, null);
ConstrainedDragAndDropView dndView = (ConstrainedDragAndDropView) v.findViewById(R.id.dndView);
dndView.setDragHandle(v.findViewById(R.id.cartoon_image),v.findViewById(R.id.half_left),heart);
dndView.setAllowVerticalDrag(false,FeedModeActivity.this);
RelativeLayout Cartoon_image=(RelativeLayout)v.findViewById(R.id.cartoon_image);
ImageView ivDummy =(ImageView)v.findViewById(R.id.dummy);
try{
loader.DisplayImageRelative( al_new.get(position).replace(" ", "%20"),ivDummy, Cartoon_image);
}
catch(Exception e){
e.printStackTrace();
}
return v;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return al_new.size();
}
#Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
}
Here is my custom dragDrop view:
public class ConstrainedDragAndDropView extends LinearLayout {
Activity main;
protected View dragHandle,half,heart;
protected List<View> dropTargets = new ArrayList<View>();
protected boolean dragging = false;
protected int pointerId;
protected int selectedDropTargetIndex = -1;
protected int lastSelectedDropTargetIndex = -1;
protected int lastDroppedIndex = -1;
protected boolean allowHorizontalDrag = true;
protected boolean allowVerticalDrag = true;
protected DropListener dropListener;
public interface DropListener {
public void onDrop(final int dropIndex, final View dropTarget);
}
public ConstrainedDragAndDropView(Context context) {
super(context);
}
public ConstrainedDragAndDropView(Context context, AttributeSet attrs) {
super(context, attrs);
applyAttrs(context, attrs);
}
#SuppressLint("NewApi")
public ConstrainedDragAndDropView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
applyAttrs(context, attrs);
}
public DropListener getDropListener() {
return dropListener;
}
public void setDropListener(DropListener dropListener) {
this.dropListener = dropListener;
}
public View getDragHandle() {
return dragHandle;
}
public void setDragHandle(View dragHandle,View half_left,View heart) {
this.dragHandle = dragHandle;
this.half=half_left;
this.heart=heart;
setupDragHandle();
}
public List<View> getDropTargets() {
return dropTargets;
}
public void setDropTargets(List<View> dropTargets) {
this.dropTargets = dropTargets;
}
public void addDropTarget(View target) {
if (dropTargets == null) {
dropTargets = new ArrayList<View>();
}
dropTargets.add(target);
}
public boolean isAllowHorizontalDrag() {
return allowHorizontalDrag;
}
public void setAllowHorizontalDrag(boolean allowHorizontalDrag) {
this.allowHorizontalDrag = allowHorizontalDrag;
}
public boolean isAllowVerticalDrag() {
return allowVerticalDrag;
}
public void setAllowVerticalDrag(boolean allowVerticalDrag,Activity c) {
this.allowVerticalDrag = allowVerticalDrag;
this.main=c;
}
protected void applyAttrs(Context context, AttributeSet attrs) {
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ConstrainedDragAndDropView, 0, 0);
try {
/*
layoutId = a.getResourceId(R.styleable.ConstrainedDragAndDropView_layoutId, 0);
if (layoutId > 0) {
LayoutInflater.from(context).inflate(layoutId, this, true);
}
*/
} finally {
a.recycle();
}
}
protected void setupDragHandle() {
this.setOnTouchListener(new DragAreaTouchListener());
}
protected class DragAreaTouchListener implements OnTouchListener {
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d("Action down", "action down in listener");
onActionDown(view, motionEvent);
break;
case MotionEvent.ACTION_UP:
Log.d("Action up", "action up in listener");
onActionUp(view, motionEvent);
break;
case MotionEvent.ACTION_MOVE:
Log.d("Action move", "action move in listener");
onActionMove(view, motionEvent);
break;
default:
break;
}
return true;
}
}
public static int param;
protected void onActionDown(View view, MotionEvent motionEvent) {
// if we're not already dragging, and the touch position is on the drag handle,
// then start dragging
if(!dragging && isDragHandleTouch(motionEvent)) {
pointerId = motionEvent.getPointerId(0);
Float s1= dragHandle.getX();
param=Integer.valueOf(s1.intValue());
Log.e("param",""+param);
// updateDragPosition(motionEvent);
dragging = true;
Log.d("drag", "drag start");
}
}
protected void onActionUp(View view, MotionEvent motionEvent) {
Log.d("Action up", "action up");
// if we're dragging, then stop dragging
if (dragging && motionEvent.getPointerId(0) == pointerId) {
Log.e("condition","satisfied");
Log.e("x val"+(int)motionEvent.getX(),"y val"+(int)motionEvent.getY());
Log.e("x1"+half.getLeft(),"y1"+half.getTop());
Log.e("x4"+half.getRight(),"y4"+half.getBottom());
Float s1=motionEvent.getX();
Float s2=motionEvent.getY();
int x=Integer.valueOf(s1.intValue());
dragging = false;
int y=Integer.valueOf(s2.intValue());
if((half.getLeft()<x)&&(x<half.getRight())&&((half.getTop()<y)&&(y<half.getBottom())))
{
Log.e("drop","on target");
try {
Thread.sleep(1000);
dragHandle.setX(param);
heart.setVisibility(View.VISIBLE);
Animation pulse = AnimationUtils.loadAnimation(main, R.anim.pulse);
heart.startAnimation(pulse);
// heart.setVisibility(View.GONE);
pulse.setAnimationListener(new AnimationListener() {
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
Log.e("animation","start");
}
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
public void onAnimationEnd(Animation animation) {
// TODO Auto-generated method stub
Log.e("animation","end");
heart.setVisibility(View.GONE);
}
});
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// class SimpleThread extends Thread {
//
// public void run() {
//
// try {
// sleep(1000);
// runOnUiThread(new Runnable() {
// public void run() {
// dragHandle.setX(param);
// heart.setVisibility(View.VISIBLE);
//
// Animation pulse = AnimationUtils.loadAnimation(main, R.anim.pulse);
// heart.startAnimation(pulse);
// }
// });
//
// }
// catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
//
// }
// }
//
// new SimpleThread().start();
}
else{
Log.e("drop",""+"outside target");
dragHandle.setX(param);
// TranslateAnimation transAnimation= new TranslateAnimation(x, 300, y, 300);
// transAnimation.setDuration(1000);//set duration
// view.startAnimation(transAnimation);
}
// if()
// updateDragPosition(motionEvent);
Log.d("drag", "drag end");
// find out what drop target, if any, the drag handle was dropped on
int dropTargetIndex = findDropTargetIndexUnderDragHandle();
if(dropTargetIndex >= 0) { // if drop was on a target, select the target
Log.d("drag", "drop on target " + dropTargetIndex);
// selectDropTarget(dropTargetIndex);
// snapDragHandleToDropTarget(dropTargetIndex);
// lastDroppedIndex = dropTargetIndex;
if(dropListener != null) {
dropListener.onDrop(dropTargetIndex, dropTargets.get(dropTargetIndex));
}
} else { // if drop was not on a target, re-select the last selected target
// deselectDropTarget();
// snapDragHandleToDropTarget(lastDroppedIndex);
}
}
else{
Log.e("condition not","satisfied");
}
}
protected void onActionMove(View view, MotionEvent motionEvent) {
Log.d("Action move", "action move");
if (dragging && motionEvent.getPointerId(0) == pointerId) {
updateDragPosition(motionEvent);
int dropTargetIndex = findDropTargetIndexUnderDragHandle();
if(dropTargetIndex >= 0) {
Log.d("drag", "hover on target " + dropTargetIndex);
// selectDropTarget(dropTargetIndex);
} else {
// deselectDropTarget();
}
}
}
#SuppressLint("NewApi")
protected void updateDragPosition(MotionEvent motionEvent) {
// this is where we constrain the movement of the dragHandle
if(allowHorizontalDrag) {
float candidateX = motionEvent.getX() - dragHandle.getWidth() / 2;
if(candidateX > 0 && candidateX + dragHandle.getWidth() < this.getWidth()) {
dragHandle.setX(candidateX);
}
}
if(allowVerticalDrag) {
float candidateY = motionEvent.getY() - dragHandle.getHeight() / 2;
if(candidateY > 0 && candidateY + dragHandle.getHeight() < this.getHeight()) {
dragHandle.setY(candidateY);
}
}
}
#SuppressLint("NewApi")
protected void snapDragHandleToDropTarget(int dropTargetIndex) {
if(dropTargetIndex > -1) {
View dropTarget = dropTargets.get(dropTargetIndex);
float xCenter = dropTarget.getX() + dropTarget.getWidth() / 2;
float yCenter = dropTarget.getY() + dropTarget.getHeight() / 2;
float xOffset = dragHandle.getWidth() / 2;
float yOffset = dragHandle.getHeight() / 2;
float x = xCenter - xOffset;
float y = yCenter - yOffset;
dragHandle.setX(x);
dragHandle.setY(y);
}
}
protected boolean isDragHandleTouch(MotionEvent motionEvent) {
Point point = new Point(
new Float(motionEvent.getRawX()).intValue(),
new Float(motionEvent.getRawY()).intValue()
);
return isPointInView(point, dragHandle);
}
protected int findDropTargetIndexUnderDragHandle() {
int dropTargetIndex = -1;
for(int i = 0; i < dropTargets.size(); i++) {
if(isCollision(dragHandle, dropTargets.get(i))) {
dropTargetIndex = i;
break;
}
}
return dropTargetIndex;
}
/**
* Determines whether a raw screen coordinate is within the bounds of the specified view
* #param point - Point containing screen coordinates
* #param view - View to test
* #return true if the point is in the view, else false
*/
protected boolean isPointInView(Point point, View view) {
int[] viewPosition = new int[2];
view.getLocationOnScreen(viewPosition);
int left = viewPosition[0];
int right = left + view.getWidth();
int top = viewPosition[1];
int bottom = top + view.getHeight();
return point.x >= left && point.x <= right && point.y >= top && point.y <= bottom;
}
#SuppressLint("NewApi")
protected boolean isCollision(View view1, View view2) {
boolean collision = false;
do {
if(view1.getY() + view1.getHeight() < view2.getY()) {
break;
}
if(view1.getY() > view2.getY() + view2.getHeight()) {
break;
}
if(view1.getX() > view2.getX() + view2.getWidth()) {
break;
}
if(view1.getX() + view1.getWidth() < view2.getX()) {
break;
}
collision = true;
} while(false);
return collision;
}
protected void selectDropTarget(int index) {
if(index > -1) {
deselectDropTarget();
selectedDropTargetIndex = index;
dropTargets.get(selectedDropTargetIndex).setSelected(true);
}
}
protected void deselectDropTarget() {
if(selectedDropTargetIndex > -1) {
dropTargets.get(selectedDropTargetIndex).setSelected(false);
lastSelectedDropTargetIndex = selectedDropTargetIndex;
selectedDropTargetIndex = -1;
}
}
}
i want to create one screen for my android application in this application i want to create sliding navigation feature which is full visible on swipe (Left to Right ) and when user again swipe (RIght to Left ) it again swipe and close navigation window half and display half screen , i have used navigation drawer but i am not aware with this so please some help me if you have any code so please send me its will be my pleasure .
i am sending one image for reference where .
Find below code create a class AnimationLayout
import usb.terminal.R;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
public class AnimationLayout extends ViewGroup {
public final static int DURATION = 1000;
protected boolean mPlaceLeft = true;
public boolean mOpened;
protected View mSidebar;
protected View mContent;
protected int mSidebarWidth = 100; /*
* assign default value. It will be
* overwrite in onMeasure by Layout xml
* resource.
*/
protected Animation mAnimation;
protected OpenListener mOpenListener;
protected CloseListener mCloseListener;
protected Listener mListener;
protected boolean mPressed = false;
public AnimationLayout(Context context) {
this(context, null);
}
public AnimationLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public void onFinishInflate() {
super.onFinishInflate();
mSidebar = findViewById(R.id.animation_layout_sidebar);
mContent = findViewById(R.id.animation_layout_content);
if (mSidebar == null) {
throw new NullPointerException("no view id = animation_sidebar");
}
if (mContent == null) {
throw new NullPointerException("no view id = animation_content");
}
mOpenListener = new OpenListener(mSidebar, mContent);
mCloseListener = new CloseListener(mSidebar, mContent);
}
#Override
public void onLayout(boolean changed, int l, int t, int r, int b) {
/* the title bar assign top padding, drop it */
int sidebarLeft = l;
if (!mPlaceLeft) {
sidebarLeft = r - mSidebarWidth;
}
mSidebar.layout(sidebarLeft, 0, sidebarLeft + mSidebarWidth,
0 + mSidebar.getMeasuredHeight());
if (mOpened) {
if (mPlaceLeft) {
mContent.layout(l + mSidebarWidth, 0, r + mSidebarWidth, b);
} else {
mContent.layout(l - mSidebarWidth, 0, r - mSidebarWidth, b);
}
} else {
mContent.layout(l, 0, r, b);
}
}
#Override
public void onMeasure(int w, int h) {
super.onMeasure(w, h);
super.measureChildren(w, h);
mSidebarWidth = mSidebar.getMeasuredWidth();
}
#Override
protected void measureChild(View child, int parentWSpec, int parentHSpec) {
/* the max width of Sidebar is 90% of Parent */
if (child == mSidebar) {
int mode = MeasureSpec.getMode(parentWSpec);
int width = (int) (getMeasuredWidth() * 0.9);
super.measureChild(child, MeasureSpec.makeMeasureSpec(width, mode),
parentHSpec);
} else {
super.measureChild(child, parentWSpec, parentHSpec);
}
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (!isOpening()) {
return false;
}
int action = ev.getAction();
if (action != MotionEvent.ACTION_UP
&& action != MotionEvent.ACTION_DOWN) {
return false;
}
/*
* if user press and release both on Content while sidebar is opening,
* call listener. otherwise, pass the event to child.
*/
int x = (int) ev.getX();
int y = (int) ev.getY();
if (mContent.getLeft() < x && mContent.getRight() > x
&& mContent.getTop() < y && mContent.getBottom() > y) {
if (action == MotionEvent.ACTION_DOWN) {
mPressed = true;
}
if (mPressed && action == MotionEvent.ACTION_UP
&& mListener != null) {
mPressed = false;
return mListener.onContentTouchedWhenOpening();
}
} else {
mPressed = false;
}
return false;
}
public void setListener(Listener l) {
mListener = l;
}
/* to see if the Sidebar is visible */
public boolean isOpening() {
return mOpened;
}
public void toggleSidebar() {
if (mContent.getAnimation() != null) {
return;
}
if (mOpened) {
/* opened, make close animation */
if (mPlaceLeft) {
mAnimation = new TranslateAnimation(0, -mSidebarWidth, 0, 0);
} else {
mAnimation = new TranslateAnimation(0, mSidebarWidth, 0, 0);
}
mAnimation.setAnimationListener(mCloseListener);
} else {
/* not opened, make open animation */
if (mPlaceLeft) {
mAnimation = new TranslateAnimation(0, mSidebarWidth, 0, 0);
} else {
mAnimation = new TranslateAnimation(0, -mSidebarWidth, 0, 0);
}
mAnimation.setAnimationListener(mOpenListener);
}
mAnimation.setDuration(DURATION);
mAnimation.setFillAfter(true);
mAnimation.setFillEnabled(true);
mContent.startAnimation(mAnimation);
}
public void openSidebar() {
if (!mOpened) {
toggleSidebar();
}
}
public void closeSidebar() {
if (mOpened) {
toggleSidebar();
}
}
class OpenListener implements Animation.AnimationListener {
View iSidebar;
View iContent;
OpenListener(View sidebar, View content) {
iSidebar = sidebar;
iContent = content;
}
public void onAnimationRepeat(Animation animation) {
}
public void onAnimationStart(Animation animation) {
iSidebar.setVisibility(View.VISIBLE);
}
public void onAnimationEnd(Animation animation) {
iContent.clearAnimation();
mOpened = !mOpened;
requestLayout();
if (mListener != null) {
mListener.onSidebarOpened();
}
}
}
class CloseListener implements Animation.AnimationListener {
View iSidebar;
View iContent;
CloseListener(View sidebar, View content) {
iSidebar = sidebar;
iContent = content;
}
public void onAnimationRepeat(Animation animation) {
}
public void onAnimationStart(Animation animation) {
}
public void onAnimationEnd(Animation animation) {
iContent.clearAnimation();
iSidebar.setVisibility(View.INVISIBLE);
mOpened = !mOpened;
requestLayout();
if (mListener != null) {
mListener.onSidebarClosed();
}
}
}
public interface Listener {
public void onSidebarOpened();
public void onSidebarClosed();
public boolean onContentTouchedWhenOpening();
}
}
create a mainlayout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<yourpackage..AnimationLayout
android:id="#+id/animation_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!--Create you Layout which you want and just call in this include-->
<include
android:id="#id/animation_layout_sidebar"
android:layout_width="470dp"
android:layout_height="match_parent"
layout="#layout/my_cook_menu"
android:orientation="vertical" >
</include>
<!--Create you Layout which you want and just call in this include-->
<include
android:id="#id/animation_layout_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
layout="#layout/sound_my_cook"
android:clickable="true"
android:focusable="true"
android:orientation="vertical" >
</include>
</yourpackage.AnimationLayout>
</RelativeLayout>
</RelativeLayout>
create id.xml in values folder
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item type="id" name="animation_layout_sidebar" />
<item type="id" name="animation_layout_content" />
</resources>
write this code in which activity you are calling
public class MainActivity extends Activity implements
AnimationLayout.Listener, OnClickListener{
AnimationDrawable frameAnimation;
AnimationLayout animationLayout;
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.mainlayout);
}
public void onClick(View v) {
try {
animationLayout = (AnimationLayout) findViewById(R.id.animation_layout);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
animationLayout.toggleSidebar();
}
#Override
public void onSidebarOpened() {
// TODO Auto-generated method stub
}
#Override
public void onSidebarClosed() {
// TODO Auto-generated method stub
}
#Override
public boolean onContentTouchedWhenOpening() {
// TODO Auto-generated method stub
return false;
}
}
I haven't tried it yet but I think DrawerLayout recently added to support library could give you what you need. Here is the link for documentation. This is something what Facebook app is using to slide a pannel from left to right. Here is the tutorial.
I am using PagerAdapter for horizontal swiping for showing newspaper pages in my app.
Currently I want to implement the circular scrolling in this app.Right now what I have done is whenever I am getting on last page I try to set the currentItem to first pagei.e that functionality working for last page to first page,but the problem is that how can I go to last page from first page.
Here I am pasting my code related to pagerAdapter & onPageChangeListener:-
awesomeAdapter = new AwesomePagerAdapter(awesomePager);
awesomePager.setAdapter(awesomeAdapter);
awesomePager.setPageMargin(10);
awesomePager.setOnPageChangeListener(new OnPageChangeListener() {
int lastPosition;
float posOffset = 0;
#Override
public void onPageSelected(int position) {
viewerPage = position;
CommonLogic.logMessage("Viewer Page:- "+ viewerPage, TAG, Log.VERBOSE);
posOffset = 0;
}
#Override
public void onPageScrolled(int position,float positionOffset,int positionOffsetPixels) {
if (positionOffset == 0 && positionOffsetPixels == 0 && position != 0) {
lastPosition = position;
}
posOffset -= positionOffset;
CommonLogic.logMessage(" Position:- "
+ position + " Position Offset:- " + positionOffset
+ " Position Offset Variable:- "
+ posOffset
+ " Position Offset Pixels:- "
+ positionOffsetPixels
+ " Last Position " + lastPosition,
TAG, Log.VERBOSE);
CommonLogic.logMessage(" Last Position "
+ lastPosition, TAG, Log.VERBOSE);
}
#Override
public void onPageScrollStateChanged(int state) {
// To Detect the Last Page & This Sets it to first page.This working fine.
if (state == ViewPager.SCROLL_STATE_DRAGGING && viewerPage == (uris.size() - 1)) {
CommonLogic.logMessage("Scroll State Changed ", TAG,Log.VERBOSE);
postDelayed(new Runnable() {
#Override
public void run() {
awesomePager.setCurrentItem(0, true);
}
}, 200);
}
// I have also used this to detect whether the user is on first & try to move on last page,but it is not working well.
else if (state == ViewPager.SCROLL_STATE_DRAGGING && (lastPosition == 0 || lastPosition == (uris.size() - 1)) && viewerPage == 0 && posOffset <= 0) {
CommonLogic.logMessage( "Scroll State Changed ", TAG,Log.VERBOSE);
postDelayed(new Runnable() {
#Override
public void run() {
awesomePager.setCurrentItem((uris.size() - 1), true);
}
}, 200);
}
}
}
});
Also the PagerAdapter i.e AwesomweAdapter in my case,is also as folllows:-
private class AwesomePagerAdapter extends PagerAdapter {
ViewPager pdfContainer;
DocumentNewView documentNewView;
CustomViewPager customViewPager;
public AwesomePagerAdapter(CustomViewPager awesomePager) {
this.customViewPager = awesomePager;
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public int getCount() {
return uris.size();
}
public DocumentNewView addViewAt(int position, DocumentNewView mainView) {
CommonLogic.logMessage("Position of View:- " + position, TAG,
Log.VERBOSE);
pdfContainer.addView(mainView);
return mainView;
}
/**
* Create the page for the given position. The adapter is responsible
* for adding the view to the container given here, although it only
* must ensure this is done by the time it returns from
* {#link #finishUpdate()}.
*
* #param container
* The containing View in which the page will be shown.
* #param position
* The page position to be instantiated.
* #return Returns an Object representing the new page. This does not
* need to be a View, but can be some other container of the
* page.
*/
#Override
public Object instantiateItem(View collection, int position) {
CommonLogic
.logMessage("Instantiate Item Called ", TAG, Log.VERBOSE);
documentNewView = new DocumentNewView(cxt, display, customViewPager);
documentNewView.setPdfContext(new PdfContext());
CodecDocument codecDocument = documentNewView.open(uris
.get(position));
documentNewView.renderDocument(codecDocument);
documentNewView.setMaxZoom(4f);
documentNewView.setVerticalScrollBarEnabled(true);
codecDocument = null;
this.pdfContainer = (ViewPager) collection;
return addViewAt(position, documentNewView);
}
/**
* Remove a page for the given position. The adapter is responsible for
* removing the view from its container, although it only must ensure
* this is done by the time it returns from {#link #finishUpdate()}.
*
* #param container
* The containing View from which the page will be removed.
* #param position
* The page position to be removed.
* #param object
* The same object that was returned by
* {#link #instantiateItem(View, int)}.
*/
#Override
public void destroyItem(View collection, int position, Object view) {
pdfContainer.removeView((DocumentNewView) view);
}
/**
* Called when the a change in the shown pages has been completed. At
* this point you must ensure that all of the pages have actually been
* added or removed from the container as appropriate.
*
* #param container
* The containing View which is displaying this adapter's
* page views.
*/
#Override
public void finishUpdate(View arg0) {
CommonLogic.logMessage("Finish Update Called ", TAG, Log.VERBOSE);
}
#Override
public void restoreState(Parcelable arg0, ClassLoader arg1) {
}
#Override
public Parcelable saveState() {
return null;
}
#Override
public void startUpdate(View arg0) {
CommonLogic.logMessage("State Update Called ", TAG, Log.VERBOSE);
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == ((DocumentNewView) object);
}
Please give me any suggestions/changes in my code (if applicable) for it.
Thanks in Advance.
I could achieve this by overriding onPageSelected method of OnPageChangeListener. Consider you have three pages in this order A<->B<->C. To goal is to reach C if we scroll right from A and similarly to reach A if we scroll left from C.
To do this, define your to have 5 pages (3+2), and organize the pages as follows:
C<->A<->B<->C<->A
Now in the onPageSelected method, check and if position if 0, change it to 3 (getCount()-2) and if position is 4 (getCount()-1), change it to 1. Make sure to use the method:
setCurrentItem(item, smoothScroll)
Here is complete code for CircularPagerAdaptor Class :
package zolender.adapters;
import android.content.Context;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.LayoutInflater;
import android.view.View;
public class CircularPagerAdapter extends PagerAdapter{
private int[] pageIDsArray;
private int count;
public CircularPagerAdapter(final ViewPager pager, int... pageIDs) {
super();
int actualNoOfIDs = pageIDs.length;
count = actualNoOfIDs + 2;
pageIDsArray = new int[count];
for (int i = 0; i < actualNoOfIDs; i++) {
pageIDsArray[i + 1] = pageIDs[i];
}
pageIDsArray[0] = pageIDs[actualNoOfIDs - 1];
pageIDsArray[count - 1] = pageIDs[0];
pager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
int pageCount = getCount();
if (position == 0){
pager.setCurrentItem(pageCount-2,false);
} else if (position == pageCount-1){
pager.setCurrentItem(1,false);
}
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// TODO Auto-generated method stub
}
#Override
public void onPageScrollStateChanged(int state) {
// TODO Auto-generated method stub
}
});
}
public int getCount() {
return count;
}
public Object instantiateItem(View container, int position) {
LayoutInflater inflater = (LayoutInflater) container.getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
int pageId = pageIDsArray[position];
View view = inflater.inflate(pageId, null);
((ViewPager) container).addView(view, 0);
return view;
}
#Override
public void destroyItem(View container, int position, Object object) {
((ViewPager) container).removeView((View) object);
}
#Override
public void finishUpdate(View container) {
// TODO Auto-generated method stub
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == ((View) object);
}
#Override
public void restoreState(Parcelable state, ClassLoader loader) {
// TODO Auto-generated method stub
}
#Override
public Parcelable saveState() {
// TODO Auto-generated method stub
return null;
}
#Override
public void startUpdate(View container) {
// TODO Auto-generated method stub
}
}
And here is how you can use it:
myPager = (ViewPager) findViewById(R.id.myfivepanelpager);
PagerAdapter adapter = new CircularPagerAdapter(myPager, new int[]{R.layout.farleft, R.layout.left, R.layout.middle, R.layout.right, R.layout.farright});
myPager.setAdapter(adapter);
myPager.setCurrentItem(3);
I also needed a circular ViewPager. This is what I've done. I assume you get pageCount value from somewhere.
...
pager = (ViewPager) findViewById(R.id.pager);
//Gesture detection
final GestureDetector gestureDetector = new GestureDetector(new MyGestureDetector());
pager.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
});
//pagelistener is just for getting selected page
pager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
selectedPage = position;
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
and here is the GestureDetector.
Copied from here
class MyGestureDetector extends SimpleOnGestureListener {
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
int SWIPE_MIN_DISTANCE = Utils.ConvertToPixel(mContext, 50);
int SWIPE_MAX_OFF_PATH = Utils.ConvertToPixel(mContext, 250);
int SWIPE_THRESHOLD_VELOCITY = Utils.ConvertToPixel(mContext, 200);
try {
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return false;
// right to left swipe
if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY
&& selectedPage == (pageCount - 1)) {
pager.setCurrentItem(0);
return true;
} else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY
&& selectedPage == 0) {
pager.setCurrentItem(pageCount - 1);
return true;
}
} catch (Exception e) {
// nothing
}
return false;
}
}
Expanding on Z0lenDer's answer, when using a regular ViewPager where you don't need to free the memory for each associated view, it's more efficient to store the created views rather than the layout IDs. This is necessary if wanting to get rid of any delay and flicker when the item is being switched.
There's also an issue with the animation when using onPageSelected, as it doesn't let the slide finish before doing the switch. The only way I found to avoid this is to only perform the switch once the scroll state has changed to SCROLL_STATE_IDLE and just setting the current item in onPageSelected.
private int currentPage = 0;
...
pager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
currentPage = position;
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageScrollStateChanged(int state) {
// TODO Auto-generated method stub
Log.d(TAG, "onPageScrollStateChanged: " + state);
if (state == ViewPager.SCROLL_STATE_IDLE) {
int pageCount = getCount();
if (currentPage == 0){
pager.setCurrentItem(pageCount-2,false);
} else if (currentPage == pageCount-1){
pager.setCurrentItem(1,false);
}
}
}
});
Try this
((ViewPager) container)
.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
Log.i("TAG", "pos::" + position);
}
#Override
public void onPageScrollStateChanged(int state) {
// TODO Auto-generated method stub
int currentPage = pager.getCurrentItem();
Log.i("TAG", "currentPage::" + currentPage);
Log.i("TAG", "currentState::" + currentState);
Log.i("TAG", "previousState::" + previousState);
if (currentPage == 4 || currentPage == 0) {
previousState = currentState;
currentState = state;
if (previousState == 1 && currentState == 0) {
pager.setCurrentItem(currentPage == 0 ? 4 : 0);
}
}
}
#Override
public void onPageScrolled(int arg0, float arg1,
int arg2) {
// TODO Auto-generated method stub
}
});
return
This should be placed inside
#Override
public Object instantiateItem(final View container, int position) {}
I used it this way,
fragment layouts in adapter 0>1>2>3>4>5,
0 & 5 are dummy
viewPager.setAdapter(adapter);
viewPager.setCurrentItem(1, false); //going to page 1;
final int[] pagePosition = new int[1];
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
pagePosition[0] = position;
}
#Override
public void onPageScrollStateChanged(int state) { //state changes from 2 to 0 during a swipe
if (state == 0 && pagePosition[0] == 0){
viewPager.setCurrentItem(4, false);
} else if (state == 0 && pagePosition[0] == 5){
viewPager.setCurrentItem(1, false);
}
}
});
Well this helped
private class CircularViewPagerHandler implements ViewPager.OnPageChangeListener {
private ViewPager mViewPager;
private int mCurrentPosition;
private int mScrollState;
private int mPreviousPosition;
public CircularViewPagerHandler(final ViewPager viewPager) {
mViewPager = viewPager;
}
#Override
public void onPageSelected(final int position) {
mCurrentPosition = position;
mPreviousPosition = position-1;
}
#Override
public void onPageScrollStateChanged(final int state) {
if (state == ViewPager.SCROLL_STATE_IDLE) {
setNextItemIfNeeded();
}
mScrollState = state;
}
private void setNextItemIfNeeded() {
if (!isScrollStateSettling()) {
handleSetNextItem();
}
}
private boolean isScrollStateSettling() {
return mScrollState == ViewPager.SCROLL_STATE_SETTLING; //indicated page is settling to it's final position
}
private void handleSetNextItem() {
final int lastPosition = mViewPager.getAdapter().getCount() - 1;
if (mCurrentPosition == 0) {
mViewPager.setCurrentItem(lastPosition,false);
} else if (mCurrentPosition == lastPosition) {
mViewPager.setCurrentItem(0, false);
}
}
#Override
public void onPageScrolled(final int position, final float positionOffset, final int positionOffsetPixels) {
}
}
It was #tobi_b's answer