First up Effect chart:
This control is actually relatively lightweight, I believe many small partners can do it. Because the project encountered a number of special customization requirements, so I wrote one, here put it out.
Let's first analyze the functionality of this control:
• Ability to respond to left and right slides and to respond to fast sliding
• There are different style expressions for selections and not selected items, such as foreground, background, and font size.
• Automatically scroll until the current option is fully exposed if the current option is not fully present in front of the interface when switching options
The first two also, simple to achieve, mainly the 3rd, this is the reason I customize this control! So what do you need to use to implement this control?
• Use Scroller to implement control scrolling
• Use Velocitytracker to enable fast scrolling of controls
If you already have both of these technologies, then we can start to explain the code. The first is the Getter/setter method of some attributes, the chain setting method used here:
public Indicatorview Color (int colordefault, int colorselected, int colorbg) {
this.colordefault = Colordefault;
this.colorselected = colorselected;
THIS.COLORBG = COLORBG;
return this;
}
Public Indicatorview textsize (int textsize) {
this.textsize = textsize;
return this;
}
Public Indicatorview text (string[] texts) {
this.texts = texts;
return this;
}
Public Indicatorview padding (int[] padding) {
this.padding = padding;
return this;
}
Public Indicatorview defaultselect (int defaultselect) {
this.selectitem = defaultselect;
return this;
}
Public Indicatorview lineheight (int lineheight) {
this.lineheight = lineheight;
return this;
}
Public Indicatorview Listener (Onindicatorchangedlistener listener) {
This.listener = listener;
return this;
}
Public Indicatorview type (type type) {
this.type = type;
return this;
}
Here we abstract each option into an item class:
public class Item {
String text;
int colordefault;
int colorselected;
int textsize;
Boolean isselected = false;
int width;
Point Drawpoint;
int[] padding = new Int[4];
Rect Rect = new Rect ();
}
Then the initialization of the control, mainly based on the width of the current control, and some of the properties set, to initialize the item option:
@Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {width = measurespec.getsize (Widthmea
SURESPEC);
Height = measurespec.getsize (heightmeasurespec);
Initialize item inititems ();
Super.onmeasure (Widthmeasurespec, Heightmeasurespec);
private void Inititems () {items.clear ();
measurewidth = 0;
for (int i = 0; i < texts.length i++) {item = new item ();
Item.text = Texts[i];
Item.colordefault = Colordefault;
item.colorselected = colorselected;
Item.textsize = Textsize;
for (int j = 0; J < Item.padding.length; J +) {Item.padding[j] = padding[j];
} mpaint.settextsize (Item.textsize);
Item.width = (int) mpaint.measuretext (item.text);
int dx = 0;
if (I-1 < 0) {dx = 0; }else{for (int j = 0; J < i; j) {DX + items.get (j). Padding[0] + items.get (j). Width + items.get (j). padding[2
];
int startx = item.padding[0] + dx;
Paint.fontmetrics metrics = Mpaint.getfontmetrics (); int starty = (int) (HEIGHT/2 + (metrics.bottom-metrics.top)/2-metrics.bottom);
Item.drawpoint = new Point (StartX, starty);
Set the area Item.rect.left = item.drawpoint.x-item.padding[0];
item.rect.top = 0;
Item.rect.right = item.drawpoint.x + item.width + item.padding[2];
Item.rect.bottom = height;
Sets the default if (i = = SelectItem) {item.isselected = true;
} Measurewidth + = Item.rect.width ();
Items.Add (item);
//Redraw invalidate ();
}
Next is event handling, and the logic is simple. Record the coordinate value in down time, handle the control's scrolling in move, the restore operation when the scrolling screen is processed in the up, and the clicked action. &NBSP
@Override public boolean ontouchevent (Motionevent event) {if (Mvelocitytracker = null) {Mvelocitytracker = Veloci
Tytracker.obtain ();
} mvelocitytracker.addmovement (event);
Switch (event.getaction ()) {Case MotionEvent.ACTION_DOWN:mTouchX = (int) event.getx ();
Mtouchy = (int) event.gety ();
Mmovex = Mtouchx;
return true;
Case MotionEvent.ACTION_MOVE:if (Measurewidth > width) {int dx = (int) event.getx ()-Mmovex; if (dx > 0) {//Right slip if (Mscroller.getfinalx () > 0) {mscroller.startscroll (), Mscroller.getfinalx (), Mscroller
. Getfinaly (),-DX, 0);
}else{mscroller.setfinalx (0); }}else{//Zoli if (mscroller.getfinalx () + WIDTH-DX < Measurewidth) {Mscroller.startscroll (Mscroller).
Getfinalx (), Mscroller.getfinaly (),-DX, 0);
}else{Mscroller.setfinalx (measurewidth-width);
} Mmovex = (int) event.getx ();
Invalidate ();
} break; Case Motionevent.actiOn_up:case MotionEvent.ACTION_CANCEL:if (Measurewidth > width) {mvelocitytracker.computecurrentvelocity (10
00);
int max = Math.max (Math.Abs (Mscroller.getcurrx ()), Math.Abs (Measurewidth-width-mscroller.getcurrx ())); Mscroller.fling (Mscroller.getfinalx (), Mscroller.getfinaly (), (int)-mvelocitytracker.getxvelocity (), (int)-
Mvelocitytracker.getyvelocity (), 0, Max, Mscroller.getfinaly (), mscroller.getfinaly ());
When the finger is raised, initialize the position according to the scrolling offset if (Mscroller.getcurrx () < 0) {mscroller.abortanimation ();
Mscroller.startscroll (Mscroller.getcurrx (), Mscroller.getcurry (),-mscroller.getcurrx (), 0);
}else if (Mscroller.getcurrx () + width > measurewidth) {mscroller.abortanimation ();
Mscroller.startscroll (Mscroller.getcurrx (), Mscroller.getcurry (), Measurewidth-width-mscroller.getcurrx (), 0);
} if (event.getaction () = = motionevent.action_up) {int mupx = (int) event.getx ();
int mupy = (int) event.gety (); Analog clicksAction if (Math.Abs (MUPX-MTOUCHX) <= mtouchslop && math.abs (mupy-mtouchy) <= mtouchslop) {for (int i = 0; I < items.size ();
i++) {if (Items.get (i). Rect.contains (Mscroller.getcurrx () + MUPX, getscrolly () + mupy)) {setselected (i);
Return Super.ontouchevent (event);
Break in}}};
Default:break;
Return Super.ontouchevent (event);
}
Next is a very important piece of code, because it allows you to automatically scroll to full display when the item option that is not fully displayed is selected:
public void setselected (int position) {
if (position >= items.size ()) {return
;
}
for (int i = 0; i < items.size (); i++) {
if (i = = position) {
items.get (i). IsSelected = true;
if (i!= selectitem) {
selectitem = i;
Determine if it is necessary to slide to the fully visible
if (Mscroller.getcurrx () + Width < Items.get (i). Rect.right) {
Mscroller.startscroll ( Mscroller.getfinalx (), Mscroller.getfinaly (), Items.get (i). Rect.right-mscroller.getcurrx ()-width, Mscroller.getfinaly ());
}
if (Items.get (i). Rect.left < Mscroller.getcurrx ()) {
mscroller.startscroll (Mscroller.getfinalx (), Mscroller.getfinaly (), Items.get (i). Rect.left-mscroller.getcurrx (), mscroller.getfinaly ());
if (listener!= null) {
listener.onchanged (SelectItem);}}}
else{
Items.get (i). isselected = false;
}
}
Invalidate ();
}
Then is the drawing method, which is equivalent to the full agent giving the item to implement: &NBSP;
@Override protected void OnDraw (Canvas Canvas) {Mpaint.setantialias (true);
Canvas.drawcolor (COLORBG);
for (Item item:items) {mpaint.settextsize (item.textsize);
if (item.isselected) {if (type = = Type.selectbyline) {//Draw Red Line Mpaint.setcolor (item.colorselected);
Mpaint.setstyle (Paint.Style.FILL); Canvas.drawroundrect (New RECTF (Item.rect.left, Item.rect.bottom-lineheight, Item.rect.right, Item.rect.bottom), 3, 3
, Mpaint); }else if (type = = Type.selectbyfill) {//Draw red background mpaint.setcolor (GetContext (). Getresources (). GetColor (Android.
R.color.holo_red_light));
Mpaint.setstyle (Paint.Style.FILL); Canvas.drawroundrect (New RECTF (Item.rect.left + 6, item.rect.top, item.rect.right-6, Item.rect.bottom),
Item.rect.height () * 5/12, Item.rect.height () * 5/12, Mpaint);
} mpaint.setcolor (item.colorselected);
}else{Mpaint.setcolor (Item.colordefault); } canvas.drawtext (Item.text, Item.drawpoint.x, Item.drawpoint.y, Mpaint);
}
}
The next step is how to use the control, the layout file:
<?xml version= "1.0" encoding= "Utf-8"?> <relativelayout xmlns:android=
"http://schemas.android.com/apk" /res/android "
android:id=" @+id/listview "
android:layout_width=" match_parent "
android:layout_height" = "Match_parent" >
<cc.wxf.androiddemo.indicator.indicatorview
android:id= "@+id/indicator"
Android:layout_width= "Match_parent"
android:layout_height= "38DP"/>
</RelativeLayout>
In mainactvity:
Package Cc.wxf.androiddemo;
Import Android.content.Context;
Import android.content.res.Resources;
Import Android.os.Bundle;
Import android.support.v4.app.FragmentActivity;
Import Cc.wxf.androiddemo.indicator.IndicatorView;
public class Mainactivity extends Fragmentactivity {private Indicatorview indicatorview;
@Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
Setcontentview (R.layout.activity_main);
Initindicator ();
private void Initindicator () {Indicatorview = (Indicatorview) Findviewbyid (r.id.indicator);
Resources of resources = getresources (); Indicatorview.color (Resources.getcolor) (Android. R.color.black), Resources.getcolor (Android. R.color.holo_red_light), Resources.getcolor (Android. R.color.darker_gray)). Textsize (sp2px (this)). Padding (The new int[]{dip2px (this,), dip2px (this,), dip2px (thi S,), dip2px (This,)}). Text (New string[]{"TV series", "movie", "Comprehensive Art", "Flower", "anime", "Entertainment", "member 1", "Member 2", "Member 3", "Member 4", "member 5", "member 6"}). Defaultselect (0). Lineheight (Dip2px (this, 3)). Listener (New Indicatorview.onindicatorchangedlistene
R () {@Override public void onchanged (int position) {}}). commit (); public static int dip2px (context context, float Dipvalue) {final float scale = context.getresources (). Getdisplaymetr
ICS (). Density;
return (int) (Dipvalue * scale + 0.5f); public static int sp2px (context context, float Spvalue) {final float scale = context.getresources (). getdisplaymetric
S (). Scaleddensity;
return (int) (Spvalue * scale + 0.5f);
} @Override protected void OnDestroy () {Super.ondestroy ();
Indicatorview.release ();
}
}
The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.