This library provides advance views for lists and stacks. Some of the views are build on top of RecyclerView and others are written in their own. Annotations are compiled by annotation processor to generate bind classes. DOCS -->
@Layout
along with the generated classes required by the libraryA new annotation @Keep
is added for the purpose of keeping the class and its methods when minify is enabled. This was required by the library so to reference the generated classes for the item views.
This annotations as a by product can be utilised by the client code to prevent any class from being obfuscated.
@Recycle
Addition To PlaceHolderViewIt will provide the callback to the ViewItem when the ViewHolder containing that ViewItem is recycled. It can then be used to clean up views and data.
Example:
@Layout(R.layout.row_user)
public class UserDetailView {
@View(R.id.et_user_name)
private EditText etUserName;
private User user;
private TextWatcher textWatcher;
public UserDetailView(User user){
this.user = user;
textWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int pos, int i1, int i2) {
if (charSequence.toString().length() > 0) {
user.setName(charSequence.toString())
}
}
@Override
public void afterTextChanged(Editable editable) {
}
};
}
@Resolve
private void onResolved() {
etUserName.setText(user.getName());
etUserName.addTextChangedListener(textWatcher);
}
@Recycle
private void onRecycle() {
etUserName.removeTextChangedListener(textWatcher);
}
}
The EditText in Android don't allow to remove TextChangedListener if TextWatcher instance is not known. Thus when ViewHolder is recycled then it leads to addition of multiple listeners and causes unpredictable behavior.
setTextChangedListener
and removeTextChangedListener
. etUserName.setTextChangedListener(new RecyclableEditText.OnTextChangeListener() {
@Override
public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
// Do something
}
});
Now we can apply sort to the views added to the PlaceHolderView
. This will refresh the views with new sort order.
Example: If the View Items added to the PlaceHolderView
is of class ItemView
, then we have to supply a Comparator
that defines the comparison between the itemView objects. Here the itemView's title string is being compared for the sorting.
NOTE: Check item1 and item2 are of type ItemView for this example. This is required because any type of View Item class can be added into the PlaceHolderView
placeHolderView.sort(new Comparator<Object>() {
@Override
public int compare(Object item1, Object item2) {
if (item1 instanceof ItemView && item2 instanceof ItemView) {
ItemView view1 = (ItemView) item1;
ItemView view2 = (ItemView) item2;
return view1.getTitle().compareTo(view2.getTitle());
}
return 0;
}
});
SwipePlaceHolderView
will now provide SwipeHead
annotation for callback when a card comes on top of the stack.
@SwipeHead
private void onSwipeHeadCard() {
// do something when the card comes on the top
}
Example: In the below example link, the cards below the top card are blurred and when a card come on the top then it's blur removed. Link: TinderCard
The child views were getting added in reverse order and hence it is fixed now.
setSwipeMaxChangeAngle
method has been added to the SwipeDecor
that defines the maximum angle change allowed for subsequent card movement while swiping.
For allowing only up to 1 degree rotation increment (default is 2 degrees) keep it smaller for smoother animation.
swipeDecor().setSwipeMaxChangeAngle(1f)
For smooth transition of card rotation keep setHeightSwipeDistFactor
and setWidthSwipeDistFactor
smaller and setSwipeMaxChangeAngle
less than 2 degrees(default).
mSwipeView.getBuilder()
.setHeightSwipeDistFactor(8)
.setWidthSwipeDistFactor(4)
0.7.0 version provides SwipeDirectionalView
class, which is build on top of SwipePlaceHolderView
. This View provides more refines directional callbacks for the swipes. All the properties of SwipePlaceHolderView is available to SwipeDirectionalView.
Usage:
<com.mindorks.placeholderview.SwipeDirectionalView
android:id="@+id/swipeView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
private SwipeDirectionalView mSwipeView;
...
mSwipeView.getBuilder()
.setSwipeVerticalThreshold(Utils.dpToPx(50))
.setSwipeHorizontalThreshold(Utils.dpToPx(50))
...
setSwipeVerticalThreshold
: It defines the vertical area from the initial touch location.
setSwipeHorizontalThreshold
: It defines the horizontal area from the initial touch location.
If the swipe take place within these areas then it will be considered for TOP, BOTTOM, LEFT or RIGHT direction swipe else the direction will be RIGHT_TOP, RIGHT_BOTTOM, LEFT_TOP or LEFT_BOTTOM
For receiving the directional callbacks for SwipeDirectionalView
, new Annotations has been added:
@SwipeOutDirectional
: It is called when the card is either left swiped or top swiped. @SwipeOutDirectional
private void onSwipeOutDirectional(SwipeDirection direction) {
Log.d("DEBUG", "SwipeOutDirectional " + direction.name());
}
@SwipeInDirectional
: It is called when the card is either right swiped or bottom swiped. @SwipeInDirectional
private void onSwipeInDirectional(SwipeDirection direction) {
Log.d("DEBUG", "SwipeInDirectional " + direction.name());
}
@SwipingDirection
: It is called when the card is swiping in some direction. @SwipingDirection
private void onSwipingDirection(SwipeDirection direction) {
Log.d("DEBUG", "SwipingDirection " + direction.name());
}
Refer to this demo example to understand it's usage: Link
SwipeTouch
CallbackThis callback is added to SwipePlaceHolderView
. It provides the starting and current touch point's coordinates on the card while it is getting swiped.
@SwipeTouch
private void onSwipeTouch(float xStart, float yStart, float xCurrent, float yCurrent) {
Log.d("DEBUG", "onSwipeTouch "
+ " xStart : " + xStart
+ " yStart : " + yStart
+ " xCurrent : " + xCurrent
+ " yCurrent : " + yCurrent
+ " distance : "
+ Math.sqrt(Math.pow(xCurrent - xStart, 2) + (Math.pow(yCurrent - yStart, 2)))
);
}
SwipePlaceHolderView
with Animation.The mSwipeView.undoLastSwipe();
will now put back the swiped card back into the stack by making a reverse animation.
ExpandablePlaceHolderView
// These will expand the desired parent
public <T> void expand(T resolver) throws Resources.NotFoundException
public void expand(int position) throws Resources.NotFoundException
// These will collapse the desired parent
public <T> void collapse(T resolver) throws Resources.NotFoundException
public void collapse(int position) throws Resources.NotFoundException
// This will collapse all the expanded parents
public void collapseAll()
//Example
@OnClick(R.id.collapse)
void onCollapse() {
try {
mExpandableView.collapse(parentItem);
//mExpandableView.collapse(0);
} catch (Resources.NotFoundException e) {
e.printStackTrace();
}
}
getAllResolvers() has been added to the SwipePlaceHolderView. This method will give the list of all the currently added and reserved views in the SwipePlaceHolderView.
Example:
for(Object view : mSwipeView.getAllResolvers()){
// do with the added view objects
}
SwipePlaceHolderView
will now accept ItemRemovedListener
. It will listen to the itemView remove events. onItemRemoved
method will be called with the count of the current items in the view list after the view removal.
mSwipePlaceHolderView.addItemRemoveListener(new ItemRemovedListener() {
@Override
public void onItemRemoved(int count) {
//do something when the count changes to some specific value.
//For Example: Call server to fetch more data when count is zero
}
});
RecyclerView is updated to 25.+
com.android.support:recyclerview-v7:25.+
SwipePlaceHolderView can now remove all its child views to reset its empty state using:
mSwipePlaceHolderView.removeAllViews();
mSwipePlaceHolderView.deActivatePutBack()
is renamed to mSwipePlaceHolderView.deactivatePutBack()
This version adds two method to enable/disable swiping on touch. The programmatic swipe will still be enabled.
mSwipePlaceHolderView.disableTouchSwipe();
mSwipePlaceHolderView.enableTouchSwipe();