android实现uc和墨迹天气那样的左右拖动效果

[代码] FlingGalleryActivity

001import android.app.Activity;
002import android.os.Bundle;
003  
004import android.content.Context;
005import android.graphics.Color;
006import android.util.Log;
007import android.view.Gravity;
008import android.view.MotionEvent;
009import android.view.View;
010import android.view.ViewGroup;
011import android.view.View.OnClickListener;
012import android.widget.ArrayAdapter;
013import android.widget.Button;
014import android.widget.CheckBox;
015import android.widget.EditText;
016import android.widget.LinearLayout;
017import android.widget.TableLayout;
018import android.widget.TextView;
019  
020public class FlingGalleryActivity extends Activity
021{
022    private final int color_red = Color.argb(100, 200, 0, 0);
023    private final int color_green = Color.argb(100, 0, 200, 0);
024    private final int color_blue = Color.argb(100, 0, 0, 200);
025    private final int color_yellow = Color.argb(100, 200, 200, 0);
026    private final int color_purple = Color.argb(100, 200, 0, 200);
027  
028    private final String[] mLabelArray = {"View1", "View2", "View3", "View4", "View5"};
029    private final int[] mColorArray = {color_red, color_green, color_blue, color_yellow, color_purple};
030  
031    private FlingGallery mGallery;
032    private CheckBox mCheckBox;
033  
034    // Note: The following handler is critical to correct function of
035    // the FlingGallery class. This enables the FlingGallery class to
036    // detect when the motion event has ended by finger being lifted
037  
038    @Override
039    public boolean onTouchEvent(MotionEvent event)
040    {
041        return mGallery.onGalleryTouchEvent(event);
042    }
043  
044    public void onCreate(Bundle savedInstanceState)
045    {
046        super.onCreate(savedInstanceState);
047  
048        mGallery = new FlingGallery(this);
049        mGallery.setPaddingWidth(5);
050        mGallery.setAdapter(new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, mLabelArray)
051        {
052            @Override
053            public View getView(int position, View convertView, ViewGroup parent)
054            {
055                Log.d("111", "count="+position);
056//              if (convertView != null && convertView instanceof GalleryViewItem)
057//                {
058//                  GalleryViewItem galleryView = (GalleryViewItem) convertView;
059//
060//                  galleryView.mEdit1.setText("");
061//                  galleryView.mText1.setText(mLabelArray[position]);
062//                  galleryView.mText1.setBackgroundColor(mColorArray[position]);
063//                  galleryView.mText2.setText(mLabelArray[position]);
064//                  galleryView.mText2.setBackgroundColor(mColorArray[position]);
065//                  
066//                  Log.d("111", "count="+position);
067//                  
068//                  return galleryView;
069//                  
070//                }
071                  
072                return new GalleryViewItem(getApplicationContext(), position);
073            }
074        });
075  
076        LinearLayout layout = new LinearLayout(getApplicationContext());
077        layout.setOrientation(LinearLayout.VERTICAL);
078  
079        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
080                LinearLayout.LayoutParams.MATCH_PARENT,
081                LinearLayout.LayoutParams.MATCH_PARENT);
082  
083        layoutParams.setMargins(10, 10, 10, 10);
084        layoutParams.weight = 1.0f;
085    
086        layout.addView(mGallery, layoutParams);
087          
088        mCheckBox = new CheckBox(getApplicationContext());
089        mCheckBox.setText("Gallery is Circular");
090        mCheckBox.setText("Gallery is Circular");
091        mCheckBox.setPadding(50, 10, 0, 10);
092        mCheckBox.setTextSize(30);
093        mCheckBox.setChecked(true);
094        mCheckBox.setOnClickListener(new OnClickListener()
095        {
096            @Override
097            public void onClick(View view)
098            {
099                mGallery.setIsGalleryCircular(mCheckBox.isChecked());
100            }
101        });
102  
103        layout.addView(mCheckBox, new LinearLayout.LayoutParams(
104                LinearLayout.LayoutParams.MATCH_PARENT,
105                LinearLayout.LayoutParams.WRAP_CONTENT));
106          
107        setContentView(layout);
108    }   
109  
110    private class GalleryViewItem extends TableLayout
111    {
112        private EditText mEdit1;
113        private TextView mText1;
114        private TextView mText2;
115        private Button mButton1;
116        private Button mButton2;
117  
118        public GalleryViewItem(Context context, int position)
119        {
120            super(context);
121  
122            this.setOrientation(LinearLayout.VERTICAL);
123  
124            this.setLayoutParams(new LinearLayout.LayoutParams(
125                    LinearLayout.LayoutParams.MATCH_PARENT,
126                    LinearLayout.LayoutParams.MATCH_PARENT));
127              
128            mEdit1 = new EditText(context);
129  
130            this.addView(mEdit1, new LinearLayout.LayoutParams(
131                    LinearLayout.LayoutParams.MATCH_PARENT,
132                    LinearLayout.LayoutParams.WRAP_CONTENT)); 
133  
134            mText1 = new TextView(context);
135            mText1.setText(mLabelArray[position]);
136            mText1.setTextSize(30);
137            mText1.setGravity(Gravity.LEFT);
138            mText1.setBackgroundColor(mColorArray[position]);
139  
140            this.addView(mText1, new LinearLayout.LayoutParams(
141                    LinearLayout.LayoutParams.MATCH_PARENT,
142                    LinearLayout.LayoutParams.WRAP_CONTENT)); 
143  
144            mButton1 = new Button(context);
145            mButton1.setText("<<");
146            mButton1.setGravity(Gravity.LEFT);
147            mButton1.setOnClickListener(new OnClickListener()
148            {
149                @Override
150                public void onClick(View view)
151                {
152                    mGallery.movePrevious();
153                }
154            });
155              
156            this.addView(mButton1, new LinearLayout.LayoutParams(
157                    LinearLayout.LayoutParams.MATCH_PARENT,
158                    LinearLayout.LayoutParams.WRAP_CONTENT)); 
159  
160            mButton2 = new Button(context);
161            mButton2.setText(">>");
162            mButton2.setGravity(Gravity.RIGHT);
163            mButton2.setOnClickListener(new OnClickListener()
164            {
165                @Override
166                public void onClick(View view)
167                {
168                    mGallery.moveNext();
169                }
170            });
171              
172            this.addView(mButton2, new LinearLayout.LayoutParams(
173                    LinearLayout.LayoutParams.MATCH_PARENT,
174                    LinearLayout.LayoutParams.WRAP_CONTENT)); 
175  
176            mText2 = new TextView(context);
177            mText2.setText(mLabelArray[position]);
178            mText2.setTextSize(30);
179            mText2.setGravity(Gravity.RIGHT);
180            mText2.setBackgroundColor(mColorArray[position]);
181  
182            this.addView(mText2, new LinearLayout.LayoutParams(
183                    LinearLayout.LayoutParams.MATCH_PARENT,
184                    LinearLayout.LayoutParams.MATCH_PARENT, 1)); 
185        }
186    }
187}

[代码] FlingGallery

001import android.content.Context;
002import android.view.GestureDetector;
003import android.view.KeyEvent;
004import android.view.MotionEvent;
005import android.view.View;
006import android.view.animation.Animation;
007import android.view.animation.AnimationUtils;
008import android.view.animation.Interpolator;
009import android.view.animation.Transformation;
010import android.widget.Adapter;
011import android.widget.FrameLayout;
012import android.widget.LinearLayout;
013  
014// TODO:
015  
016// 1. In order to improve performance Cache screen bitmap and use for animation
017// 2. Establish superfluous memory allocations and delay or replace with reused objects
018//    Probably need to make sure we are not allocating objects (strings, etc.) in loops
019  
020public class FlingGallery extends FrameLayout
021{
022    // Constants
023      
024    private final int swipe_min_distance = 120;
025    private final int swipe_max_off_path = 250;
026    private final int swipe_threshold_veloicty = 400;
027  
028    // Properties
029      
030    private int mViewPaddingWidth = 0;
031    private int mAnimationDuration = 250;
032    private float mSnapBorderRatio = 0.5f;
033    private boolean mIsGalleryCircular = true;
034  
035    // Members
036  
037    private int mGalleryWidth = 0;
038    private boolean mIsTouched = false;
039    private boolean mIsDragging = false;
040    private float mCurrentOffset = 0.0f;
041    private long mScrollTimestamp = 0;
042    private int mFlingDirection = 0;
043    private int mCurrentPosition = 0;
044    private int mCurrentViewNumber = 0;
045  
046    private Context mContext;
047    private Adapter mAdapter;
048    private FlingGalleryView[] mViews;
049    private FlingGalleryAnimation mAnimation;
050    private GestureDetector mGestureDetector;
051    private Interpolator mDecelerateInterpolater;
052  
053    public FlingGallery(Context context)
054    {
055        super(context);
056  
057        mContext = context;
058        mAdapter = null;
059          
060        mViews = new FlingGalleryView[3];
061        mViews[0] = new FlingGalleryView(0, this);
062        mViews[1] = new FlingGalleryView(1, this);
063        mViews[2] = new FlingGalleryView(2, this);
064  
065        mAnimation = new FlingGalleryAnimation();
066        mGestureDetector = new GestureDetector(new FlingGestureDetector());
067        mDecelerateInterpolater = AnimationUtils.loadInterpolator(mContext, android.R.anim.decelerate_interpolator);
068    }
069  
070    public void setPaddingWidth(int viewPaddingWidth)
071    {
072        mViewPaddingWidth = viewPaddingWidth;
073    }
074  
075    public void setAnimationDuration(int animationDuration)
076    {
077        mAnimationDuration = animationDuration;
078    }
079      
080    public void setSnapBorderRatio(float snapBorderRatio)
081    {
082        mSnapBorderRatio = snapBorderRatio;
083    }
084  
085    public void setIsGalleryCircular(boolean isGalleryCircular) 
086    {
087        if (mIsGalleryCircular != isGalleryCircular)
088        {
089            mIsGalleryCircular = isGalleryCircular;
090      
091            if (mCurrentPosition == getFirstPosition())
092            {
093                // We need to reload the view immediately to the left to change it to circular view or blank
094                mViews[getPrevViewNumber(mCurrentViewNumber)].recycleView(getPrevPosition(mCurrentPosition));           
095            }
096      
097            if (mCurrentPosition == getLastPosition())
098            {
099                // We need to reload the view immediately to the right to change it to circular view or blank
100                mViews[getNextViewNumber(mCurrentViewNumber)].recycleView(getNextPosition(mCurrentPosition));           
101            }
102        }
103    }
104  
105    public int getGalleryCount()
106    {
107        return (mAdapter == null) ? 0 : mAdapter.getCount();
108    }
109  
110    public int getFirstPosition()
111    {
112        return 0;
113    }
114  
115    public int getLastPosition()
116    {
117        return (getGalleryCount() == 0) ? 0 : getGalleryCount() - 1;
118    }
119  
120    private int getPrevPosition(int relativePosition)
121    {
122        int prevPosition = relativePosition - 1;
123  
124        if (prevPosition < getFirstPosition())
125        {
126            prevPosition = getFirstPosition() - 1;
127  
128            if (mIsGalleryCircular == true)
129            {
130                prevPosition = getLastPosition();
131            }
132        }
133  
134        return prevPosition;
135    }
136  
137    private int getNextPosition(int relativePosition)
138    {
139        int nextPosition = relativePosition + 1;
140  
141        if (nextPosition > getLastPosition())
142        {
143            nextPosition = getLastPosition() + 1;
144  
145            if (mIsGalleryCircular == true)
146            {
147                nextPosition = getFirstPosition();
148            }
149        }
150  
151        return nextPosition;
152    }
153  
154    private int getPrevViewNumber(int relativeViewNumber)
155    {
156        return (relativeViewNumber == 0) ? 2 : relativeViewNumber - 1;
157    }
158  
159    private int getNextViewNumber(int relativeViewNumber)
160    {
161        return (relativeViewNumber == 2) ? 0 : relativeViewNumber + 1;
162    }
163      
164    @Override
165    protected void onLayout(boolean changed, int left, int top, int right, int bottom)
166    {
167        super.onLayout(changed, left, top, right, bottom);
168  
169        // Calculate our view width
170        mGalleryWidth = right - left;
171  
172        if (changed == true)
173        {
174            // Position views at correct starting offsets
175            mViews[0].setOffset(0, 0, mCurrentViewNumber);
176            mViews[1].setOffset(0, 0, mCurrentViewNumber);
177            mViews[2].setOffset(0, 0, mCurrentViewNumber);
178        }
179    }
180  
181    public void setAdapter(Adapter adapter)
182    {
183        mAdapter = adapter;
184        mCurrentPosition = 0;
185        mCurrentViewNumber = 0;
186  
187        // Load the initial views from adapter
188        mViews[0].recycleView(mCurrentPosition);
189        mViews[1].recycleView(getNextPosition(mCurrentPosition));
190        mViews[2].recycleView(getPrevPosition(mCurrentPosition));
191  
192        // Position views at correct starting offsets
193        mViews[0].setOffset(0, 0, mCurrentViewNumber);
194        mViews[1].setOffset(0, 0, mCurrentViewNumber);
195        mViews[2].setOffset(0, 0, mCurrentViewNumber);
196    }
197  
198    private int getViewOffset(int viewNumber, int relativeViewNumber)
199    {
200        // Determine width including configured padding width
201        int offsetWidth = mGalleryWidth + mViewPaddingWidth;
202  
203        // Position the previous view one measured width to left
204        if (viewNumber == getPrevViewNumber(relativeViewNumber))
205        {
206            return offsetWidth;
207        }
208  
209        // Position the next view one measured width to the right
210        if (viewNumber == getNextViewNumber(relativeViewNumber))
211        {
212            return offsetWidth * -1;
213        }
214  
215        return 0;
216    }
217  
218    void movePrevious()
219    {
220        // Slide to previous view
221        mFlingDirection = 1;
222        processGesture();
223    }
224  
225    void moveNext()
226    {
227        // Slide to next view
228        mFlingDirection = -1;
229        processGesture();
230    }
231  
232     @Override
233     public boolean onKeyDown(int keyCode, KeyEvent event)
234     {
235        switch (keyCode)
236        {
237        case KeyEvent.KEYCODE_DPAD_LEFT:
238            movePrevious();
239            return true;
240      
241        case KeyEvent.KEYCODE_DPAD_RIGHT:
242            moveNext();
243            return true;
244      
245        case KeyEvent.KEYCODE_DPAD_CENTER:
246        case KeyEvent.KEYCODE_ENTER:
247        }
248  
249        return super.onKeyDown(keyCode, event);
250    }
251  
252    public boolean onGalleryTouchEvent(MotionEvent event)
253    {
254        boolean consumed = mGestureDetector.onTouchEvent(event);
255          
256        if (event.getAction() == MotionEvent.ACTION_UP)
257        {
258            if (mIsTouched || mIsDragging)
259            {
260                processScrollSnap();
261                processGesture();
262            }
263        }
264          
265        return consumed;
266    }
267  
268    void processGesture()
269    {
270        int newViewNumber = mCurrentViewNumber;
271        int reloadViewNumber = 0;
272        int reloadPosition = 0;
273  
274        mIsTouched = false;
275        mIsDragging = false;
276  
277        if (mFlingDirection > 0)
278        {
279            if (mCurrentPosition > getFirstPosition() || mIsGalleryCircular == true)
280            {
281                // Determine previous view and outgoing view to recycle
282                newViewNumber = getPrevViewNumber(mCurrentViewNumber);
283                mCurrentPosition = getPrevPosition(mCurrentPosition);
284                reloadViewNumber = getNextViewNumber(mCurrentViewNumber); 
285                reloadPosition = getPrevPosition(mCurrentPosition);
286            }
287        }
288  
289        if (mFlingDirection < 0)
290        {
291            if (mCurrentPosition < getLastPosition() || mIsGalleryCircular == true)
292            {
293                // Determine the next view and outgoing view to recycle
294                newViewNumber = getNextViewNumber(mCurrentViewNumber);
295                mCurrentPosition = getNextPosition(mCurrentPosition);
296                reloadViewNumber = getPrevViewNumber(mCurrentViewNumber);
297                reloadPosition = getNextPosition(mCurrentPosition);
298            }
299        }
300  
301        if (newViewNumber != mCurrentViewNumber)
302        {
303            mCurrentViewNumber = newViewNumber; 
304  
305            // Reload outgoing view from adapter in new position
306            mViews[reloadViewNumber].recycleView(reloadPosition);
307        }
308  
309        // Ensure input focus on the current view
310        mViews[mCurrentViewNumber].requestFocus();
311  
312        // Run the slide animations for view transitions
313        mAnimation.prepareAnimation(mCurrentViewNumber);
314        this.startAnimation(mAnimation);
315  
316        // Reset fling state
317        mFlingDirection = 0;
318    }
319  
320    void processScrollSnap()
321    {
322        // Snap to next view if scrolled passed snap position
323        float rollEdgeWidth = mGalleryWidth * mSnapBorderRatio;
324        int rollOffset = mGalleryWidth - (int) rollEdgeWidth;
325        int currentOffset = mViews[mCurrentViewNumber].getCurrentOffset();
326  
327        if (currentOffset <= rollOffset * -1)
328        {
329            // Snap to previous view
330            mFlingDirection = 1;
331        }
332  
333        if (currentOffset >= rollOffset)
334        {
335            // Snap to next view
336            mFlingDirection = -1;
337        }
338    }
339  
340    private class FlingGalleryView
341    {
342        private int mViewNumber;
343        private FrameLayout mParentLayout;
344          
345        private FrameLayout mInvalidLayout = null;
346        private LinearLayout mInternalLayout = null;
347        private View mExternalView = null;
348  
349        public FlingGalleryView(int viewNumber, FrameLayout parentLayout)
350        {
351            mViewNumber = viewNumber;
352            mParentLayout = parentLayout;
353  
354            // Invalid layout is used when outside gallery
355            mInvalidLayout = new FrameLayout(mContext);
356            mInvalidLayout.setLayoutParams(new LinearLayout.LayoutParams( 
357                    LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
358  
359            // Internal layout is permanent for duration
360            mInternalLayout = new LinearLayout(mContext);
361            mInternalLayout.setLayoutParams(new LinearLayout.LayoutParams( 
362                    LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
363  
364            mParentLayout.addView(mInternalLayout);
365        }
366  
367        public void recycleView(int newPosition)
368        {
369            if (mExternalView != null)
370            {
371                mInternalLayout.removeView(mExternalView);
372            }
373  
374            if (mAdapter != null)
375            {
376                if (newPosition >= getFirstPosition() && newPosition <= getLastPosition())
377                {
378                    mExternalView = mAdapter.getView(newPosition, mExternalView, mInternalLayout);
379                }
380                else
381                {
382                    mExternalView = mInvalidLayout;
383                }
384            }
385  
386            if (mExternalView != null)
387            {
388                mInternalLayout.addView(mExternalView, new LinearLayout.LayoutParams( 
389                    LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
390            }
391        }
392  
393        public void setOffset(int xOffset, int yOffset, int relativeViewNumber)
394        {
395            // Scroll the target view relative to its own position relative to currently displayed view
396            mInternalLayout.scrollTo(getViewOffset(mViewNumber, relativeViewNumber) + xOffset, yOffset);
397        }
398          
399        public int getCurrentOffset()
400        {
401            // Return the current scroll position
402            return mInternalLayout.getScrollX();
403        }
404  
405        public void requestFocus()
406        {
407            mInternalLayout.requestFocus();
408        }
409    }
410  
411    private class FlingGalleryAnimation extends Animation
412    {
413        private boolean mIsAnimationInProgres;
414        private int mRelativeViewNumber;
415        private int mInitialOffset;
416        private int mTargetOffset;
417        private int mTargetDistance;    
418   
419        public FlingGalleryAnimation()
420        {
421            mIsAnimationInProgres = false;
422            mRelativeViewNumber = 0;
423            mInitialOffset = 0;
424            mTargetOffset = 0;
425            mTargetDistance = 0;
426        }
427   
428        public void prepareAnimation(int relativeViewNumber)
429        {
430            // If we are animating relative to a new view
431            if (mRelativeViewNumber != relativeViewNumber)
432            {
433                if (mIsAnimationInProgres == true)
434                {
435                    // We only have three views so if requested again to animate in same direction we must snap 
436                    int newDirection = (relativeViewNumber == getPrevViewNumber(mRelativeViewNumber)) ? 1 : -1;
437                    int animDirection = (mTargetDistance < 0) ? 1 : -1
438  
439                    // If animation in same direction
440                    if (animDirection == newDirection)
441                    {
442                        // Ran out of time to animate so snap to the target offset
443                        mViews[0].setOffset(mTargetOffset, 0, mRelativeViewNumber);
444                        mViews[1].setOffset(mTargetOffset, 0, mRelativeViewNumber);
445                        mViews[2].setOffset(mTargetOffset, 0, mRelativeViewNumber); 
446                    }
447                }
448      
449                // Set relative view number for animation
450                mRelativeViewNumber = relativeViewNumber;
451            }
452  
453            // Note: In this implementation the targetOffset will always be zero
454            // as we are centering the view; but we include the calculations of
455            // targetOffset and targetDistance for use in future implementations
456  
457            mInitialOffset = mViews[mRelativeViewNumber].getCurrentOffset();
458            mTargetOffset = getViewOffset(mRelativeViewNumber, mRelativeViewNumber);
459            mTargetDistance = mTargetOffset - mInitialOffset;
460  
461            // Configure base animation properties
462            this.setDuration(mAnimationDuration);
463            this.setInterpolator(mDecelerateInterpolater);
464  
465            // Start/continued animation
466            mIsAnimationInProgres = true;
467        }
468  
469        @Override
470        protected void applyTransformation(float interpolatedTime, Transformation transformation)
471        {
472            // Ensure interpolatedTime does not over-shoot then calculate new offset
473            interpolatedTime = (interpolatedTime > 1.0f) ? 1.0f : interpolatedTime;
474            int offset = mInitialOffset + (int) (mTargetDistance * interpolatedTime);
475  
476            for (int viewNumber = 0; viewNumber < 3; viewNumber++)
477            {
478                // Only need to animate the visible views as the other view will always be off-screen
479                if ((mTargetDistance > 0 && viewNumber != getNextViewNumber(mRelativeViewNumber)) ||
480                    (mTargetDistance < 0 && viewNumber != getPrevViewNumber(mRelativeViewNumber)))
481                {
482                    mViews[viewNumber].setOffset(offset, 0, mRelativeViewNumber);
483                }
484            }
485        }
486  
487        @Override
488        public boolean getTransformation(long currentTime, Transformation outTransformation)
489        {
490            if (super.getTransformation(currentTime, outTransformation) == false)
491            {
492                // Perform final adjustment to offsets to cleanup animation
493                mViews[0].setOffset(mTargetOffset, 0, mRelativeViewNumber);
494                mViews[1].setOffset(mTargetOffset, 0, mRelativeViewNumber);
495                mViews[2].setOffset(mTargetOffset, 0, mRelativeViewNumber);
496  
497                // Reached the animation target
498                mIsAnimationInProgres = false;
499  
500                return false;
501            }
502   
503            // Cancel if the screen touched
504            if (mIsTouched || mIsDragging)
505            {
506                // Note that at this point we still consider ourselves to be animating
507                // because we have not yet reached the target offset; its just that the
508                // user has temporarily interrupted the animation with a touch gesture
509  
510                return false;
511            }
512  
513            return true;
514        }
515    }
516  
517    private class FlingGestureDetector extends GestureDetector.SimpleOnGestureListener
518    {
519        @Override
520        public boolean onDown(MotionEvent e)
521        {
522            // Stop animation
523            mIsTouched = true;
524  
525            // Reset fling state
526            mFlingDirection = 0;
527            return true;
528        }
529  
530        @Override
531        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
532        {
533            if (e2.getAction() == MotionEvent.ACTION_MOVE)
534            {
535                if (mIsDragging == false)
536                {
537                    // Stop animation
538                    mIsTouched = true;
539       
540                    // Reconfigure scroll
541                    mIsDragging = true;
542                    mFlingDirection = 0;
543                    mScrollTimestamp = System.currentTimeMillis();
544                    mCurrentOffset = mViews[mCurrentViewNumber].getCurrentOffset();
545                }
546  
547                float maxVelocity = mGalleryWidth / (mAnimationDuration / 1000.0f);
548                long timestampDelta = System.currentTimeMillis() - mScrollTimestamp;
549                float maxScrollDelta = maxVelocity * (timestampDelta / 1000.0f); 
550                float currentScrollDelta = e1.getX() - e2.getX();
551  
552                if (currentScrollDelta < maxScrollDelta * -1) currentScrollDelta = maxScrollDelta * -1;
553                if (currentScrollDelta > maxScrollDelta) currentScrollDelta = maxScrollDelta;
554                int scrollOffset = Math.round(mCurrentOffset + currentScrollDelta);
555  
556                // We can't scroll more than the width of our own frame layout
557                if (scrollOffset >= mGalleryWidth) scrollOffset = mGalleryWidth;
558                if (scrollOffset <= mGalleryWidth * -1) scrollOffset = mGalleryWidth * -1;
559                  
560                mViews[0].setOffset(scrollOffset, 0, mCurrentViewNumber);
561                mViews[1].setOffset(scrollOffset, 0, mCurrentViewNumber);
562                mViews[2].setOffset(scrollOffset, 0, mCurrentViewNumber);
563            }
564  
565            return false;
566        }
567  
568        @Override
569        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
570        {
571            if (Math.abs(e1.getY() - e2.getY()) <= swipe_max_off_path)
572            {
573                if (e2.getX() - e1.getX() > swipe_min_distance && Math.abs(velocityX) > swipe_threshold_veloicty)
574                {
575                    movePrevious();
576                }
577  
578                if(e1.getX() - e2.getX() > swipe_min_distance && Math.abs(velocityX) > swipe_threshold_veloicty)
579                {
580                    moveNext();
581                }
582            }
583  
584            return false;
585        }
586  
587        @Override
588        public void onLongPress(MotionEvent e)
589        {
590            // Finalise scrolling
591            mFlingDirection = 0;
592            processGesture();
593        }
594  
595        @Override
596        public void onShowPress(MotionEvent e)
597        {
598        }
599  
600        @Override
601        public boolean onSingleTapUp(MotionEvent e)
602        {
603            // Reset fling state
604            mFlingDirection = 0;
605            return false;
606        }
607    }
608}
智慧旅游解决方案利用云计算、物联网和移动互联网技术,通过便携终端设备,实现对旅游资源、经济、活动和旅游者信息的智能感知和发布。这种技术的应用旨在提升游客在旅游各个环节的体验,使他们能够轻松获取信息、规划行程、预订票务和安排食宿。智慧旅游平台为旅游管理部门、企业和游客提供服务,包括政策发布、行政管理、景区安全、游客流量统计分析、投诉反馈等。此外,平台还提供广告促销、库存信息、景点介绍、电子门票、社交互动等功能。 智慧旅游的建设规划得到了国家政策的支持,如《国家中长期科技发展规划纲要》和国务院的《关于加快发展旅游业的意见》,这些政策强调了旅游信息服务平台的建设和信息化服务的重要性。随着技术的成熟和政策环境的优化,智慧旅游的时机已经到来。 智慧旅游平台采用SaaS、PaaS和IaaS等云服务模式,提供简化的软件开发、测试和部署环境,实现资源的按需配置和快速部署。这些服务模式支持旅游企业、消费者和管理部门开发高性能、高可扩展的应用服务。平台还整合了旅游信息资源,提供了丰富的旅游产品创意平台和统一的旅游综合信息库。 智慧旅游融合应用面向游客和景区景点主管机构,提供无线城市门户、智能导游、智能门票及优惠券、景区综合安防、车辆及停车场管理等服务。这些应用通过物联网和云计算技术,实现了旅游服务的智能化、个性化和协同化,提高了旅游服务的自由度和信息共享的动态性。 智慧旅游的发展标志着旅游信息化建设的智能化和应用多样化趋势,多种技术和应用交叉渗透至旅游行业的各个方面,预示着全面的智慧旅游时代已经到来。智慧旅游不仅提升了游客的旅游体验,也为旅游管理和服务提供了高效的技术支持。
智慧旅游解决方案利用云计算、物联网和移动互联网技术,通过便携终端设备,实现对旅游资源、经济、活动和旅游者信息的智能感知和发布。这种技术的应用旨在提升游客在旅游各个环节的体验,使他们能够轻松获取信息、规划行程、预订票务和安排食宿。智慧旅游平台为旅游管理部门、企业和游客提供服务,包括政策发布、行政管理、景区安全、游客流量统计分析、投诉反馈等。此外,平台还提供广告促销、库存信息、景点介绍、电子门票、社交互动等功能。 智慧旅游的建设规划得到了国家政策的支持,如《国家中长期科技发展规划纲要》和国务院的《关于加快发展旅游业的意见》,这些政策强调了旅游信息服务平台的建设和信息化服务的重要性。随着技术的成熟和政策环境的优化,智慧旅游的时机已经到来。 智慧旅游平台采用SaaS、PaaS和IaaS等云服务模式,提供简化的软件开发、测试和部署环境,实现资源的按需配置和快速部署。这些服务模式支持旅游企业、消费者和管理部门开发高性能、高可扩展的应用服务。平台还整合了旅游信息资源,提供了丰富的旅游产品创意平台和统一的旅游综合信息库。 智慧旅游融合应用面向游客和景区景点主管机构,提供无线城市门户、智能导游、智能门票及优惠券、景区综合安防、车辆及停车场管理等服务。这些应用通过物联网和云计算技术,实现了旅游服务的智能化、个性化和协同化,提高了旅游服务的自由度和信息共享的动态性。 智慧旅游的发展标志着旅游信息化建设的智能化和应用多样化趋势,多种技术和应用交叉渗透至旅游行业的各个方面,预示着全面的智慧旅游时代已经到来。智慧旅游不仅提升了游客的旅游体验,也为旅游管理和服务提供了高效的技术支持。
深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值