android二级listview列表实现代码
程序员文章站
2024-02-10 12:34:40
今天来实现以下大众点评客户端的横向listview二级列表,先看一下样式。 这种横向的listview二级列表在手机软件上还不太常见,但是使用过平板的都应该知道...
今天来实现以下大众点评客户端的横向listview二级列表,先看一下样式。
这种横向的listview二级列表在手机软件上还不太常见,但是使用过平板的都应该知道,在平板上市比较常见的。可能是因为平板屏幕比较大,而且也能展现更多的内容。
下面来看一下我的实现步骤。
首先自定义一个listview,代码如下:
public class mylistview extends listview implements runnable {
private float mlastdowny = 0f;
private int mdistance = 0;
private int mstep = 10;
private boolean mpositive = false;
public mylistview (context context, attributeset attrs) {
super(context, attrs);
}
public mylistview (context context, attributeset attrs, int defstyle) {
super(context, attrs, defstyle);
}
public mylistview (context context) {
super(context);
}
@override
public boolean ontouchevent(motionevent event) {
switch (event.getaction()) {
case motionevent.action_down:
if (mlastdowny == 0f && mdistance == 0) {
mlastdowny = event.gety();
return true;
}
break;
case motionevent.action_cancel:
break;
case motionevent.action_up:
if (mdistance != 0) {
mstep = 1;
mpositive = (mdistance >= 0);
this.post(this);
return true;
}
mlastdowny = 0f;
mdistance = 0;
break;
case motionevent.action_move:
if (mlastdowny != 0f) {
mdistance = (int) (mlastdowny - event.gety());
if ((mdistance < 0 && getfirstvisibleposition() == 0 && getchildat(0).gettop() == 0) || (mdistance > 0 && getlastvisibleposition() == getcount() - 1)) {
mdistance /= 2;
scrollto(0, mdistance);
return true;
}
}
mdistance = 0;
break;
}
return super.ontouchevent(event);
}
public void run() {
mdistance += mdistance > 0 ? -mstep : mstep;
scrollto(0, mdistance);
if ((mpositive && mdistance <= 0) || (!mpositive && mdistance >= 0)) {
scrollto(0, 0);
mdistance = 0;
mlastdowny = 0f;
return;
}
mstep += 1;
this.postdelayed(this, 10);
}
}
然后看一下xml的布局:
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<com.example.multilistview.mylistview
android:id="@+id/listview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:choicemode="singlechoice"
android:scrollbars="none"
android:divider="@drawable/listitem_divide"
android:listselector="#00000000"
android:background="#e4e3de"
>
</com.example.multilistview.mylistview>
<com.example.multilistview.mylistview
android:id="@+id/sublistview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#e4e3de"
>
</com.example.multilistview.mylistview>
</linearlayout>
两个自定义的listview 横向布局,然后是父listview的适配器
public class myadapter extends baseadapter {
context context;
layoutinflater inflater;
string [] foods;
int last_item;
int [] images;
private int selectedposition = -1;
public myadapter(context context,string [] foods,int[] images){
this.context = context;
this.foods = foods;
this.images = images;
inflater=layoutinflater.from(context);
}
@override
public int getcount() {
// todo auto-generated method stub
return foods.length;
}
@override
public object getitem(int position) {
// todo auto-generated method stub
return position;
}
@override
public long getitemid(int position) {
// todo auto-generated method stub
return position;
}
@override
public view getview(int position, view convertview, viewgroup parent) {
// todo auto-generated method stub
viewholder holder = null;
if(convertview==null){
convertview = inflater.inflate(r.layout.mylist_item, null);
holder = new viewholder();
holder.textview =(textview)convertview.findviewbyid(r.id.textview);
holder.imageview =(imageview)convertview.findviewbyid(r.id.imageview);
holder.layout=(linearlayout)convertview.findviewbyid(r.id.colorlayout);
convertview.settag(holder);
}
else{
holder=(viewholder)convertview.gettag();
}
// 设置选中效果
if(selectedposition == position)
{
holder.textview.settextcolor(color.blue);
holder.layout.setbackgroundcolor(color.ltgray);
} else {
holder.textview.settextcolor(color.white);
holder.layout.setbackgroundcolor(color.transparent);
}
holder.textview.settext(foods[position]);
holder.textview.settextcolor(color.black);
holder.imageview.setbackgroundresource(images[position]);
return convertview;
}
public static class viewholder{
public textview textview;
public imageview imageview;
public linearlayout layout;
}
public void setselectedposition(int position) {
selectedposition = position;
}
}
对应的 item布局:
<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/colorlayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<imageview
android:id="@+id/imageview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginleft="10dip"
android:layout_margintop="5dip"
/>
<textview
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textsize="16dip"
android:layout_margintop="8dip"
android:layout_marginleft="8dip"
android:layout_marginbottom="8dip"/>
<!-- android:background="@drawable/selector" 自定义listview 样式-->
</linearlayout>
然后是子适配器代码:
public class subadapter extends baseadapter {
context context;
layoutinflater layoutinflater;
string[][] cities;
public int foodpoition;
public subadapter(context context, string[][] cities,int position) {
this.context = context;
this.cities = cities;
layoutinflater = (layoutinflater) context.getsystemservice(context.layout_inflater_service);
this.foodpoition = position;
}
@override
public int getcount() {
// todo auto-generated method stub
return cities.length;
}
@override
public object getitem(int position) {
// todo auto-generated method stub
return getitem(position);
}
@override
public long getitemid(int position) {
// todo auto-generated method stub
return position;
}
@override
public view getview(int position, view convertview, viewgroup parent) {
// todo auto-generated method stub
viewholder viewholder = null;
final int location=position;
if (convertview == null) {
convertview = layoutinflater.inflate(r.layout.sublist_item, null);
viewholder = new viewholder();
viewholder.textview = (textview) convertview
.findviewbyid(r.id.textview1);
convertview.settag(viewholder);
} else {
viewholder = (viewholder) convertview.gettag();
}
viewholder.textview.settext(cities[foodpoition][position]);
viewholder.textview.settextcolor(color.black);
return convertview;
}
public static class viewholder {
public textview textview;
}
}
对应的xml布局:
<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<textview
android:id="@+id/textview1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="aaaaa"
android:textsize="16dip"
android:layout_margintop="10dip"
android:layout_marginleft="8dip"
android:layout_marginbottom="8dip"/>
</linearlayout>
最后看下主activity的实现代码
public class mainactivity extends activity {
private mylistview listview;
private mylistview sublistview;
private myadapter myadapter;
private subadapter subadapter;
string cities[][] = new string[][] {
new string[] {"全部美食", "本帮江浙菜", "川菜", "粤菜", "湘菜","东北菜","*菜","*/清真","素菜","火锅","自助餐","小吃快餐","日本","韩国料理",
"东南亚菜","西餐","面包甜点","其他"},
new string[] {"全部休闲娱乐","咖啡厅","酒吧","茶馆","ktv","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
"diy手工坊","桌球馆","桌面游戏","更多休闲娱乐"},
new string[] {"全部购物", "综合商场", "服饰鞋包", "运动户外","珠宝饰品","化妆品","数码家电","亲子购物","家居建材"
,"书店","书店","眼镜店","特色集市","更多购物场所","食品茶酒","超市/便利店","药店"},
new string[] {"全部休闲娱乐","咖啡厅","酒吧","茶馆","ktv","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
"diy手工坊","桌球馆","桌面游戏","更多休闲娱乐"},
new string[] {"全","咖啡厅","酒吧","茶馆","ktv","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
"diy手工坊","桌球馆","桌面游戏","更多休闲娱乐"},
new string[] {"全部","咖啡厅","酒吧","茶馆","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
"diy手工坊","桌球馆","桌面游戏","更多休闲娱乐"},
new string[] {"全部休","咖啡厅","酒吧","茶馆","ktv","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
"diy手工坊","桌球馆","桌面游戏","更多休闲娱乐"},
new string[] {"全部休闲","咖啡厅","酒吧","茶馆","ktv","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
"diy手工坊","桌球馆","桌面游戏","更多休闲娱乐"},
new string[] {"全部休闲娱","咖啡厅","酒吧","茶馆","ktv","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
"diy手工坊","桌球馆","桌面游戏"},
new string[] {"全部休闲娱乐","咖啡厅","酒吧","茶馆","ktv","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
"diy手工坊","桌球馆","桌面游戏","更多休闲娱乐"},
new string[] {"全部休闲aaa","咖啡厅","酒吧","茶馆","ktv","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
"diy手工坊","桌球馆","桌面游戏"},
};
string foods[] =new string []{"全部频道","美食","休闲娱乐","购物","酒店","丽人","运动健身","结婚","亲子","爱车","生活服务"};
int images[] = new int[]{r.drawable.ic_category_0,r.drawable.ic_category_10,r.drawable.ic_category_30,r.drawable.ic_category_20
,r.drawable.ic_category_60,r.drawable.ic_category_50,r.drawable.ic_category_45,r.drawable.ic_category_50,r.drawable.ic_category_70,
r.drawable.ic_category_65,r.drawable.ic_category_80};
@override
public void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.activity_main);
init();
myadapter=new myadapter(getapplicationcontext(), foods, images);
listview.setadapter(myadapter);
selectdefult();
listview.setonitemclicklistener(new onitemclicklistener() {
@override
public void onitemclick(adapterview<?> arg0, view arg1, int position,
long arg3) {
// todo auto-generated method stub
final int location=position;
myadapter.setselectedposition(position);
myadapter.notifydatasetinvalidated();
subadapter=new subadapter(getapplicationcontext(), cities, position);
sublistview.setadapter(subadapter);
sublistview.setonitemclicklistener(new onitemclicklistener() {
@override
public void onitemclick(adapterview<?> arg0, view arg1,
int position, long arg3) {
// todo auto-generated method stub
toast.maketext(getapplicationcontext(), cities[location][position], toast.length_short).show();
}
});
}
});
}
private void init(){
listview=(mylistview) findviewbyid(r.id.listview);
sublistview=(mylistview) findviewbyid(r.id.sublistview);
}
private void selectdefult(){
final int location=0;
myadapter.setselectedposition(0);
myadapter.notifydatasetinvalidated();
subadapter=new subadapter(getapplicationcontext(), cities, 0);
sublistview.setadapter(subadapter);
sublistview.setonitemclicklistener(new onitemclicklistener() {
@override
public void onitemclick(adapterview<?> arg0, view arg1,
int position, long arg3) {
// todo auto-generated method stub
toast.maketext(getapplicationcontext(), cities[location][position], toast.length_short).show();
}
});
}
}
默认我选中了第0个,下面看一下运行效果:
这种横向的listview二级列表在手机软件上还不太常见,但是使用过平板的都应该知道,在平板上市比较常见的。可能是因为平板屏幕比较大,而且也能展现更多的内容。
下面来看一下我的实现步骤。
首先自定义一个listview,代码如下:
复制代码 代码如下:
public class mylistview extends listview implements runnable {
private float mlastdowny = 0f;
private int mdistance = 0;
private int mstep = 10;
private boolean mpositive = false;
public mylistview (context context, attributeset attrs) {
super(context, attrs);
}
public mylistview (context context, attributeset attrs, int defstyle) {
super(context, attrs, defstyle);
}
public mylistview (context context) {
super(context);
}
@override
public boolean ontouchevent(motionevent event) {
switch (event.getaction()) {
case motionevent.action_down:
if (mlastdowny == 0f && mdistance == 0) {
mlastdowny = event.gety();
return true;
}
break;
case motionevent.action_cancel:
break;
case motionevent.action_up:
if (mdistance != 0) {
mstep = 1;
mpositive = (mdistance >= 0);
this.post(this);
return true;
}
mlastdowny = 0f;
mdistance = 0;
break;
case motionevent.action_move:
if (mlastdowny != 0f) {
mdistance = (int) (mlastdowny - event.gety());
if ((mdistance < 0 && getfirstvisibleposition() == 0 && getchildat(0).gettop() == 0) || (mdistance > 0 && getlastvisibleposition() == getcount() - 1)) {
mdistance /= 2;
scrollto(0, mdistance);
return true;
}
}
mdistance = 0;
break;
}
return super.ontouchevent(event);
}
public void run() {
mdistance += mdistance > 0 ? -mstep : mstep;
scrollto(0, mdistance);
if ((mpositive && mdistance <= 0) || (!mpositive && mdistance >= 0)) {
scrollto(0, 0);
mdistance = 0;
mlastdowny = 0f;
return;
}
mstep += 1;
this.postdelayed(this, 10);
}
}
然后看一下xml的布局:
复制代码 代码如下:
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<com.example.multilistview.mylistview
android:id="@+id/listview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:choicemode="singlechoice"
android:scrollbars="none"
android:divider="@drawable/listitem_divide"
android:listselector="#00000000"
android:background="#e4e3de"
>
</com.example.multilistview.mylistview>
<com.example.multilistview.mylistview
android:id="@+id/sublistview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#e4e3de"
>
</com.example.multilistview.mylistview>
</linearlayout>
两个自定义的listview 横向布局,然后是父listview的适配器
复制代码 代码如下:
public class myadapter extends baseadapter {
context context;
layoutinflater inflater;
string [] foods;
int last_item;
int [] images;
private int selectedposition = -1;
public myadapter(context context,string [] foods,int[] images){
this.context = context;
this.foods = foods;
this.images = images;
inflater=layoutinflater.from(context);
}
@override
public int getcount() {
// todo auto-generated method stub
return foods.length;
}
@override
public object getitem(int position) {
// todo auto-generated method stub
return position;
}
@override
public long getitemid(int position) {
// todo auto-generated method stub
return position;
}
@override
public view getview(int position, view convertview, viewgroup parent) {
// todo auto-generated method stub
viewholder holder = null;
if(convertview==null){
convertview = inflater.inflate(r.layout.mylist_item, null);
holder = new viewholder();
holder.textview =(textview)convertview.findviewbyid(r.id.textview);
holder.imageview =(imageview)convertview.findviewbyid(r.id.imageview);
holder.layout=(linearlayout)convertview.findviewbyid(r.id.colorlayout);
convertview.settag(holder);
}
else{
holder=(viewholder)convertview.gettag();
}
// 设置选中效果
if(selectedposition == position)
{
holder.textview.settextcolor(color.blue);
holder.layout.setbackgroundcolor(color.ltgray);
} else {
holder.textview.settextcolor(color.white);
holder.layout.setbackgroundcolor(color.transparent);
}
holder.textview.settext(foods[position]);
holder.textview.settextcolor(color.black);
holder.imageview.setbackgroundresource(images[position]);
return convertview;
}
public static class viewholder{
public textview textview;
public imageview imageview;
public linearlayout layout;
}
public void setselectedposition(int position) {
selectedposition = position;
}
}
对应的 item布局:
复制代码 代码如下:
<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/colorlayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<imageview
android:id="@+id/imageview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginleft="10dip"
android:layout_margintop="5dip"
/>
<textview
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textsize="16dip"
android:layout_margintop="8dip"
android:layout_marginleft="8dip"
android:layout_marginbottom="8dip"/>
<!-- android:background="@drawable/selector" 自定义listview 样式-->
</linearlayout>
然后是子适配器代码:
复制代码 代码如下:
public class subadapter extends baseadapter {
context context;
layoutinflater layoutinflater;
string[][] cities;
public int foodpoition;
public subadapter(context context, string[][] cities,int position) {
this.context = context;
this.cities = cities;
layoutinflater = (layoutinflater) context.getsystemservice(context.layout_inflater_service);
this.foodpoition = position;
}
@override
public int getcount() {
// todo auto-generated method stub
return cities.length;
}
@override
public object getitem(int position) {
// todo auto-generated method stub
return getitem(position);
}
@override
public long getitemid(int position) {
// todo auto-generated method stub
return position;
}
@override
public view getview(int position, view convertview, viewgroup parent) {
// todo auto-generated method stub
viewholder viewholder = null;
final int location=position;
if (convertview == null) {
convertview = layoutinflater.inflate(r.layout.sublist_item, null);
viewholder = new viewholder();
viewholder.textview = (textview) convertview
.findviewbyid(r.id.textview1);
convertview.settag(viewholder);
} else {
viewholder = (viewholder) convertview.gettag();
}
viewholder.textview.settext(cities[foodpoition][position]);
viewholder.textview.settextcolor(color.black);
return convertview;
}
public static class viewholder {
public textview textview;
}
}
对应的xml布局:
复制代码 代码如下:
<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<textview
android:id="@+id/textview1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="aaaaa"
android:textsize="16dip"
android:layout_margintop="10dip"
android:layout_marginleft="8dip"
android:layout_marginbottom="8dip"/>
</linearlayout>
最后看下主activity的实现代码
复制代码 代码如下:
public class mainactivity extends activity {
private mylistview listview;
private mylistview sublistview;
private myadapter myadapter;
private subadapter subadapter;
string cities[][] = new string[][] {
new string[] {"全部美食", "本帮江浙菜", "川菜", "粤菜", "湘菜","东北菜","*菜","*/清真","素菜","火锅","自助餐","小吃快餐","日本","韩国料理",
"东南亚菜","西餐","面包甜点","其他"},
new string[] {"全部休闲娱乐","咖啡厅","酒吧","茶馆","ktv","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
"diy手工坊","桌球馆","桌面游戏","更多休闲娱乐"},
new string[] {"全部购物", "综合商场", "服饰鞋包", "运动户外","珠宝饰品","化妆品","数码家电","亲子购物","家居建材"
,"书店","书店","眼镜店","特色集市","更多购物场所","食品茶酒","超市/便利店","药店"},
new string[] {"全部休闲娱乐","咖啡厅","酒吧","茶馆","ktv","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
"diy手工坊","桌球馆","桌面游戏","更多休闲娱乐"},
new string[] {"全","咖啡厅","酒吧","茶馆","ktv","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
"diy手工坊","桌球馆","桌面游戏","更多休闲娱乐"},
new string[] {"全部","咖啡厅","酒吧","茶馆","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
"diy手工坊","桌球馆","桌面游戏","更多休闲娱乐"},
new string[] {"全部休","咖啡厅","酒吧","茶馆","ktv","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
"diy手工坊","桌球馆","桌面游戏","更多休闲娱乐"},
new string[] {"全部休闲","咖啡厅","酒吧","茶馆","ktv","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
"diy手工坊","桌球馆","桌面游戏","更多休闲娱乐"},
new string[] {"全部休闲娱","咖啡厅","酒吧","茶馆","ktv","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
"diy手工坊","桌球馆","桌面游戏"},
new string[] {"全部休闲娱乐","咖啡厅","酒吧","茶馆","ktv","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
"diy手工坊","桌球馆","桌面游戏","更多休闲娱乐"},
new string[] {"全部休闲aaa","咖啡厅","酒吧","茶馆","ktv","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
"diy手工坊","桌球馆","桌面游戏"},
};
string foods[] =new string []{"全部频道","美食","休闲娱乐","购物","酒店","丽人","运动健身","结婚","亲子","爱车","生活服务"};
int images[] = new int[]{r.drawable.ic_category_0,r.drawable.ic_category_10,r.drawable.ic_category_30,r.drawable.ic_category_20
,r.drawable.ic_category_60,r.drawable.ic_category_50,r.drawable.ic_category_45,r.drawable.ic_category_50,r.drawable.ic_category_70,
r.drawable.ic_category_65,r.drawable.ic_category_80};
@override
public void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.activity_main);
init();
myadapter=new myadapter(getapplicationcontext(), foods, images);
listview.setadapter(myadapter);
selectdefult();
listview.setonitemclicklistener(new onitemclicklistener() {
@override
public void onitemclick(adapterview<?> arg0, view arg1, int position,
long arg3) {
// todo auto-generated method stub
final int location=position;
myadapter.setselectedposition(position);
myadapter.notifydatasetinvalidated();
subadapter=new subadapter(getapplicationcontext(), cities, position);
sublistview.setadapter(subadapter);
sublistview.setonitemclicklistener(new onitemclicklistener() {
@override
public void onitemclick(adapterview<?> arg0, view arg1,
int position, long arg3) {
// todo auto-generated method stub
toast.maketext(getapplicationcontext(), cities[location][position], toast.length_short).show();
}
});
}
});
}
private void init(){
listview=(mylistview) findviewbyid(r.id.listview);
sublistview=(mylistview) findviewbyid(r.id.sublistview);
}
private void selectdefult(){
final int location=0;
myadapter.setselectedposition(0);
myadapter.notifydatasetinvalidated();
subadapter=new subadapter(getapplicationcontext(), cities, 0);
sublistview.setadapter(subadapter);
sublistview.setonitemclicklistener(new onitemclicklistener() {
@override
public void onitemclick(adapterview<?> arg0, view arg1,
int position, long arg3) {
// todo auto-generated method stub
toast.maketext(getapplicationcontext(), cities[location][position], toast.length_short).show();
}
});
}
}
默认我选中了第0个,下面看一下运行效果:
上一篇: js数字计算 误差问题的快速解决方法