/***
* Horizontal scroll bar, modified version, scroll from left to right, support HTML code and HTML inside the network picture
*/
public class Marqueeview extends LinearLayout {
Private context context;
Private TextView Mtextfield;
Private ScrollView Mscrollview;
private static final int text_view_virtual_width = 2000;
Private Animation mmovetextout = null;
Private Animation mmovetextin = null;
Private Paint Mpaint;
Private Boolean mmarqueeneeded = false;
private static final String TAG = MarqueeView.class.getSimpleName ();
private float mtextdifference;
Private drawable drawable;
/**
* Control the speed. The lower this value, the faster it'll scroll.
*/
private static final int default_speed = 60;
/**
* Control The pause between the animations. Also, after starting this activity.
*/
private static final int default_animation_pause = 2000;
private int mspeed = Default_speed;
private int manimationpause = Default_animation_pause;
Private Boolean mautostart = false;
Private Interpolator Minterpolator = new Linearinterpolator ();
Private Boolean mcancelled = false;
Private Runnable manimationstartrunnable;
Private Boolean mstarted;
Private Networkimagegetter Mimagegetter;
/**
* Sets the animation speed.
* The lower the value, the faster the animation would be displayed.
*
* @param speed Milliseconds per PX.
*/
public void Setspeed (int. speed) {
This.mspeed = speed;
}
/**
* Sets the pause between animations
*
* @param pause in milliseconds.
*/
public void setpausebetweenanimations (int pause) {
This.manimationpause = pause;
}
/**
* Sets a custom interpolator for the animation.
*
* @param interpolator Animation interpolator.
*/
public void Setinterpolator (Interpolator interpolator) {
This.minterpolator = Interpolator;
}
@SuppressWarnings ({"Unuseddeclaration"})
Public Marqueeview (Context context) {
Super (context);
This.context = context;
Init (context);
}
@SuppressWarnings ({"Unuseddeclaration"})
Public Marqueeview (context context, AttributeSet Attrs) {
Super (context, attrs);
This.context = context;
Init (context);
Extractattributes (ATTRS);
}
@TargetApi (build.version_codes. Honeycomb)
Public Marqueeview (context context, AttributeSet attrs, int defstyle) {
Super (context, attrs, Defstyle);
This.context = context;
Init (context);
Extractattributes (ATTRS);
}
private void Extractattributes (AttributeSet attrs) {
if (getcontext () = = null) {
Return
}
TypedArray a = GetContext (). Obtainstyledattributes (Attrs, R.styleable.asia_ivity_android_marqueeview_marqueeview);
if (a = = null) {
Return
}
Mspeed = A.getinteger (R.styleable.asia_ivity_android_marqueeview_marqueeview_speed, DEFAULT_SPEED);
Manimationpause = A.getinteger (R.styleable.asia_ivity_android_marqueeview_marqueeview_pause, DEFAULT_ANIMATION_ PAUSE);
Mautostart = A.getboolean (R.styleable.asia_ivity_android_marqueeview_marqueeview_autostart, false);
A.recycle ();
}
private void init (context context) {
Init Helper
Mpaint = new Paint ();
Mpaint.setantialias (TRUE);
Mpaint.setstrokewidth (1);
Mpaint.setstrokecap (Paint.Cap.ROUND);
Minterpolator = new Linearinterpolator ();
}
@Override
protected void OnLayout (Boolean changed, int l, int t, int r, int b) {
Super.onlayout (changed, L, T, R, b);
if (getchildcount () = = 0 | | getchildcount () > 1) {
throw new RuntimeException ("Marqueeview must has exactly one child element.");
}
if (changed && Mscrollview = = null) {
View v = getchildat (0);
Fixes #1: Exception when using android:layout_width= "Fill_parent". There seems to is an additional ScrollView parent.
if (v instanceof ScrollView && ((ScrollView) v). Getchildcount () = = 1) {
v = ((ScrollView) v). Getchildat (0);
}
if (! ( V instanceof TextView)) {
throw new RuntimeException ("The child view of this marqueeview must is a TextView instance.");
}
Initview (GetContext ());
Prepareanimation ();
if (Mautostart) {
StartMarquee ();
}
}
}
Private String message;
Private Boolean startscroll = true;
/***
* Start scrolling
* @param _message
*/
public void Startscrollview (String _message) {
if (Message.equals (_message)) return;
This.message = _message;
if (Startscroll) {
Mtextfield.settext (html.fromhtml (message, mimagegetter, null));
StartMarquee ();
}
}
/**
* Starts the configured marquee effect.
*/
public void StartMarquee () {
if (mmarqueeneeded) {
Startscroll = false;
Starttextfieldanimation ();
}
mcancelled = false;
Mstarted = true;
}
private void Starttextfieldanimation () {
manimationstartrunnable = new Runnable () {
public void Run () {
Mtextfield.startanimation (mmovetextout);
}
};
Postdelayed (manimationstartrunnable, manimationpause);
}
/**
* Disables the animations.
*/
public void Reset () {
Mcancelled = true;
if (manimationstartrunnable! = null) {
Removecallbacks (manimationstartrunnable);
}
Mtextfield.clearanimation ();
mstarted = false;
Mtextfield.setvisibility (INVISIBLE);
Mmovetextout.reset ();
Mmovetextin.reset ();
Mscrollview.removeview (Mtextfield);
Mscrollview.addview (Mtextfield);
Invalidate ();
}
private void Prepareanimation () {
Measure
Mpaint.settextsize (Mtextfield.gettextsize ());
Mpaint.settypeface (Mtextfield.gettypeface ());
Final float mtextwidth = Mpaint.measuretext (Mtextfield.gettext (). toString ());
See how much functions is needed at all
mmarqueeneeded = mtextwidth > Getmeasuredwidth ();
if (drawable! = null) {
When the HTML has a picture, cannot get to the picture length, I here the scroll bar has 15 long picture, therefore needs to add separately
Mtextdifference = Math.Abs (mtextwidth) + drawable.getintrinsicwidth () * 15 + 5;
}else {
Mtextdifference = Math.Abs (mtextwidth) + 5;
}//gets the scrollbar length, calculates the scrolling time based on scrolling speed and length (scrolling animation duration)
if (true) {
LOG.D (TAG, "mtextwidth:" + mtextwidth);
LOG.D (TAG, "measuredwidth:" + getmeasuredwidth ());
LOG.D (TAG, "mmarqueeneeded:" + mmarqueeneeded);
LOG.D (TAG, "mtextdifference:" + mtextdifference);
// }
Final int duration = (int) (mtextdifference * mspeed);
Mmovetextout = new Translateanimation (Getmeasuredwidth (),-mtextdifference, 0, 0);
Mmovetextout.setduration (duration);
Mmovetextout.setinterpolator (Minterpolator);
Mmovetextout.setanimationlistener (New Animation.animationlistener () {
public void Onanimationstart (Animation Animation) {
Expandtextview (Mtextwidth);
Mtextfield.setvisibility (VISIBLE);
}
public void Onanimationend (Animation Animation) {
Mtextfield.settext (html.fromhtml (message));
Mtextfield.settext (html.fromhtml (message, mimagegetter, null));
if (mcancelled) {
Return
}
Mtextfield.startanimation (mmovetextout);
}
public void Onanimationrepeat (Animation Animation) {
}
});
}
private void Initview (context context) {
Mimagegetter = new Networkimagegetter ();
Scroll View
Layoutparams SV1LP = new Layoutparams (layoutparams.match_parent, layoutparams.wrap_content);
sv1lp.gravity = Gravity.center_horizontal;
Mscrollview = new ScrollView (context);
Scroll View 1-text Field
Mtextfield = (TextView) getchildat (0);
Removeview (Mtextfield);
Mscrollview.addview (Mtextfield, New Scrollview.layoutparams (Text_view_virtual_width, LayoutParams.WRAP_CONTENT));
Mtextfield.addtextchangedlistener (New Textwatcher () {
@Override
public void beforetextchanged (charsequence charsequence, int i, int i2, int i3) {
}
@Override
public void ontextchanged (charsequence charsequence, int i, int i2, int i3) {
}
@Override
public void aftertextchanged (Editable Editable) {
Final Boolean continueanimation = mstarted;
Reset ();
Prepareanimation ();
Cuttextview ();
Post (new Runnable () {
@Override
public void Run () {
if (continueanimation) {
Startscroll = true;
StartMarquee ();
}
}
});
}
});
AddView (Mscrollview, SV1LP);
}
private void Expandtextview (float width) {
Viewgroup.layoutparams LP = Mtextfield.getlayoutparams ();
if (drawable! = null) {
When the HTML has a picture, cannot get to the picture length, I here the scroll bar has 15 long picture, therefore needs to add separately
Lp.width = (int) width + drawable.getintrinsicwidth () * 15 +1;
}else {
Lp.width = (int) width +1;
}//Set the scrolling length, the interior of the scroll is actually a textview, scrolling is actually textview left to do the move
MTEXTFIELD.SETLAYOUTPARAMS (LP);
}
private void Cuttextview () {
if (mtextfield.getwidth () = Getmeasuredwidth ()) {
Viewgroup.layoutparams LP = Mtextfield.getlayoutparams ();
Lp.width = Getmeasuredwidth ();
MTEXTFIELD.SETLAYOUTPARAMS (LP);
}
}
/***
* Based on the image address inside the HTML to get the network image stored locally
*/
Class Networkimagegetter implements html.imagegetter{
@Override
Public drawable getdrawable (String source) {
Package path
File File = Storageutils.getcachefile (context, "JPG", source);//Gets whether the picture is in the local SD card
Final URI uri = Uri.parse (File.getabsolutepath ());
Final String Path = Uri.getpath ();
drawable = Drawable.createfrompath (path);
Determine whether to start with HTTP
if (Source.startswith ("http")) {
Determine if a path exists
if (file.exists () && file.length () > 0) {
There is the acquisition of drawable
drawable = Drawable.createfrompath (File.getabsolutepath ());
Drawable.setbounds (0, 0, drawable.getintrinsicwidth (), Drawable.getintrinsicheight ());
} else {
Do not exist open asynchronous task load network picture
Toastservice (context,source, "JPG");
}
}
return drawable;
}
}
/**
* Local Download Image Service
* @param context
* @param URL
* @param extension
*/
private void Toastservice (Context context,string url,string extension) {
Intent Intent = new Intent (context,htmlcacheservice.class);
Intent.putextra (Htmlcacheservice.down_url,url);
Intent.putextra (htmlcacheservice.extension,extension);
Context.startservice (Intent);
}
}
Android Landscape scroll bar