Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use TextView to realize the effect of Racing Lantern in Android

2025-03-30 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

Most people do not understand the knowledge points of this article "how to use TextView to achieve racing lantern effect in Android", so the editor summarizes the following content, detailed content, clear steps, and has a certain reference value. I hope you can get something after reading this article. Let's take a look at this "how to use TextView in Android to achieve racing lantern effect" article.

[preface]

When the width of the Textview setting is limited and there are a lot of text to be displayed, it is often necessary to set the racing lantern effect for the Textview to let the user see all the set text completely, so it is very common to set the racing lantern effect for the TextView.

1. The effect of setting racing lanterns for beginners

1. Set the corresponding properties for Textview in xml first

2. Then set the request to get the focus in the code

TextView tv = findViewById (R.id.tv); tv.requestFocus ()

After this setting, the effect of the racing lantern will come out.

[explanation of key points]

1. Android:layout_width is limited to a fixed width, while the length of the text is greater than the set width. If android:layout_width is set to wrap_content, then the width of Textview will widen as the length of the text becomes longer, so the effect of horse racing lantern cannot appear.

2. Android:singleLine= "true" sets Textview to display only on one line. If it is not set to true, it will automatically wrap lines and display multiple lines by default. In this case, there will be no racing lantern effect.

3. Android:ellipsize= "marquee" setting if the length of the text exceeds the width of the Textview, the text should be displayed as a racing lantern effect. This is the most critical setting for setting the racing lantern effect. Android:ellipsize can also take values of start, end, middle and none, showing ellipsis at the beginning, ellipsis at the end, ellipsis in the middle, and truncation directly.

4. Android:focusable= "true" sets Textview to get focus. Horse racing lantern effect takes effect only when it gets focus. Textview does not get focus by default.

5. Android:focusableInTouchMode= "true" is set to gain focus in touch mode. At present, most smartphones enter touch mode automatically. In fact, as long as you set android:focusableInTouchMode= "true", the default android:focusable will become true.

6. Android:marqueeRepeatLimit= "- 1" sets the number of racing lantern cycles.-1 indicates an infinite cycle. If not, the default is 3 cycles.

7. Tv.requestFocus (); sets the focus, which takes effect only if the focusable attribute of the view is true

[summary]

1. Be sure to set android:focusableInTouchMode= "true". If only android:focusable= "true" is set but android:focusableInTouchMode is not set, the racing lantern effect will not take effect, because after entering the touch mode, isFocusable () returns false. Take a look at the Texivew startMarquee () source code to know what conditions need to be met to start the racing lantern special effect:

Private void startMarquee () {/ / Do not ellipsize EditText if (getKeyListener ()! = null) return; if (compressText (getWidth ()-getCompoundPaddingLeft ()-getCompoundPaddingRight () {return } / / 1. The racing lantern control class has not been created or the effect of the racing lantern has stopped if ((mMarquee = = null | | mMarquee.isStopped ()) & & / 2, whether the current Textview is focused or selected (isFocused () | | isSelected ()) / / 3, There is only one line of text & & getLineCount () = = 1 / 4, and the length of the text is greater than the width of Textview & & canMarquee () {if (mMarqueeFadeMode = = MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {mMarqueeFadeMode = MARQUEE_FADE_SWITCH_SHOW_FADE Final Layout tmp = mLayout; mLayout = mSavedMarqueeModeLayout; mSavedMarqueeModeLayout = tmp; setHorizontalFadingEdgeEnabled (true); requestLayout (); invalidate ();} if (mMarquee = = null) mMarquee = new Marquee (this); mMarquee.start (mMarqueeRepeatLimit) }} private boolean canMarquee () {int width = mRight-mLeft-getCompoundPaddingLeft ()-getCompoundPaddingRight (); return width > 0 & & (mLayout.getLineWidth (0) > width | | (mMarqueeFadeMode! = MARQUEE_FADE_NORMAL & & mSavedMarqueeModeLayout! = null & & mSavedMarqueeModeLayout.getLineWidth (0) > width); second, high-end players set racing lantern effect

From the TextView racing lamp source code summarized above, we can see that as long as the isFocusable () or isSelected () method returns true, there is no need to care about whether to touch the mode or whether the focus can be obtained, so we can customize a class that inherits from TextView, and then overrides isFocusable () to return true directly:

Public class MarqueeTextView extends TextView {public MarqueeTextView (Context context) {super (context); initView (context);} public MarqueeTextView (Context context, AttributeSet attrs) {super (context, attrs); initView (context);} public MarqueeTextView (Context context, AttributeSet attrs, int defStyleAttr) {super (context, attrs, defStyleAttr); initView (context) } private void initView (Context context) {this.setEllipsize (TextUtils.TruncateAt.MARQUEE); this.setSingleLine (true); this.setMarqueeRepeatLimit (- 1);} / / the most critical part public boolean isFocused () {return true;}}

1. Directly use the custom MarqueeTextView in Xml, and the racing lantern effect will come out without any additional configuration.

Let's see how it works:

Third, extended reading

If there is such a demand: because the space for displaying the text is limited, we can only use the effect of the racing lantern to show the text to the user, but after the user has read the text completely, we need to hide the Textview, then the question is, how do we know when the racing lantern effect will be finished? First, let's take a look at the Textview racing lantern part of the Marquee class part of the source code:

If void start (int repeatLimit) {/ / repeat number is set to 0, then stop the racing light if (repeatLimit = = 0) {stop (); return;} / /. Omit most irrelevant code mChoreographer.postFrameCallback (mStartCallback);}} private Choreographer.FrameCallback mStartCallback = new Choreographer.FrameCallback () {@ Override public void doFrame (long frameTimeNanos) {mStatus = MARQUEE_RUNNING; mLastAnimationMs = mChoreographer.getFrameTime (); tick () }}; void tick () {if (mStatus! = MARQUEE_RUNNING) {return;} if (textView! = null & & (textView.isFocused () | | textView.isSelected () {long currentMs = mChoreographer.getFrameTime (); long deltaMs = currentMs-mLastAnimationMs; mLastAnimationMs = currentMs Float deltaPx = deltaMs * mPixelsPerMs; mScroll + = deltaPx; / / if the racing lantern rolling distance is greater than the maximum distance, then return to mRestartCallback if (mScroll > mMaxScroll) {mScroll = mMaxScroll; mChoreographer.postFrameCallbackDelayed (mRestartCallback, MARQUEE_DELAY) } else {mChoreographer.postFrameCallback (mTickCallback);} textView.invalidate () }} private Choreographer.FrameCallback mRestartCallback = new Choreographer.FrameCallback () {@ Override public void doFrame (long frameTimeNanos) {if (mStatus = = MARQUEE_RUNNING) {if (mRepeatLimit > = 0) {mRepeatLimit-- } start (mRepeatLimit);}

From the above analysis of the Marquee source code, we can see that the doFrame method of the Marquee class mRestartCallback object will be called after a round of racing lantern running, so let's take a trick to "steal the dragon and turn the Phoenix" and replace the mRestartCallback object with our own instantiated object through reflection, then it will be adjusted back to our replacement object after one round of racing lantern running. In this way, the monitoring of the effect of racing lantern running after one round is realized, and the source code is as follows:

Public class MarqueeTextView extends androidx.appcompat.widget.AppCompatTextView {private Choreographer.FrameCallback mRealRestartCallbackObj; private Choreographer.FrameCallback mFakeRestartCallback; private OnShowTextListener mOnShowTextListener; public MarqueeTextView (Context context, OnShowTextListener onShowTextListener) {super (context); initView (context); this.mOnShowTextListener = onShowTextListener;} public MarqueeTextView (Context context, AttributeSet attrs) {super (context, attrs); initView (context) } public MarqueeTextView (Context context, AttributeSet attrs, int defStyleAttr) {super (context, attrs, defStyleAttr); initView (context);} private void initView (Context context) {/ / bypass the restriction of hidden api Reflection.unseal (context.getApplicationContext ()); / / set the effective condition of racing lantern this.setEllipsize (TextUtils.TruncateAt.MARQUEE); this.setSingleLine (true) This.setFocusable (true); / / reflection setting horse lantern listener try {/ / find the defined field mMarquee Field marqueeField = ReflectUtil.getDeclaredField (TextView.class, "mMarquee") from the TextView class; / / get the constructor of the Marquee class Marquee (TextView v) Constructor declaredConstructor = ReflectUtil.getDeclaredConstructor (Class.forName ("android.widget.TextView$Marquee"), TextView.class) / / instantiate a Marquee object with the passed parameter Textview object Object marqueeObj = declaredConstructor.newInstance (this); / / find the defined field mRestartCallback in the Marquee class and call back to this object the doFrame () method Field restartCallbackField = ReflectUtil.getDeclaredField ("android.widget.TextView$Marquee") ("mRestartCallback") when you restart a round of racing lanterns. / / get the real mRestartCallback object mRealRestartCallbackObj = (Choreographer.FrameCallback) restartCallbackField.get (marqueeObj) from the Marquee instance object / / construct a fake mRestartCallback object to listen to when the running light effect mFakeRestartCallback = new Choreographer.FrameCallback () {@ Override public void doFrame (long frameTimeNanos) {/ / this is still the code logic mRealRestartCallbackObj.doFrame (frameTimeNanos) that executes the real mRestartCallback object. Log.i ("min77", "Racing Lantern text display is complete"); / / callback notification to finish a round of if (MarqueeTextView.this.mOnShowTextListener! = null) {MarqueeTextView.this.mOnShowTextListener.onComplete (0);} / / setting fake mRestartCallback objects to Marquee objects is actually proxy mode restartCallbackField.set (marqueeObj, mFakeRestartCallback); / / setting your instantiated Marquee objects to Textview marqueeField.set (this, marqueeObj);} catch (Exception e) {e.printStackTrace (); Log.e ("min77", e.getMessage ()) }} / / the most critical part public boolean isFocused () {return true;} / * whether the full text is displayed * / public interface OnShowTextListener {void onComplete (int delayMillisecond);}}

The effect is as follows:

The above is about the content of this article on "how to use TextView to achieve racing lantern effect in Android". I believe we all have a certain understanding. I hope the content shared by the editor will be helpful to you. If you want to know more related knowledge, please pay attention to the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report