处理ExpandableListView
并使用SwipetoDismissNOA来检测元素上的滑动手势listView
,我想自定义此代码,因此当我对子元素执行滑动操作时 - (它们FrameLayout
内部有两个布局) -上面的视图只是走出屏幕和下方视图按钮变为可见,并通过向上方视图的其他方向滑动再次返回。
你们能帮帮我吗?
处理ExpandableListView
并使用SwipetoDismissNOA来检测元素上的滑动手势listView
,我想自定义此代码,因此当我对子元素执行滑动操作时 - (它们FrameLayout
内部有两个布局) -上面的视图只是走出屏幕和下方视图按钮变为可见,并通过向上方视图的其他方向滑动再次返回。
你们能帮帮我吗?
我会根据需要以某种方式对其进行更改,因此希望它也对您有用。
我将它与列表片段一起使用,您可以使用您想要的方式。
package com.example.android.swipedismiss;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.ListFragment;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class fragmentActivity extends FragmentActivity {
// static ArrayAdapter<String> mAdapter;
private static final int SWIPE_MIN_DISTANCE = 120;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
private GestureDetector gestureDetector;
View.OnTouchListener gestureListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gestureDetector = new GestureDetector(this, new MyGestureDetector());
gestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
};
FragmentManager fm = getSupportFragmentManager();
if (fm.findFragmentById(android.R.id.content) == null) {
MyListFragment1 list = new MyListFragment1();
fm.beginTransaction().add(android.R.id.content, list).commit();
}
}
public static class MyListFragment1 extends ListFragment {
public class MyListAdapter extends BaseAdapter {
String[] month;
Context myContext;
int ints = -1;
public void remove(int position) {
// TODO Auto-generated method stub
// getItem(get)
if (ints == -1) {
ints = position;
} else if (position != ints) {
ints = position;
} else {
ints = -1;
}
myListAdapter.notifyDataSetChanged();
}
private void permanentDelete(int position) {
List<String> list = new ArrayList<String>(Arrays.asList(month));
list.remove(position);
month = list.toArray(new String[0]);
myListAdapter.notifyDataSetChanged();
}
public MyListAdapter(Context context, int textViewResourceId, String[] objects) {
super();
month = objects;
myContext = context;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Log.e("getView", "Here " + month[position]);
LayoutInflater inflater = (LayoutInflater) myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = null;
// for (int i = 0; i < month.length; i++) {
if (position != ints) {
row = inflater.inflate(R.layout.row, parent, false);
TextView label = (TextView) row.findViewById(R.id.month);
label.setText(month[position]);
ImageView icon = (ImageView) row.findViewById(R.id.icon);
// Customize your icon here
icon.setImageResource(R.drawable.icon);
} else {
row = inflater.inflate(R.layout.after_swipe, parent, false);
Button undo = (Button) row.findViewById(R.id.undo);
Button action1 = (Button) row.findViewById(R.id.action_one);
Button action2 = (Button) row.findViewById(R.id.action_two);
undo.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
ints = -1;
myListAdapter.notifyDataSetChanged();
}
});
action1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(getActivity().getApplicationContext(), "In Action 1", Toast.LENGTH_SHORT).show();
}
});
action2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(getActivity().getApplicationContext(), "In Action 2", Toast.LENGTH_SHORT).show();
}
});
}
// }
Log.e("Selected Item", "Item" + ints);
return row;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return month.length;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public long getItemId(int position) {
return position;
}
}
String[] month = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
MyListAdapter myListAdapter;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
ListView listView = getListView();
SwipeDismissListViewTouchListener touchListener = new SwipeDismissListViewTouchListener(listView, new SwipeDismissListViewTouchListener.OnDismissCallback() {
@Override
public void onDismiss(ListView listView, int[] reverseSortedPositions) {
for (int position : reverseSortedPositions) {
Log.e("Hello", "Hello");
myListAdapter.remove(position);
}
myListAdapter.notifyDataSetChanged();
}
});
listView.setOnTouchListener(touchListener);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/*
* ListAdapter myListAdapter = new ArrayAdapter<String>( getActivity(), android.R.layout.simple_list_item_1, month); setListAdapter(myListAdapter);
*/
myListAdapter = new MyListAdapter(getActivity(), R.layout.row, month);
setListAdapter(myListAdapter);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.listfragment1, container, false);
}
@Override
public void onListItemClick(ListView listView, View v, int position, long id) {
// Toast.makeText(getActivity(), getListView().getItemAtPosition(position).toString(), Toast.LENGTH_LONG).show();
//
// SwipeDismissListViewTouchListener touchListener = new SwipeDismissListViewTouchListener(listView, new SwipeDismissListViewTouchListener.OnDismissCallback() {
// @Override
// public void onDismiss(ListView listView, int[] reverseSortedPositions) {
// for (int position : reverseSortedPositions) {
// Log.e("Hello", "Hello");
// myListAdapter.remove(position);
// }
// myListAdapter.notifyDataSetChanged();
// }
// });
// listView.setOnTouchListener(touchListener);
}
}
class MyGestureDetector extends SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Log.e("There", "There");
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) {
Toast.makeText(fragmentActivity.this, "Left Swipe", Toast.LENGTH_SHORT).show();
} else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
Toast.makeText(fragmentActivity.this, "Right Swipe", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
// nothing
}
return false;
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}
}
}
这是 SwipeDismissListViewTouchListener。
// THIS IS A BETA! I DON'T RECOMMEND USING IT IN PRODUCTION CODE JUST YET
/*
* Copyright 2012 Roman Nurik
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.swipedismiss;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ListView;
import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.AnimatorListenerAdapter;
import com.nineoldandroids.animation.ValueAnimator;
import com.pepperpk.eventi.ui.adapter.AttendeesListAdapter;
import com.pepperpk.eventi.ui.fragment.AttendeesInnerFragment;
import com.pepperpk.eventi.ui.fragment.AttendeesListFragment;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static com.nineoldandroids.view.ViewHelper.setAlpha;
import static com.nineoldandroids.view.ViewHelper.setTranslationX;
import static com.nineoldandroids.view.ViewPropertyAnimator.animate;
public class SwipeDismissListViewTouchListener implements View.OnTouchListener {
// Cached ViewConfiguration and system-wide constant values
private int mSlop;
private int mMinFlingVelocity;
private int mMaxFlingVelocity;
private long mAnimationTime;
// Fixed properties
private ListView mListView;
private OnDismissCallback mCallback;
private int mViewWidth = 1; // 1 and not 0 to prevent dividing by zero
// Transient properties
private List<PendingDismissData> mPendingDismisses = new ArrayList<PendingDismissData>();
private int mDismissAnimationRefCount = 0;
private float mDownX;
private boolean mSwiping;
private VelocityTracker mVelocityTracker;
private int mDownPosition;
private View mDownView;
private boolean mPaused;
int selectedPosition;
/**
* The callback interface used by {@link SwipeDismissListViewTouchListener} to inform its client about a successful dismissal of one or more list item positions.
*/
public interface OnDismissCallback {
/**
* Called when the user has indicated they she would like to dismiss one or more list item positions.
*
* @param listView
* The originating {@link ListView}.
* @param reverseSortedPositions
* An array of positions to dismiss, sorted in descending order for convenience.
*/
void onDismiss(ListView listView, int[] reverseSortedPositions);
}
/**
* Constructs a new swipe-to-dismiss touch listener for the given list view.
*
* @param listView
* The list view whose items should be dismissable.
* @param callback
* The callback to trigger when the user has indicated that she would like to dismiss one or more list items.
*/
public SwipeDismissListViewTouchListener(ListView listView, OnDismissCallback callback) {
ViewConfiguration vc = ViewConfiguration.get(listView.getContext());
mSlop = vc.getScaledTouchSlop();
mMinFlingVelocity = vc.getScaledMinimumFlingVelocity();
mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity();
mAnimationTime = listView.getContext().getResources().getInteger(android.R.integer.config_shortAnimTime);
mListView = listView;
mCallback = callback;
}
/**
* Enables or disables (pauses or resumes) watching for swipe-to-dismiss gestures.
*
* @param enabled
* Whether or not to watch for gestures.
*/
public void setEnabled(boolean enabled) {
mPaused = !enabled;
}
/**
* Returns an {@link android.widget.AbsListView.OnScrollListener} to be added to the {@link ListView} using {@link ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener)}. If a scroll listener is already assigned, the caller should still pass scroll changes through to this
* listener. This will ensure that this {@link SwipeDismissListViewTouchListener} is paused during list view scrolling.</p>
*
* @see {@link SwipeDismissListViewTouchListener}
*/
public AbsListView.OnScrollListener makeScrollListener() {
return new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView absListView, int scrollState) {
setEnabled(scrollState != AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
}
@Override
public void onScroll(AbsListView absListView, int i, int i1, int i2) {
}
};
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (mViewWidth < 2) {
mViewWidth = mListView.getWidth();
}
switch (motionEvent.getActionMasked()) {
case MotionEvent.ACTION_DOWN: {
if (mPaused) {
return false;
}
// TODO: ensure this is a finger, and set a flag
// Find the child view that was touched (perform a hit test)
Rect rect = new Rect();
int childCount = mListView.getChildCount();
int[] listViewCoords = new int[2];
mListView.getLocationOnScreen(listViewCoords);
int x = (int) motionEvent.getRawX() - listViewCoords[0];
int y = (int) motionEvent.getRawY() - listViewCoords[1];
View child;
for (int i = 0; i < childCount; i++) {
child = mListView.getChildAt(i);
child.getHitRect(rect);
if (rect.contains(x, y)) {
mDownView = child;
break;
}
}
if (mDownView != null) {
mDownX = motionEvent.getRawX();
mDownPosition = mListView.getPositionForView(mDownView);
mVelocityTracker = VelocityTracker.obtain();
mVelocityTracker.addMovement(motionEvent);
}
view.onTouchEvent(motionEvent);
return true;
}
case MotionEvent.ACTION_UP: {
if (mVelocityTracker == null) {
break;
}
float deltaX = motionEvent.getRawX() - mDownX;
mVelocityTracker.addMovement(motionEvent);
mVelocityTracker.computeCurrentVelocity(1000);
float velocityX = Math.abs(mVelocityTracker.getXVelocity());
float velocityY = Math.abs(mVelocityTracker.getYVelocity());
boolean dismiss = false;
boolean dismissRight = false;
if (Math.abs(deltaX) > mViewWidth / 2) {
dismiss = true;
dismissRight = deltaX > 0;
} else if (mMinFlingVelocity <= velocityX && velocityX <= mMaxFlingVelocity && velocityY < velocityX) {
dismiss = true;
dismissRight = mVelocityTracker.getXVelocity() > 0;
}
if (dismiss) {
if (dismissRight) {
Log.e("Right", "Right");
} else {
Log.e("Left", "Left");
}
// dismiss
final View downView = mDownView; // mDownView gets null'd before animation ends
final int downPosition = mDownPosition;
++mDismissAnimationRefCount;
animate(mDownView).translationX(dismissRight ? mViewWidth : -mViewWidth).alpha(0).setDuration(mAnimationTime).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
performDismiss(downView, downPosition);
Log.e("Here i am", "Here i am");
}
});
} else {
// cancel
Log.e("Here i am else", "Here i am else");
animate(mDownView).translationX(0).alpha(1).setDuration(mAnimationTime).setListener(null);
((AttendeesListAdapter)mListView.getAdapter()).onClick(selectedPosition);
}
mVelocityTracker = null;
mDownX = 0;
mDownView = null;
mDownPosition = ListView.INVALID_POSITION;
mSwiping = false;
break;
}
case MotionEvent.ACTION_MOVE: {
if (mVelocityTracker == null || mPaused) {
break;
}
mVelocityTracker.addMovement(motionEvent);
float deltaX = motionEvent.getRawX() - mDownX;
if (Math.abs(deltaX) > mSlop) {
mSwiping = true;
mListView.requestDisallowInterceptTouchEvent(true);
// Cancel ListView's touch (un-highlighting the item)
MotionEvent cancelEvent = MotionEvent.obtain(motionEvent);
cancelEvent.setAction(MotionEvent.ACTION_CANCEL | (motionEvent.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
mListView.onTouchEvent(cancelEvent);
}
if (mSwiping) {
setTranslationX(mDownView, deltaX);
setAlpha(mDownView, Math.max(0f, Math.min(1f, 1f - 2f * Math.abs(deltaX) / mViewWidth)));
return true;
}
break;
}
}
return false;
}
class PendingDismissData implements Comparable<PendingDismissData> {
public int position;
public View view;
public PendingDismissData(int position, View view) {
this.position = position;
this.view = view;
}
@Override
public int compareTo(PendingDismissData other) {
// Sort by descending position
return other.position - position;
}
}
private void performDismiss(final View dismissView, final int dismissPosition) {
// Animate the dismissed list item to zero-height and fire the dismiss callback when
// all dismissed list item animations have completed. This triggers layout on each animation
// frame; in the future we may want to do something smarter and more performant.
final ViewGroup.LayoutParams lp = dismissView.getLayoutParams();
final int originalHeight = dismissView.getHeight();
ValueAnimator animator = ValueAnimator.ofInt(originalHeight, 1).setDuration(mAnimationTime);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
--mDismissAnimationRefCount;
if (mDismissAnimationRefCount == 0) {
// No active animations, process all pending dismisses.
// Sort by descending position
Collections.sort(mPendingDismisses);
int[] dismissPositions = new int[mPendingDismisses.size()];
for (int i = mPendingDismisses.size() - 1; i >= 0; i--) {
dismissPositions[i] = mPendingDismisses.get(i).position;
}
mCallback.onDismiss(mListView, dismissPositions);
ViewGroup.LayoutParams lp;
for (PendingDismissData pendingDismiss : mPendingDismisses) {
// Reset view presentation
setAlpha(pendingDismiss.view, 1f);
setTranslationX(pendingDismiss.view, 0);
lp = pendingDismiss.view.getLayoutParams();
lp.height = originalHeight;
pendingDismiss.view.setLayoutParams(lp);
}
mPendingDismisses.clear();
}
}
});
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
lp.height = (Integer) valueAnimator.getAnimatedValue();
dismissView.setLayoutParams(lp);
}
});
mPendingDismisses.add(new PendingDismissData(dismissPosition, dismissView));
// animator.start();
--mDismissAnimationRefCount;
if (mDismissAnimationRefCount == 0) {
// No active animations, process all pending dismisses.
// Sort by descending position
Collections.sort(mPendingDismisses);
int[] dismissPositions = new int[mPendingDismisses.size()];
for (int i = mPendingDismisses.size() - 1; i >= 0; i--) {
dismissPositions[i] = mPendingDismisses.get(i).position;
}
mCallback.onDismiss(mListView, dismissPositions);
ViewGroup.LayoutParams lpp;
for (PendingDismissData pendingDismiss : mPendingDismisses) {
// Reset view presentation
setAlpha(pendingDismiss.view, 1f);
setTranslationX(pendingDismiss.view, 0);
lpp = pendingDismiss.view.getLayoutParams();
lpp.height = originalHeight;
pendingDismiss.view.setLayoutParams(lp);
}
mPendingDismisses.clear();
}
}
}