`
iaiai
  • 浏览: 2196733 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Android中实现左右滑动View

 
阅读更多
iphone中有很多应用都能够左右滑动,非常cool,关键是实现起来非常简单。android比起来就差远了,网上有不少帖子。 我在这边重新分享下自己的经验吧。

运行效果:



AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
	package="com.iaiai.test.gallery" android:versionCode="1"
	android:versionName="1.0">
	<application android:icon="@drawable/icon" android:label="@string/app_name">
		<activity android:name=".TestGallery" android:label="@string/app_name">
			<intent-filter>
				<action android:name="android.intent.action.MAIN" />
				<category android:name="android.intent.category.LAUNCHER" />
			</intent-filter>
		</activity>

	</application>
	<uses-sdk android:minSdkVersion="4" />

</manifest> 


TestGallery.java
package com.iaiai.test.gallery;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.iaiai.test.view.FlingGallery;
import com.iaiai.test.view.OnGalleryChangeListener;

/**
 * 
 * <p>
 * Title: TestGallery.java
 * </p>
 * <p>
 * E-Mail: 176291935@qq.com
 * </p>
 * <p>
 * QQ: 176291935
 * </p>
 * <p>
 * Http: iaiai.iteye.com
 * </p>
 * <p>
 * Create time: 2011-9-29
 * </p>
 * 
 * @author 丸子
 * @version 0.0.1
 */
public class TestGallery extends Activity {
	private final int color_red = Color.argb(100, 200, 0, 0);
	private final int color_green = Color.argb(100, 0, 200, 0);
	private final int color_blue = Color.argb(100, 0, 0, 200);
	private final int color_yellow = Color.argb(100, 200, 200, 0);
	private final int color_purple = Color.argb(100, 200, 0, 200);

	private FlingGallery gallery;
	private final String[] mLabelArray = { "View1", "View2", "View3", "View4",
			"View5" };
	private final int[] mColorArray = { color_red, color_green, color_blue,
			color_yellow, color_purple };

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		gallery = new FlingGallery(this); 
		gallery.setPaddingWidth(5);
		// gallery.setBackgroundColor(Color.WHITE);
		gallery.setAdapter(new ArrayAdapter<String>(getApplicationContext(),
				android.R.layout.simple_list_item_1, mLabelArray) {

			@Override
			public View getView(int position, View convertView, ViewGroup parent) {
				LinearLayout view = new LinearLayout(getApplicationContext());
				view.setBackgroundColor(mColorArray[position]);
				view.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
						LayoutParams.FILL_PARENT));
				TextView label = new TextView(getApplicationContext());
				label.setText(mLabelArray[position]);
				label.setTextSize(24);
				label.setTextColor(Color.WHITE);
				label.setGravity(Gravity.CENTER);
				view.addView(label, LayoutParams.FILL_PARENT,
						LayoutParams.WRAP_CONTENT);
				return view;
			}

		});
		
		gallery.addGalleryChangeListener(new OnGalleryChangeListener() {  
			  
            @Override  
            public void onGalleryChange(int currentItem) {  
                // 干些想干的事件  
            	Log.v("m","currentItem:"+currentItem);
            }  
  
        });  
		setContentView(gallery);
	}

	public boolean onTouchEvent(MotionEvent event) {
		return gallery.onGalleryTouchEvent(event);
	}

}


FlingGallery.java
package com.iaiai.test.view;

import java.util.HashSet;
import java.util.Set;

import android.content.Context;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.view.animation.Transformation;
import android.widget.Adapter;
import android.widget.FrameLayout;
import android.widget.LinearLayout;

/**
 * 
 * <p>
 * Title: FlingGallery.java
 * </p>
 * <p>
 * E-Mail: 176291935@qq.com
 * </p>
 * <p>
 * QQ: 176291935
 * </p>
 * <p>
 * Http: iaiai.iteye.com
 * </p>
 * <p>
 * Create time: 2011-9-29
 * </p>
 * 
 * @author 丸子
 * @version 0.0.1
 */
public class FlingGallery extends FrameLayout {
	private Set<OnGalleryChangeListener> listeners;
	private final int swipe_min_distance = 120;
	private final int swipe_max_off_path = 250;
	private final int swipe_threshold_veloicty = 400;

	private int mViewPaddingWidth = 0;
	private int mAnimationDuration = 250;
	private float mSnapBorderRatio = 0.5f;
	private boolean mIsGalleryCircular = true;

	private int mGalleryWidth = 0;
	private boolean mIsTouched = false;
	private boolean mIsDragging = false;
	private float mCurrentOffset = 0.0f;
	private long mScrollTimestamp = 0;
	private int mFlingDirection = 0;
	private int mCurrentPosition = 0;
	private int mCurrentViewNumber = 0;

	private Context mContext;
	private Adapter mAdapter;
	private FlingGalleryView[] mViews;
	private FlingGalleryAnimation mAnimation;
	private GestureDetector mGestureDetector;
	private Interpolator mDecelerateInterpolater;

	public FlingGallery(Context context) {
		super(context);

		listeners = new HashSet<OnGalleryChangeListener>();

		mContext = context;
		mAdapter = null;

		mViews = new FlingGalleryView[3];
		mViews[0] = new FlingGalleryView(0, this);
		mViews[1] = new FlingGalleryView(1, this);
		mViews[2] = new FlingGalleryView(2, this);

		mAnimation = new FlingGalleryAnimation();
		mGestureDetector = new GestureDetector(new FlingGestureDetector());
		mDecelerateInterpolater = AnimationUtils.loadInterpolator(mContext,
				android.R.anim.decelerate_interpolator);
	}

	public void addGalleryChangeListener(OnGalleryChangeListener listener) {
		listeners.add(listener);
	}

	public void setPaddingWidth(int viewPaddingWidth) {
		mViewPaddingWidth = viewPaddingWidth;
	}

	public void setAnimationDuration(int animationDuration) {
		mAnimationDuration = animationDuration;
	}

	public void setSnapBorderRatio(float snapBorderRatio) {
		mSnapBorderRatio = snapBorderRatio;
	}

	public void setIsGalleryCircular(boolean isGalleryCircular) {
		if (mIsGalleryCircular != isGalleryCircular) {
			mIsGalleryCircular = isGalleryCircular;

			if (mCurrentPosition == getFirstPosition()) {
				// We need to reload the view immediately to the left to change
				// it to circular view or blank
				mViews[getPrevViewNumber(mCurrentViewNumber)]
						.recycleView(getPrevPosition(mCurrentPosition));
			}

			if (mCurrentPosition == getLastPosition()) {
				// We need to reload the view immediately to the right to change
				// it to circular view or blank
				mViews[getNextViewNumber(mCurrentViewNumber)]
						.recycleView(getNextPosition(mCurrentPosition));
			}
		}
	}

	public int getGalleryCount() {
		return (mAdapter == null) ? 0 : mAdapter.getCount();
	}

	public int getFirstPosition() {
		return 0;
	}

	public int getLastPosition() {
		return (getGalleryCount() == 0) ? 0 : getGalleryCount() - 1;
	}

	private int getPrevPosition(int relativePosition) {
		int prevPosition = relativePosition - 1;

		if (prevPosition < getFirstPosition()) {
			prevPosition = getFirstPosition() - 1;

			if (mIsGalleryCircular == true) {
				prevPosition = getLastPosition();
			}
		}
		NotifyGalleryChange();
		return prevPosition;
	}

	private int getNextPosition(int relativePosition) {
		int nextPosition = relativePosition + 1;

		if (nextPosition > getLastPosition()) {
			nextPosition = getLastPosition() + 1;

			if (mIsGalleryCircular == true) {
				nextPosition = getFirstPosition();
			}
		}
		NotifyGalleryChange();
		return nextPosition;
	}

	//
	private void NotifyGalleryChange() {
		for (OnGalleryChangeListener listener : listeners) {
			listener.onGalleryChange(mCurrentPosition);
		}
	}

	private int getPrevViewNumber(int relativeViewNumber) {
		return (relativeViewNumber == 0) ? 2 : relativeViewNumber - 1;
	}

	private int getNextViewNumber(int relativeViewNumber) {
		return (relativeViewNumber == 2) ? 0 : relativeViewNumber + 1;
	}

	@Override
	protected void onLayout(boolean changed, int left, int top, int right,
			int bottom) {
		super.onLayout(changed, left, top, right, bottom);

		// Calculate our view width
		mGalleryWidth = right - left;

		if (changed) {
			// Position views at correct starting offsets
			mViews[0].setOffset(0, 0, mCurrentViewNumber);
			mViews[1].setOffset(0, 0, mCurrentViewNumber);
			mViews[2].setOffset(0, 0, mCurrentViewNumber);
		}
	}

	public void setAdapter(Adapter adapter) {
		mAdapter = adapter;
		mCurrentPosition = 0;
		mCurrentViewNumber = 0;

		// Load the initial views from adapter
		mViews[0].recycleView(mCurrentPosition);
		mViews[1].recycleView(getNextPosition(mCurrentPosition));
		mViews[2].recycleView(getPrevPosition(mCurrentPosition));

		// Position views at correct starting offsets
		mViews[0].setOffset(0, 0, mCurrentViewNumber);
		mViews[1].setOffset(0, 0, mCurrentViewNumber);
		mViews[2].setOffset(0, 0, mCurrentViewNumber);
	}

	private int getViewOffset(int viewNumber, int relativeViewNumber) {
		// Determine width including configured padding width
		int offsetWidth = mGalleryWidth + mViewPaddingWidth;

		// Position the previous view one measured width to left
		if (viewNumber == getPrevViewNumber(relativeViewNumber)) {
			return offsetWidth;
		}

		// Position the next view one measured width to the right
		if (viewNumber == getNextViewNumber(relativeViewNumber)) {
			return offsetWidth * -1;
		}

		return 0;
	}

	void movePrevious() {
		// Slide to previous view
		mFlingDirection = 1;
		processGesture();
	}

	void moveNext() {
		// Slide to next view
		mFlingDirection = -1;
		processGesture();
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		switch (keyCode) {
		case KeyEvent.KEYCODE_DPAD_LEFT:
			movePrevious();
			return true;

		case KeyEvent.KEYCODE_DPAD_RIGHT:
			moveNext();
			return true;

		case KeyEvent.KEYCODE_DPAD_CENTER:
		case KeyEvent.KEYCODE_ENTER:
		}

		return super.onKeyDown(keyCode, event);
	}

	public boolean onGalleryTouchEvent(MotionEvent event) {
		boolean consumed = mGestureDetector.onTouchEvent(event);

		if (event.getAction() == MotionEvent.ACTION_UP) {
			if (mIsTouched || mIsDragging) {
				processScrollSnap();
				processGesture();
			}
		}

		return consumed;
	}

	void processGesture() {
		int newViewNumber = mCurrentViewNumber;
		int reloadViewNumber = 0;
		int reloadPosition = 0;

		mIsTouched = false;
		mIsDragging = false;

		if (mFlingDirection > 0) {
			if (mCurrentPosition > getFirstPosition()
					|| mIsGalleryCircular == true) {
				// Determine previous view and outgoing view to recycle
				newViewNumber = getPrevViewNumber(mCurrentViewNumber);
				mCurrentPosition = getPrevPosition(mCurrentPosition);
				reloadViewNumber = getNextViewNumber(mCurrentViewNumber);
				reloadPosition = getPrevPosition(mCurrentPosition);
			}
		}

		if (mFlingDirection < 0) {
			if (mCurrentPosition < getLastPosition()
					|| mIsGalleryCircular == true) {
				// Determine the next view and outgoing view to recycle
				newViewNumber = getNextViewNumber(mCurrentViewNumber);
				mCurrentPosition = getNextPosition(mCurrentPosition);
				reloadViewNumber = getPrevViewNumber(mCurrentViewNumber);
				reloadPosition = getNextPosition(mCurrentPosition);
			}
		}

		if (newViewNumber != mCurrentViewNumber) {
			mCurrentViewNumber = newViewNumber;

			// Reload outgoing view from adapter in new position
			mViews[reloadViewNumber].recycleView(reloadPosition);
		}

		// Ensure input focus on the current view
		mViews[mCurrentViewNumber].requestFocus();

		// Run the slide animations for view transitions
		mAnimation.prepareAnimation(mCurrentViewNumber);
		this.startAnimation(mAnimation);

		// Reset fling state
		mFlingDirection = 0;
	}

	void processScrollSnap() {
		// Snap to next view if scrolled passed snap position
		float rollEdgeWidth = mGalleryWidth * mSnapBorderRatio;
		int rollOffset = mGalleryWidth - (int) rollEdgeWidth;
		int currentOffset = mViews[mCurrentViewNumber].getCurrentOffset();

		if (currentOffset <= rollOffset * -1) {
			// Snap to previous view
			mFlingDirection = 1;
		}

		if (currentOffset >= rollOffset) {
			// Snap to next view
			mFlingDirection = -1;
		}
	}

	private class FlingGalleryView {
		private int mViewNumber;
		private FrameLayout mParentLayout;

		private FrameLayout mInvalidLayout = null;
		private LinearLayout mInternalLayout = null;
		private View mExternalView = null;

		public FlingGalleryView(int viewNumber, FrameLayout parentLayout) {
			mViewNumber = viewNumber;
			mParentLayout = parentLayout;

			// Invalid layout is used when outside gallery
			mInvalidLayout = new FrameLayout(mContext);
			mInvalidLayout.setLayoutParams(new LinearLayout.LayoutParams(
					LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));

			// Internal layout is permanent for duration
			mInternalLayout = new LinearLayout(mContext);
			mInternalLayout.setLayoutParams(new LinearLayout.LayoutParams(
					LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));

			mParentLayout.addView(mInternalLayout);
		}

		public void recycleView(int newPosition) {
			if (mExternalView != null) {
				mInternalLayout.removeView(mExternalView);
			}

			if (mAdapter != null) {
				if (newPosition >= getFirstPosition()
						&& newPosition <= getLastPosition()) {
					mExternalView = mAdapter.getView(newPosition,
							mExternalView, mInternalLayout);
				} else {
					mExternalView = mInvalidLayout;
				}
			}

			if (mExternalView != null) {
				mInternalLayout.addView(mExternalView,
						new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
								LayoutParams.FILL_PARENT));
			}
		}

		public void setOffset(int xOffset, int yOffset, int relativeViewNumber) {
			// Scroll the target view relative to its own position relative to
			// currently displayed view
			mInternalLayout.scrollTo(
					getViewOffset(mViewNumber, relativeViewNumber) + xOffset,
					yOffset);
		}

		public int getCurrentOffset() {
			// Return the current scroll position
			return mInternalLayout.getScrollX();
		}

		public void requestFocus() {
			mInternalLayout.requestFocus();
		}
	}

	private class FlingGalleryAnimation extends Animation {
		private boolean mIsAnimationInProgres;
		private int mRelativeViewNumber;
		private int mInitialOffset;
		private int mTargetOffset;
		private int mTargetDistance;

		public FlingGalleryAnimation() {
			mIsAnimationInProgres = false;
			mRelativeViewNumber = 0;
			mInitialOffset = 0;
			mTargetOffset = 0;
			mTargetDistance = 0;
		}

		public void prepareAnimation(int relativeViewNumber) {
			// If we are animating relative to a new view
			if (mRelativeViewNumber != relativeViewNumber) {
				if (mIsAnimationInProgres == true) {
					// We only have three views so if requested again to animate
					// in same direction we must snap
					int newDirection = (relativeViewNumber == getPrevViewNumber(mRelativeViewNumber)) ? 1
							: -1;
					int animDirection = (mTargetDistance < 0) ? 1 : -1;

					// If animation in same direction
					if (animDirection == newDirection) {
						// Ran out of time to animate so snap to the target
						// offset
						mViews[0].setOffset(mTargetOffset, 0,
								mRelativeViewNumber);
						mViews[1].setOffset(mTargetOffset, 0,
								mRelativeViewNumber);
						mViews[2].setOffset(mTargetOffset, 0,
								mRelativeViewNumber);
					}
				}

				// Set relative view number for animation
				mRelativeViewNumber = relativeViewNumber;
			}

			// Note: In this implementation the targetOffset will always be zero
			// as we are centering the view; but we include the calculations of
			// targetOffset and targetDistance for use in future implementations

			mInitialOffset = mViews[mRelativeViewNumber].getCurrentOffset();
			mTargetOffset = getViewOffset(mRelativeViewNumber,
					mRelativeViewNumber);
			mTargetDistance = mTargetOffset - mInitialOffset;

			// Configure base animation properties
			this.setDuration(mAnimationDuration);
			this.setInterpolator(mDecelerateInterpolater);

			// Start/continued animation
			mIsAnimationInProgres = true;
		}

		@Override
		protected void applyTransformation(float interpolatedTime,
				Transformation transformation) {
			// Ensure interpolatedTime does not over-shoot then calculate new
			// offset
			interpolatedTime = (interpolatedTime > 1.0f) ? 1.0f
					: interpolatedTime;
			int offset = mInitialOffset
					+ (int) (mTargetDistance * interpolatedTime);

			for (int viewNumber = 0; viewNumber < 3; viewNumber++) {
				// Only need to animate the visible views as the other view will
				// always be off-screen
				if ((mTargetDistance > 0 && viewNumber != getNextViewNumber(mRelativeViewNumber))
						|| (mTargetDistance < 0 && viewNumber != getPrevViewNumber(mRelativeViewNumber))) {
					mViews[viewNumber]
							.setOffset(offset, 0, mRelativeViewNumber);
				}
			}
		}

		@Override
		public boolean getTransformation(long currentTime,
				Transformation outTransformation) {
			if (super.getTransformation(currentTime, outTransformation) == false) {
				// Perform final adjustment to offsets to cleanup animation
				mViews[0].setOffset(mTargetOffset, 0, mRelativeViewNumber);
				mViews[1].setOffset(mTargetOffset, 0, mRelativeViewNumber);
				mViews[2].setOffset(mTargetOffset, 0, mRelativeViewNumber);

				// Reached the animation target
				mIsAnimationInProgres = false;

				return false;
			}

			// Cancel if the screen touched
			if (mIsTouched || mIsDragging) {
				// Note that at this point we still consider ourselves to be
				// animating
				// because we have not yet reached the target offset; its just
				// that the
				// user has temporarily interrupted the animation with a touch
				// gesture

				return false;
			}

			return true;
		}
	}

	private class FlingGestureDetector extends
			GestureDetector.SimpleOnGestureListener {
		@Override
		public boolean onDown(MotionEvent e) {
			// Stop animation
			mIsTouched = true;

			// Reset fling state
			mFlingDirection = 0;
			return true;
		}

		@Override
		public boolean onScroll(MotionEvent e1, MotionEvent e2,
				float distanceX, float distanceY) {
			if (e2.getAction() == MotionEvent.ACTION_MOVE) {
				if (mIsDragging == false) {
					// Stop animation
					mIsTouched = true;

					// Reconfigure scroll
					mIsDragging = true;
					mFlingDirection = 0;
					mScrollTimestamp = System.currentTimeMillis();
					mCurrentOffset = mViews[mCurrentViewNumber]
							.getCurrentOffset();
				}

				float maxVelocity = mGalleryWidth
						/ (mAnimationDuration / 1000.0f);
				long timestampDelta = System.currentTimeMillis()
						- mScrollTimestamp;
				float maxScrollDelta = maxVelocity * (timestampDelta / 1000.0f);
				float currentScrollDelta = e1.getX() - e2.getX();

				if (currentScrollDelta < maxScrollDelta * -1)
					currentScrollDelta = maxScrollDelta * -1;
				if (currentScrollDelta > maxScrollDelta)
					currentScrollDelta = maxScrollDelta;
				int scrollOffset = Math.round(mCurrentOffset
						+ currentScrollDelta);

				// We can't scroll more than the width of our own frame layout
				if (scrollOffset >= mGalleryWidth)
					scrollOffset = mGalleryWidth;
				if (scrollOffset <= mGalleryWidth * -1)
					scrollOffset = mGalleryWidth * -1;

				mViews[0].setOffset(scrollOffset, 0, mCurrentViewNumber);
				mViews[1].setOffset(scrollOffset, 0, mCurrentViewNumber);
				mViews[2].setOffset(scrollOffset, 0, mCurrentViewNumber);
			}

			return false;
		}

		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
				float velocityY) {
			if (Math.abs(e1.getY() - e2.getY()) <= swipe_max_off_path) {
				if (e2.getX() - e1.getX() > swipe_min_distance
						&& Math.abs(velocityX) > swipe_threshold_veloicty) {
					movePrevious();
				}

				if (e1.getX() - e2.getX() > swipe_min_distance
						&& Math.abs(velocityX) > swipe_threshold_veloicty) {
					moveNext();
				}
			}

			return false;
		}

		@Override
		public void onLongPress(MotionEvent e) {
			// Finalise scrolling
			mFlingDirection = 0;
			processGesture();
		}

		@Override
		public void onShowPress(MotionEvent e) {
		}

		@Override
		public boolean onSingleTapUp(MotionEvent e) {
			// Reset fling state
			mFlingDirection = 0;
			return false;
		}

	}

	public GestureDetector getMGestureDetector() {
		return mGestureDetector;
	}
}


OnGalleryChangeListener.java
package com.iaiai.test.view;

/**
 * 
 * <p>
 * Title: OnGalleryChangeListener.java
 * </p>
 * <p>
 * E-Mail: 176291935@qq.com
 * </p>
 * <p>
 * QQ: 176291935
 * </p>
 * <p>
 * Http: iaiai.iteye.com
 * </p>
 * <p>
 * Create time: 2011-9-29
 * </p>
 * 
 * @author 丸子
 * @version 0.0.1
 */
public interface OnGalleryChangeListener {
	public void onGalleryChange(int currentItem);
}
  • 大小: 15 KB
  • 大小: 16.7 KB
分享到:
评论

相关推荐

    android中实现左右滑动View

    在Android开发中,实现左右滑动视图通常是通过创建一个可滑动的布局或使用特定的库来达成目的。这个过程涉及到多个知识点,包括布局管理、触摸事件处理、动画效果以及用户交互设计。以下是对这些关键点的详细阐述: ...

    Android实现图片左右滑动效果

    在Android开发中,实现图片左右滑动效果是常见的需求,比如在查看相册或轮播图时。这个功能可以通过多种方式实现,其中最常用的是使用ViewPager组件。ViewPager允许用户通过左右滑动手势在多个页面之间切换,非常...

    Android 界面禁止左右滑动切换

    首先,Android界面的左右滑动切换通常是通过`ViewPager`组件实现的,它允许用户通过横向滑动来浏览多个页面。如果我们想要禁止这种行为,我们需要对`ViewPager`进行定制。以下是一种可能的方法: 1. **自定义...

    Android点击左右按钮实现左右滑动页面切换

    在Android开发中,实现左右按钮控制页面滑动切换是一种常见的交互设计,这通常涉及到ViewPager、Fragment或自定义布局的运用。在这个场景中,我们可以通过监听按钮的点击事件,然后改变ViewPager的内容来达到页面...

    Android中实现左右滑动

    总结一下,Android中实现左右滑动可以通过以下几种方式: 1. 使用`GestureDetector`监听滑动事件并自定义滑动行为。 2. 利用`ViewPager`组件,它内置了滑动切换页面的功能。 3. 对于更复杂的场景,可以结合`...

    Android中实现试图左右滑动的功能

    在Android开发中,实现视图左右滑动的功能是常见的需求,比如在应用的主界面或者图片浏览器中。这种效果通常通过使用特殊的布局管理器或第三方库来实现。本教程将探讨如何在Android中创建一个可以左右滑动的视图。 ...

    Android 自定义可上下左右滑动table

    标题"Android 自定义可上下左右滑动table"指向的就是一个专门为Android平台设计的定制化表格控件,它不仅支持垂直滚动(上下滑动),还支持水平滚动(左右滑动),这在处理大数据量或需要展示宽幅信息时非常有用。...

    Android项目使用ViewPager实现左右滑动翻页.rar

    通过以上步骤,你可以在Android项目中实现一个具备左右滑动翻页功能的应用。在这个过程中,你可以根据实际需求调整适配器和页面切换效果,以创建个性化的用户体验。这个RAR文件提供的就是一个实际示例,你可以下载并...

    Android实现导航菜单左右滑动效果

    为了实现左右滑动的效果,你需要在`Activity`或`Fragment`中初始化`ViewPager`并设置适配器。在`onCreate()`或`onActivityCreated()`方法中,找到`ViewPager`实例,然后调用`setAdapter()`方法传入之前创建的`...

    本文介绍Android中实现左右滑动的指引效果。

    本篇文章将深入探讨如何在Android中实现这样的功能。 首先,我们需要理解这种效果的基本原理。左右滑动的指引通常包含一组页面,用户可以通过左右滑动来浏览这些页面。每个页面可能包含文字说明、图片示例或者高亮...

    Android使用Photoview实现图片左右滑动及缩放功能

    本文将详细介绍如何在Android项目中使用`Photoview`实现图片左右滑动和缩放。 首先,我们需要在项目的`build.gradle`文件中添加必要的依赖。引入`Picasso`库用于图片加载,以及`Photoview`库用于手势处理: ```...

    android左右滑动的选择控件

    在Android开发中,创建一个可左右滑动的选择控件是一个常见的需求,这通常涉及到自定义View或者使用现有的库来实现。这种控件可以用于展示多个选项,用户通过左右滑动来浏览和选择。下面我们将详细探讨如何实现这样...

    安卓Android 排班自定义view 支持左右上下滑动 支持点击事件,支持更改每个框的内容

    首先,这个自定义View能够实现左右上下滑动,这意味着它可能基于ScrollView或者HorizontalScrollView进行扩展,通过嵌套布局或者使用ViewPager实现了多方向的滚动效果。在Android中,处理这种多方向滑动冲突是一个...

    Android项目导航菜单横向左右滑动并和下方的控件实现联动.rar

    本项目"Android项目导航菜单横向左右滑动并和下方的控件实现联动"就是针对这一需求设计的,它实现了侧滑导航菜单与主内容区域的动态联动效果。这种效果常见于许多流行的移动应用中,比如Google Maps和Facebook等。 ...

    android 模仿QQ左右滑动

    在Android开发中,模仿QQ的左右滑动效果是一项常见的需求,尤其在构建聊天或社交应用时。QQ的滑动交互设计使得用户可以在不离开当前页面的情况下,方便地切换上下文或者访问不同功能。本示例"android 模仿QQ左右滑动...

    android 实现左右滑动指引效果

    在Android开发中,实现左右滑动的指引效果是一种常见的用户引导功能,主要用于向初次使用应用的用户介绍关键操作或功能。这种效果通常采用 ViewPager 或者 RecyclerView 结合自定义动画来实现,让页面在用户的手势下...

    Android顶部、底部菜单左右滑动

    在实现左右滑动的过程中,开发者可能用到`SwipeRefreshLayout`,这是一个允许用户通过下拉刷新内容的组件。然而,对于左右滑动的需求,`ViewPager`是一个更合适的工具。`ViewPager`允许用户左右滑动页面,通常与`...

    android左右循环滑动效果

    在Android开发中,实现左右循环滑动的效果是一种常见的需求,特别是在设计各种滚动列表或轮播图时。这种效果能够提供用户友好的体验,使他们能够方便地浏览内容。本项目的核心在于实现一个可无限循环的滑动视图,让...

    Android ViewPager实现圆点导航左右滑动和Fragment页面切换

    在Android开发中,`ViewPager` 是一个非常重要的组件,它允许用户通过左右滑动来浏览多个页面,通常用于实现滑动切换的界面效果。在这个示例中,我们结合`ViewPager`、`Fragment`、`PagerAdapter` 和 `...

    Android ViewPager实现左右滑动

    在Android开发中,ViewPager是一个非常重要的组件,它用于展示可以左右滑动的多个页面,常用于实现类似TabLayout的效果或者创建水平滚动的内容区域。本文将深入讲解如何利用Android的ViewPager实现页面的左右滑动,...

Global site tag (gtag.js) - Google Analytics