Why the emphasis is not custom adapter, because I this custom control is the source and the company's new project, just started to find a circle on Baidu, are said to be custom ListView, point in is custom adaper, some people will say you are not too serious, Custom adapter Basically can achieve a variety of effects, why to customize the ListView, today I do this is really not good with adapter do, first, the right of the motion diagram from the left side of the project a control.
Because of our project, six channels of the detection process to be dynamic display at the same time, so that the location is reasonable deployment, because the layout of six channels are similar, so at that time considered fragment or custom control, later, Because the following four buttons to correspond to four different pages, it is necessary to use viewpager+fragment,fragment is not supported by the fragment, and the detection of each channel will vary depending on the type of items detected, so, You can only use a custom control.
When it comes to custom controls, you have to decide which one to use, no matter what you think, anyway, I look at the first glance and the ListView, I first consider the custom ListView, and at the beginning also want to use the custom adapter, we want to achieve, given the item number to calculate the item height and set, I thought about getting the height of the custom ListView in the OnLayout in the custom ListView, then the public method exposes the ListView height and then adapter the GetView To get the height of the custom ListView and calculate the setting item height, it turns out that I think more, the GetView method of item is executed in front of the OnLayout method of the ListView, there is a picture for evidence
I've wasted a lot of time trying to find this mistake, it's all tears.
The size parameter can only be done in the custom ListView, and the dynamic item status is also done in the custom ListView.
Then our steps are clear.
1. Custom adapter, dynamically to the ListView in fixed number
2. Customize the ListView, set the size information for the item, and implement the scrolling process logic
3. Bind data to a custom ListView in Mainactivity.
First, give the Lvadapter code.
Package Diasia.cdc.com.simplelistview;import Android.animation.valueanimator;import Android.content.Context; Import Android.view.layoutinflater;import Android.view.view;import Android.view.viewgroup;import Android.widget.baseadapter;import android.widget.textview;/** * Created by LV on 2015/1/15. */public class Lvadapter extends Baseadapter {private string[] strs; Private context context; Private Boolean B = true; Public Lvadapter (string[] atrs, Context context) {this.strs = ATRs; This.context = context; } @Override public int getcount () {return strs.length; } @Override public Object getItem (int position) {return strs[position]; } @Override public long getitemid (int position) {return position; } @Override public View getView (int position, view Convertview, ViewGroup parent) {Viewhold viewhold; if (Convertview = = null) {Viewhold = new viewhold (); Convertview = LayOutinflater.from (context). Inflate (R.layout.item_layout, parent, false); Convertview.settag (Viewhold); } else {viewhold = (viewhold) convertview.gettag (); } Viewhold.textview = (TextView) Convertview.findviewbyid (R.id.textview); ViewHold.textView.setText (Strs[position]); ViewHold.textView.setTextSize (25); if (position = = 1) {Startscaleto (Convertview, 0.6f, 1.0f); } else {Startscaleto (Convertview, 1.0f, 0.6f); } return Convertview; public void Startscaleto (final view view, float start, float end) {Valueanimator animator = Valueanimator.off Loat (start, end); Animator.setduration (500); Animator.start (); Animator.addupdatelistener (New Valueanimator.animatorupdatelistener () {@Override public void Onanim Ationupdate (Valueanimator animation) {Float value = (float) animation.getanimatedvalue (); View. Setscalex (value); View.setscaley (0.4f + (0.6f * value)); } }); } public class Viewhold {public TextView TextView; }}
The general settings inside, I do not have to say, you should also write to not be familiar with, as to the problem of reuse, should also be difficult to fall. I'll explain that.
if (position = = 1) { Startscaleto (Convertview, 0.6f, 1.0f), } else { Startscaleto (Convertview, 1.0f, 0.6f); c4/>}
This is when the item content is first loaded, and all items except the second one are shrunk (the illusion is that the middle one is magnified)
Post the code in the R.layout.item_layout.xml and put the Item_background.xml
<?xml version= "1.0" encoding= "Utf-8"? ><linearlayout xmlns:android= "http://schemas.android.com/apk/res/ Android " android:layout_width=" match_parent " android:layout_height=" match_parent " android:padding= "20DP" > <textview android:id= "@+id/textview" android:layout_width= "Match_parent" Android : layout_height= "match_parent" android:gravity= "center" android:text= "in pre-temperature" android:background= "@ Drawable/item_background "/></linearlayout>
Item_background.xml
<?xml version= "1.0" encoding= "Utf-8"? ><shape xmlns:android= "Http://schemas.android.com/apk/res/android" > <stroke android:width= "2DP" android:color= "@android: Color/holo_orange_dark" /> <corners android:radius= "150DP" /></shape>
These two files do not have to be explained, it is simple, it is decided the appearance of each item
Then is today's protagonist Lvlistview debut, the code a paragraph of the paste, to ensure that the whole, first put out some global variables, the back of the control to see
Package Diasia.cdc.com.simplelistview;import Android.animation.valueanimator;import Android.content.Context; Import Android.content.res.typedarray;import Android.util.attributeset;import Android.util.log;import Android.view.motionevent;import Android.view.view;import Android.view.viewgroup;import Android.widget.AbsListView Import Android.widget.linearlayout;import android.widget.listview;/** * Todo:document your custom view class. */public class Lvlistview extends ListView implements Abslistview.onscrolllistener {/** * display on screen How many item */ private int showitemcount; /** * Height per item */private int itemheight; /** * Records the first displayed item *//** * Animation from the number of lines */private int scaleflagindex = 1; /** * is the last line */private Boolean lastflag = false; /** * Step * */private int step = 0; /** * Number of steps * */private int stepcount;
Next, the method of post-construction:
Public Lvlistview (Context context) {This (context, NULL); } Public Lvlistview (context context, AttributeSet attrs) {This (context, attrs, 0); } /** * Construct method to get custom attribute Showviewcount and set scrolling listening * * @param context * @param attrs * @param defstyleattr * /Public Lvlistview (context context, AttributeSet attrs, int defstyleattr) { Super (context, attrs, DEFSTYLEATTR); Get Showviewcount TypedArray TypedArray = context.obtainstyledattributes (Attrs, r.styleable.lvlistview); Showitemcount = Typedarray.getint (r.styleable.lvlistview_showviewcount, 0); Typedarray.recycle (); Set a scrolling listener setonscrolllistener (this); }
In the construction method, two things are done: to get the custom attribute, the user sets the number of items to display, we set it back to 3, and by the way we paste the file from the defined property
<resources> <declare-styleable name= "Lvlistview" > <attr name= "Showviewcount" format= " Integer "/> </declare-styleable></resources>
Next, rewrite the OnLayout method to get the size of the Lvlistview to set the size of the item
@Override protected void OnLayout (Boolean changed, int l, int t, int r, int b) { super.onlayout (changed, L, T, R, b); if (changed) { itemheight = This.getheight ()/showitemcount; for (int i = 0; i < Getchildcount (); i++) { linearlayout layout = (linearlayout) getchildat (i); Abslistview.layoutparams layoutparams = new Layoutparams (ViewGroup.LayoutParams.MATCH_PARENT, itemheight); Layout.setlayoutparams (Layoutparams); } Stepcount = Getadapter (). GetCount ()-2; } }
Which, in this section, I'm confused.
LinearLayout layout = (linearlayout) getchildat (i); Abslistview.layoutparams layoutparams = new Layoutparams (ViewGroup.LayoutParams.MATCH_PARENT, itemheight); Layout.setlayoutparams (Layoutparams);
But also troubled me for a long time, just started to use the Viewgroup.layoutparams, always reportedwrongJava.lang.classcastexception:android.widget.linearlayout$layoutparams cannot be cast Toandroid.widget.abslistview$layoutparams, I use reflection to get the type of Getchildat (i), which is a abslistview type, which I express very puzzling, Clearly I above the item layout of the outer layer is a linearlayout layout, the reason I found, is because of my adapter in the Layoutinflater.from (context). Inflate (R.layout.item_layout, Parent,false) This sentence, although the back with false, let the effect is not implemented, but the layout of the relationship already exists, because layoutinflater.from (context). Inflate (r.layout.item_ layout, NULL) write will report warning, on a foreign site to see that this is not standard, there will be problems (PS: Although I do not know what the problem, but the unknown problem is the most terrible, I do not try), so the layout parameter type is changed, Changed to Abslistview.layoutparams, anyway not error is good. Then Stepcount = Getadapter (). GetCount ()-2; The number of steps to be assigned, why subtract 2, because the first step and the last step we do not go, do not understand see the front and below the dynamic diagram.
Rewrite ontouchevent
/** * Disable finger swipe * * @param ev * @return * /@Override public Boolean ontouchevent ( Motionevent ev) { return false; }
The notes are very detailed and do not change the interpretation
Then, zoom the animation
/** * Zoom Animation * * @param view * @param start * @param end * /public void Startscaleanimator ( Final view view, float start, float end) { Valueanimator animator = valueanimator.offloat (start, end); Animator.setduration (+); Animator.start (); Animator.addupdatelistener (New Valueanimator.animatorupdatelistener () { @Override public Void Onanimationupdate (Valueanimator animation) { float value = (float) animation.getanimatedvalue (); View.setscalex (value); View.setscaley (0.4f + (0.6f * value)); } );
Here to say, by the way to explain the adapter, because our item is a low but very wide control, then the horizontal scale and vertical scaling can not adopt the uniform standard, horizontal scaling is used to pass over the value, but the vertical scale to calculate the value of a bit, through 0.4f + (0.6f * Value), the scaling interval is reduced, please bring in the same value between the same 0-1 in the calculation, here to emphasize that the decimal must be followed by F, careful data loss.
Next, is the method of our Next button call, the function of our company is to get the call in other code, not with the button
/** * Settings Scroll to the specified item * /public void Scrolltoitem () { step++; if (step = = Stepcount) { step = 0; This.lastflag = true; Startscaleanimator (Getchildat (Scaleflagindex), 1.0f, 0.6f); This.smoothscrolltopositionfromtop (step, 0, +); } else { this.smoothscrolltopositionfromtop (step, 0, $); } }
step++ is to push the step after a step, that is, the next, if (step = = Stepcount) to determine whether to the last step, if not to the last step, call Smoothscrolltopositionfromtop scroll to the specified item, The second parameter is the distance required from the top of the view at the end of the < code > position </code> pixel scrolling, is this sentence not understood? Don't ask me, I do not understand, anyway, I am useless, I set to 0, the third parameter is the scrolling time, as for the interpolator What, do not care. If you go to the last step, set step 0, change the LASTFLAG flag to True, the following will be used, Startscaleanimator (Getchildat (Scaleflagindex), 1.0f, 0.6f); is to reduce the last magnified item, This.smoothscrolltopositionfromtop (step, 0, 1000); As for why to give 1000 milliseconds, because from the last scroll to the front, scroll the item too much, The time is too short to see.
Next is the focus of Lvlistview, implementing the Abslistview.onscrolllistener interface and implementing the two abstract methods
@Override public void onscrollstatechanged (abslistview view, int scrollstate) { log.e ("onscrollstatechanged") , "scrollstate--" + scrollstate); if (scrollstate = = onscrolllistener.scroll_state_fling) { if (!lastflag) { Startscaleanimator ( View.getchildat (Scaleflagindex), 1.0f, 0.6f); Startscaleanimator (View.getchildat (Scaleflagindex + 1), 0.6f, 1.0f); Scaleflagindex = 2; } } else if (scrollstate = = Onscrolllistener.scroll_state_idle && lastflag) { This.lastflag = false; Scaleflagindex = 1; } } @Override public void Onscroll (abslistview view, int firstvisibleitem, int visibleitemcount, int totalitemcount) { C16/>LOG.E ("Onscroll", "firstvisibleitem--" + Firstvisibleitem); }
The former is the logic of dynamically setting the animation effect of item when the ListView scrolls down each time, Abslistview view represents the container of the ListView item currently displayed on the screen, Scrollstate is the state of the current ListView, Scrollstate has three states, which are idle (scroll complete), scroll, start scrolling,
<span style= "White-space:pre" ></span>public static int scroll_state_idle = 0; public static int scroll_state_touch_scroll = 1; public static int scroll_state_fling = 2;
When we point to the next step, the animation must be played synchronously at the beginning of the scroll, so if (scrollstate = = onscrolllistener.scroll_state_fling) is to set the scrolling in the scrolling while playing the animation screen to make the second item smaller, point is the next, the first item will disappear, the second will go to the first position, so so, I because F (lastflag), the animation effect is set in Scrolltoitem, Here the settings are repeated, so set af (!lastflag) condition, set This.lastflag = False at each end, indicating that there is no final step, as to the question of Scaleflagindex = 1 or equal to 2, the problem is very strange, when we return to the item header, View.getchildat (1) would be in the first, so setting it up would be a different treatment for the first click of the head.
Next say onscroll, this is the method that executes several times in the scroll, should be the reason that we use the Code call scrolls, I use log to print the value of it, no matter how scroll, inside of four values are too strong, motionless, This is why I use attribute animation as a relatively low-performance way to achieve results.
Finally, attach the source code, because to learn csdn classroom knowledge, so to a point, there are points of the holding a field, no points in contact me to you
Customizing the ListView Effect to make the middle item dynamic (not custom adapter)