- 浏览: 5831415 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (890)
- WindowsPhone (0)
- android (88)
- android快速迭代 (17)
- android基础 (34)
- android进阶 (172)
- android高级 (0)
- android拾遗 (85)
- android动画&效果 (68)
- Material Design (13)
- LUA (5)
- j2me (32)
- jQuery (39)
- spring (26)
- hibernate (20)
- struts (26)
- tomcat (9)
- javascript+css+html (62)
- jsp+servlet+javabean (14)
- java (37)
- velocity+FCKeditor (13)
- linux+批处理 (9)
- mysql (19)
- MyEclipse (9)
- ajax (7)
- wap (8)
- j2ee+apache (24)
- 其他 (13)
- phonegap (35)
最新评论
-
Memories_NC:
本地lua脚本终于执行成功了,虽然不是通过redis
java中调用lua脚本语言1 -
ZHOU452840622:
大神://处理返回的接收状态 这个好像没有监听到 遇 ...
android 发送短信的两种方式 -
PXY:
拦截部分地址,怎么写的for(int i=0;i<lis ...
判断是否登录的拦截器SessionFilter -
maotou1988:
Android控件之带清空按钮(功能)的AutoComplet ...
自定义AutoCompleteTextView -
yangmaolinpl:
希望有表例子更好。。。,不过也看明白了。
浅谈onInterceptTouchEvent、onTouchEvent与onTouch
原帖看:
http://www.eoeandroid.com/thread-70194-1-1.html
或者看这个:
android中的左右滑动
http://www.iteye.com/topic/1102128
之所以说其不完美是因为FlingGallery使用到了Adapter,这样会造成各界面的一致性,比较单一.如果能随便什么界面都能拖动就完美了.(什么?想要完美?我的博客里找!)
不过它的循环显示效果不错.
下面是它的源码:
测试代码:
呵呵 你自己跑跑看不就知道了么 看起来是滑动的效果 就是真的滑动么 不能用动画么
http://www.eoeandroid.com/thread-70194-1-1.html
或者看这个:
android中的左右滑动
http://www.iteye.com/topic/1102128
之所以说其不完美是因为FlingGallery使用到了Adapter,这样会造成各界面的一致性,比较单一.如果能随便什么界面都能拖动就完美了.(什么?想要完美?我的博客里找!)
不过它的循环显示效果不错.
下面是它的源码:
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; // TODO: // 1. In order to improve performance Cache screen bitmap and use for animation // 2. Establish superfluous memory allocations and delay or replace with reused objects // Probably need to make sure we are not allocating objects (strings, etc.) in loops public class FlingGallery extends FrameLayout { // Constants private final int swipe_min_distance = 120; private final int swipe_max_off_path = 250; private final int swipe_threshold_veloicty = 400; // Properties private int mViewPaddingWidth = 0; private int mAnimationDuration = 250; private float mSnapBorderRatio = 0.5f; private boolean mIsGalleryCircular = true; // Members 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); 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 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(); } } return prevPosition; } private int getNextPosition(int relativePosition) { int nextPosition = relativePosition + 1; if (nextPosition > getLastPosition()) { nextPosition = getLastPosition() + 1; if (mIsGalleryCircular == true) { nextPosition = getFirstPosition(); } } return nextPosition; } 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 == true) { // 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.MATCH_PARENT, LayoutParams.MATCH_PARENT)); // Internal layout is permanent for duration mInternalLayout = new LinearLayout(mContext); mInternalLayout.setLayoutParams(new LinearLayout.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_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.MATCH_PARENT, LayoutParams.MATCH_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; } } }
测试代码:
import android.app.Activity; import android.os.Bundle; import android.content.Context; import android.graphics.Color; import android.util.Log; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.View.OnClickListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TableLayout; import android.widget.TextView; public class FlingGalleryActivity extends Activity { private final String[] mLabelArray = { "View1", "View2", "View3", "View4", "View5" }; private final int[] mColorArray = { Color.argb(100, 200, 0, 0), Color.argb(100, 0, 200, 0), Color.argb(100, 0, 0, 200), Color.argb(100, 200, 200, 0), Color.argb(100, 200, 0, 200) }; private FlingGallery mGallery; private CheckBox mCheckBox; @Override public boolean onTouchEvent(MotionEvent event) { return mGallery.onGalleryTouchEvent(event); } public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mGallery = new FlingGallery(this); mGallery.setPaddingWidth(5); mGallery.setAnimationDuration(500); mGallery.setAdapter(new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, mLabelArray) { @Override public View getView(int position, View convertView, ViewGroup parent) { Log.d("111", "count=" + position); return new GalleryViewItem(getApplicationContext(), position); } }); LinearLayout layout = new LinearLayout(getApplicationContext()); layout.setOrientation(LinearLayout.VERTICAL); LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); layoutParams.setMargins(10, 10, 10, 10); layoutParams.weight = 1.0f; layout.addView(mGallery, layoutParams); mCheckBox = new CheckBox(getApplicationContext()); mCheckBox.setText("Gallery is Circular"); mCheckBox.setPadding(50, 10, 0, 10); mCheckBox.setTextSize(30); mCheckBox.setChecked(true); mCheckBox.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { mGallery.setIsGalleryCircular(mCheckBox.isChecked()); } }); layout.addView(mCheckBox, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); setContentView(layout); } private class GalleryViewItem extends TableLayout { private EditText mEdit1; private TextView mText1; private TextView mText2; private Button mButton1; private Button mButton2; public GalleryViewItem(Context context, int position) { super(context); this.setOrientation(LinearLayout.VERTICAL); this.setLayoutParams(new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)); mEdit1 = new EditText(context); this.addView(mEdit1, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); mText1 = new TextView(context); mText1.setText(mLabelArray[position]); mText1.setTextSize(30); mText1.setGravity(Gravity.LEFT); mText1.setBackgroundColor(mColorArray[position]); this.addView(mText1, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); mButton1 = new Button(context); mButton1.setText("<<"); mButton1.setGravity(Gravity.LEFT); mButton1.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { mGallery.movePrevious(); } }); this.addView(mButton1, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); mButton2 = new Button(context); mButton2.setText(">>"); mButton2.setGravity(Gravity.RIGHT); mButton2.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { mGallery.moveNext(); } }); this.addView(mButton2, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); mText2 = new TextView(context); mText2.setText(mLabelArray[position]); mText2.setTextSize(30); mText2.setGravity(Gravity.RIGHT); mText2.setBackgroundColor(mColorArray[position]); this.addView(mText2, new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT, 1)); } } }
- FlingGallery.rar (68.7 KB)
- 下载次数: 233
评论
4 楼
北冥泪
2013-07-10
楼主,你说完美的是哪篇文章呢?我现在用的各种自定义布局,想放在flinggallery中,想参考下。
3 楼
米其林的微笑
2012-02-22
andsiban 写道
各位开发者,这个类能滑动?难道你们的API比较特殊吗!滑动的关键方法onTouchEvent(MotionEvent event)都没有重写,用个onGalleryTouchEvent(MotionEvent event)方法,你们就能滑动了,真是牛人。
呵呵 你自己跑跑看不就知道了么 看起来是滑动的效果 就是真的滑动么 不能用动画么
2 楼
andsiban
2012-02-16
各位开发者,这个类能滑动?难道你们的API比较特殊吗!滑动的关键方法onTouchEvent(MotionEvent event)都没有重写,用个onGalleryTouchEvent(MotionEvent event)方法,你们就能滑动了,真是牛人。
1 楼
米其林的微笑
2011-09-03
博主,你好,你所说的完美解决的是指你的哪篇文章呢,请指点一下。
还有一个问题想请教下,我用了FlingGallery 这个类,每个子View 都是一张图片,我用了回调先加载模糊图片然后再加载清晰图片,但是加载未完成发生滚动时,子View就无法更新了?项目卡在这里了,请博主指点一下!
还有一个问题想请教下,我用了FlingGallery 这个类,每个子View 都是一张图片,我用了回调先加载模糊图片然后再加载清晰图片,但是加载未完成发生滚动时,子View就无法更新了?项目卡在这里了,请博主指点一下!
发表评论
-
NestedScrollView滚动到顶部固定子View悬停挂靠粘在顶端
2018-10-31 20:45 7031网上有一个StickyScrollView,称之为粘性Scro ... -
自定义Behavior实现AppBarLayout越界弹性效果
2017-03-31 09:33 10395一、继承AppBarLayout.Beha ... -
Android - 一种相似图片搜索算法的实现
2017-03-31 09:33 2636算法 缩小尺寸。 将图片缩小到8x8的尺寸,总共64个 ... -
使用SpringAnimation实现带下拉弹簧动画的 ScrollView
2017-03-30 11:30 2865在刚推出的 Support Library 25.3.0 里面 ... -
Android为应用添加角标(Badge)
2017-03-30 11:21 62061.需求简介 角标是什么意思呢? 看下图即可明了: 可 ... -
Android端与笔记本利用局域网进行FTP通信
2017-03-23 10:17 995先看图 打开前: 打开后: Activity类 ... -
PorterDuffColorFilter 在项目中的基本使用
2017-03-03 10:58 1368有时候标题栏会浮在内容之上,而内容会有颜色的变化,这时候就要求 ... -
ColorAnimationView 实现了滑动Viewpager 时背景色动态变化的过渡效果
2017-02-24 09:41 2236用法在注释中: import android.anima ... -
迷你轻量级全方向完美滑动处理侧滑控件SlideLayout
2017-01-16 16:53 2608纯手工超级迷你轻量级全方向完美滑动处理侧滑控件(比官方 sup ... -
Effect
2017-01-05 09:57 0https://github.com/JetradarMobi ... -
动态主题库Colorful,容易地改变App的配色方案
2016-12-27 14:49 2581Colorful是一个动态主题库,允许您很容易地改变App的配 ... -
对视图的对角线切割DiagonalView
2016-12-27 14:23 1130提供对视图的对角线切割,具有很好的用户定制 基本用法 ... -
仿淘宝京东拖拽商品详情页上下滚动黏滞效果
2016-12-26 16:53 3519比较常用的效果,有现成的,如此甚好!:) import ... -
让任意view具有滑动效果的SlideUp
2016-12-26 09:26 1720基本的类,只有一个: import android.a ... -
AdvancedWebView
2016-12-21 09:44 16https://github.com/delight-im/A ... -
可设置圆角背景边框的按钮, 通过调节色彩明度自动计算按下(pressed)状态颜色
2016-11-02 22:13 1937可设置圆角背景边框的的按钮, 通过调节色彩明度自动计算按下(p ... -
网络请求库相关
2016-10-09 09:35 62https://github.com/amitshekhari ... -
ASimpleCache一个简单的缓存框架
2015-10-26 22:53 2193ASimpleCache 是一个为android制定的 轻量级 ... -
使用ViewDragHelper实现的DragLayout开门效果
2015-10-23 10:55 3439先看一下图,有个直观的了解,向下拖动handle就“开门了”: ... -
保证图片长宽比的同时拉伸图片ImageView
2015-10-16 15:40 3747按比例放大图片,不拉伸失真 import android. ...
相关推荐
总结,实现一个完美的Android FlingGallery类,需要对Android手势识别、布局管理、动画效果、性能优化、事件分发以及UI反馈有深入理解。通过合理的设计和编码,可以创造出一款既美观又高效的多页面手势拖动组件。在...
`FlingGallery`就是这样一个仿照墨迹天气应用重新定义的`Gallery`控件,它旨在提供更好的用户体验和更多的定制选项。 `FlingGallery`的核心特性在于它的滑动手势(Fling Gesture),让用户可以流畅地在各个项目间...
`FlingGallery`通常是一个自定义的视图类,继承自`ViewGroup`或`ViewPager`,并进行了定制化处理,以便支持平滑的滑动手势以及多页面的展示。在这个源码中,`FlingGallery`可能包含了以下核心功能: 1. **手势检测*...
为了实现滑动效果,`FlingGallery`可能使用了Android的`GestureDetector`或`Scroller`类,这两个类可以帮助识别和处理滑动、滚动等手势。`GestureDetector`可以监听滑动、点击等基本手势,而`Scroller`则可以提供...
在Android开发中,FlingGallery通常是指一个可滑动浏览图片或内容的组件,它具有平滑的动画效果,能够给用户带来更好的交互体验。这个"FlingGallery.zip"文件是专门为Android平台设计的一个项目,使用Java语言编写,...
这个"Android 仿UC、墨迹天气左右拖动多屏幕显示效果源码.zip"提供的就是一个实现这种效果的示例项目,名为"FlingGallery"。 FlingGallery是Android中的一个自定义滚动视图组件,它允许用户通过手指左右滑动来浏览...
在你提供的源码压缩包"Android 仿UC,墨迹天气左右拖动多屏幕显示效果源码.rar"中,包含的核心文件是"FlingGallery",这很可能是一个自定义的Android组件,实现了滑动切换的效果。 **滑动画廊(Fling Gallery)实现...
总的来说,“蚂蚁乐园的代码仓库 之 安卓 Android (一)”提供的FlingGallery源码是一个学习Android自定义视图和手势识别的好材料。通过研究这个组件,开发者不仅能掌握Android UI的高级技巧,还能提升对Android...
"FlingGallery"这个名字暗示这是一个实现此类功能的库或者示例代码。下面我们将深入探讨如何在Android中实现循环划屏效果以及可能涉及的关键技术点。 首先,我们要理解的是Android中的滚动机制。在Android中,我们...
在提供的压缩包文件中,“FlingGallery”可能是一个实现了翻页效果的示例项目,它可能包含了一个自定义的`Gallery`视图,利用`FlingGesture`实现了平滑的左右滑动翻页。`ServiceTest`可能是一个关于Android服务...
`FlingGallery`是一个自定义的Android控件,它模仿了`Gallery`的行为,并且增强了滑动效果,例如平滑的动画过渡、弹性回弹等。这个控件通常用于创建图片画廊、应用选择器或者任何需要水平滚动内容的场景。其主要特点...
例如,`FlingGallery`这个文件可能包含一个滑动手势的示例,用于实现类似相册翻页的效果。 4. **响应式设计**:为了确保应用在不同屏幕尺寸上都能良好工作,开发者需要遵循响应式设计原则。可以使用`...
FlingGallery可能是作者创建的一个自定义视图,模仿了ViewPager的功能,但可能增加了更丰富的手势操作,如快速滑动(fling)和更个性化的动画效果。 在Android中,ViewPager是通过PagerAdapter接口来获取和展示页面...
这个名为"Android项目之——页面特效集合(附源码).zip"的压缩包文件包含了一个Android项目的源代码,特别关注于实现各种页面特效。这个项目由Java编写,旨在为开发者提供一系列的视觉效果示例,可以用于增强...
- 使用第三方库:一些第三方库,如FlingGallery(从文件名推测可能是一个滑动图片库),提供了防止误滑动的功能。开发者可以通过配置这些库的参数来调整防滑动的行为。 3. 实际应用的重要性: - 用户体验:防UC滑动...
在仿制源代码中,开发者需要理解和实现`GestureDetector`、`Scroller`类来处理触摸事件,实现平滑的滑动效果。 3. **WebView集成**:UC浏览器的核心是`WebView`组件,它用于加载和渲染网页内容。开发者需要掌握如何...
在网上搜集的事例 :android例子,bottomtab EMail FlingGallery HanziToPinyin ScrollView Tab TestListView02 ViewFlipperTest Tab与TabHost.pdf testTabActivity
支持多屏幕自由左右切换效果,源码flinggallery,并且源码实现gallery是圆形的,gallery is circular,该项目实现了多屏幕显示效果,通过左右滑动屏幕或点击示意左右按钮可以实现不同屏幕的切换,具体大家还是看演示...