2011-05-07 36 views
19

預期的效果 我有一堆小圖片,我想展現一個「牆」然後讓用戶向任何方向扔這個牆並選擇一個圖像。尋找實現牆(GridView的?)那熄滅屏幕和用戶可以通過觸摸來移動它

初步設想 作爲一個可能的實現我在想一個GridView比屏幕可以顯示大 - 但使用這個小部件的所有實例表明,該畫廊沒有超出屏幕的大小。

問題 什麼是最好的部件來實現所需的效果?代碼示例將特別有益。

編輯... 如果有人有示例代碼,這將讓我把大約30圖像上的「牆」(表將是一件好事),那麼我會接受的答案。請注意,「牆」應該看起來像它超出了顯示器的邊緣,並允許用戶使用手指將「牆」向左下拖動。拖動應該處於「自由形式」模式。在圖像上點擊一下即可選中它,並且可以檢測到回調。我爲這個解決方案創造了一個獎勵。

回答

11

該解決方案其實很簡單,但很痛苦。我不得不在我最近做的一個計劃中實現這一點。有幾個棘手的事情你必須避開。必須注意的是,不同的操作系統版本有不同的體驗。需要某些專業知識或者圍繞這項工作,因爲繪圖有時會受到這種方法的不利影響。雖然有一個工作拷貝,我提供的代碼並不適合每一個人,並受到任何已經在你的代碼已經做了修改或自定義。

  • 設置android:layout_widthwrap_content
  • 設置android:layout_heightwrap_content
  • 在您的代碼:
    • 確定多少行,你都會有。通過行數項
    • 鴻溝號。
    • 添加GridView控件。 setStretchMode(NO_STRETCH);
    • 添加GridView控件。 setNumColumns(數列);
    • 的添加GridView控件。 setColumnWidth(像素);
  • 一個明確的寬度要滾動:
    • 您可以簡單地使用GridView控件。 scrollBy()onTouchEvent()

這些步驟。所有這些都是必需的,才能使其發揮作用。關鍵是具有特定寬度的明確列數的NO_STRETCH。如果您需要澄清,可以提供更多細節。你甚至可以使用VelocityTracker或onFling來處理投擲。我在我的snappingToPage啓用。使用此解決方案,甚至不需要覆蓋onDraw()onLayout()。這三行代碼擺脫了對WebView或任何其他嵌入或嵌套的需求。

雙向滾動也很容易實現。這是一個簡單的代碼解決方案:

  1. 首先,你的班級開始跟蹤X和Y位置,通過製作兩個班級成員。還要添加狀態跟蹤;

    // Holds the last position of the touch event (including movement) 
    int myLastX; 
    int myLastY; 
    
    // Tracks the state of the Touch handling 
    final static private int TOUCH_STATE_REST = 0; 
    final static private int TOUCH_STATE_SCROLLING = 1; 
    int myState = TOUCH_STATE_REST; 
    
  2. 其次,一定要檢查滾動,這樣你仍然可以點擊或長按圖片自己。

    @Override public boolean onInterceptTouchEvent(final MotionEvent ev) 
    {//User is already scrolling something. If we haven't interrupted this already, 
    // then something else is handling its own scrolling and we should let this be. 
    // Once we return TRUE, this event no longer fires and instead all goes to 
    // onTouch() until the next TouchEvent begins (often beginning with ACTION_DOWN). 
        if ((ev.getAction() == MotionEvent.ACTION_MOVE) 
        && (myState != TOUCH_STATE_REST)) 
         return false; 
    
    // Grab the X and Y positions of the MotionEvent 
        final float _x = ev.getX(); 
        final float _y = ev.getY(); 
        switch (ev.getAction()) 
        { case MotionEvent.ACTION_MOVE: 
          final int _diffX = (int) Math.abs(_x - myLastX); 
          final int _diffY = (int) Math.abs(_y - myLastY); 
    
          final boolean xMoved = _diffX > 0; 
          final boolean yMoved = _diffY > 0; 
          if (xMoved || yMoved) 
           myState = TOUCH_STATE_SCROLLING; 
          break; 
         case MotionEvent.ACTION_DOWN: 
         // Remember location of down touch 
          myLastX = _x; 
          myLastY = _y; 
          break; 
         case MotionEvent.ACTION_CANCEL: 
         case MotionEvent.ACTION_UP: 
          if (myState == TOUCH_STATE_SCROLLING) 
          // Release the drag 
           myState = TOUCH_STATE_REST; 
    
        } 
        //If we are not At Rest, start handling in our own onTouch() 
        return myState != TOUCH_STATE_REST; 
    } 
    
  3. 後在GridView知道您正在滾動,它會發送所有觸摸事件onTouch。在這裏做你的滾動。

    @Override public boolean onTouchEvent(final MotionEvent ev) 
    { 
        final int action = ev.getAction(); 
        final float x = ev.getX(); 
        final float y = ev.getY(); 
        final View child; 
    
        switch (action) 
        { 
         case MotionEvent.ACTION_DOWN: 
          //Supplemental code, if needed 
          break; 
         case MotionEvent.ACTION_MOVE: 
          // This handles Scrolling only. 
          if (myState == TOUCH_STATE_SCROLLING) 
          { 
           // Scroll to follow the motion event 
           // This will update the vars as long as your finger is down. 
           final int deltaX = (int) (myLastX - x); 
           final int deltaY = (int) (myLastY - y); 
           myLastX = x; 
           myLastY = y; 
           scrollBy(deltaX, deltaY); 
          } 
          break; 
         case MotionEvent.ACTION_UP: 
         // If Scrolling, stop the scroll so we can scroll later. 
          if (myState == TOUCH_STATE_SCROLLING) 
           myState = TOUCH_STATE_REST; 
          break 
         case MotionEvent.ACTION_CANCEL: 
         // This is just a failsafe. I don't even know how to cancel a touch event 
          myState = TOUCH_STATE_REST; 
        } 
    
    return true; 
    } 
    

如果當然,這個解決方案在移動X和Y同時。如果您想一次只移動一個方向,則可以通過檢查X和Y差異中的較大差異輕鬆進行區分。 (即Math.abs(deltaX) > Math.abs(deltaY))以下是一個方向滾動的部分示例,但可以在X或Y方向之間切換。

3b。如果你想在同一時間處理一個方向你OnTouch()更改此:

  case MotionEvent.ACTION_MOVE: 
       if (myState == TOUCH_STATE_SCROLLING) 
       { 
        //This will update the vars as long as your finger is down. 
        final int deltaX = (int) (myLastX - x); 
        final int deltaY = (int) (myLastY - y); 
        myLastX = x; 
        myLastY = y; 

        // Check which direction is the bigger of the two 
        if (Math.abs(deltaX) > Math.abs(deltaY)) 
         scrollBy(deltaX, 0); 
        else if (Math.abs(deltaY) > Math.abs(deltaX)) 
         scrollBy(0, deltaY); 
        // We do nothing if they are equal. 
       } 
       break; 

FuzzicalLogic

+0

我會提供一個完整的示例,但這些是唯一的3行是重要的他們可能被放置在任何地方。我有三個這樣的GridView,每個放置在不同的地方(一個在初始聲明中,一個在CursorAdapter中,另一個在一個單獨的方法中,從多個地方調用。 – 2011-10-11 22:52:19

+1

並且...作爲一個附註,我一個星期的戳和刺激找到,我很高興,當我這樣做。 – 2011-10-11 22:53:26

+0

mScroller在這種情況下提到什麼?如果你詳細說明一點點,我會獎勵你的賞金 – 2011-10-12 06:29:29

5

A GridView可以具有超出屏幕大小的內容,但僅限於垂直方向。

問:什麼是最好的部件來實現所需的效果?
沒有實現2D滾動的默認小部件(至少在3.0之前)。他們都只實現一維(向一個方向滾動)。可悲的是,解決您的問題並不容易。

,你可以:

  • 放置一個TableLayout定製ScrollView類裏面,自己處理觸摸事件。這將允許您進行適當的2D平移,但對於大型數據集不太適合,因爲沒有視圖可回收
  • 如果可能,修改GridView以啓用水平滾動功能(如果可以的話可能是最好的解決方案)
  • 嘗試把一個TableLayout一個ScrollView內(含layout_width="wrap_content),你把裏面HorizontalScrollView - 儘管這可能工作,它不會是最佳的解決方案
  • 做一些與OpenGL和直畫到畫布 - 這是如何將默認Gallery 3D app做成「圖片牆」
+0

我已經開始了具體的解決方案 – 2011-05-11 19:38:42

+0

你總是可以看看Gallery3D源代碼賞金 - http://android.git.kernel.org/?p=platform/packages/apps/Gallery3D .git; a =摘要 - 直到有人回答。 – 2011-05-11 22:41:24

+1

我有一個想法,它可以很容易地完成,我會在這個週末做一個演示,看看它是否有效。 – 2011-05-19 00:47:50

0

我認爲,唯一的Android本地解決方案是擁有一個嵌入式WebView,您可以在其中使用該二維滾動(並且順便說一下,這是唯一具備此功能的東西)。

按下圖像,您可以通過從JavaScript到JAva的回調來控制行爲。

這不是很「漂亮」,但是......它是唯一可行的方式來做你想要的「開箱即用」。

+0

webview是一個有趣的想法。我可能會用這個想法作爲最後的手段。到目前爲止,我仍然處於研究模式,我發現的最好的「樣本」在這裏:http://stackoverflow.com/questions/3058164/android-scrolling-an-imageview – 2011-05-12 16:49:12

+0

另一個研究樣本,也許我可以調整一個圖像的牆壁:http://blog.sephiroth.it/2011/04/04/imageview-zoom-and-scroll/ – 2011-05-12 16:54:53

0

我實現了一個GridView,它覆蓋onInterceptTouchEvent方法。我按照Fuzzical Logic的說明設置了OnTouchListener。我的問題是設置一個自定義的OnTouchListener,我的gridView的對象不再可點擊。那是因爲GridView的默認OnTouchListener調用onItemClickListener嗎?

我想有一個2方向滾動GridView,但仍然可以cliackable對象。我是否應該實施自己的方法來檢查觸摸是否與項目匹配,或者是否有更簡單的方法來實現此目的?

Grodak

相關問題