一个类似MIUI中原生短信编辑功能

来源:互联网 发布:苹果最新系统下载软件 编辑:程序博客网 时间:2024/06/05 15:35

首先描述下需求:

1、新增短信时,进来收件人是为空,显示一行文字(提醒)

2、从通讯录选择联系人后,回到短信编辑界面,收件栏显示一行,内容为“收件人:XXX、XXX、XXX、XXX.....”

3、当点击收件栏时,收件栏内容变化,变成可删除,最多显示四行,多余四行有上下滑动轮,不足四行,是几行显示几行

4、填写短信内容,即时计算短信条算,并有文本提示

下面是实现后效果图




下面终于到了代码实现块了,主要写一些主要用到的类,其他不太重要的就忽略写,读者自行补全。

首先是短信收件人是一个自定义的流布局,这个流布局不是本人写的,只是在上面加了些修改来满足自己的业务需求。

TagFlowLayout类

import java.util.HashSet;import java.util.Iterator;import java.util.Set;import com.zhaonongzi.wnshhseller.R;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Rect;import android.os.Bundle;import android.os.Parcelable;import android.text.TextUtils;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;/** * 自定义tag 页面的整体页面 *  * 实现绑定数据,事件处理 * @author admin * */public class TagFlowLayout extends FlowLayout implementsTagAdapter.OnDataChangedListener {private TagAdapter mTagAdapter;private boolean mAutoSelectEffect = true;private int mSelectedMax = -1;// -1为不限制数量private static final String TAG = "TagFlowLayout";private MotionEvent mMotionEvent;private Set<Integer> mSelectedView = new HashSet<Integer>();public TagFlowLayout(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.TagFlowLayout);mAutoSelectEffect = ta.getBoolean(R.styleable.TagFlowLayout_auto_select_effect, true);mSelectedMax = ta.getInt(R.styleable.TagFlowLayout_max_select, -1);ta.recycle();if (mAutoSelectEffect) {setClickable(true);}}public TagFlowLayout(Context context, AttributeSet attrs) {this(context, attrs, 0);}public TagFlowLayout(Context context) {this(context, null);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int cCount = getChildCount();for (int i = 0; i < cCount; i++) {TagView tagView = (TagView) getChildAt(i);if (tagView.getVisibility() == View.GONE)continue;if (tagView.getTagView().getVisibility() == View.GONE) {tagView.setVisibility(View.GONE);}}super.onMeasure(widthMeasureSpec, heightMeasureSpec);}public interface OnSelectListener {void onSelected(Set<Integer> selectPosSet);}private OnSelectListener mOnSelectListener;public void setOnSelectListener(OnSelectListener onSelectListener) {mOnSelectListener = onSelectListener;if (mOnSelectListener != null)setClickable(true);}public interface OnTagClickListener {boolean onTagClick(View view, int position, FlowLayout parent);}private OnTagClickListener mOnTagClickListener;public void setOnTagClickListener(OnTagClickListener onTagClickListener) {mOnTagClickListener = onTagClickListener;if (onTagClickListener != null)setClickable(true);}public void setAdapter(TagAdapter adapter) {// if (mTagAdapter == adapter)// return;mTagAdapter = adapter;mTagAdapter.setOnDataChangedListener(this);changeAdapter();}private void changeAdapter() {removeAllViews();TagAdapter adapter = mTagAdapter;TagView tagViewContainer = null;HashSet preCheckedList = mTagAdapter.getPreCheckedList();for (int i = 0; i < adapter.getCount(); i++) {View tagView = adapter.getView(this, i, adapter.getItem(i));tagViewContainer = new TagView(getContext());// ViewGroup.MarginLayoutParams clp = (ViewGroup.MarginLayoutParams)// tagView.getLayoutParams();// ViewGroup.MarginLayoutParams lp = new// ViewGroup.MarginLayoutParams(clp);// lp.width = ViewGroup.LayoutParams.WRAP_CONTENT;// lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;// lp.topMargin = clp.topMargin;// lp.bottomMargin = clp.bottomMargin;// lp.leftMargin = clp.leftMargin;// lp.rightMargin = clp.rightMargin;tagView.setDuplicateParentStateEnabled(true);tagViewContainer.setLayoutParams(tagView.getLayoutParams());tagViewContainer.addView(tagView);addView(tagViewContainer);if (preCheckedList.contains(i)) {tagViewContainer.setChecked(true);}}mSelectedView.addAll(preCheckedList);}@Overridepublic boolean onTouchEvent(MotionEvent event) {if (event.getAction() == MotionEvent.ACTION_UP) {mMotionEvent = MotionEvent.obtain(event);}return super.onTouchEvent(event);}@Overridepublic boolean performClick() {if (mMotionEvent == null)return super.performClick();int x = (int) mMotionEvent.getX();int y = (int) mMotionEvent.getY();mMotionEvent = null;TagView child = findChild(x, y);int pos = findPosByView(child);if (child != null) {doSelect(child, pos);if (mOnTagClickListener != null) {return mOnTagClickListener.onTagClick(child.getTagView(), pos,this);}}return super.performClick();}public void setMaxSelectCount(int count) {if (mSelectedView.size() > count) {Log.w(TAG, "you has already select more than " + count+ " views , so it will be clear .");mSelectedView.clear();}mSelectedMax = count;}public Set<Integer> getSelectedList() {return new HashSet<Integer>(mSelectedView);}private void doSelect(TagView child, int position) {if (mAutoSelectEffect) {if (!child.isChecked()) {// 处理max_select=1的情况if (mSelectedMax == 1 && mSelectedView.size() == 1) {Iterator<Integer> iterator = mSelectedView.iterator();Integer preIndex = iterator.next();TagView pre = (TagView) getChildAt(preIndex);pre.setChecked(false);child.setChecked(true);mSelectedView.remove(preIndex);mSelectedView.add(position);} else {if (mSelectedMax > 0&& mSelectedView.size() >= mSelectedMax)return;child.setChecked(true);mSelectedView.add(position);}} else {child.setChecked(false);mSelectedView.remove(position);}if (mOnSelectListener != null) {mOnSelectListener.onSelected(new HashSet<Integer>(mSelectedView));}}}private static final String KEY_CHOOSE_POS = "key_choose_pos";private static final String KEY_DEFAULT = "key_default";@Overrideprotected Parcelable onSaveInstanceState() {Bundle bundle = new Bundle();bundle.putParcelable(KEY_DEFAULT, super.onSaveInstanceState());String selectPos = "";if (mSelectedView.size() > 0) {for (int key : mSelectedView) {selectPos += key + "|";}selectPos = selectPos.substring(0, selectPos.length() - 1);}bundle.putString(KEY_CHOOSE_POS, selectPos);return bundle;}@Overrideprotected void onRestoreInstanceState(Parcelable state) {if (state instanceof Bundle) {Bundle bundle = (Bundle) state;String mSelectPos = bundle.getString(KEY_CHOOSE_POS);if (!TextUtils.isEmpty(mSelectPos)) {String[] split = mSelectPos.split("\\|");for (String pos : split) {int index = Integer.parseInt(pos);mSelectedView.add(index);TagView tagView = (TagView) getChildAt(index);tagView.setChecked(true);}}super.onRestoreInstanceState(bundle.getParcelable(KEY_DEFAULT));return;}super.onRestoreInstanceState(state);}private int findPosByView(View child) {final int cCount = getChildCount();for (int i = 0; i < cCount; i++) {View v = getChildAt(i);if (v == child)return i;}return -1;}private TagView findChild(int x, int y) {final int cCount = getChildCount();for (int i = 0; i < cCount; i++) {TagView v = (TagView) getChildAt(i);if (v.getVisibility() == View.GONE)continue;Rect outRect = new Rect();v.getHitRect(outRect);if (outRect.contains(x, y)) {return v;}}return null;}@Overridepublic void onChanged() {changeAdapter();}}
FlowLayout类

import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.View;import android.view.ViewGroup;import java.util.ArrayList;import java.util.List;import com.zhaonongzi.wnshhseller.activity.customer.AddMessageActivity;import com.zhaonongzi.wnshhseller.utils.GlobalMemoryCache;/** * Tag 页面布局基类 主要实现测量子view,绘制view *  * @author admin * */public class FlowLayout extends ViewGroup {protected List<List<View>> mAllViews = new ArrayList<List<View>>();protected List<Integer> mLineHeight = new ArrayList<Integer>();private int lines, counts, lastItem;// 限制显示多少行private boolean isShow;// 是否需要在最后显示省略号private LastListerInterface lastListerInterface = null;private int ihegth;public FlowLayout(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}public FlowLayout(Context context, AttributeSet attrs) {this(context, attrs, 0);}public FlowLayout(Context context) {this(context, null);}public void setLines(int line) {this.lines = line;}public int getLastItem() {Log.e("lastItem", lastItem + "");return lastItem;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);int modeWidth = MeasureSpec.getMode(widthMeasureSpec);int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);int modeHeight = MeasureSpec.getMode(heightMeasureSpec);// wrap_contentint width = 0;int height = 0;int lineWidth = 0;int lineHeight = 0;int childHeight1 = 0;int cCount = getChildCount();for (int i = 0; i < cCount; i++) {View child = getChildAt(i);if (child.getVisibility() == View.GONE) {if (i == cCount - 1) {width = Math.max(lineWidth, width);height += lineHeight;}continue;}measureChild(child, widthMeasureSpec, heightMeasureSpec);MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();int childWidth = child.getMeasuredWidth() + lp.leftMargin+ lp.rightMargin;int childHeight = child.getMeasuredHeight() + lp.topMargin+ lp.bottomMargin;childHeight1 = childHeight;if (lineWidth + childWidth > sizeWidth - getPaddingLeft()- getPaddingRight()) {width = Math.max(width, lineWidth);lineWidth = childWidth;height += lineHeight;lineHeight = childHeight;} else {lineWidth += childWidth;lineHeight = Math.max(lineHeight, childHeight);}if (i == cCount - 1) {width = Math.max(lineWidth, width);height += lineHeight;}if (lastItem == 0 && height == (3 * childHeight)) {lastItem = i - 1;if (lastItem > 0 && null != lastListerInterface) {lastListerInterface.getLastItem(lastItem);}}// Log.e("lastItem", lastItem + "");}height = (height <= (lines * childHeight1)) ? height: (lines * childHeight1);ihegth = height;AddMessageActivity.iheight = childHeight1;setMeasuredDimension(//modeWidth == MeasureSpec.EXACTLY ? sizeWidth : width+ getPaddingLeft() + getPaddingRight(),modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height+ getPaddingTop() + getPaddingBottom()//);}public int getHeigth() {return ihegth;}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {mAllViews.clear();mLineHeight.clear();int width = getWidth();int lineWidth = 0;int lineHeight = 0;List<View> lineViews = new ArrayList<View>();int cCount = getChildCount();for (int i = 0; i < cCount; i++) {View child = getChildAt(i);if (child.getVisibility() == View.GONE)continue;MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();int childWidth = child.getMeasuredWidth();int childHeight = child.getMeasuredHeight();if (childWidth + lineWidth + lp.leftMargin + lp.rightMargin > width- getPaddingLeft() - getPaddingRight()) {if (mAllViews.size() < lines) {mLineHeight.add(lineHeight);mAllViews.add(lineViews);lineWidth = 0;lineHeight = childHeight + lp.topMargin + lp.bottomMargin;lineViews = new ArrayList<View>();}}lineWidth += childWidth + lp.leftMargin + lp.rightMargin;lineHeight = Math.max(lineHeight, childHeight + lp.topMargin+ lp.bottomMargin);lineViews.add(child);}mLineHeight.add(lineHeight);mAllViews.add(lineViews);int left = getPaddingLeft();int top = getPaddingTop();int lineNum = mAllViews.size();AddMessageActivity.ilines = lineNum;if (lines > 0) {lineNum = lineNum > lines ? lines : lineNum;}for (int i = 0; i < lineNum; i++) {lineViews = mAllViews.get(i);lineHeight = mLineHeight.get(i);for (int j = 0; j < lineViews.size(); j++) {View child = lineViews.get(j);if (child.getVisibility() == View.GONE) {continue;}MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();int lc = left + lp.leftMargin;int tc = top + lp.topMargin;int rc = lc + child.getMeasuredWidth();int bc = tc + child.getMeasuredHeight();child.layout(lc, tc, rc, bc);left += child.getMeasuredWidth() + lp.leftMargin+ lp.rightMargin;}left = getPaddingLeft();top += lineHeight;}if ((boolean) GlobalMemoryCache.getInstance().get("addMessage")) {AddMessageActivity.tfl_add_message_labellay.setVisibility(View.GONE);AddMessageActivity.scr_add_message_labellay.setVisibility(View.GONE);}}@Overridepublic LayoutParams generateLayoutParams(AttributeSet attrs) {return new MarginLayoutParams(getContext(), attrs);}@Overrideprotected LayoutParams generateDefaultLayoutParams() {return new MarginLayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);}@Overrideprotected LayoutParams generateLayoutParams(LayoutParams p) {return new MarginLayoutParams(p);}public interface LastListerInterface {public void getLastItem(int lastItem);}public void setLastListener(LastListerInterface lastListerInterface) {this.lastListerInterface = lastListerInterface;}}

TagAdapter类

import java.util.ArrayList;import java.util.Arrays;import java.util.HashSet;import java.util.List;import android.view.View;/** * tag 布局适配器 * @author admin * * @param <T> */public abstract class TagAdapter<T>{    private List<T> mTagDatas;    private OnDataChangedListener mOnDataChangedListener;    private HashSet<Integer> mCheckedPosList = new HashSet<Integer>();    public TagAdapter(List<T> datas)    {        mTagDatas = datas;    }    public TagAdapter(T[] datas)    {        mTagDatas = new ArrayList<T>(Arrays.asList(datas));    }static interface OnDataChangedListener    {        void onChanged();    }    void setOnDataChangedListener(OnDataChangedListener listener)    {        mOnDataChangedListener = listener;    }    public void setSelectedList(int... pos)    {        for (int i = 0; i < pos.length; i++)            mCheckedPosList.add(pos[i]);        notifyDataChanged();    }    HashSet<Integer> getPreCheckedList()    {        return mCheckedPosList;    }    public int getCount()    {        return mTagDatas == null ? 0 : mTagDatas.size();    }    public void notifyDataChanged()    {        mOnDataChangedListener.onChanged();    }    public T getItem(int position)    {        return mTagDatas.get(position);    }    public abstract View getView(FlowLayout parent, int position, T t);}
TagView类

import android.content.Context;import android.view.View;import android.widget.Checkable;import android.widget.FrameLayout;/** * 单个Tag 的自定义布局 *  * @author admin * */public class TagView extends FrameLayout implements Checkable{    private boolean isChecked;    private static final int[] CHECK_STATE = new int[]{android.R.attr.state_checked};    public TagView(Context context)    {        super(context);    }    public View getTagView()    {        return getChildAt(0);    }    @Override    public int[] onCreateDrawableState(int extraSpace)    {        int[] states = super.onCreateDrawableState(extraSpace + 1);        if (isChecked())        {            mergeDrawableStates(states, CHECK_STATE);        }        return states;    }    /**     * Change the checked state of the view     *     * @param checked The new checked state     */    @Override    public void setChecked(boolean checked)    {        if (this.isChecked != checked)        {            this.isChecked = checked;            refreshDrawableState();        }    }    /**     * @return The current checked state of the view     */    @Override    public boolean isChecked()    {        return isChecked;    }    /**     * Change the checked state of the view to the inverse of its current state     */    @Override    public void toggle()    {        setChecked(!isChecked);    }}


上面是用到TagFlowLayout这个自定义控件需要的类。

下面给出短信编辑的布局xml文件

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tag="http://schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="#f5f5f5"    android:focusable="true"    android:focusableInTouchMode="true"    android:orientation="vertical" >    <com.zhaonongzi.wnshhseller.view.TopBar        android:id="@+id/message_mass_top"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:layout_gravity="center|top" />    <LinearLayout        android:id="@+id/linear_edit_message_add_receiver"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:layout_below="@+id/message_mass_top"        android:orientation="horizontal" >        <TextView            android:id="@+id/txt_add_message_customer_declare"            android:layout_width="wrap_content"            android:layout_height="45dp"            android:gravity="center"            android:paddingLeft="15dp"            android:text="收信人"            android:textColor="@color/black"            android:visibility="gone" />        <FrameLayout            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="center"            android:layout_weight="1" >            <TextView                android:id="@+id/txt_add_message_add_customer_btn"                android:layout_width="fill_parent"                android:layout_height="fill_parent"                android:gravity="left|center"                android:paddingLeft="15dp"                android:singleLine="true"                android:text="点击添加收信客户"                android:textColor="@color/gray" />            <ScrollView                android:id="@+id/scr_add_message_labellay"                android:layout_width="fill_parent"                android:layout_height="90dp"                android:visibility="gone" >                <com.zhaonongzi.wnshhseller.view.flowlayout.TagFlowLayout                    android:id="@+id/tfl_add_message_labellay"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_below="@+id/ac_include"                    android:layout_marginTop="4dp"                    android:layout_weight="1"                    android:paddingLeft="10dp"                    android:paddingRight="10dp"                    android:visibility="gone"                    tag:max_select="-1" />            </ScrollView>        </FrameLayout>        <LinearLayout            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:orientation="vertical"            android:paddingLeft="10dp"            android:paddingRight="15dp"             android:layout_gravity="center"            android:paddingTop="5dp"            android:paddingBottom="5dp">            <ImageView                android:id="@+id/img_add_message_add_customer"                android:layout_width="30dp"                android:layout_height="30dp"                android:layout_gravity="center"                android:src="@drawable/username" />            <TextView                android:id="@+id/txt_add_message_customer_counts"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_gravity="center"                android:textColor="@color/black"                android:text="0" />        </LinearLayout>    </LinearLayout>    <View        android:id="@+id/line_1"        android:layout_width="fill_parent"        android:layout_height="1dp"        android:layout_below="@+id/linear_edit_message_add_receiver"        android:layout_marginBottom="2dp"        android:layout_marginTop="2dp"        android:background="#A0A0A0" />    <EditText        android:id="@+id/edittext_add_message_add_content"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:layout_below="@+id/line_1"        android:background="@drawable/select_white_bg"        android:minHeight="80dp"        android:padding="15dp"        android:maxLength="650"        android:scrollbars="vertical"        android:maxHeight="200dp"        android:textColor="@color/black" />    <TextView        android:id="@+id/txt_add_message_add_content_num"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_below="@+id/edittext_add_message_add_content"        android:layout_toLeftOf="@+id/txt_add_message_add_content_word"        android:paddingTop="10dp"        android:text="0"        android:textColor="@color/orange_title" />    <TextView        android:id="@+id/txt_add_message_add_content_word"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentRight="true"        android:layout_below="@+id/edittext_add_message_add_content"        android:paddingRight="15dp"        android:paddingTop="10dp"        android:text=""        android:textColor="@color/gray" /></RelativeLayout>
实例化一个收件人adapter

adapter = new TagAdapter<String>(meBean.getReceiver()) {final LayoutInflater mInflater = LayoutInflater.from(AddMessageActivity.this);@SuppressLint("NewApi")@Overridepublic View getView(FlowLayout parent, final int position,final String s) {final TextView tv = (TextView) mInflater.inflate(R.layout.item_label_tv_medium,tfl_add_message_labellay, false);SpannableStringBuilder sp1 = new SpannableStringBuilder(s);// 姓名SpannableStringBuilder sp2 = new SpannableStringBuilder("x");// 删除sp1.setSpan(new ForegroundColorSpan(Color.rgb(102, 102, 102)), 0, s.length(),Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);sp2.setSpan(new ForegroundColorSpan(Color.rgb(255, 0, 0)),0, "X".length(),Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);SpannableStringBuilder sp = new SpannableStringBuilder();//sp.append(sp1).append(sp2);if (position == 0) {tv.setText(s);tv.setTextColor(android.graphics.Color.parseColor("#666666"));} else {tv.setText(sp);tv.setTextSize(16);tv.setBackgroundResource(R.drawable.selector_contacts_gray_btn);}tv.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 跳页面带值if (position != 0) {meBean.getReceiver().remove(position);handler.sendEmptyMessage(1);}}});return tv;}};

计算短信条数方法:

/** * 计算短信内容条算 *  * @param wordNum * @return */public int getSMSCounts(int wordNum) {int counts;if (wordNum <= 63)counts = 1;else if (wordNum <= 127)counts = 2;else {counts = (wordNum - 127) % 67 == 0 ? ((wordNum - 127) / 67 + 2): ((wordNum + 7) / 67 + 1);}return counts;}

监听编辑文本框来提示短信条数和字数:

edittext_edit_message_add_content.addTextChangedListener(new TextWatcher() {@Overridepublic void onTextChanged(CharSequence s, int start,int before, int count) {// TODO Auto-generated method stub}@Overridepublic void beforeTextChanged(CharSequence s, int start,int count, int after) {}@Overridepublic void afterTextChanged(Editable s) {if (getSMSCounts(edittext_edit_message_add_content.getText().toString().trim().length()) == 1) {int c = 63 - edittext_edit_message_add_content.getText().toString().trim().length();txt_add_message_add_content_num.setText(c + "");txt_add_message_add_content_word.setText("");} else if (getSMSCounts(edittext_edit_message_add_content.getText().toString().trim().length()) == 2) {int c = 127 - edittext_edit_message_add_content.getText().toString().trim().length();txt_add_message_add_content_num.setText(c + "");txt_add_message_add_content_word.setText("(2)");} else if (getSMSCounts(edittext_edit_message_add_content.getText().toString().trim().length()) > 2) {int c = getSMSCounts(edittext_edit_message_add_content.getText().toString().trim().length())* 67- 7- edittext_edit_message_add_content.getText().toString().trim().length();txt_add_message_add_content_num.setText(c + "");txt_add_message_add_content_word.setText("("+ getSMSCounts(edittext_edit_message_add_content.getText().toString().trim().length()) + ")");}}});


接收删除后的handler处理:

private Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {if (msg.what == 1) {tfl_add_message_labellay.onChanged();txt_add_message_customer_counts.setText((meBean.getReceiver().size() - 1) + "");}};};

上面已经把关键的代码都贴出来了,其实最重要的 地方是按流布局去显示收件人,原生的是没有限制显示行数,也没有处理多行后的滑动轮,头疼的地方是去计算显示高度并动态设置scrollview的高地。坑都已经踩过了,但是这个代码的效率不是很高,有待继续完善,或者有什么好的建议也可以给我提。




1 0
原创粉丝点击