वहाँ हमेशा = "मार्की" हमेशा स्क्रॉल करने के लिए एक तरीका है?


93

मैं एक TextView पर मार्की प्रभाव का उपयोग करना चाहता हूं, लेकिन पाठ केवल तब स्क्रॉल किया जा रहा है जब TextView फ़ोकस हो जाता है। यह एक समस्या है, क्योंकि मेरे मामले में, यह नहीं हो सकता।

मै इस्तेमाल कर रहा हूँ:

  android:ellipsize="marquee"
  android:marqueeRepeatLimit="marquee_forever"

क्या टेक्स्टव्यू को हमेशा अपने पाठ को स्क्रॉल करने का एक तरीका है? मैंने इसे एंड्रॉइड मार्केट ऐप में किया जा रहा है, जहां ऐप का नाम शीर्षक बार में स्क्रॉल किया जाएगा, भले ही यह फोकस प्राप्त नहीं करता हो, लेकिन मुझे यह एपीआई डॉक्स में उल्लिखित नहीं मिला।


मार्की कार्य करने के लिए टेक्स्टव्यू को चुना जाना चाहिए, न कि केंद्रित। फोकस चयन देता है लेकिन रिवर्स नहीं।
डेनिस ग्लैडकी

1
AlwaysMarqueeTextView प्रयास करें stackoverflow.com/a/28806003/3496570
AndroidGeek

जवाबों:


62

मैं समस्या का सामना कर रहा हूं और सबसे छोटा समाधान जो मैं लेकर आया हूं, वह है टेक्स्टव्यू से निकाली गई एक नई कक्षा बनाना। क्लास को तीन तरीकों को ओवरफोकसैन्ग , ऑनविन्डोफोकसचेंज और ओवरफोकड करना चाहिए , जिससे टेक्स्टव्यू सभी केंद्रित हो जाए।

@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
    if(focused)
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
}

@Override
public void onWindowFocusChanged(boolean focused) {
    if(focused)
        super.onWindowFocusChanged(focused);
}


@Override
public boolean isFocused() {
    return true;
}

बिल्कुल सही - यह सिर्फ वह उपाय है जिसकी मुझे तलाश थी।
जेसन

6
यदि आप चाहते हैं कि मेन्यू बंद होने पर मार्की न रुके, तो आपको onWindowFocusChanged विधि को भी ओवरराइड करना चाहिए।
virsir

7
वैसे, हमें वास्तव में इस समाधान के साथ समस्या थी, क्योंकि यह स्टेटफुल ड्रॉज को गड़बड़ कर देता है: यदि आप फोकस-इन / फोकस-आउट के साथ ड्रॉबल्स बदलते हैं, तो यह टूट जाएगा। लगभग हमें डिबगिंग का लगभग एक घंटा लग गया जब तक हमें एहसास नहीं हुआ कि यह हैक पैदा कर रहा था।
मथायस

क्या आप इस मुद्दे का अधिक विस्तृत विवरण प्रदान कर सकते हैं? मैं इस सुविधा का उपयोग कई ऐप में करता हूं। मैं इस समस्या पर भी ध्यान देना चाहूंगा।
7

1
यह हैक बहुत अच्छा काम करता है और इसकी आवश्यकता तब होती है जब एक ही समय में कई टेक्स्ट व्यू स्क्रीन पर होते हैं (जैसे जब लिस्ट व्यू में उपयोग किया जाता है) - क्योंकि आमतौर पर उनमें से केवल एक को फोकस किया जा सकता है, लेकिन यह समाधान सिस्टम को उन सभी को बताकर 'ट्रिक्स' करता है। हैं :) अन्यथा के लिए एकल TextView सरल एवर जैसे कि stackoverflow.com/a/3510891/258848 का उपयोग किया जाना चाहिए।
डिम्यूज़

120

मैं अंत में आज इस समस्या के खिलाफ आया और इसलिए hierarchyviewerएंड्रॉइड मार्केट एप्लिकेशन पर निकाल दिया गया ।

ऐप की डिटेल स्क्रीन पर शीर्षक को देखते हुए, वे एक सादे पुराने का उपयोग करते हैं TextView। इसके गुणों की जांच करने पर पता चला कि इसे केंद्रित नहीं किया गया था, ध्यान केंद्रित नहीं किया जा सकता था और आम तौर पर बहुत सामान्य था - इस तथ्य के अलावा कि इसे चयनित के रूप में चिह्नित किया गया था

बाद में कोड की एक पंक्ति और मेरे पास यह काम था :)

textView.setSelected(true);

यह समझ में आता है, यह देखते हुए कि जवादोक क्या कहता है :

एक दृश्य चुना जा सकता है या नहीं। ध्यान दें कि चयन फोकस के समान नहीं है। दृश्य आमतौर पर सूची दृश्य या ग्रिड दृश्य जैसे किसी एडॉप्टर व्यू के संदर्भ में चुने जाते हैं।

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

दुर्भाग्य से, जहां तक ​​मुझे पता है कि लेआउट एक्सएमएल से चयनित राज्य को पूर्व-निर्धारित करने का कोई तरीका नहीं है।
लेकिन ऊपर वाला वन-लाइनर मेरे लिए ठीक काम करता है।


बस सोच रहा था: क्या यह TextViews के लिए भी काम करेगा जो ध्यान देने योग्य हैं, लेकिन ध्यान केंद्रित नहीं होने पर भी स्क्रॉल करना चाहिए? Iow, क्या फोकस स्थिति बदलने पर भी "स्टिक" का चयन करता है?
मथियास

मुझे ऐसा लगता हैं। मैं यह नहीं देखता कि क्यों एक बुनियादी TextView(यानी किसी तरह "चयन योग्य" में एम्बेडेड नहीं है) पर एक फोकस परिवर्तन ListViewचयनित स्थिति को बदल देगा।
क्रिस्टोफर ओर

यह मेरे लिए भी ठीक काम करता है। आपके उत्तर के लिए धन्यवाद। क्या पुनरावृत्ति के तरीके को बदलने की संभावना है ?!
टिम्मा

@ मूर: हां, TextViewडॉक्यूमेंटेशन पढ़ें और देख लें android:marqueeRepeatLimit
क्रिस्टोफर ओर

1
यह विधि फ़ोकस वाले से बेहतर है क्योंकि यह फ़ोकस फ़ोकस के साथ गड़बड़ नहीं करता है। यदि आपके पास ऐसे विचार हैं जिनके लिए उनके माता-पिता को ध्यान केंद्रित करने की आवश्यकता होती है, तो यह विधि ध्यान को गड़बड़ कर देगी। यह विधि सरल, कुशल है और फ़ोकस को हर बार बदलने के लिए हैक पर निर्भर नहीं होती है। धन्यवाद!
आयनॉट नेगरू

75

बस इन मापदंडों को अपने TextView में रखें। यह काम करता हैं :)

    android:singleLine="true" 
    android:ellipsize="marquee"
    android:marqueeRepeatLimit ="marquee_forever"
    android:scrollHorizontally="true"
    android:focusable="true"
    android:focusableInTouchMode="true" 

1
यदि यह उत्तर धागा पहले से ही मृत नहीं है, तो यह मेरी राय में स्वीकृत उत्तर होना चाहिए। मैंने इसे पाठ दृश्य के लिए अपनी XML परिभाषा में जोड़ा, और इसने पहले शॉट पर काम किया। मैंने अन्य सुझावों की कोशिश की है, और यह सबसे सरल है। - इसके अलावा, जोड़ने "एंड्रॉयड: marqueeRepeatLimit =" marquee_forever "बनाता है यह अनिश्चित काल के लिए स्क्रॉल
Brack

19
यदि TextView इसके अंदर है, तो इसका उपयोग सूची दृश्य पंक्ति के फ़ोकस चयन को तोड़ देता है।
टिवी

अच्छी तरह से काम। सरल और सुरुचिपूर्ण समाधान। धन्यवाद!
रबी

टेक्स्टव्यू की शुरुआत कैसे करें और रोकें
द्विवेदी जी

यह मेरे लिए तब तक काम नहीं आया जब तक मैंने दूसरे उत्तर की कोशिश नहीं की - textView.setSelected (true);
जस्टिन

13

TranslateAnimationएक निर्दिष्ट राशि से एक दिशा में "खींच" द्वारा काम करता है। आप यह सेट कर सकते हैं कि इस "पुलिंग" को कहां से शुरू किया जाए और कहां खत्म किया जाए।

TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta);

fromXDelta ने एक्स अक्ष में आंदोलन की प्रारंभिक स्थिति की भरपाई की।

fromXDelta = 0 //no offset. 
fromXDelta = 300 //the movement starts at 300px to the right.
fromXDelta = -300 //the movement starts at 300px to the left

एक्सएक्सडेल्टा एक्स अक्ष में आंदोलन की ऑफसेट समाप्ति स्थिति को परिभाषित करता है।

toXDelta = 0 //no offset. 
toXDelta = 300 //the movement ends at 300px to the right.
toXDelta = -300 //the movement ends at 300px to the left.

यदि आपके पाठ की चौड़ाई अधिक है कि fromXDelta और toXDelta के बीच अंतर का मॉड्यूल, पाठ स्क्रीन के भीतर समग्र और उचित रूप से स्थानांतरित करने में सक्षम नहीं होगा।


उदाहरण

मान लें कि हमारी स्क्रीन का आकार 320x240 px है। हमारे पास एक TextView टेक्स्ट है जिसमें 700px चौड़ाई है और हम एक एनीमेशन बनाना चाहते हैं जो टेक्स्ट को "खींच" ताकि हम वाक्यांश के अंत को देख सकें।

                                       (screen)
                             +---------------------------+
                             |<----------320px---------->|
                             |                           |
                             |+---------------------------<<<< X px >>>>
               movement<-----|| some TextView with text that goes out...
                             |+---------------------------
                             |  unconstrained size 700px |
                             |                           |
                             |                           |
                             +---------------------------+


                             +---------------------------+
                             |                           |
                             |                           |
               <<<< X px >>>>---------------------------+|
movement<----- some TextView with text that goes out... ||
                             ---------------------------+|
                             |                           |
                             |                           |
                             |                           |
                             +---------------------------+

पहले हम सेट करते हैं fromXDelta = 0ताकि आंदोलन की शुरुआत न हो। अब हमें toXDelta मान का पता लगाने की आवश्यकता है। वांछित प्रभाव को प्राप्त करने के लिए हमें पाठ को ठीक उसी px को "खींचने" की आवश्यकता है जिसे वह स्क्रीन से बाहर फैलाता है। (इस योजना में <<<< X px >>>> का प्रतिनिधित्व किया गया है) क्योंकि हमारे पाठ की चौड़ाई 700 है, और दृश्य क्षेत्र 320px (स्क्रीन की चौड़ाई) है जो हमने निर्धारित किया है:

tXDelta = 700 - 320 = 380

और हम स्क्रीन की चौड़ाई और टेक्स्ट चौड़ाई को कैसे आंकते हैं?


कोड

ज़रा स्निपेट को एक प्रारंभिक बिंदु के रूप में लेना:

    /**
     * @param view The Textview or any other view we wish to apply the movement
     * @param margin A margin to take into the calculation (since the view
     *               might have any siblings in the same "row")
     *
     **/
public static Animation scrollingText(View view, float margin){

    Context context = view.getContext(); //gets the context of the view

            // measures the unconstrained size of the view
            // before it is drawn in the layout
    view.measure(View.MeasureSpec.UNSPECIFIED, 
                         View.MeasureSpec.UNSPECIFIED); 

            // takes the unconstrained wisth of the view
    float width = view.getMeasuredWidth();

            // gets the screen width
    float screenWidth = ((Activity) context).getWindowManager().getDefaultDisplay().getWidth();


            // perfrms the calculation
    float toXDelta = width - (screenWidth - margin);

            // sets toXDelta to 0 if the text width is smaller that the screen size
    if (toXDelta < 0) {toXDelta = 0; } else { toXDelta = 0 - toXDelta;}

            // Animation parameters
    Animation mAnimation = new TranslateAnimation(0, toXDelta, 0, 0);
    mAnimation.setDuration(15000); 
    mAnimation.setRepeatMode(Animation.RESTART);
    mAnimation.setRepeatCount(Animation.INFINITE);

    return mAnimation;
}

इसे करने के आसान तरीके हो सकते हैं, लेकिन यह आपके विचार के लिए काम करता है और पुन: प्रयोज्य है। यह विशेष रूप से उपयोगी है यदि आप टेक्स्ट व्यू के सक्षम / ऑनफोकस क्षमताओं को तोड़ने के बिना एक सूची दृश्य में एक पाठ दृश्य को चेतन करना चाहते हैं। यदि दृश्य केंद्रित नहीं है तो भी यह लगातार स्क्रॉल करता है।


क्या मेरा उत्तर ऊपर है (यानी कोड की एक पंक्ति जोड़ें:) textView.setSelected(true);आपकी स्थिति में काम नहीं करता है?
क्रिस्टोफर ऑर्ट

दुर्भाग्यवश नहीं। मैं प्रत्येक पंक्ति में कई TextViews (इसलिए अंतरिक्ष संकट = पी) के साथ सूचीबद्ध एक सूची दृश्य था। टेक्स्टव्यू की प्रत्येक पंक्ति क्लिक करने योग्य है और एक संदर्भ मेनू को पॉप अप करती है। सेट करना सही है संदर्भ मेनू को तोड़ना प्रतीत होता है।
टिवी 9:10

क्या यह? अधिकांश मामलों के लिए एक तरह का ओवरशूट हो सकता है। मेरे लिए, ऊपर वर्णित कारण के लिए, एकमात्र समाधान था। (यह पुन: प्रयोज्य है, Btw!) = P
टिवी

12

मुझे नहीं पता कि आपको अभी भी उत्तर की आवश्यकता है, लेकिन मुझे ऐसा करने का एक आसान तरीका मिला।

अपना एनीमेशन इस तरह सेट करें:

Animation mAnimation = new TranslateAnimation(START_POS_X, END_POS_X, 
                START_POS_Y, END_POS_Y);
mAnimation.setDuration(TICKER_DURATION); 
mAnimation.setRepeatMode(Animation.RESTART);
mAnimation.setRepeatCount(Animation.INFINITE);

START_POS_X, END_POS_X, START_POS_Yऔर END_POS_Yकर रहे हैं float, मूल्यों, जबकि TICKER_DURATIONएक intमैं अपने अन्य स्थिरांक के साथ की घोषणा की।

तो अब आप इस एनीमेशन को अपने TextView पर लागू कर सकते हैं:

TextView tickerText = (TextView) findViewById(R.id.ticker);
tickerText.setAnimation(mAnimation);

और बस। :)

मेरा एनीमेशन राइट साइड ऑफ-स्क्रीन (300f) से शुरू होता है और 15s (15000) की अवधि के साथ बाईं ओर ऑफ-स्क्रीन (-300 एफ) पर समाप्त होता है।


1
यह बहुत आसान नहीं लगता है। लेकिन मुझे नहीं लगता कि उसे अभी भी उत्तर की आवश्यकता है; ऊपर दिए गए स्वीकृत उत्तर को देखें .. :)
क्रिस्टोफर ओर

2
लेकिन मुझे लगता है कि एक नया वर्ग बनाने की तुलना में यह समाधान सरल है। : D जैसा कि यह है, आप एनीमेशन ऑब्जेक्ट को अन्य विचारों के लिए फिर से उपयोग कर सकते हैं जिन्हें आप चेतन करना चाहते हैं। ;)
जरहा

यह अच्छी तरह से काम करता है, लेकिन लंबे ग्रंथों को प्रदर्शित करने के लिए मुझे क्या करना चाहिए? अब मेरा पाठ सिर्फ काट दिया जाएगा
Tima

@ मूर वोट: क्या आपने अपने टेक्स्ट व्यू की चौड़ाई को लपेटने की कोशिश की है?
जरहा

3
एक महान समाधान नहीं है, क्योंकि आकार और अवधि पैरामीटर पाठ के आकार पर बेहद निर्भर हैं। आगे, चेतन होगा, भले ही पाठ की लंबाई दृश्य चौड़ाई से कम हो। setSelected (सच) वास्तव में सबसे आसान समाधान है।
एएनएम

5

मैंने मार्की टेक्स्ट आइटम के साथ एक सूची दृश्य के लिए निम्न कोड लिखा था। यह ऊपर वर्णित समुच्चय समाधान पर आधारित है। मूल रूप से, मैं ArrayAdapter क्लास बढ़ा रहा हूं और इसे वापस करने से पहले TextView का चयन करने के लिए getView पद्धति को ओवरराइड कर रहा हूं:

    // Create an ArrayAdapter which selects its TextViews before returning      
    // them. This would enable marqueeing while still making the list item
    // clickable.
    class SelectingAdapter extends ArrayAdapter<LibraryItem>
    {
        public
        SelectingAdapter(
            Context context, 
            int resource, 
            int textViewResourceId, 
            LibraryItem[] objects
        )
        {
            super(context, resource, textViewResourceId, objects);
        }

        @Override
        public
        View getView(int position, View convertView, ViewGroup parent)
        {
            View view = super.getView(position, convertView, parent);
            TextView textview = (TextView) view.findViewById(
                R.id.textview_playlist_item_title
            );
            textview.setSelected(true);
            textview.setEnabled(true);
            textview.setFocusable(false);
            textview.setTextColor(0xffffffff);
            return view;

        }
    }

1

यह ऐसा उत्तर है जो मेरी Google खोज में सबसे ऊपर आता है, इसलिए मैंने सोचा कि मैं यहां एक उपयोगी उत्तर पोस्ट कर सकता हूं क्योंकि मैं इसे अक्सर याद रखने के साथ संघर्ष करता हूं। वैसे भी, यह मेरे लिए काम करता है और XML विशेषताओं और एक onFocusChangeListener की आवश्यकता है।

//XML
        <TextView
            android:id="@+id/blank_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="5dp"
            android:layout_gravity="center_horizontal|center_vertical"
            android:background="#a4868585"
            android:textColor="#fff"
            android:textSize="15sp"
            android:singleLine="true"
            android:lines="1"
            android:ellipsize="marquee"
            android:marqueeRepeatLimit ="marquee_forever"
            android:scrollHorizontally="true"
            android:focusable="true"
            android:focusableInTouchMode="true"
            tools:ignore="Deprecated" />

//JAVA
    titleText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if (!hasFocus) {
                titleText.setSelected(true);
            }
        }
    });

1

// xml

 <TextView
            android:id="@+id/tvMarque"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="marquee"
            android:layout_gravity="center_horizontal"
            android:fadingEdge="horizontal"
            android:marqueeRepeatLimit="marquee_forever"
            android:scrollHorizontally="true"
            android:padding="5dp"
            android:textSize="16sp"
            android:text=""
            android:textColor="@color/colorSyncText"
            android:visibility="visible" />

// जावा में

        mtvMarque.setEllipsize(TextUtils.TruncateAt.MARQUEE);
        mtvMarque.setSelected(true);
        mtvMarque.setSingleLine(true);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.