JavaBean类 --- DialogCityItem.java

package cn.newcom.domain;/*** JavaBean*/
public class DialogCityItem {private String name;//省市县 名称private String pcode;//对应private String desc;//描述public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}public String getName() {return name;}public String getPcode() {return pcode;}public void setName(String name) {this.name = name;}public void setPcode(String pcode) {this.pcode = pcode;}@Overridepublic String toString() {return "MyListItem [name=" + name + ", pcode=" + pcode + "]";}
}

View Code

日志记录类 --- Loger.java

package cn.newcom.loger;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import android.os.Environment;
import android.util.Log;
/*** 日志记录*/
public class Loger{private LogerImp instance;//日志名称private String logerName;//调试时可以设置为true;发布时需要设置为false;protected static boolean isOpen = true;/*** 开始输入日志信息<br\>* (只作为程序日志开关,在个人设置中开启,其他应用中不得调用)*/public static void openPrint(){if (isOpen){LogerImp.instance.startRun();}}/*** 关闭日志打印 <br\>* (只作为程序日志开关,在个人设置中开启,其他应用中不得调用)*/public static void closePrint(){if (isOpen){LogerImp.instance.stopRun();}}private static Loger loger = new Loger("[Loger]");/*** 输出日志信息* @param msg String 日志*/public synchronized static void print(String msg){if (isOpen){loger.output(msg);}}/*** 输出日志信息及异常发生的详细信息* @param msg String 日志* @param e Exception*/public synchronized static void print(String msg, Exception e){if (isOpen){loger.output(msg, e);}}/*** 构造函数* @param name String*/public Loger(String name){logerName = name;instance = LogerImp.getInstance();}/*** 输出日志信息* @param msg String 日志*/public synchronized void output(String msg){if (isOpen){Log.i(logerName, msg);instance.submitMsg(logerName+" "+msg);}}/*** 输出日志信息及异常发生的详细信息* @param msg String 日志* @param e Exception*/public synchronized void output(String msg, Exception e){if (isOpen){Log.i(logerName, msg, e);StringBuffer buf = new StringBuffer(msg);buf.append(logerName).append(" : ").append(msg).append("\n");buf.append(e.getClass()).append(" : ");buf.append(e.getLocalizedMessage());buf.append("\n");StackTraceElement[] stack = e.getStackTrace();for(StackTraceElement trace : stack){buf.append("\t at ").append(trace.toString()).append("\n");}instance.submitMsg(buf.toString());}}/*** 打印当前的内存信息*/public void printCurrentMemory(){if (isOpen){StringBuilder logs = new StringBuilder();long freeMemory = Runtime.getRuntime().freeMemory()/1024;long totalMemory = Runtime.getRuntime().totalMemory()/1024;long maxMemory = Runtime.getRuntime().maxMemory()/1024;logs.append("\t[Memory_free]: ").append(freeMemory).append(" kb");logs.append("\t[Memory_total]: ").append(totalMemory).append(" kb");logs.append("\t[Memory_max]: ").append(maxMemory).append(" kb");Log.i(logerName, logs.toString());instance.submitMsg(logerName+" "+logs.toString());}}
}/*** 日志输出的具体实现类* @author Administrator**/
class LogerImp implements Runnable{private Loger log = new Loger("[LogerImp]");static LogerImp instance = new LogerImp();//日志存放的队列private List<String> printOutList = new ArrayList<String>();//日志文件private FileOutputStream fos = null;//日志输出流private PrintStream print = null;//时间格式private DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");//线程轮询标识private boolean runFlag = false;//当前天,每天生成一个日志文件private int currDay = -1;private GcCheck gcRun = new GcCheck();class GcCheck implements Runnable {boolean flag = true;@Overridepublic void run() {int count = 40;StringBuffer logs = new StringBuffer();while(flag){if (count >= 50){long freeMemory = Runtime.getRuntime().freeMemory()/1024;long totalMemory = Runtime.getRuntime().totalMemory()/1024;long maxMemory = Runtime.getRuntime().maxMemory()/1024;logs.append("\t[Memory_free]:").append(freeMemory).append(" kb");logs.append("\t[Memory_total]:").append(totalMemory).append(" kb");logs.append("\t[Memory_max]:").append(maxMemory).append(" kb");synchronized (printOutList) {printOutList.add(logs.toString());}Log.i("Memory", logs.toString());logs.setLength(0);if (freeMemory < 400){System.gc();count = 40;logs.append("<GC>");}else{count = 0;}}try {count++;Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}}};/*** 得到单例对象* @return LogerImp*/public static LogerImp getInstance(){return instance;}/*** 私有方法,单例*/private LogerImp(){}//    void listenGC(){
//        gcRun.flag = true;
//        new Thread(gcRun).start();
//    }//    void stopLintenGC(){
//        gcRun.flag = false;
//    }//初始化文件输出流private void initPrint(){Calendar date = Calendar.getInstance();currDay = date.get(Calendar.DAY_OF_YEAR);DateFormat dfm = new SimpleDateFormat("yyyy-MM-dd");String fileName = new String(dfm.format(date.getTime())+".txt");String path = null;try {if (null != print){close();}path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/weiboShare/";File dir = new File(path);if (!dir.exists()){dir.mkdir();}fos = new FileOutputStream(path+fileName, true);print = new PrintStream(fos, true);} catch (Exception e) {log.output("[LogerImp] 未能打开文件:"+path+" 文件名:"+fileName+" 异常描述:"+e.getLocalizedMessage());}}/*** 线程开启*/public void startRun(){if (!runFlag){runFlag = true;new Thread(this).start();}else{log.output("[LogerImp] < warn > thread already run !");}}/*** 线程停止*/public void stopRun(){if (runFlag){gcRun.flag = false;runFlag = false;Log.i("Thread", "队列大小:"+printOutList.size());printToFile("[LogerImp] < info > thread stop !");close();}}private void close() {print.flush();print.close();print = null;try{fos.close();fos = null;}catch(IOException e){e.printStackTrace();}}/*** 向队列中增加日志数据* @param msg String 日志数据*/protected synchronized void submitMsg(String msg) {synchronized (printOutList) {printOutList.add(msg);}}public void run(){try{initPrint();printToFile("[LogerImp] < info > start new thread ... ");while(runFlag){runMethod();}runFlag = false;}catch(Exception e){printToFile("[LogerImp] < warn > thread error : "+e.getLocalizedMessage());if (runFlag){printToFile("[LogerImp] 线程强制中断 "+e.getLocalizedMessage());new Thread(this).start();}}}//线程需要重复执行的操作private void runMethod() throws Exception {String line = null;synchronized (printOutList) {if (!printOutList.isEmpty()){line = printOutList.remove(0);}}if (null != line){printToFile(line);}else{Thread.sleep(10);}}//把数据持久到文件private void printToFile(String line){Calendar date = Calendar.getInstance();int day = date.get(Calendar.DAY_OF_YEAR);if (day != currDay){initPrint();}if (null == print){return;}print.println(">>> "+format.format(date.getTime())+" -- "+line);print.flush();}
}

View Code

查询省份数据库的工具类 --- DialogCityDB.java

package cn.newcom.db;import java.util.ArrayList;
import java.util.List;
import cn.newcom.domain.DialogCityItem;
import cn.newcom.loger.Loger;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;/*** 查询省份数据库的工具类*/
public class DialogCityDB {private static DialogCityDBManager dbm;private static SQLiteDatabase db;private static Loger log = new Loger(DialogCityDB.class.getSimpleName());/*** 查询所有的省份信息* @param context Context* @return List<MyListItem>*/public static List<DialogCityItem> getAllProInfo(Context context) {dbm = new DialogCityDBManager(context);dbm.openDatabase();db = dbm.getDatabase();List<DialogCityItem> list = new ArrayList<DialogCityItem>();try {String sql = "SELECT DISTINCT (province) FROM CityRegion";Cursor cursor = db.rawQuery(sql, null);log.output("cursor:" + cursor.getCount());int i = 0;while (cursor.moveToNext()) {i++;String province = cursor.getString(cursor.getColumnIndex("province"));DialogCityItem myListItem = new DialogCityItem();myListItem.setName(province);list.add(myListItem);}log.output("i:" + i);} catch (Exception e) {log.output("提取所有省份信息异常", e);}dbm.closeDatabase();return list;}/*** 返回所有省份的字符串信息* @param context* @return*/public static List<String> getAllProInfoStr(Context context) {dbm = new DialogCityDBManager(context);dbm.openDatabase();db = dbm.getDatabase();List<String> list = new ArrayList<String>();try {String sql = "SELECT DISTINCT (province) FROM CityRegion";Cursor cursor = db.rawQuery(sql, null);log.output("cursor:" + cursor.getCount());int i = 0;while (cursor.moveToNext()) {i++;String province = cursor.getString(cursor.getColumnIndex("province"));list.add(province);}log.output("i:" + i);} catch (Exception e) {log.output("提取所有省份信息异常", e);}dbm.closeDatabase();return list;}/*** 获取指定省份的城市信息* @param context Context* @param pro String* @return List<MyListItem>*/public static List<DialogCityItem> getCityInfo(Context context, String pro) {dbm = new DialogCityDBManager(context);dbm.openDatabase();db = dbm.getDatabase();List<DialogCityItem> list = new ArrayList<DialogCityItem>();try {String sql = "select DISTINCT(city) from CityRegion where province = ?";Cursor cursor = db.rawQuery(sql, new String[] { pro });while (cursor.moveToNext()) {String city = cursor.getString(cursor.getColumnIndex("city"));DialogCityItem myListItem = new DialogCityItem();myListItem.setName(city);list.add(myListItem);}} catch (Exception e) {log.output("提取指定省份信息异常,省份:"+pro, e);}dbm.closeDatabase();db.close();return list;}public static List<String> getCityInfoStr(Context context, String pro) {dbm = new DialogCityDBManager(context);dbm.openDatabase();db = dbm.getDatabase();List<String> list = new ArrayList<String>();try {String sql = "select DISTINCT(city) from CityRegion where province = ?";Cursor cursor = db.rawQuery(sql, new String[] { pro });while (cursor.moveToNext()) {String city = cursor.getString(cursor.getColumnIndex("city"));list.add(city);}} catch (Exception e) {log.output("提取指定省份信息异常,省份:"+pro, e);}dbm.closeDatabase();db.close();return list;}/*** 获取指定城市下的县级信息* @param context Context* @param pro String 省份* @param city String 城市* @return List<MyListItem>*/public static List<DialogCityItem> getCountyInfo(Context context, String pro, String city) {dbm = new DialogCityDBManager(context);dbm.openDatabase();db = dbm.getDatabase();List<DialogCityItem> list = new ArrayList<DialogCityItem>();try {String sql = "select code,area,desc from CityRegion where province = ? and city = ? ";Cursor cursor = db.rawQuery(sql, new String[] { pro, city });while (cursor.moveToNext()) {String area = cursor.getString(cursor.getColumnIndex("area"));String code = cursor.getString(cursor.getColumnIndex("code"));String desc = cursor.getString(cursor.getColumnIndex("desc"));DialogCityItem myListItem = new DialogCityItem();myListItem.setName(area);myListItem.setPcode(code);myListItem.setDesc(desc);list.add(myListItem);}cursor.close();} catch (Exception e) {log.output("提取指定的县级信息异常,省份:"+pro+"  城市:"+city, e);}dbm.closeDatabase();db.close();return list;}
}

View Code

操作已有数据库的类(复制到SD卡中) --- DialogCityDBManager.java

package cn.newcom.db;/*** 操作已有数据库的类——复制到SD卡中*/
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import cn.newcom.loger.Loger;
import cn.newcom.pickdemo.R;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.os.Environment;
import android.util.Log;public class DialogCityDBManager {private final int BUFFER_SIZE = 1024;public static final String DB_NAME = "xxt.db";//其他应用用到时,需要修改包名public static final String PACKAGE_NAME = "cn.newcom.pickdemo";// 把raw目录下的数据库文件复制到data下public static final String DB_PATH = "/data"+ Environment.getDataDirectory().getAbsolutePath() + "/"+ PACKAGE_NAME + "/databases";private SQLiteDatabase database;private Context context;private File file = null;private Loger log = new Loger("[" + this.getClass().getSimpleName() + "]");public DialogCityDBManager(Context context) {this.context = context;}public void openDatabase() {this.database = this.openDatabase(DB_PATH + "/" + DB_NAME);}public SQLiteDatabase getDatabase() {return this.database;}private SQLiteDatabase openDatabase(String dbfile) {try {log.output("路径:" + DB_PATH);Log.e("cc", "open and return");File dir = new File(DB_PATH);if (!dir.exists())dir.mkdir();file = new File(dbfile);if (!file.exists()) {Log.e("cc", "file");InputStream is = context.getResources().openRawResource(R.raw.xxt);if (is == null) {Log.e("cc", "is null");}FileOutputStream fos = new FileOutputStream(dbfile);if (fos != null) {Log.e("cc", "fos null");}byte[] buffer = new byte[BUFFER_SIZE];int count = 0;while ((count = is.read(buffer)) > 0) {fos.write(buffer, 0, count);fos.flush();}fos.close();is.close();}database = SQLiteDatabase.openOrCreateDatabase(dbfile, null);return database;} catch (FileNotFoundException e) {Log.e("cc", "File not found");e.printStackTrace();} catch (IOException e) {Log.e("cc", "IO exception");e.printStackTrace();} catch (Exception e) {Log.e("cc", "exception " + e.toString());}return null;}public void closeDatabase() {Log.e("cc", "closeDatabase()");if (this.database != null)this.database.close();}
}

View Code

适配list集合的 适配器 --- ArrayWheelAdapter1.java

package cn.newcom.pickdemo;/*** 适配list集合的 适配器*/
import java.util.List;
import cn.newcom.wheelview.WheelAdapter;public class ArrayWheelAdapter1 implements WheelAdapter {public static final int DEFAULT_LENGTH = -1;private List<String> list;private int length;public ArrayWheelAdapter1(List<String> list, int length) {this.list = list;this.length = length;}public ArrayWheelAdapter1(List<String> list) {this(list, DEFAULT_LENGTH);}@Overridepublic int getItemsCount() {return list.size();}@Overridepublic int getMaximumLength() {return length;}@Overridepublic String getItem(int index) {return list.get(index);}
}

View Code

省市联动的主页面,使用自定义控件 --- PickViewDemoActivity.java

package cn.newcom.pickdemo;/*** 省市联动的主页面,使用自定义控件*/
import java.util.ArrayList;
import java.util.List;
import cn.newcom.db.DialogCityDB;
import cn.newcom.domain.DialogCityItem;
import cn.newcom.pickdemo.R;
import cn.newcom.wheelview.OnWheelChangedListener;
import cn.newcom.wheelview.WheelView;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;public class PickViewDemoActivity extends Activity {private WheelView province;//省份控件private WheelView city;private WheelView town;private String pro;private String ct;private String tw;private List<String> pros;//省份名称集合private List<String> cities;private List<String> towns;private List<DialogCityItem> countyInfo;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.cities_layout);province = (WheelView) findViewById(R.id.province);city = (WheelView) findViewById(R.id.city);town = (WheelView) findViewById(R.id.town);initPickPro();}//初始化省份列表private void initPickPro() {pros = DialogCityDB.getAllProInfoStr(this);province.setAdapter(new ArrayWheelAdapter1(pros));
//        province.setCurrentItem(pros.size()/2);province.addChangingListener(new ProListener());}//省份列表滑动监听private class ProListener implements OnWheelChangedListener{@Overridepublic void onChanged(WheelView wheel, int oldValue, int newValue) {pro = pros.get(newValue);initPickCity(pro);}}//初始化城市列表public void initPickCity(String pro) {cities = DialogCityDB.getCityInfoStr(this, pro);city.setAdapter(new ArrayWheelAdapter1(cities));city.setCurrentItem(cities.size()/2);city.addChangingListener(new CityListener());}private class CityListener implements OnWheelChangedListener{@Overridepublic void onChanged(WheelView wheel, int oldValue, int newValue) {ct = cities.get(newValue);initPickTown(pro , ct);}}public void initPickTown(String pro, String city) {countyInfo = DialogCityDB.getCountyInfo(this, pro, city);towns = new ArrayList<String>();for (int i = 0; i < countyInfo.size(); i++) {towns.add(countyInfo.get(i).getName());}town.setAdapter(new ArrayWheelAdapter1(towns));town.setCurrentItem(towns.size()/2);town.addChangingListener(new TownListener());}private String desc;private String pcode;private class TownListener implements OnWheelChangedListener{@Overridepublic void onChanged(WheelView wheel, int oldValue, int newValue) {DialogCityItem dc = countyInfo.get(newValue);desc = dc.getDesc();pcode = dc.getPcode();}}public void done(View v){String content = desc + "," + pcode ;Toast.makeText(this, content, 0).show();}
}

View Code

自定义控件 --- WheelView.java

/**  Android Wheel Control.*  https://code.google.com/p/android-wheel/*  *  Copyright 2010 Yuri Kanivets**  Licensed under the Apache License, Version 2.0 (the "License");*  you may not use this file except in compliance with the License.*  You may obtain a copy of the License at**  http://www.apache.org/licenses/LICENSE-2.0**  Unless required by applicable law or agreed to in writing, software*  distributed under the License is distributed on an "AS IS" BASIS,*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*  See the License for the specific language governing permissions and*  limitations under the License.*/package cn.newcom.wheelview;/*** 自定义控件*/
import java.util.LinkedList;
import java.util.List;import cn.newcom.pickdemo.R;
import cn.newcom.pickdemo.R.drawable;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.GradientDrawable.Orientation;
import android.os.Handler;
import android.os.Message;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Interpolator;
import android.widget.Scroller;/*** Numeric wheel view.*/
public class WheelView extends View {/** Scrolling duration */private static final int SCROLLING_DURATION = 400;/** Minimum delta for scrolling */private static final int MIN_DELTA_FOR_SCROLLING = 1;/** Current value & label text color */private static final int VALUE_TEXT_COLOR = 0xF0000000;/** Items text color */private static final int ITEMS_TEXT_COLOR = 0xFF000000;/** Top and bottom shadows colors */private static final int[] SHADOWS_COLORS = new int[] { 0xFF111111,0x00AAAAAA, 0x00AAAAAA };/** Additional items height (is added to standard text item height) */private static final int ADDITIONAL_ITEM_HEIGHT = 15;/** Text size */private static final int TEXT_SIZE = 24;/** Top and bottom items offset (to hide that) */private static final int ITEM_OFFSET = TEXT_SIZE / 5;/** Additional width for items layout */private static final int ADDITIONAL_ITEMS_SPACE = 10;/** Label offset */private static final int LABEL_OFFSET = 8;/** Left and right padding value */private static final int PADDING = 10;/** Default count of visible items */private static final int DEF_VISIBLE_ITEMS = 5;// Wheel Valuesprivate WheelAdapter adapter = null;private int currentItem = 0;// Widthsprivate int itemsWidth = 0;private int labelWidth = 0;// Count of visible itemsprivate int visibleItems = DEF_VISIBLE_ITEMS;// Item heightprivate int itemHeight = 0;// Text paintsprivate TextPaint itemsPaint;private TextPaint valuePaint;// Layoutsprivate StaticLayout itemsLayout;private StaticLayout labelLayout;private StaticLayout valueLayout;// Label & backgroundprivate String label;private Drawable centerDrawable;// Shadows drawablesprivate GradientDrawable topShadow;private GradientDrawable bottomShadow;// Scrollingprivate boolean isScrollingPerformed; private int scrollingOffset;// Scrolling animationprivate GestureDetector gestureDetector;private Scroller scroller;private int lastScrollY;// Cyclicboolean isCyclic = false;// Listenersprivate List<OnWheelChangedListener> changingListeners = new LinkedList<OnWheelChangedListener>();private List<OnWheelScrollListener> scrollingListeners = new LinkedList<OnWheelScrollListener>();/*** Constructor*/public WheelView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);initData(context);}/*** Constructor*/public WheelView(Context context, AttributeSet attrs) {super(context, attrs);initData(context);}/*** Constructor*/public WheelView(Context context) {super(context);initData(context);}/*** Initializes class data* @param context the context*/private void initData(Context context) {gestureDetector = new GestureDetector(context, gestureListener);gestureDetector.setIsLongpressEnabled(false);scroller = new Scroller(context);}/*** Gets wheel adapter* @return the adapter*/public WheelAdapter getAdapter() {return adapter;}/*** Sets wheel adapter* @param adapter the new wheel adapter*/public void setAdapter(WheelAdapter adapter) {this.adapter = adapter;invalidateLayouts();invalidate();}/*** Set the the specified scrolling interpolator* @param interpolator the interpolator*/public void setInterpolator(Interpolator interpolator) {scroller.forceFinished(true);scroller = new Scroller(getContext(), interpolator);}/*** Gets count of visible items* * @return the count of visible items*/public int getVisibleItems() {return visibleItems;}/*** Sets count of visible items* * @param count*            the new count*/public void setVisibleItems(int count) {visibleItems = count;invalidate();}/*** Gets label* * @return the label*/public String getLabel() {return label;}/*** Sets label* * @param newLabel*            the label to set*/public void setLabel(String newLabel) {if (label == null || !label.equals(newLabel)) {label = newLabel;labelLayout = null;invalidate();}}/*** Adds wheel changing listener* @param listener the listener */public void addChangingListener(OnWheelChangedListener listener) {changingListeners.add(listener);}/*** Removes wheel changing listener* @param listener the listener*/public void removeChangingListener(OnWheelChangedListener listener) {changingListeners.remove(listener);}/*** Notifies changing listeners* @param oldValue the old wheel value* @param newValue the new wheel value*/protected void notifyChangingListeners(int oldValue, int newValue) {for (OnWheelChangedListener listener : changingListeners) {listener.onChanged(this, oldValue, newValue);}}/*** Adds wheel scrolling listener* @param listener the listener */public void addScrollingListener(OnWheelScrollListener listener) {scrollingListeners.add(listener);}/*** Removes wheel scrolling listener* @param listener the listener*/public void removeScrollingListener(OnWheelScrollListener listener) {scrollingListeners.remove(listener);}/*** Notifies listeners about starting scrolling*/protected void notifyScrollingListenersAboutStart() {for (OnWheelScrollListener listener : scrollingListeners) {listener.onScrollingStarted(this);}}/*** Notifies listeners about ending scrolling*/protected void notifyScrollingListenersAboutEnd() {for (OnWheelScrollListener listener : scrollingListeners) {listener.onScrollingFinished(this);}}/*** Gets current value* * @return the current value*/public int getCurrentItem() {return currentItem;}/*** Sets the current item. Does nothing when index is wrong.* * @param index the item index* @param animated the animation flag*/public void setCurrentItem(int index, boolean animated) {if (adapter == null || adapter.getItemsCount() == 0) {return; // throw?
        }if (index < 0 || index >= adapter.getItemsCount()) {if (isCyclic) {while (index < 0) {index += adapter.getItemsCount();}index %= adapter.getItemsCount();} else{return; // throw?
            }}if (index != currentItem) {if (animated) {scroll(index - currentItem, SCROLLING_DURATION);} else {invalidateLayouts();int old = currentItem;currentItem = index;notifyChangingListeners(old, currentItem);invalidate();}}}/*** Sets the current item w/o animation. Does nothing when index is wrong.* * @param index the item index*/public void setCurrentItem(int index) {setCurrentItem(index, false);}    /*** Tests if wheel is cyclic. That means before the 1st item there is shown the last one* @return true if wheel is cyclic*/public boolean isCyclic() {return isCyclic;}/*** Set wheel cyclic flag* @param isCyclic the flag to set*/public void setCyclic(boolean isCyclic) {this.isCyclic = isCyclic;invalidate();invalidateLayouts();}/*** Invalidates layouts*/private void invalidateLayouts() {itemsLayout = null;valueLayout = null;scrollingOffset = 0;}/*** Initializes resources*/private void initResourcesIfNecessary() {if (itemsPaint == null) {itemsPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG| Paint.FAKE_BOLD_TEXT_FLAG);//itemsPaint.density = getResources().getDisplayMetrics().density;
            itemsPaint.setTextSize(TEXT_SIZE);}if (valuePaint == null) {valuePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG| Paint.FAKE_BOLD_TEXT_FLAG | Paint.DITHER_FLAG);//valuePaint.density = getResources().getDisplayMetrics().density;
            valuePaint.setTextSize(TEXT_SIZE);valuePaint.setShadowLayer(0.1f, 0, 0.1f, 0xFFC0C0C0);}if (centerDrawable == null) {centerDrawable = getContext().getResources().getDrawable(R.drawable.wheel_val);}if (topShadow == null) {topShadow = new GradientDrawable(Orientation.TOP_BOTTOM, SHADOWS_COLORS);}if (bottomShadow == null) {bottomShadow = new GradientDrawable(Orientation.BOTTOM_TOP, SHADOWS_COLORS);}setBackgroundResource(R.drawable.wheel_bg);}/*** Calculates desired height for layout* * @param layout*            the source layout* @return the desired layout height*/private int getDesiredHeight(Layout layout) {if (layout == null) {return 0;}int desired = getItemHeight() * visibleItems - ITEM_OFFSET * 2- ADDITIONAL_ITEM_HEIGHT;// Check against our minimum heightdesired = Math.max(desired, getSuggestedMinimumHeight());return desired;}/*** Returns text item by index* @param index the item index* @return the item or null*/private String getTextItem(int index) {if (adapter == null || adapter.getItemsCount() == 0) {return null;}int count = adapter.getItemsCount();if ((index < 0 || index >= count) && !isCyclic) {return null;} else {while (index < 0) {index = count + index;}}index %= count;return adapter.getItem(index);}/*** Builds text depending on current value* * @param useCurrentValue* @return the text*/private String buildText(boolean useCurrentValue) {StringBuilder itemsText = new StringBuilder();int addItems = visibleItems / 2 + 1;for (int i = currentItem - addItems; i <= currentItem + addItems; i++) {if (useCurrentValue || i != currentItem) {String text = getTextItem(i);if (text != null) {itemsText.append(text);}}if (i < currentItem + addItems) {itemsText.append("\n");}}return itemsText.toString();}/*** Returns the max item length that can be present* @return the max length*/private int getMaxTextLength() {WheelAdapter adapter = getAdapter();if (adapter == null) {return 0;}int adapterLength = adapter.getMaximumLength();if (adapterLength > 0) {return adapterLength;}String maxText = null;int addItems = visibleItems / 2;for (int i = Math.max(currentItem - addItems, 0);i < Math.min(currentItem + visibleItems, adapter.getItemsCount()); i++) {String text = adapter.getItem(i);if (text != null && (maxText == null || maxText.length() < text.length())) {maxText = text;}}return maxText != null ? maxText.length() : 0;}/*** Returns height of wheel item* @return the item height*/private int getItemHeight() {if (itemHeight != 0) {return itemHeight;} else if (itemsLayout != null && itemsLayout.getLineCount() > 2) {itemHeight = itemsLayout.getLineTop(2) - itemsLayout.getLineTop(1);return itemHeight;}return getHeight() / visibleItems;}/*** Calculates control width and creates text layouts* @param widthSize the input layout width* @param mode the layout mode* @return the calculated control width*/private int calculateLayoutWidth(int widthSize, int mode) {initResourcesIfNecessary();int width = widthSize;int maxLength = getMaxTextLength();if (maxLength > 0) {float textWidth = FloatMath.ceil(Layout.getDesiredWidth("0", itemsPaint));itemsWidth = (int) (maxLength * textWidth);} else {itemsWidth = 0;}itemsWidth += ADDITIONAL_ITEMS_SPACE; // make it some more
labelWidth = 0;if (label != null && label.length() > 0) {labelWidth = (int) FloatMath.ceil(Layout.getDesiredWidth(label, valuePaint));}boolean recalculate = false;if (mode == MeasureSpec.EXACTLY) {width = widthSize;recalculate = true;} else {width = itemsWidth + labelWidth + 2 * PADDING;if (labelWidth > 0) {width += LABEL_OFFSET;}// Check against our minimum widthwidth = Math.max(width, getSuggestedMinimumWidth());if (mode == MeasureSpec.AT_MOST && widthSize < width) {width = widthSize;recalculate = true;}}if (recalculate) {// recalculate widthint pureWidth = width - LABEL_OFFSET - 2 * PADDING;if (pureWidth <= 0) {itemsWidth = labelWidth = 0;}if (labelWidth > 0) {double newWidthItems = (double) itemsWidth * pureWidth/ (itemsWidth + labelWidth);itemsWidth = (int) newWidthItems;labelWidth = pureWidth - itemsWidth;} else {itemsWidth = pureWidth + LABEL_OFFSET; // no label
            }}if (itemsWidth > 0) {createLayouts(itemsWidth, labelWidth);}return width;}/*** Creates layouts* @param widthItems width of items layout* @param widthLabel width of label layout*/private void createLayouts(int widthItems, int widthLabel) {if (itemsLayout == null || itemsLayout.getWidth() > widthItems) {itemsLayout = new StaticLayout(buildText(isScrollingPerformed), itemsPaint, widthItems,widthLabel > 0 ? Layout.Alignment.ALIGN_OPPOSITE : Layout.Alignment.ALIGN_CENTER,1, ADDITIONAL_ITEM_HEIGHT, false);} else {itemsLayout.increaseWidthTo(widthItems);}if (!isScrollingPerformed && (valueLayout == null || valueLayout.getWidth() > widthItems)) {String text = getAdapter() != null ? getAdapter().getItem(currentItem) : null;valueLayout = new StaticLayout(text != null ? text : "",valuePaint, widthItems, widthLabel > 0 ?Layout.Alignment.ALIGN_OPPOSITE : Layout.Alignment.ALIGN_CENTER,1, ADDITIONAL_ITEM_HEIGHT, false);} else if (isScrollingPerformed) {valueLayout = null;} else {valueLayout.increaseWidthTo(widthItems);}if (widthLabel > 0) {if (labelLayout == null || labelLayout.getWidth() > widthLabel) {labelLayout = new StaticLayout(label, valuePaint,widthLabel, Layout.Alignment.ALIGN_NORMAL, 1,ADDITIONAL_ITEM_HEIGHT, false);} else {labelLayout.increaseWidthTo(widthLabel);}}}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);int width = calculateLayoutWidth(widthSize, widthMode);int height;if (heightMode == MeasureSpec.EXACTLY) {height = heightSize;} else {height = getDesiredHeight(itemsLayout);if (heightMode == MeasureSpec.AT_MOST) {height = Math.min(height, heightSize);}}setMeasuredDimension(width, height);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (itemsLayout == null) {if (itemsWidth == 0) {calculateLayoutWidth(getWidth(), MeasureSpec.EXACTLY);} else {createLayouts(itemsWidth, labelWidth);}}if (itemsWidth > 0) {canvas.save();// Skip padding space and hide a part of top and bottom itemscanvas.translate(PADDING, -ITEM_OFFSET);drawItems(canvas);drawValue(canvas);canvas.restore();}drawCenterRect(canvas);drawShadows(canvas);}/*** Draws shadows on top and bottom of control* @param canvas the canvas for drawing*/private void drawShadows(Canvas canvas) {topShadow.setBounds(0, 0, getWidth(), getHeight() / visibleItems);topShadow.draw(canvas);bottomShadow.setBounds(0, getHeight() - getHeight() / visibleItems,getWidth(), getHeight());bottomShadow.draw(canvas);}/*** Draws value and label layout* @param canvas the canvas for drawing*/private void drawValue(Canvas canvas) {valuePaint.setColor(VALUE_TEXT_COLOR);valuePaint.drawableState = getDrawableState();Rect bounds = new Rect();itemsLayout.getLineBounds(visibleItems / 2, bounds);// draw labelif (labelLayout != null) {canvas.save();canvas.translate(itemsLayout.getWidth() + LABEL_OFFSET, bounds.top);labelLayout.draw(canvas);canvas.restore();}// draw current valueif (valueLayout != null) {canvas.save();canvas.translate(0, bounds.top + scrollingOffset);valueLayout.draw(canvas);canvas.restore();}}/*** Draws items* @param canvas the canvas for drawing*/private void drawItems(Canvas canvas) {canvas.save();int top = itemsLayout.getLineTop(1);canvas.translate(0, - top + scrollingOffset);itemsPaint.setColor(ITEMS_TEXT_COLOR);itemsPaint.drawableState = getDrawableState();itemsLayout.draw(canvas);canvas.restore();}/*** Draws rect for current value* @param canvas the canvas for drawing*/private void drawCenterRect(Canvas canvas) {int center = getHeight() / 2;int offset = getItemHeight() / 2;centerDrawable.setBounds(0, center - offset, getWidth(), center + offset);centerDrawable.draw(canvas);}@Overridepublic boolean onTouchEvent(MotionEvent event) {WheelAdapter adapter = getAdapter();if (adapter == null) {return true;}if (!gestureDetector.onTouchEvent(event) && event.getAction() == MotionEvent.ACTION_UP) {justify();}return true;}/*** Scrolls the wheel* @param delta the scrolling value*/private void doScroll(int delta) {scrollingOffset += delta;int count = scrollingOffset / getItemHeight();int pos = currentItem - count;if (isCyclic && adapter.getItemsCount() > 0) {// fix position by rotatingwhile (pos < 0) {pos += adapter.getItemsCount();}pos %= adapter.getItemsCount();} else if (isScrollingPerformed) {// if (pos < 0) {count = currentItem;pos = 0;} else if (pos >= adapter.getItemsCount()) {count = currentItem - adapter.getItemsCount() + 1;pos = adapter.getItemsCount() - 1;}} else {// fix positionpos = Math.max(pos, 0);pos = Math.min(pos, adapter.getItemsCount() - 1);}int offset = scrollingOffset;if (pos != currentItem) {setCurrentItem(pos, false);} else {invalidate();}// update offsetscrollingOffset = offset - count * getItemHeight();if (scrollingOffset > getHeight()) {scrollingOffset = scrollingOffset % getHeight() + getHeight();}}// gesture listenerprivate SimpleOnGestureListener gestureListener = new SimpleOnGestureListener() {public boolean onDown(MotionEvent e) {if (isScrollingPerformed) {scroller.forceFinished(true);clearMessages();return true;}return false;}public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {startScrolling();doScroll((int)-distanceY);return true;}public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {lastScrollY = currentItem * getItemHeight() + scrollingOffset;int maxY = isCyclic ? 0x7FFFFFFF : adapter.getItemsCount() * getItemHeight();int minY = isCyclic ? -maxY : 0;scroller.fling(0, lastScrollY, 0, (int) -velocityY / 2, 0, 0, minY, maxY);setNextMessage(MESSAGE_SCROLL);return true;}};// Messagesprivate final int MESSAGE_SCROLL = 0;private final int MESSAGE_JUSTIFY = 1;/*** Set next message to queue. Clears queue before.* * @param message the message to set*/private void setNextMessage(int message) {clearMessages();animationHandler.sendEmptyMessage(message);}/*** Clears messages from queue*/private void clearMessages() {animationHandler.removeMessages(MESSAGE_SCROLL);animationHandler.removeMessages(MESSAGE_JUSTIFY);}// animation handlerprivate Handler animationHandler = new Handler() {public void handleMessage(Message msg) {scroller.computeScrollOffset();int currY = scroller.getCurrY();int delta = lastScrollY - currY;lastScrollY = currY;if (delta != 0) {doScroll(delta);}// scrolling is not finished when it comes to final Y// so, finish it manually if (Math.abs(currY - scroller.getFinalY()) < MIN_DELTA_FOR_SCROLLING) {currY = scroller.getFinalY();scroller.forceFinished(true);}if (!scroller.isFinished()) {animationHandler.sendEmptyMessage(msg.what);} else if (msg.what == MESSAGE_SCROLL) {justify();} else {finishScrolling();}}};/*** Justifies wheel*/private void justify() {if (adapter == null) {return;}lastScrollY = 0;int offset = scrollingOffset;int itemHeight = getItemHeight();boolean needToIncrease = offset > 0 ? currentItem < adapter.getItemsCount() : currentItem > 0; if ((isCyclic || needToIncrease) && Math.abs((float) offset) > (float) itemHeight / 2) {if (offset < 0)offset += itemHeight + MIN_DELTA_FOR_SCROLLING;elseoffset -= itemHeight + MIN_DELTA_FOR_SCROLLING;}if (Math.abs(offset) > MIN_DELTA_FOR_SCROLLING) {scroller.startScroll(0, 0, 0, offset, SCROLLING_DURATION);setNextMessage(MESSAGE_JUSTIFY);} else {finishScrolling();}}/*** Starts scrolling*/private void startScrolling() {if (!isScrollingPerformed) {isScrollingPerformed = true;notifyScrollingListenersAboutStart();}}/*** Finishes scrolling*/void finishScrolling() {if (isScrollingPerformed) {notifyScrollingListenersAboutEnd();isScrollingPerformed = false;}invalidateLayouts();invalidate();}/*** Scroll the wheel* @param itemsToSkip items to scroll* @param time scrolling duration*/public void scroll(int itemsToScroll, int time) {scroller.forceFinished(true);lastScrollY = scrollingOffset;int offset = itemsToScroll * getItemHeight();scroller.startScroll(0, lastScrollY, 0, offset - lastScrollY, time);setNextMessage(MESSAGE_SCROLL);startScrolling();}}

View Code

OnWheelChangedListener.java

/**  Copyright 2010 Yuri Kanivets**  Licensed under the Apache License, Version 2.0 (the "License");*  you may not use this file except in compliance with the License.*  You may obtain a copy of the License at**  http://www.apache.org/licenses/LICENSE-2.0**  Unless required by applicable law or agreed to in writing, software*  distributed under the License is distributed on an "AS IS" BASIS,*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*  See the License for the specific language governing permissions and*  limitations under the License.*/package cn.newcom.wheelview;/*** Wheel changed listener interface.* <p>The currentItemChanged() method is called whenever current wheel positions is changed:* <li> New Wheel position is set* <li> Wheel view is scrolled*/
public interface OnWheelChangedListener {/*** Callback method to be invoked when current item changed* @param wheel the wheel view whose state has changed* @param oldValue the old value of current item* @param newValue the new value of current item*/void onChanged(WheelView wheel, int oldValue, int newValue);
}

View Code

OnWheelScrollListener.java

/**  Copyright 2010 Yuri Kanivets**  Licensed under the Apache License, Version 2.0 (the "License");*  you may not use this file except in compliance with the License.*  You may obtain a copy of the License at**  http://www.apache.org/licenses/LICENSE-2.0**  Unless required by applicable law or agreed to in writing, software*  distributed under the License is distributed on an "AS IS" BASIS,*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*  See the License for the specific language governing permissions and*  limitations under the License.*/package cn.newcom.wheelview;/*** Wheel scrolled listener interface.*/
public interface OnWheelScrollListener {/*** Callback method to be invoked when scrolling started.* @param wheel the wheel view whose state has changed.*/void onScrollingStarted(WheelView wheel);/*** Callback method to be invoked when scrolling ended.* @param wheel the wheel view whose state has changed.*/void onScrollingFinished(WheelView wheel);
}

View Code

WheelAdapter.java

/**  Copyright 2010 Yuri Kanivets**  Licensed under the Apache License, Version 2.0 (the "License");*  you may not use this file except in compliance with the License.*  You may obtain a copy of the License at**  http://www.apache.org/licenses/LICENSE-2.0**  Unless required by applicable law or agreed to in writing, software*  distributed under the License is distributed on an "AS IS" BASIS,*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*  See the License for the specific language governing permissions and*  limitations under the License.*/package cn.newcom.wheelview;public interface WheelAdapter {/*** Gets items count* @return the count of wheel items*/public int getItemsCount();/*** Gets a wheel item by index.* * @param index the item index* @return the wheel item text or null*/public String getItem(int index);/*** Gets maximum item length. It is used to determine the wheel width. * If -1 is returned there will be used the default wheel width.* * @return the maximum item length or -1*/public int getMaximumLength();
}

View Code

cities_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="wrap_content"android:background="@drawable/layout_bg"android:gravity="center"android:orientation="vertical" ><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal" ><cn.newcom.wheelview.WheelViewandroid:id="@+id/province"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:layout_weight="1" /><cn.newcom.wheelview.WheelViewandroid:id="@+id/city"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="5dp"android:layout_weight="1" /><cn.newcom.wheelview.WheelViewandroid:id="@+id/town"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="5dp"android:layout_weight="1" /></LinearLayout><Button android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="确定"android:onClick="done"/>
</LinearLayout>

View Code

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical" ><TextViewandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:text="@string/hello" /></LinearLayout>

View Code

DEMO 完整下载路径:http://download.csdn.net/detail/androidsj/5587597

自定义控件省市区:仿苹果级联菜单相关推荐

  1. android仿优酷菜单,Android自定义控件之仿优酷菜单

    去年的优酷HD版有过这样一种菜单,如下图: 应用打开之后,先是三个弧形的三级菜单,点击实体键menu之后,这三个菜单依次旋转退出,再点击实体键menu之后,一级菜单会旋转进入,点击一级菜单,二级菜单旋 ...

  2. android 苹果电脑底部图标滚动效果,JS实现仿苹果底部任务栏菜单效果代码

    本文实例讲述了JS实现仿苹果底部任务栏菜单效果代码.分享给大家供大家参考.具体如下: 这款仿苹果电脑的底部任务栏菜单,是纯JavaScript实现的菜单特效,鼠标放上有响应效果,菜单图标会变大,而且动 ...

  3. Java Excel省市区级联菜单设置

    主要解决使用POI写excel,并且添加数据校验,以及省市区级联菜单设置,分Excel2003与Excel2007两个版本. 关于POI与Excel之间的一些关系,以及设计方面的一些思想说明: Jav ...

  4. android汽车之家顶部滑动菜单,Android自定义控件之仿汽车之家下拉刷新

    关于下拉刷新的实现原理我在上篇文章Android自定义控件之仿美团下拉刷新中已经详细介绍过了,这篇文章主要介绍表盘的动画实现原理 汽车之家的下拉刷新分为三个状态: 第一个状态为下拉刷新状态(pull ...

  5. iphonex重量_精仿苹果iPhone X手机配置介绍

    精仿苹果iPhone X手机配置介绍 [上市时间] 2017年10月最新版 [屏幕色彩] 1600万 [分 辨 率] 1920X1080 [屏幕尺寸] 5.8英寸IPS全视角电容式触摸屏 [处 理 器 ...

  6. php仿苹果,关于8个超炫酷仿苹果应用的HTML5动画的图文详解

    苹果的产品一直以精美的UI著称,无论是软件应用还是硬件设备.本文主要分享了8个很不错的HTML5动画应用,这些动画正式模仿了苹果的各类应用,有焦点图.钟表.菜单等HTML5应用和jQuery插件,大家 ...

  7. 苹果x处理器多少_精仿苹果iPhone XR手机配置介绍

    精仿苹果iPhone XR手机配置介绍 [上市时间]2018年10月 [手机类型]智能手机 安卓手机 4G [适用频率]850/900/1800/1900MHz [网络制式]GSM WCDMA [处 ...

  8. 8个超酷炫仿苹果应用的HTML5动画

    苹果的产品一直以精美的UI著称,无论是软件应用还是硬件设备.本文主要分享了8个很不错的HTML5动画应用,这些动画正式模仿了苹果的各类应用,有焦点图.钟表.菜单等HTML5应用和jQuery插件,大家 ...

  9. ios8.0 html样式,8个超炫酷仿苹果应用的HTML5动画

    苹果的产品一直以精美的UI著称,无论是软件应用还是硬件设备.本文主要分享了8个很不错的HTML5动画应用,这些动画正式模仿了苹果的各类应用,有焦点图.钟表.菜单等HTML5应用和jQuery插件,大家 ...

最新文章

  1. php excel 追加写入,phpexcel写入追加已有的excel文件
  2. Swift学习------常量与变量
  3. GetAdaptersInfo获取MAC地址
  4. 无法运行的愿意_旧电脑的福音:Win10精简版,运行比Win7更快,安装包不到3GB
  5. 使用mysql服务来记录用户的反馈
  6. 如何控制局域网网速_免费局域网监控软件如何提升控制性能 - 百科
  7. Java ques:java.lang.NoClassDefFoundError: org/junit/platform/engine/ConfigurationParameters
  8. word安全模式解除
  9. linux调色软件,达芬奇电影级调色软件 DaVinci Resolve Lite v10.1(Win/Mac/Linux)
  10. postgres查询序列_PostgreSQL 序列使用
  11. 玻色量子CEO文凯受邀出席首经贸金融学院系列讲座
  12. 快应用开发必备工具下载
  13. 2022上半年软考电子证书可以查询拉!
  14. 对撞机_纪中3074_暴力?
  15. 服务器安装360文档卫士,360文档卫士
  16. LFS 好辛苦的工作,据说要坚持至少12个小时,而如果不用“风无痕9588”大侠的脚本代码而手工输入的话,据说要200个小时!
  17. Linux—DNS域名解析服务
  18. asciidoc html java_如何使用AsciiDoclet从.java文件中的javadoc注释生成asciidoc文件
  19. VMware 下载与安装 Windows版本
  20. 华中科技大学 计算机 数据库 试卷,华中科技大学计算机学院数据库总复习

热门文章

  1. JVM 字节码 对照表
  2. Windows系统中通过命令查看文件的MD5,SHA1,SHA256校验值
  3. php 开发桌面应用,使用NW将开发的网站打包成桌面应用
  4. python讲解-详解python中@的用法
  5. java jdbc 回滚_java_详解Java的JDBC API中事务的提交和回滚,如果JDBC连接是在自动提交模式 - phpStudy...
  6. Python 猜数字游戏
  7. 泰森怎么会输给道格拉斯_巅峰泰森为何遭遇六连败?日本女孩不是主因,而是这位黑人超模...
  8. docker 删除image_不是吧!Docker上手,看会觉得自己又行了!
  9. 用python写一个telnet另一台电脑并开启某个应用程序_Python-Anaconda的安装和配置
  10. matlab常数编程,用MATLAB编程序,拟合方程,求常数。 - 计算模拟 - 小木虫 - 学术 科研 互动社区...