ellipsize =“ marquee”を常にスクロールさせる方法はありますか?


93

TextViewでマーキー効果を使用したいのですが、TextViewがフォーカスを取得したときにのみテキストがスクロールされます。私の場合、それができないので、それは問題です。

使ってます:

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

TextViewが常にテキストをスクロールする方法はありますか?これがAndroidマーケットアプリで行われるのを見てきました。フォーカスを取得していなくても、アプリ名がタイトルバーでスクロールしますが、APIドキュメントに記載されていません。


マーキーを機能させるには、TextViewを選択する必要があります。フォーカスは選択を提供しますが、その逆は行いません。
Denis Gladkiy 2014年

1
alwaysMarqueeTextViewを試すstackoverflow.com/a/28806003/3496570
AndroidGeek

私はこの1つの正しい答えを変更しますstackoverflow.com/a/3700651/4548520
user25

回答:


62

私は問題に直面しており、思いついた最も短い解決策は、TextViewから派生した新しいクラスを作成することです。クラスは、3つのメソッドonFocusChangedonWindowFocusChangedおよびisFocusedオーバーライドして、TextViewをすべてフォーカスする必要があります。

@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 2010年

7
ところで、このソリューションはステートフルなドローアブルをめちゃくちゃにするので、実際に問題がありました。フォーカスイン/フォーカスアウトでドローアブルを変更すると、これは壊れます。このハッキングによって引き起こされていることに気づくまで、デバッグに1時間近くかかりました。
Matthias

問題の詳細な説明を提供できますか?私は多くのアプリでこの機能を使用しています。私もこの問題を見てみたいと思います。
hnviet

1
このハックはうまく機能し、複数のTextViewが同時に画面に表示されている場合(ListViewで使用される場合など)にのみ必要です-通常、そのうちの1つだけに焦点を当てることができるためですが、この解決策は、すべてに伝えることによってシステムを「だまします」それ以外の場合:)それ以外の場合、stackoverflow.com / a / 3510891/258848のような単一のTextViewシンプルな回答を使用する必要があります。
dimsuz 2013

120

私は本日、この問題にようやく思いついたのでhierarchyviewer、Androidマーケットアプリケーションに気を配りました。

アプリの詳細画面でタイトルを見ると、普通のを使用していますTextView。そのプロパティを調べると、フォーカスされていない、フォーカスできず選択されているとマークさているという事実を除いて、一般的には非常に普通であることがわかりまし

後の1行のコードと私はそれを機能させました:)

textView.setSelected(true);

これは、Javadocが言うことを考えると理にかなっています

ビューを選択するかどうかを選択できます。選択はフォーカスと同じではないことに注意してください。ビューは通常、ListViewやGridViewなどのAdapterViewのコンテキストで選択されます。

つまり、リストビュー(マーケットアプリなど)でアイテムをスクロールすると、その時点でのみ、現在選択されているテキストがスクロールを開始します。また、この特定のものTextViewはフォーカス可能でもクリック可能でもないため、選択状態が失われることはありません。

残念ながら、私が知る限り、選択した状態をレイアウトXMLから事前設定する方法はありません。
しかし、上記のワンライナーは私にはうまくいきます。


ただ疑問に思っています:これはフォーカス可能なTextViewでも機能しますが、フォーカスされていないときでもスクロールする必要がありますか?フォーカスの状態が変わっても、選択状態は「固定」されますか?
Matthias

たぶんそうだ。ベーシックTextView(つまり、のような「選択可能」なものに埋め込まれていないものListView)にフォーカスを変更すると、選択された状態が変化する理由がわかりません。
Christopher Orr

それも私にとってはうまくいきます。お返事ありがとうございます。繰り返し方を変える可能性はありますか?!
Tima

@Mur:はい、TextViewドキュメントを読んで、を見てくださいandroid:marqueeRepeatLimit
Christopher Orr

1
この方法は、ビューのフォーカスを混乱させないため、フォーカスのある方法よりも優れています。親がフォーカスする必要があるビューがある場合、そのメソッドはフォーカスをめちゃくちゃにします。この方法はシンプルで効率的であり、毎回フォーカスを変更するためのハックに依存しません。ありがとうございました!
Ionut Negru 2014

75

これらのパラメーターをTextViewに配置するだけです。できます :)

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

1
私の意見では、この回答スレッドがまだ死んでいない場合、これは受け入れられる回答になるはずです。これをテキストビューのXML定義に追加すると、最初のショットで機能しました。私は他の提案を試しましたが、これが最も簡単です。-また、 "android:marqueeRepeatLimit =" marquee_forever "を追加すると、無期限にスクロールします
Brack

19
TextViewがその中にある場合、これを使用すると、ListView Rowのフォーカス選択が解除されます。
Tivie

完璧に動作します。シンプルでエレガントなソリューション。ありがとう!
ラビ

TextViewのマーキーを開始および停止する方法
Dwivedi Ji

これは、他の答えを試すまで機能しませんでした-textView.setSelected(true);
ジャスティン

13

TranslateAnimation指定された量だけビューを一方向に「引く」ことにより機能します。この「プル」を開始する場所と終了する場所を設定できます。

TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta);

fromXDeltaは、X軸の動きの開始位置のオフセットを設定します。

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は、X軸での移動のオフセット終了位置を定義します。

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ピクセルであるとします。幅700pxのテキストを含むTextViewがあり、フレーズの終わりを確認できるように、テキストを「引く」アニメーションを作成します。

                                       (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

また、画面の幅とテキストの幅をどのように把握するのでしょうか。


コード

Zarah Snippetを出発点として:

    /**
     * @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の有効化/ onFocus機能を損なうことなく、ListViewでTextViewをアニメーション化する場合に特に便利です。また、ビューがフォーカスされていなくても継続的にスクロールします。


上記の私の答え(つまり、1行のコードを追加するtextView.setSelected(true);)はあなたの状況では機能しませんか?
Christopher Orr

残念だけど違う。ListViewに各行にいくつかのTextViewを配置しました(したがって、スペースクリシス= P)。テキストビューの各行はクリック可能で、コンテキストメニューがポップアップします。setSelectedをtrueに設定すると、コンテキストメニューが壊れるようです。
Tivie

それは...ですか?ほとんどの場合、行き過ぎの可能性があります。上記の理由から、私にとっては唯一の解決策でした。(それは再利用可能です、ところで!)= P
Tivie

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_XEND_POS_XSTART_POS_YEND_POS_Yしているfloat一方で、値TICKER_DURATIONであるint私は私の他の定数を宣言しました。

次に、このアニメーションをTextViewに適用できます。

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

以上です。:)

私のアニメーションは、画面の右側(300f)で始まり、画面の左側(-300f)で終了します。持続時間は15秒(15000)です。


1
それは簡単なことではないようです。しかし、私は彼がまだ答えを必要としているとは思いません。上記受け入れ答えを参照してください。.. :)
クリストファー・オアに

2
しかし、この解決策は新しいクラスを作成するよりも簡単だと思います。:Dそのままで、アニメーション化したい他のビューにアニメーションオブジェクトを再利用することもできます。;)
Zarah

うまくいきますが、長いテキストを表示するにはどうすればよいですか?今私のテキストはカットされます
Tima

@Mur Votema:TextViewの幅をwrap_contentに設定してみましたか?
ツアラー

3
サイズと継続時間のパラメータはテキストのサイズに大きく依存するため、優れたソリューションではありません。さらに、テキストの長さがビューの幅よりも短い場合でもアニメーション化します。setSelected(true)は本当に最も簡単なソリューションです。
Anm

5

マーキーテキストアイテムを含むListViewの次のコードを記述しました。これは、上記のsetSelectedソリューションに基づいています。基本的に、私はArrayAdapterクラスを拡張し、getViewメソッドをオーバーライドして、それを返す前にTextViewを選択します。

    // 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

これは私のグーグル検索の上部にポップアップする答えなので、私はこれをかなり頻繁に思い出すことに苦労しているので、ここに役立つ答えを投稿できると思いました。とにかく、これは私にとっては機能し、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" />

// Javaで

        mtvMarque.setEllipsize(TextUtils.TruncateAt.MARQUEE);
        mtvMarque.setSelected(true);
        mtvMarque.setSingleLine(true);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.