web-dev-qa-db-ja.com

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

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

使っています:

  Android:ellipsize="Marquee"
  Android:marqueeRepeatLimit="Marquee_forever"

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

89
Matthias

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

@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;
}
62
hnviet

今日、この問題についに思いついたので、Androidマーケットアプリケーションで hierarchyviewer ==を起動しました。

アプリの詳細画面でタイトルを見ると、彼らは普通のTextViewを使用しています。そのプロパティを調べると、フォーカスされていない、フォーカスされていない、、一般的に非常に普通であることが示されました。ただし、selected

あとで1行のコードで、動作させました:)

textView.setSelected(true);

これは理にかなっています Javadocの言う

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

つまり、(マーケットアプリのように)リストビューでアイテムをスクロールすると、now-selectedテキストのスクロールが開始されます。また、この特定のTextViewはフォーカスもクリックもできないため、選択状態が失われることはありません。

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

117
Christopher Orr

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

    Android:singleLine="true" 
    Android:ellipsize="Marquee"
    Android:marqueeRepeatLimit ="Marquee_forever"
    Android:scrollHorizontally="true"
    Android:focusable="true"
    Android:focusableInTouchMode="true" 
75
Vinayak

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値を計算する必要があります。目的の効果を得るには、画面からはみ出すのとまったく同じピクセルをテキストに「プル」する必要があります。 (スキームでは<<<< 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のenabled/onFocus機能を損なうことなくListViewでTextViewをアニメーション化する場合に特に役立ちます。また、ビューがフォーカスされていない場合でも継続的にスクロールします。

13
Tivie

それでも答えが必要かどうかはわかりませんが、簡単な方法を見つけました。

次のようにアニメーションを設定します。

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_YおよびEND_POS_Yfloatの値ですが、TICKER_DURATIONは、他の定数で宣言したintです。

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

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

以上です。 :)

私のアニメーションは右側のオフスクリーン(300f)で始まり、左側のオフスクリーン(-300f)で終わります。持続時間は15秒(15000)です。

12
Zarah

Marqueeテキストアイテムを使用した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;

        }
    }
5
smichak

これは私のグーグル検索の一番上に表示される答えなので、これをかなり頻繁に思い出すのに苦労しているので、ここに便利な答えを投稿できると思いました。とにかく、これは私のために機能し、XML属性とA 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);
            }
        }
    });
2
Thunderstick

// 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);
1
Soni Kumar