Android में स्क्रॉल ऊर्ध्वाधर और क्षैतिज


152

मैं ऊर्ध्वाधर और क्षैतिज स्क्रॉलव्यू के समाधान की तलाश में वास्तव में थक गया हूं।

मैंने पढ़ा कि इस सुविधा को लागू करने वाले ढांचे में कोई विचार / लेआउट नहीं हैं, लेकिन मुझे कुछ इस तरह की आवश्यकता है:

मुझे दूसरे के भीतर एक लेआउट को परिभाषित करने की आवश्यकता है, बच्चे के लेआउट को आगे बढ़ने के लिए स्क्रॉलिंग ऊर्ध्वाधर / क्षैतिज लागू करना होगा।

प्रारंभ में एक कोड लागू किया जो पिक्सेल द्वारा लेआउट पिक्सेल को स्थानांतरित कर दिया, लेकिन मुझे लगता है कि यह सही तरीका नहीं है। मैंने इसे स्क्रॉलव्यू और हॉरिज़ॉन्टल स्क्रॉलव्यू के साथ आज़माया था, लेकिन मैं जैसा चाहता हूं, वैसा कुछ भी नहीं है, क्योंकि यह केवल ऊर्ध्वाधर या क्षैतिज स्क्रॉल को लागू करता है।

कैनवास मेरा समाधान नहीं है क्योंकि मुझे किसी के बाल तत्वों में श्रोताओं को संलग्न करने की आवश्यकता है।

मैं क्या कर सकता हूँ?



14
यह बिल्कुल हास्यास्पद है कि यह एंड्रॉइड के साथ बॉक्स से बाहर उपलब्ध नहीं है। हमने आधा दर्जन अन्य यूआई तकनीकों के साथ काम किया है और एक क्षैतिज / स्थिर कंटेनर के रूप में इस तरह की बुनियादी चीज नहीं होना अनसुना है।
flexicious.com

ठीक है, तो आखिरकार हमने अपने डेटाग्रिड के लिए अपना खुद का लिखा: androidjetpack.com/Home/AndroidDataGrid । केवल क्षैतिज / ऊर्ध्वाधर स्क्रॉल की तुलना में बहुत अधिक है। लेकिन विचार मूल रूप से एक ऊर्ध्वाधर स्कॉलर के अंदर एक एचएसक्रोलर लपेट रहा है। आपको आंतरिक स्कॉलर और कुछ अन्य शीननिगों को लक्षित करने के लिए बाल विधियों को जोड़ना / हटाना ओवरराइड करना होगा, लेकिन यह काम करता है।
flexicious.com

जवाबों:


91

उपरोक्त सुझावों में से कुछ को मिलाकर, और एक अच्छा समाधान प्राप्त करने में सक्षम था:

कस्टम स्क्रॉल दृश्य:

package com.scrollable.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ScrollView;

public class VScroll extends ScrollView {

    public VScroll(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public VScroll(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public VScroll(Context context) {
        super(context);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return false;
    }
}

कस्टम क्षैतिज क्षैतिज दृश्य:

package com.scrollable.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.HorizontalScrollView;

public class HScroll extends HorizontalScrollView {

    public HScroll(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public HScroll(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public HScroll(Context context) {
        super(context);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return false;
    }
}

स्क्रॉल करने योग्य क्षमता:

package com.scrollable.view;

import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.widget.HorizontalScrollView;
import android.widget.ScrollView;

public class ScrollableImageActivity extends Activity {

    private float mx, my;
    private float curX, curY;

    private ScrollView vScroll;
    private HorizontalScrollView hScroll;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        vScroll = (ScrollView) findViewById(R.id.vScroll);
        hScroll = (HorizontalScrollView) findViewById(R.id.hScroll);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float curX, curY;

        switch (event.getAction()) {

            case MotionEvent.ACTION_DOWN:
                mx = event.getX();
                my = event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                curX = event.getX();
                curY = event.getY();
                vScroll.scrollBy((int) (mx - curX), (int) (my - curY));
                hScroll.scrollBy((int) (mx - curX), (int) (my - curY));
                mx = curX;
                my = curY;
                break;
            case MotionEvent.ACTION_UP:
                curX = event.getX();
                curY = event.getY();
                vScroll.scrollBy((int) (mx - curX), (int) (my - curY));
                hScroll.scrollBy((int) (mx - curX), (int) (my - curY));
                break;
        }

        return true;
    }

}

अभिन्यास:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <com.scrollable.view.VScroll android:layout_height="fill_parent"
        android:layout_width="fill_parent" android:id="@+id/vScroll">
        <com.scrollable.view.HScroll android:id="@+id/hScroll"
            android:layout_width="fill_parent" android:layout_height="fill_parent">
            <ImageView android:layout_width="fill_parent" android:layout_height="fill_parent" android:src="@drawable/bg"></ImageView>
        </com.scrollable.view.HScroll>
    </com.scrollable.view.VScroll>

</LinearLayout>

यह एक महान जवाब है, मेरे पास दृश्य में अन्य स्क्रॉलिंग तत्व थे जिन्हें बदलने की भी आवश्यकता थी। मुझे बस इतना करना था कि दूसरों के साथ उनके स्क्रॉल को ट्रिगर किया जाए।
टी। मार्कले

1
महान! खाते में वेग लेने के लिए कुछ समायोजन, और यह एकदम सही होगा (इसके अलावा, आपको प्रारंभिक LinearLayoutअनुमान लगाने की आवश्यकता नहीं है )
रोमुलड ब्रूनट

हे महदी क्या आप मुझे बता सकते हैं, किस नियंत्रण / विजेट पर आपने गतिविधि वर्ग में स्पर्श श्रोता को फिर से जोड़ा है।
शकीलियों

देरी के लिए क्षमा करें @DeepakSharma मैंने गतिविधि में किसी भी स्पर्श श्रोता को पंजीकृत नहीं किया है, मैंने अभी-अभी गतिविधि को चालू किया है।
महदी हिजाज़ी

@MahdiHijazi आप अपने कोड को क्षैतिज स्क्रॉलिंग और कार्यक्षेत्र स्क्रॉलिंग के github.com/MikeOrtiz/TouchImage में जोड़ सकते हैं, यह बटन क्लिक करने पर छवि को सफलतापूर्वक ज़ूम कर रहा है, लेकिन छवि को स्क्रॉल करने में विफल रहा
Erum

43

चूंकि यह "एंड्रॉइड वर्टिकल + हॉरिज़ॉन्टल स्क्रॉल व्यू" के लिए Google में पहला खोज परिणाम प्रतीत होता है, इसलिए मैंने सोचा कि मुझे इसे यहाँ जोड़ना चाहिए। मैट क्लार्क ने एंड्रॉइड स्रोत के आधार पर एक कस्टम दृश्य बनाया है, और यह पूरी तरह से काम करता है: दो आयामी स्क्रॉल दृश्य

खबरदार कि उस पृष्ठ के वर्ग में दृश्य की क्षितिज चौड़ाई की गणना करने वाला एक बग है। मैनुअल हिल्टी द्वारा एक टिप्पणी में है:

समाधान: लाइन 808 पर स्टेटमेंट को निम्नलिखित द्वारा बदलें:

final int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.leftMargin + lp.rightMargin, MeasureSpec.UNSPECIFIED);


संपादित करें: लिंक अब काम नहीं करता है, लेकिन यहाँ ब्लॉगपोस्ट के एक पुराने संस्करण का लिंक है


3
धन्यवाद, यही मैं ढूंढ रहा था।
एंड्रे अगिबालोव

1
यह मेरे लिए कुछ मामूली संशोधन के बाद एक आकर्षण की तरह काम करता है। मैंने फिर से लागू किया fillViewportऔर onMeasureबिल्कुल स्क्रॉलव्यू स्रोत (v2.1) की तरह। मैंने इसके साथ दो पहले कंस्ट्रक्टर को भी बदल दिया: this( context, null );और this(context, attrs, R.attr.scrollViewStyle);। उसके साथ, मैं स्क्रॉलबार का उपयोग करके setVerticalScrollBarEnabledऔर setHorizontalScrollBarEnabledकोड में उपयोग कर सकता हूं ।
ओलिवियर_एसडीजी

मेरे लिए भी महान काम करता है! आपका बहुत बहुत धन्यवाद!
अवियो

लेकिन स्क्रॉल अंगूठे का आकार कैसे प्राप्त करें और नीचे से ऊर्ध्वाधर और क्षैतिज मोड में दाईं ओर स्क्रॉल स्थिति
रवि

10
ऐसा लगता है कि लिंक की गई पोस्ट गायब हो गई है।
loeschg

28

मुझे एक बेहतर उपाय मिला।

XML: (design.xml)

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent">
  <FrameLayout android:layout_width="90px" android:layout_height="90px">
    <RelativeLayout android:id="@+id/container" android:layout_width="fill_parent" android:layout_height="fill_parent">        
    </RelativeLayout>
</FrameLayout>
</FrameLayout>

जावा कोड:

public class Example extends Activity {
  private RelativeLayout container;
  private int currentX;
  private int currentY;

  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.design);

    container = (RelativeLayout)findViewById(R.id.container);

    int top = 0;
    int left = 0;

    ImageView image1 = ...
    RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
    layoutParams.setMargins(left, top, 0, 0);               
    container.addView(image1, layoutParams);

    ImageView image2 = ...
    left+= 100;
    RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
    layoutParams.setMargins(left, top, 0, 0);               
    container.addView(image2, layoutParams);

    ImageView image3 = ...
    left= 0;
    top+= 100;
    RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
    layoutParams.setMargins(left, top, 0, 0);               
    container.addView(image3, layoutParams);

    ImageView image4 = ...
    left+= 100;     
    RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
    layoutParams.setMargins(left, top, 0, 0);               
    container.addView(image4, layoutParams);
  }     

  @Override 
  public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN: {
            currentX = (int) event.getRawX();
            currentY = (int) event.getRawY();
            break;
        }

        case MotionEvent.ACTION_MOVE: {
            int x2 = (int) event.getRawX();
            int y2 = (int) event.getRawY();
            container.scrollBy(currentX - x2 , currentY - y2);
            currentX = x2;
            currentY = y2;
            break;
        }   
        case MotionEvent.ACTION_UP: {
            break;
        }
    }
      return true; 
  }
}

यह काम करता है !!!

यदि आप अन्य लेआउट या नियंत्रण लोड करना चाहते हैं, तो संरचना समान है।


बस यह कोशिश की, और यह बहुत अच्छी तरह से काम करता है! इसमें स्क्रॉल संकेतक या फ़्लिंग नहीं है, लेकिन क्योंकि यह एक निचले-स्तर का दृष्टिकोण है, इसलिए उन चीजों को इस आसानी से बनाया जा सकता है। धन्यवाद!
ubzack

नेटवर्क पर SSH रिमोट कमांड के परिणाम से realtime आउटपुट देने वाले दो आयामी स्क्रॉल दृश्य लिखने के लिए भी मेरे लिए बहुत अच्छा काम किया।
pilcrowpipe

@ क्रोनोस: अगर मैं केवल क्षैतिज रूप से स्क्रॉल करना चाहता हूं तो क्या होगा? कंटेनर में मेरा y पैरामीटर क्या होना चाहिए ।scrollBy (currentX - x2, currentY - y2)। क्या कोई रास्ता है जहाँ हम इसे केवल क्षैतिज रूप से स्क्रॉल कर सकते हैं?
अश्विन

@ क्रोनोस: यह बहुत दूर तक स्क्रॉल करता है। क्या अंत तक पहुंचने पर स्क्रॉल को रोकने का कोई तरीका है?
अश्विन

बटन गैर स्क्रॉल करने योग्य हैं, क्यों?
सालिह कल्लै

25

मैं इसका उपयोग करता हूं और ठीक काम करता हूं:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView android:id="@+id/ScrollView02" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content"
            xmlns:android="http://schemas.android.com/apk/res/android">
<HorizontalScrollView android:id="@+id/HorizontalScrollView01" 
                      android:layout_width="wrap_content" 
                      android:layout_height="wrap_content">
<ImageView android:id="@+id/ImageView01"
           android:src="@drawable/pic" 
           android:isScrollContainer="true" 
           android:layout_height="fill_parent" 
           android:layout_width="fill_parent" 
           android:adjustViewBounds="true">
</ImageView>
</HorizontalScrollView>
</ScrollView>

स्रोत लिंक यहां है: Android-Spa


2
यह स्थिर सामग्री के लिए "बस ठीक" काम करता है, सबसे अच्छे रूप में। कई Google इंजीनियरों ने कहा है कि आप जो उपयोग करने की कोशिश कर रहे हैं, उनमें समस्याएं होंगी ( group.google.com/group/android-developers/browse_frm/thread/…) और groups.google.com/group/android-beginners/browse_thread/thread/ … )।
कॉमन्सवेयर

4
@CommonsWare: शानदार एकाधिक Google इंजीनियरों के लिए श्वेत सम्मान, उन धागों में जो उन्होंने आपको अपने स्वयं के घटक को खरोंच से फिर से लिखने के लिए कहा था: यह सबसे अच्छा तरीका है। निश्चित रूप से सच है। लेकिन वे यह नहीं कहते हैं कि यह समाधान बुरा है, और अगर यह काम करता है ... शायद उनके लिए एक मिनट लगता है, मेरे लिए मौजूदा घटकों का उपयोग करके कुछ xml लिखना बेहतर है। इसका क्या अर्थ है "स्थिर सामग्री"? मैं बटन और छवियों का उपयोग करता हूं।
रेडैक्स

3
"स्टैटिक कंटेंट" से मेरा मतलब उन चीजों से है, जिनमें टच इवेंट्स खुद शामिल नहीं हैं। मेरा उत्तर - इस उत्तर को पढ़ने वाले अन्य लोगों के लिए - यह है कि जबकि आपका समाधान ImageViewस्क्रॉल करने योग्य सामग्री के रूप में एकल के लिए काम कर सकता है, यह मनमाने ढंग से अन्य सामग्री के लिए काम कर सकता है या नहीं कर सकता है, और Google का मानना ​​है कि आपके दृष्टिकोण के साथ समस्याएँ होंगी। भविष्य के विकास के संबंध में Google की राय भी मायने रखती है - वे यह सुनिश्चित करने की कोशिश नहीं कर सकते हैं कि आपका दृष्टिकोण लंबी दौड़ में काम करता है, अगर वे लोगों को सलाह दे रहे हैं कि वे पहली बार में इसका उपयोग न करें।
कॉमन्सवेअर

यह मेरे लिए ठीक काम कर रहा है ... मैं इस स्क्रॉलव्यू में एक थ्रेडव्यू का उपयोग करके एक इमेजव्यू को रिफ्रेश कर रहा हूं
सोनू

19

मेरा हल महदी हिजाज़ी पर आधारित है , लेकिन बिना किसी कस्टम विचार के:

लेआउट:

<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/scrollHorizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ScrollView 
        android:id="@+id/scrollVertical"
        android:layout_width="wrap_content"
        android:layout_height="match_parent" >

        <WateverViewYouWant/>

    </ScrollView>
</HorizontalScrollView>

कोड (onCreate / onCreateView):

    final HorizontalScrollView hScroll = (HorizontalScrollView) value.findViewById(R.id.scrollHorizontal);
    final ScrollView vScroll = (ScrollView) value.findViewById(R.id.scrollVertical);
    vScroll.setOnTouchListener(new View.OnTouchListener() { //inner scroll listener         
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return false;
        }
    });
    hScroll.setOnTouchListener(new View.OnTouchListener() { //outer scroll listener         
        private float mx, my, curX, curY;
        private boolean started = false;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            curX = event.getX();
            curY = event.getY();
            int dx = (int) (mx - curX);
            int dy = (int) (my - curY);
            switch (event.getAction()) {
                case MotionEvent.ACTION_MOVE:
                    if (started) {
                        vScroll.scrollBy(0, dy);
                        hScroll.scrollBy(dx, 0);
                    } else {
                        started = true;
                    }
                    mx = curX;
                    my = curY;
                    break;
                case MotionEvent.ACTION_UP: 
                    vScroll.scrollBy(0, dy);
                    hScroll.scrollBy(dx, 0);
                    started = false;
                    break;
            }
            return true;
        }
    });

आप स्क्रॉलव्यू के क्रम को बदल सकते हैं। बस लेआउट और कोड में उनके क्रम को बदलें। और जाहिर है WateverViewYouWant के बजाय आप उन लेआउट / दृश्यों को डालते हैं जिन्हें आप दोनों दिशाओं को स्क्रॉल करना चाहते हैं।


मैं दृढ़ता से hScroll.setOnTouchListener में गलत लौटने का सुझाव देता हूं। जब मैं गलत में बदल गया, तो सूची को दोनों दिशाओं में उंगली पर "सुचारू रूप से ऑटो" स्क्रॉल करना शुरू कर दिया।
बजे ग्रेटा रदीसौसैकट

1
क्षैतिज रूप से स्क्रॉल करने पर काम करता है। जब ऊर्ध्वाधर पहले होता है, केवल लंबवत चला जाता है
इरला

6

विकल्प # 1: आप एक नए यूआई डिज़ाइन के साथ आ सकते हैं जिसमें एक साथ क्षैतिज और ऊर्ध्वाधर स्क्रॉलिंग की आवश्यकता नहीं होती है।

विकल्प # 2: आप स्रोत कोड को प्राप्त कर सकते हैं ScrollViewऔर HorizontalScrollViewसीख सकते हैं कि कोर एंड्रॉइड टीम ने उन पर कैसे अमल किया, और अपना खुद का BiDirectionalScrollViewकार्यान्वयन बनाया।

विकल्प # 3: आप उन निर्भरताओं से छुटकारा पा सकते हैं जो आपको विजेट सिस्टम का उपयोग करने और कैनवस पर सीधे आकर्षित करने के लिए आवश्यक हैं।

विकल्प # 4: यदि आप एक खुले स्रोत एप्लिकेशन पर ठोकर खाते हैं जो आप चाहते हैं तो लागू करने के लिए लगता है, यह देखने के लिए कि उन्होंने यह कैसे किया।


6

इसे इस्तेमाल करे

<?xml version="1.0" encoding="utf-8"?>
<ScrollView android:id="@+id/Sview" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"
        xmlns:android="http://schemas.android.com/apk/res/android">
<HorizontalScrollView 
   android:id="@+id/hview" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content">
<ImageView .......
 [here xml code for image]
</ImageView>
</HorizontalScrollView>
</ScrollView>

6

चूंकि दो आयामी स्क्रॉलव्यू लिंक मर चुका है, इसलिए मैं इसे प्राप्त नहीं कर सका इसलिए मैंने अपना घटक बनाया। यह झूलता है और मेरे लिए ठीक से काम करता है। एकमात्र प्रतिबंध यह है कि उस घटक के लिए रैप_ कॉन्टेंट ठीक से काम नहीं कर सकता है।

https://gist.github.com/androidseb/9902093


2

आपकी समस्या का हल मेरे पास है। आप स्क्रॉलव्यू कोड की जांच कर सकते हैं यह केवल ऊर्ध्वाधर स्क्रॉलिंग को संभालता है और क्षैतिज एक को अनदेखा करता है और इसे संशोधित करता है। मैं एक वेबव्यू जैसा एक दृश्य चाहता था, इसलिए स्क्रॉलव्यू को संशोधित किया और इसने मेरे लिए अच्छा काम किया। लेकिन यह आपकी आवश्यकताओं के अनुरूप नहीं हो सकता है।

मुझे पता है कि आप किस तरह के UI के लिए लक्ष्य कर रहे हैं।

सादर,

रवि पंडित


1

कोड के साथ खेलते हुए, आप एक क्षैतिज क्षैतिज स्क्रॉल में स्क्रॉल कर सकते हैं। जिससे, आपके पास एक ही दृश्य में दो स्क्रॉल विधि हो सकती है।

स्रोत: http://androiddevblog.blogspot.com/2009/12/creating-two-dimensions-scroll-view.html

मुझे उम्मीद है कि यह आपकी मदद कर सकता है।


1
यह एक अच्छा समाधान नहीं है। यदि आप देखते हैं, तो दृश्य खींचते समय, आप हमेशा लंबवत या क्षैतिज रूप से खींच रहे हैं। नेस्टेड स्क्रॉल दृश्यों का उपयोग करके आप एक विकर्ण के साथ नहीं खींच सकते।
स्काई केल्सी

विकर्ण स्क्रॉलिंग की कमी की तुलना में बदतर क्या है, दोनों स्क्रॉलबार्स की कमी है जो व्यू एज में शेष है क्योंकि एक नेस्टेड है। एक बेहतर स्क्रॉल दृश्य जवाब है और मैट क्लार्क के कोड के लिए कापा का लिंक पूर्णता और सामान्यीकरण के कारण इस समय का सबसे अच्छा समाधान है।
हपरनिकेत्स

0

इस तरह का उपयोग करें मैंने कोशिश की मैंने इसे ठीक कर दिया

अपने सभी XML लेआउट को अंदर रखें

<android.support.v4.widget.NestedScrollView 

मैंने इस लिंक में इसे वर्टिकल रिसाइक्लरव्यू और हॉरिज़ॉन्टल रिसाइक्लेरव्यू स्क्रॉल के साथ एक साथ समझाया

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.