2012-01-23 9 views
14

Estoy usando una marquesina para mostrar el texto en una de mis actividades. Mi pregunta es si es posible acelerar la velocidad de la marquesina para que se desplace más rápido a lo largo de la pantalla. A continuación está mi XML y Java.Marquee establecer velocidad

TextView et2 = (TextView) findViewById(R.id.noneednum); 
    et2.setEllipsize(TruncateAt.MARQUEE);  
    et2.setText(""); 
    if (num.size() > 0) { 
     for (String str : num) { 
      et2.append(str + " "); 
     } 
    } 
    et2.setSelected(true); 
} 

y XML:

<TextView 
    android:id="@+id/noneednum" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_centerHorizontal="true" 
    android:layout_centerVertical="true" 
    android:ellipsize="marquee" 
    android:fadingEdge="horizontal" 
    android:gravity="center_vertical|center_horizontal" 
    android:lines="1" 
    android:marqueeRepeatLimit="marquee_forever" 
    android:scrollHorizontally="true" 
    android:singleLine="true" 
    android:text="Large Text" 
    android:textColor="#fff" 
    android:textSize="140dp" /> 
+0

http://code.google.com/p/android/issues/detail?id=6567 y http://stackoverflow.com/questions/5014578/android-and-a-textviews-horizontal- marquee-scroll-rate –

+0

@SergeyBenner El primer enlace tiene 'TextView.MARQUEE_SPEED_FAST no se puede resolver' y la segunda opción se ve muy compleja ¿Debe ser una forma más fácil? – Matt

+0

El primer enlace es el problema - para una mejora para establecer la velocidad de marca :) El segundo es el enlace a una solución. Supongo que no hay otra manera, pero alguien podría haberlo resuelto de otra manera ... –

Respuesta

45

Tienes que crear una clase personalizada para el desplazamiento del texto:

ScrollTextView.java

public class ScrollTextView extends TextView { 

    // scrolling feature 
    private Scroller mSlr; 

    // milliseconds for a round of scrolling 
    private int mRndDuration = 10000; 

    // the X offset when paused 
    private int mXPaused = 0; 

    // whether it's being paused 
    private boolean mPaused = true; 

    /* 
    * constructor 
    */ 
    public ScrollTextView(Context context) { 
     this(context, null); 
     // customize the TextView 
     setSingleLine(); 
     setEllipsize(null); 
     setVisibility(INVISIBLE); 
    } 

    /* 
    * constructor 
    */ 
    public ScrollTextView(Context context, AttributeSet attrs) { 
     this(context, attrs, android.R.attr.textViewStyle); 
     // customize the TextView 
     setSingleLine(); 
     setEllipsize(null); 
     setVisibility(INVISIBLE); 
    } 

    /* 
    * constructor 
    */ 
    public ScrollTextView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     // customize the TextView 
     setSingleLine(); 
     setEllipsize(null); 
     setVisibility(INVISIBLE); 
    } 

    /** 
    * begin to scroll the text from the original position 
    */ 
    public void startScroll() { 
     // begin from the very right side 
     mXPaused = -1 * getWidth(); 
     // assume it's paused 
     mPaused = true; 
     resumeScroll(); 
    } 

    /** 
    * resume the scroll from the pausing point 
    */ 
    public void resumeScroll() { 

     if (!mPaused) return; 

     // Do not know why it would not scroll sometimes 
     // if setHorizontallyScrolling is called in constructor. 
     setHorizontallyScrolling(true); 

     // use LinearInterpolator for steady scrolling 
     mSlr = new Scroller(this.getContext(), new LinearInterpolator()); 
     setScroller(mSlr); 

     int scrollingLen = calculateScrollingLen(); 
     int distance = scrollingLen - (getWidth() + mXPaused); 
     int duration = (new Double(mRndDuration * distance * 1.00000 
     /scrollingLen)).intValue(); 

     setVisibility(VISIBLE); 
     mSlr.startScroll(mXPaused, 0, distance, 0, duration); 
     invalidate(); 
     mPaused = false; 
    } 

    /** 
    * calculate the scrolling length of the text in pixel 
    * 
    * @return the scrolling length in pixels 
    */ 
    private int calculateScrollingLen() { 
     TextPaint tp = getPaint(); 
     Rect rect = new Rect(); 
     String strTxt = getText().toString(); 
     tp.getTextBounds(strTxt, 0, strTxt.length(), rect); 
     int scrollingLen = rect.width() + getWidth(); 
     rect = null; 
     return scrollingLen; 
    } 

    /** 
    * pause scrolling the text 
    */ 
    public void pauseScroll() { 
     if (null == mSlr) return; 

     if (mPaused) 
     return; 

     mPaused = true; 

     // abortAnimation sets the current X to be the final X, 
     // and sets isFinished to be true 
     // so current position shall be saved 
     mXPaused = mSlr.getCurrX(); 

     mSlr.abortAnimation(); 
    } 

    @Override 
    /* 
    * override the computeScroll to restart scrolling when finished so as that 
    * the text is scrolled forever 
    */ 
    public void computeScroll() { 
     super.computeScroll(); 

     if (null == mSlr) return; 

     if (mSlr.isFinished() && (!mPaused)) { 
      this.startScroll(); 
     } 
    } 

    public int getRndDuration() { 
     return mRndDuration; 
    } 

    public void setRndDuration(int duration) { 
     this.mRndDuration = duration; 
    } 

    public boolean isPaused() { 
     return mPaused; 
    } 
} 

En su diseño escribir así:

<yourpackagename.ScrollTextView 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:id="@+id/scrolltext" /> 

En su actividad de escribir así:

ScrollTextView scrolltext=(ScrollTextView) findViewById(R.id.scrolltext); 
scrolltext.setText(yourscrollingtext); 
scrolltext.setTextColor(Color.BLACK); 
scrolltext.startScroll(); 

Si se desea aumentar la velocidad de desplazamiento y luego reducir el valor de:

private int mRndDuration = 10000;//reduce the value of mRndDuration to increase scrolling speed 
+1

@matt ¿Está funcionando? me fue trabajado – Ramakrishna

+0

para multilenguaje su marquesina personalizada no está funcionando? ¿sabes de otra manera? – Ghouse

+0

@Ramakrishna impresionante su código funcionando bien. Tengo una duda más sobre cómo desplazarme 1. de arriba hacia abajo 2. de abajo hacia arriba 3. de derecha a izquierda aclarar mis dudas – balaji

0

Esto funciona para mí. Si f.get (tv) devuelve null, intente llamar a mTextView.setSelected (true) antes de llamar a setMarqueeSpeed ​​(). Respuesta original: Android and a TextView's horizontal marquee scroll rate

private void setMarqueeSpeed(TextView tv, float speed, boolean speedIsMultiplier) { 

    try { 
     Field f = tv.getClass().getDeclaredField("mMarquee"); 
     f.setAccessible(true); 

     Object marquee = f.get(tv); 
     if (marquee != null) { 

      String scrollSpeedFieldName = "mScrollUnit"; 
      if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.L) 
       scrollSpeedFieldName = "mPixelsPerSecond"; 

      Field mf = marquee.getClass().getDeclaredField(scrollSpeedFieldName); 
      mf.setAccessible(true); 

      float newSpeed = speed; 
      if (speedIsMultiplier) 
       newSpeed = mf.getFloat(marquee) * speed; 

      mf.setFloat(marquee, newSpeed); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 
+0

No se puede hacer que esto funcione. ¿Alguien puede confirmar si esto está funcionando? – jay

+0

Además, ¿hay algún otro método además de usar la reflexión? – jay

0

Por encima de código falla si el TextView es una instancia de AppCompatTextView. A continuación, el código funciona si es AppCompatTextView. Probado en Marshmallow.

public static void setMarqueeSpeed(TextView tv, float speed) { 
    if (tv != null) { 
     try { 
      Field f = null; 
      if (tv instanceof AppCompatTextView) { 
       f = tv.getClass().getSuperclass().getDeclaredField("mMarquee"); 
      } else { 
       f = tv.getClass().getDeclaredField("mMarquee"); 
      } 
      if (f != null) { 
       f.setAccessible(true); 
       Object marquee = f.get(tv); 
       if (marquee != null) { 
        String scrollSpeedFieldName = "mScrollUnit"; 
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
         scrollSpeedFieldName = "mPixelsPerSecond"; 
        } 
        Field mf = marquee.getClass().getDeclaredField(scrollSpeedFieldName); 
        mf.setAccessible(true); 
        mf.setFloat(marquee, speed); 
       } 
      } else { 
       Logger.e("Marquee", "mMarquee object is null."); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 
Cuestiones relacionadas