Автоматическая горизонтальная прокрутка в TextView - PullRequest
7 голосов
/ 24 февраля 2012

У меня есть пользовательская галерея. Галерея представляет элементы, которые являются макетом кадра. Над ним один imageView и textView.

Если текст в textView слишком длинный, его нужно прокрутить автоматически. Это одна строка текста, которую нужно прокручивать по горизонтали.

Я нашел этот фрагмент кода:

TextView
    android:text="Single-line text view that scrolls automatically"       
    android:singleLine="true" 
    android:ellipsize="marquee"
    android:marqueeRepeatLimit ="marquee_forever"
    android:focusable="true"
    android:focusableInTouchMode="true" 
    android:scrollHorizontally="true"
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content"/>   

Это работает в моем тестовом приложении только с одним представлением текста. Но это не работает в моей галерее. Замечание происходит, текст просто остается неподвижным.

Любая помощь?

Ответы [ 8 ]

14 голосов
/ 14 марта 2012

Попробуйте этот пользовательский класс TextView:

public class AutoScrollingTextView extends TextView {
    public AutoScrollingTextView(Context context, AttributeSet attrs,
            int defStyle) {
        super(context, attrs, defStyle);
    }

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

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

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

и установите следующие атрибуты XML:

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

Это прекрасно работает в приложениях моего словаря, где для одновременной прокрутки нескольких записей может потребоваться автопрокрутка.

6 голосов
/ 11 марта 2012

Эффект выделения на TextView предназначен только для работы, когда вид сфокусирован или выбран. У вас есть XML-код, который постоянно фокусируется на TextView. К сожалению, поскольку в любой момент можно сфокусировать только один вид, а поскольку у вас есть несколько видов в галерее, этот подход не будет работать для вас.

В противном случае проще всего сделать так, чтобы TextViews всегда был выбран. Несколько TextViews могут удерживать выбранное состояние одновременно. Выбор предназначен для использования для активного элемента AdapterView, но все еще работает за его пределами. Во-первых, удалите атрибуты, модифицирующие фокус, из XML, а затем просто вызовите TextView.setSelected(true) через некоторое время после инициализации представления, например, в Activity.onCreate(Bundle) (для этого нет атрибута XML). Если вы предоставляете представления из адаптера, вы можете вызвать TextView.setSelected(true) во время метода getView() после того, как вы надули представление.

Здесь - пример проекта, показывающего выделение, работающее для нескольких TextView, и поведение внутри галереи.

1 голос
/ 22 марта 2012

Я перепробовал все, и, наконец, придумал это. Это работает для меня ... надеюсь, что это поможет вам когда-нибудь. Приветствия.

 package com.gui.custom_views;

 import android.content.Context;
 import android.graphics.Paint;
 import android.graphics.Typeface;
 import android.text.TextUtils; 
 import android.util.AttributeSet;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.animation.Animation;
 import android.view.animation.LinearInterpolator;
 import android.view.animation.TranslateAnimation;
 import android.widget.LinearLayout;
 import android.widget.ScrollView;
 import android.widget.TextView;

 import com.media_player.AndroidMediaPlayerActivity;

 /**
 * Custom Automatic Scrollable Text View
 * 
 * @author Veljko Ilkic
 * 
 */
 public class AutomaticScrollTextView extends LinearLayout {

// Context of application
Context context;
// TextView
private TextView mTextField1;

// Horizontal scroll
private ScrollView mScrollView1;

// Animation on start
private Animation mMoveTextOnStart = null;
// Out animation
private Animation mMoveText1TextOut = null;

// Duration of animation on start
private int durationStart;
// Duration of animation
private int duration;

// Pain for drawing text
private Paint mPaint;

// Text current width
private float mText1TextWidth;

/**
 * Control the speed. The lower this value, the faster it will scroll.
 */
public static final int MS_PER_PX = 80;

/**
 * Control the pause between the animations. Also, after starting this
 * activity.
 */
public static final int PAUSE_BETWEEN_ANIMATIONS = 0;
private boolean mCancelled = false;

// Layout width
private int mWidth;
// Animation thread
private Runnable mAnimation1StartRunnable;

public AutomaticScrollTextView(Context context) {
    super(context);
    init(context);
    this.context = context;
}

public AutomaticScrollTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
    this.context = context;
}

private void init(Context context) {
    initView(context);

    // init helper
    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setStrokeWidth(1);
    mPaint.setStrokeCap(Paint.Cap.ROUND);

}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    super.onLayout(changed, l, t, r, b);

    mWidth = getMeasuredWidth();

    // Calculate
    prepare();

    // Setup
    setupText1Marquee();

}

@Override
public void setOnClickListener(OnClickListener l) {
    super.setOnClickListener(l);

    mTextField1.setOnClickListener(l);
}

// Method to finally start the marquee.
public void startMarquee() {
    prepare();
    prepareTextFields();

    startTextField1Animation();

    mCancelled = false;
}

private void startTextField1Animation() {
    mAnimation1StartRunnable = new Runnable() {
        public void run() {
            mTextField1.setVisibility(View.VISIBLE);
            mTextField1.startAnimation(mMoveTextOnStart);
        }
    };
    postDelayed(mAnimation1StartRunnable, PAUSE_BETWEEN_ANIMATIONS);
}

public void reset() {

    mCancelled = true;

    if (mAnimation1StartRunnable != null) {
        removeCallbacks(mAnimation1StartRunnable);
    }

    mTextField1.clearAnimation();

    prepareTextFields();

    mMoveTextOnStart.reset();
    mMoveText1TextOut.reset();

    mScrollView1.removeView(mTextField1);
    mScrollView1.addView(mTextField1);

    mTextField1.setEllipsize(TextUtils.TruncateAt.END);

    invalidate();
}

public void prepareTextFields() {
    mTextField1.setEllipsize(TextUtils.TruncateAt.END);
    mTextField1.setVisibility(View.INVISIBLE);
    expandTextView(mTextField1);
}

private void setupText1Marquee() {

    // Calculate duration of animations
    durationStart = (int) ((mWidth + mText1TextWidth) * MS_PER_PX);
    duration = (int) (2 * mWidth * MS_PER_PX);

    // On start animation
    mMoveTextOnStart = new TranslateAnimation(0, -mWidth - mText1TextWidth,
            0, 0);

    mMoveTextOnStart.setDuration(durationStart);
    mMoveTextOnStart.setInterpolator(new LinearInterpolator());
    mMoveTextOnStart.setFillAfter(true);

    // Main scrolling animation
    mMoveText1TextOut = new TranslateAnimation(mWidth, -mWidth
            - mText1TextWidth, 0, 0);

    mMoveText1TextOut.setDuration(duration);
    mMoveText1TextOut.setInterpolator(new LinearInterpolator());
    mMoveText1TextOut.setFillAfter(true);
    mMoveText1TextOut.setRepeatCount(Animation.INFINITE);

    // Animation listeners
    mMoveTextOnStart
            .setAnimationListener(new Animation.AnimationListener() {
                public void onAnimationStart(Animation animation) {
                    invalidate();
                    mTextField1.invalidate();

                }

                public void onAnimationEnd(Animation animation) {

                    if (mCancelled) {
                        return;
                    }

                    mTextField1.startAnimation(mMoveText1TextOut);

                }

                public void onAnimationRepeat(Animation animation) {
                    invalidate();
                    mTextField1.invalidate();
                }
            });

    mMoveText1TextOut
            .setAnimationListener(new Animation.AnimationListener() {
                public void onAnimationStart(Animation animation) {
                    invalidate();
                    mTextField1.invalidate();

                }

                public void onAnimationEnd(Animation animation) {

                    if (mCancelled) {
                        return;
                    }

                }

                public void onAnimationRepeat(Animation animation) {
                    invalidate();
                    mTextField1.invalidate();
                }
            });

}

private void prepare() {

    // Measure
    mPaint.setTextSize(mTextField1.getTextSize());
    mPaint.setTypeface(mTextField1.getTypeface());
    mText1TextWidth = mPaint.measureText(mTextField1.getText().toString());

    setupText1Marquee();

}

private void initView(Context context) {
    setOrientation(LinearLayout.VERTICAL);
    setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
            LayoutParams.FILL_PARENT, Gravity.LEFT));
    setPadding(0, 0, 0, 0);

    // Scroll View 1
    LayoutParams sv1lp = new LayoutParams(LayoutParams.FILL_PARENT,
            LayoutParams.WRAP_CONTENT);
    sv1lp.gravity = Gravity.CENTER_HORIZONTAL;
    mScrollView1 = new ScrollView(context);

    // Scroll View 1 - Text Field
    mTextField1 = new TextView(context);
    mTextField1.setSingleLine(true);
    mTextField1.setEllipsize(TextUtils.TruncateAt.END);
    mTextField1.setTypeface(null, Typeface.BOLD);

    mScrollView1.addView(mTextField1, new ScrollView.LayoutParams(
            mTextField1.getWidth(), LayoutParams.WRAP_CONTENT));

    addView(mScrollView1, sv1lp);
}

public void setText1(String text) {

    String temp = "";
    if (text.length() < 10) {
        temp = "         " + text + "         ";
    } else {
        temp = text;
    }
    mTextField1.setText(temp);

}

public void setTextSize1(int textSize) {
    mTextField1.setTextSize(textSize);
}

public void setTextColor1(int textColor) {

    mTextField1.setTextColor(textColor);
}

private void expandTextView(TextView textView) {
    ViewGroup.LayoutParams lp = textView.getLayoutParams();
    lp.width = AndroidMediaPlayerActivity.getScreenWidth();
    textView.setLayoutParams(lp);
}
}
1 голос
/ 09 марта 2012

Попробуйте использовать ViewPager вместо галереи. Это доступно в пакетах поддержки Android. http://android -developers.blogspot.in / 2011/08 / горизонтальный ракурс-ударяя-с-viewpager.html

0 голосов
/ 10 июля 2015
public class ScrollingTextView extends TextView {

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

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

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

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

 <com.test.autoscroll.ScrollingTextView
                android:id="@+id/actionbar_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:paddingLeft="10dip"
                android:paddingRight="10dip"
                android:textSize="16dip"
                android:textStyle="bold"
                android:lines="1"
                android:scrollHorizontally="true"
                android:ellipsize="marquee"
                 android:text="autoscrollable textview without focus to textview...working...."
                android:marqueeRepeatLimit="marquee_forever"
                />
0 голосов
/ 15 ноября 2013

Этот код работает правильно для меня.

Scrollview = (Scrollview) findViewById (R.id.scrollview1); tb2.setTextSize (30);

    tb2.setMovementMethod(new ScrollingMovementMethod());
    scrollview.post(new Runnable() { 
    public void run() { 
        scrollview.fullScroll(View.FOCUS_DOWN);  
        }
    });
0 голосов
/ 16 марта 2012

Привет У вас есть тег в самом XML-файле.А также использовать свойство Scrollview для FOCUS_DOWN в файле Java ... Надеюсь, это поможет вам ...

0 голосов
/ 16 марта 2012

Однажды я столкнулся с этой проблемой и, наконец, решил ее, вызвав .setFocus () для textView.

...