首页 文章 精选 留言 我的

精选列表

搜索[网站开发],共10000篇文章
优秀的个人博客,低调大师

iOS开发-UITextView根据内容自适应高度

UITextView作为内容文本输入区域,有的时候我们需要根据内容动态改变文本区域的高度,效果如下: 定义UITextView,实现UITextViewDelegate: 1 2 3 4 5 6 7 8 9 10 11 12 -(UITextView *)textView{ if (!_textView) { //http://www.cnblogs.com/xiaofeixiang/ _textView=[[UITextView alloc]initWithFrame:CGRectMake(30, 200, CGRectGetWidth([[UIScreen mainScreen] bounds])-60, 30)]; [_textView setTextColor:[UIColor redColor]]; [_textView.layer setBorderColor:[[UIColor blackColor] CGColor]]; [_textView setFont:[UIFont systemFontOfSize:15]]; [_textView.layer setBorderWidth:1.0f]; [_textView setDelegate:self]; } return _textView; } 实现textViewDidChange方法: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 -( void )textViewDidChange:(UITextView *)textView{ //博客园-FlyElephant static CGFloat maxHeight =60.0f; CGRect frame = textView.frame; CGSize constraintSize = CGSizeMake(frame.size.width, MAXFLOAT); CGSize size = [textView sizeThatFits:constraintSize]; if (size.height<=frame.size.height) { size.height=frame.size.height; } else { if (size.height >= maxHeight) { size.height = maxHeight; textView.scrollEnabled = YES; // 允许滚动 } else { textView.scrollEnabled = NO; // 不允许滚动 } } textView.frame = CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, size.height); } 本文转自Fly_Elephant博客园博客,原文链接:http://www.cnblogs.com/xiaofeixiang/p/5148380.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

高质量 Android 开发框架 LoonAndroid 详解

整个框架式不同于androidannotations,Roboguice等ioc框架,这是一个类似spring的实现方式。在整应用的生命周期中找到切入点,然后对activity的生命周期进行拦截,然后插入自己的功能。 框架的说明 如果你想看ui方面的东西,这里没有,想要看牛逼的效果这里也没有。这只是纯实现功能的框架,它的目标是节省代码量,降低耦合,让代码层次看起来更 清晰。整个框架一部分是网上的,一部分是我改的,为了适应我的编码习惯,还有一部分像orm完全是网上的组件。在此感谢那些朋友们。整个框架式的初衷是为 了偷懒,之前都是一个功能一个jar,做项目的时候拉进去,这样对于我来说依然还是比较麻烦。最后就导致我把所有的jar做成了一个工具集合包。有很多框 架都含有这个工具集合里的功能,这些不一定都好用,因为这是根据我个人使用喜欢来实现的,如果你们有自己的想法,可以自己把架包解压了以后,源码拉出来改 动下。目前很多框架都用到了注解,除了androidannotations没有入侵我们应用的代码以外,其他的基本上都有,要么是必须继承框架里面的 activity,要么是必须在activity的oncreat里面调用某个方法。整个框架式不同于 androidannotations,Roboguice等ioc框架,这是一个类似spring的实现方式。在整应用的生命周期中找到切入点,然后对 activity的生命周期进行拦截,然后插入自己的功能。 如果需要混淆 第一步 你要先引入你得架包 -libraryjars libs/android-support-v4.jar -libraryjars libs/loonandroid.jar 第二步 你要保证注解在代码优化的时候不能被删除掉 -keepattributes Signature -keepattributes Annotation第三步 support4 要排除掉 -dontwarn android.support.v4.** -keep class android.support.v4.** { ; } -keep interface android.support.v4.app.* { ; } -keep public class * extends android.support.v4.* -keep public class * extends android.app.Fragment 第四步 只要使用了注解的包名 全部排除掉 -dontwarn xxx.** -keep class xxx.** { ; } 其中XXX替换成你使用了注解的包名第五步 保证R不被混淆 -keep class *.R$* { *; } 即OK 框架的主要功能 其中分为以下几种: 自动注入框架(只需要继承框架内的application既可) 图片加载框架(多重缓存,自动回收,最大限度保证内存的安全性) 网络请求模块(继承了基本上现在所有的http请求) eventbus(集成一个开源的框架) 验证框架(集成开源框架) json解析(支持解析成集合或者对象) 数据库(不知道是哪位写的 忘记了) 多线程断点下载(自动判断是否支持多线程,判断是否是重定向) 自动更新模块 一系列工具类 一 自动注入框架 1 无需继承任何BaseActivity 举例:普通activity publicclassFourActivityextendsActivity{ Viewxx; @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main4); xx=find......; //--------------------------------------------------------- 组件的初始化 //--------------------------------------------------------- } } 这其中我们会耗费大量的代码或者重复性的去些一些代码。特别是布局比较复杂的情况下。 如果用框架 @InjectLayer(R.layout.activity_main3) publicclassThirdActivityextendsActivity{ @InjectView Viewxx; } 即可 像软件的说明页面,就是单纯的展示一个布局,那么就是 @InjectLayer(R.layout.activity_main3) publicclassThirdActivityextendsActivity{ } 即可 整个ioc框架不需要你继承任何的acitivity,这样就保证了不会在你的代码结构层次上造成影响,因为有的时候你需要自己的BaseActivity来实现你公用的功能。 2 支持子父布局 这种情况下,对于一般的框架来说,做法有以下几种: ActivityGroup 一般的ioc框架都需要继承框架内的activity,activitygroup会让很多框架用不了,现在ActivityGroup也是不提倡的了。 BaseActivity 一般的Ioc框架会需要你的BaseActivity 去继承框架内的activity 中间用fragment 这样的情况也一样,你的FragmentActivity必须继承它的activity才能实现ioc框架功能。对于这个框架来说很容易实现 1 ActivityGroup 你不需要继承任何activity 和普通activity 实现方式(如上面的例子) 2 BaseActivity 见代码: 首先是BaseActivity @InjectPLayer(R.layout.activity_com) public class BaseActivity extends Activity {} 其中R.layout.activity_com是包括上下导航的布局,中间是一个view子activity只需要这么写即可 @InjectLayer(value=R.layout.activity_main,parent=R.id.common) publicclassMainActivityextendsBaseActivity{} 当然 又会有问题了,那么我上下导航里面的点击事件怎么绑定,怎么去初始化,难道要每一个子activity都要去写吗?当然不需要 @InjectPLayer(R.layout.activity_com) publicclassBaseActivityextendsActivity{ @InjectInit privatevoidinit(){ MeApplication.logger.s("公共类的初始化"); } //这里是第一种交互事件注入方式(单击) @InjectMethod(@InjectListener(ids={R.id.top,R.id.bottom},listeners={OnClick.class})) privatevoidclick2(Viewview){ Handler_TextStylehandler_TextStyle=newHandler_TextStyle(); switch(view.getId()){ caseR.id.top: handler_TextStyle.setString("点击了顶部按钮(在基类中统一注册,也可以单独注册)"); handler_TextStyle.setBackgroundColor(Color.RED,3,5); Toast.makeText(this,handler_TextStyle.getSpannableString(),Toast.LENGTH_LONG).show(); break; caseR.id.bottom: handler_TextStyle.setString("点击了底部按钮(在基类中统一注册,也可以单独注册)"); handler_TextStyle.setBackgroundColor(Color.RED,3,5); Toast.makeText(this,handler_TextStyle.getSpannableString(),Toast.LENGTH_LONG).show(); break; } } } 如上 其中@InjectInit注解表示不管是在子activity还是父activity 都是在布局初始化完成以后才会调用,其先后顺序是 父布局layout->子布局layout->父布局ioc和事件绑定->子布局事件绑定。 父activity 中可以对所有的公用组件和事件进行初始化和绑定还没完,又会有另一个问题,如果我某个页面下导航的a按钮和其他页面底部a按钮的功能不一样 要单独设置怎么办。那么我们可以在子布局进行@InjectMethod和@InjectView进行事件绑定和组件注入,它们会覆盖父类中相同id的组 件的操作以下是view注入的方法说明: @InjectPLayer 表示是Activity的setContentView @InjectLayer(value=R.layout.activity_main2,parent=R.id.common,isFull=true,isTitle=true) 其中需要哪个参数就用哪个,value 是必须的 如果只有layout可以这么写@InjectPLayer(R.layout.activity_com)。其中value 表示layout,parent表示它在父布局中所对应组件的id 如上图中 中间显示区域的view的id。Isfull是否全屏,默认为false.isTitle 是否有标题,默认false; @InjectView 自动注入view注解。 基本写法: @InjectView TextViewtest; 其中test表示它在xml中对应的Id为test @InjectView(R.id.next2) TextViewtest; 表示它在xml中对应的Id为next2 高级写法: @InjectView(binders={@InjectBinder(method="click",listeners={OnClick.class,OnLongClick.class})}) Buttonnext,next3,next4; 其中表示对id为next,next3,next4进行注解,其中binders 表示绑定了以下事件,binders 是个数组,也就是说可以用多个InjectBinder绑定多个事件,也可以用listeners = { OnClick.class, OnLongClick.class }来表示对组件注入了点击事件和长按事件 @InjectView(value=R.id.next2,binders={@InjectBinder(method="click",listeners={OnClick.class})}) Buttonbutton; 对于变量名和组件id不一致的view则需要设置value Click 表示那些注入的事件触发以后所调用的方法,其必须在当前类内。 // 支持由参数和无参数 即click(View view)或者click() 当然click名字必须对于变量注解中的method = “click” privatevoidclick(Viewview){ switch(view.getId()){ caseR.id.next: startActivity(newIntent(this,ThirdActivity.class)); break; ... } } @InjectResource @InjectResource Stringaction_settings; @InjectResource Drawableic_launcher; InjectResource支持string和drawable的注解 @InjectMethod // 底部导航栏 子类覆盖父类 @InjectMethod(@InjectListener(ids={R.id.bottom},listeners={OnClick.class,OnLongClick.class})) privatevoidclick3(Viewview){ Handler_TextStylehandler_TextStyle=newHandler_TextStyle(); handler_TextStyle.setString("点击了底部按钮子类覆盖了父类"); handler_TextStyle.setBackgroundColor(Color.RED,3,5); Toast.makeText(this,handler_TextStyle.getSpannableString(),Toast.LENGTH_LONG).show(); } @InjectMethod是当我们对一个组件只需要触发而不需要find出来的时候用到。 ids 表示绑定哪些id,listeners 表示绑定哪些事件 这两个参数都是数组 当然 如果嫌注解字段太长,可以自己修改。这个是整个view的注入。 @InjectInit @InjectInit voidinit(){ MeApplication.logger.s("子类的初始化"); test.setText("初始化完成,第一个页面"); } 这个注解你在activity中添加到任何一个方法名上,那么,当所有的layout和所有的view以及事件绑定完毕以后,会第一个调用含有这个注解的方法。它相当于oncreat 注意:框架注解了整个activity的生命周期,@InjectOnNewIntent,@InjectPause,@InjectResume, @InjectRestart,@InjectStart,@InjectStop其中OnDestroy无注解。 如果Activity中有含有这些注解的方法那么不同生命周期下回自动调用这些方法 二:Fragment的自动注入 @Override publicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,BundlesavedInstanceState){ this.inflater=inflater; ViewrootView=inflater.inflate(R.layout.activity_left,container,false); Handler_Inject.injectView(this,rootView); returnrootView; } 只需要在onCreateView里面调用Handler_Inject.injectView(this,rootView); 即可 在fragment中除了activity的生命周期注解和@InjectLayer注解无法使用外,组件绑定和事件绑定都可以使用,@InjectBefore也可以使用 @InjectBefore是在组件初始化之前调用 三:图片下载框架 这个是图片框架重写了好多次了,总是有点问题,里面基本上每一段代码都有注释,还有一些bug, 因为项目中用的还是这次重写之前的。 如果大家发现问题,记得告诉我框架中调用的方法名和参数基本上都不会变,避免替换jar导致需要改动大部分代码。 整个图片下载的逻辑是这样的: 1 根据url和view去调用图片下载的方法 2 从缓存去拿bitmap 3 如果bitmap不为空 判断是否针对这个url有单独的配置 没有则使用全局配置加载图片 4 如果bitmap为空 则开启线程,放到本地线程池中,然后从本地文件读取 5 如果文件存在,则转为bitmap放到缓存,然后重复2,然后9 6 如果文件不存在,则开启线程放到网络线程池中去下载文件 7 下载成功则放到本地sdcard 然后把文件转为bitmap放到缓存,然后重复2,然后9 8 下载不成功,然后重复2,然后9 9 如果bitmap不为空 判断是否针对这个url有单独的配置 没有则使用全局配置加载这张图片 如果bitmap为空 则显示失败的默认图 具体的流程 可以参考源码 缓存分为三层 第一层是LruCache(原理去百度) 第二层是LinkedHashMap 第三层是view标记 1当LruCache中的图片超过了规定了内存,那么从LruCache移除一个使用最少的,放到LinkedHashMap中 2当每一张图片的url对应一个count,一旦加载一张图片,那么这个url的count加1 3自定义AsyImageView继承ImageView,重写了onDetachedFromWindow方法,一旦 AsyImageView从当前视图移除掉会调用onDetachedFromWindow该方法,此刻该图片所对应的url数目count减1 4因为listview中的imageview如果用了ViewHolder那么第3条就不适合了,此刻每一个imagview的hashCode对应一个url, 一旦imagview更换了一个新的url,那么该imagview的hashcode上一个的引用将被移除, 那么上一次显示的url所对应的count将减1 5当LinkedHashMap超过了规定限制的时候,那么遍历所有的count一旦count为0则移除回收 图片下载使用 一:必须条件 必须在配置文件中添加配置,来打开图片下载引擎的初始化,为了减少启动时间,默认关闭。 #开启框架内置的图片下载如果不设置则无法使用框架类的图片下载 imageload_open=true 二:使用方法 1 普通图片下载 ImageDownloader.download("网络和本地图片链接",mAsyImageView); 如果需要配置bitmap的高宽 第一种方式: 在xml布局文件中对AsyImageView的高宽进行设置 第二种方式: 全局图片配置,所有图片显示默认用此配置 GlobalConfigglobalConfig=GlobalConfig.getInstance(); globalConfig.setMaxWidth(w); 来设置 第三种 SingleConfigconfig=newSingleConfig(); config....设置宽高 ImageDownloader.download("网络和本地图片链接",mAsyImageView,config) 其中优先级 第三种 > 第一种 > 第二种 其中GlobalConfig支持的设置有高宽的设置,内存缓存的大小,默认图片, 下载失败的图片,最大缓存数目,线程池,缓存类型,显示控制,listview得滑动监听,图片加载动画 其中SingleConfig支持的设置有高宽的设置,默认图片,下载失败的图片,下载进度,显示控制,加载动画 其中SingleConfig 优先于GlobalConfig 支持配置文件配置: mAsyImageView.setTemplate("one"); ImageDownloader.download("url",mAsyImageView); 其中one在配置文件里面配置,这样 不管在任何地方,只要AsyImageView.setTemplate(“one”);就可以使用名称为one的配置了。 支持本地文件加载调用接口不变。 需要进度显示的: SingleConfigconfig=newSingleConfig(); config.setDisplayer(newDisplayerLister(){ @Override publicvoidstartLoader(AsyImageViewimageView){ super.startLoader(imageView); } @Override publicBitmapfinishLoader(Bitmapbitmap,AsyImageViewimageView){ pin_progress_1.setVisibility(View.GONE); returnbitmap; } @Override publicvoidprogressLoader(intprogress,AsyImageViewimageView){ pin_progress_1.setProgress(progress); super.progressLoader(progress,imageView); } }); ImageDownloader.download("url",photo,config); 其中url的服务器必须支持获取文件长度 需要显示动画的:如果是单独某一个图片 SingleConfigconfig=newSingleConfig(); config.setDisplayerAnimation(newFadeInAnimation()); 如果是全局的 GlobalConfigconfig=newGlobalConfig(); config.setDisplayerAnimation(newFadeInAnimation()); 其中FadeInAnimation是框架自带的一个渐变的动画如果需要自定义 实现DisplayerAnimation接口即可 2 listview中图片下载 只要在listview的注解@InjectView(isasy=true)中添加了isasy=true(默认为false) 那么系统会自动给你注入OnScrollListener滚动事件,以便实现图片飞行停止才加载,缓慢拖动加载的功能。如果你要实现自己的OnScrollListener 如下 @InjectBefore voidtest(){ //@InjectView(isasy=true)表示这个listview里面有网络图片下载,并且需要实现滑动停止才加载的功能 //@InjectView(isasy=true)框架会给listview自动注入OnScrollListener,如果你自己也要滚动监听 //那么请在此配置,如下 GlobalConfigconfig=GlobalConfig.getInstance(); config.setOnScrollLoaderListener(newMyOnScrollListener()); System.out.println("before"); } //必须继承框架内的滚动监听 classMyOnScrollListenerextendsOnScrollLoaderListener{ @Override publicvoidonScrollListener(AbsListViewview,intfirstVisibleItem,intvisibleItemCount,inttotalItemCount){ ApplicationBean.logger.s("滚动监听:"+firstVisibleItem); } @Override publicvoidonScrollStateChange(AbsListViewview,intscrollState){ ApplicationBean.logger.s("滚动状态"); } } @InjectBefore表示在组件初始化以前开始调用,因为滚动监听必须在listview被初始化之前赋值,否则无效将默认使用框架内的滚动监听 3 无需显示的图片下载 ImageDownloader.download("url",newLoaderLister(){ @Override publicvoidfinishLoader(Stringurl,Filefile){ System.out.println("下载完成"+file.getPath()); } @Override publicvoidfailLoader(Stringurl){ System.out.println("下载失败"); } }); 如果需要下载进度 ImageDownloader.download("url",newLoaderLister(){ @Override publicvoidstartLoader(Stringurl){ System.out.println("开始下载"); super.startLoader(url); } @Override publicvoidfinishLoader(Stringurl,Filefile){ System.out.println("下载完成"+file.getPath()); } @Override publicvoidprogressLoader(intprogress){ System.out.println("下载进度"+progress); super.progressLoader(progress); } }); 来源:51CTO

优秀的个人博客,低调大师

Android开发七 Android中的显示单位

px (pixels)像素 一般HVGA代表320x480像素,这个用的比较多。 dip或dp (device independent pixels)设备独立像素 这个和设备硬件有关,一般为了支持WVGA、HVGA和QVGA 推荐使用这个,不依赖像素。 sp (scaled pixels — best for text size)比例像素 主要处理字体的大小,可以根据系统的字体自适应。 除了上面三个显示单位,下面还有几个不太常用: in (inches)英寸 mm (millimeters)毫米 pt (points)点,1/72英寸 为了适应不同分辨率,不同的像素密度,推荐使用dip ,文字使用sp。 本文转自左正博客园博客,原文链接:http://www.cnblogs.com/soundcode/archive/2012/04/01/2428999.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

iOS开发-适配器和外观模式

适配器模式,属于结构型模式,其主要作用是将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。适配器模式有对象适配器和类适配器两种,类适配器模式需要语言实现多继承,OC不支持多继承,所以一般我们都实现对象适配器。外观模式提供了一个统一的接口,用来访问子系统中的一群接口,外观定义了一个高层接口,让子系统更容易使用。适配器是为了转换接口,外观模式是为了简化接口。 适配器模式 对象适配器模式UML类图: 关于适配模式最常见的就是手机充电的例子,通过数据线和转换口连接,然后将转换口和插座连接,转换口就可以理解为适配器~ 数据线(Target): 1 2 3 4 5 6 7 8 9 10 11 @protocol DataLineProtocol <NSObject> @optional -( void )connect; @end @ interface DataLine : NSObject<DataLineProtocol> @end 电源插头(Adapter): 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @ interface DataAdapter(){ EleSocket *eleSocket; } @end @implementation DataAdapter -(instancetype)initWithEleSocket:(EleSocket *)socket{ self=[super init]; if (self) { eleSocket=socket; } return self; } -( void )connect{ [eleSocket speicalConnect]; } @end 被适配者(插座): 1 2 3 4 5 6 7 @implementation EleSocket -( void )speicalConnect{ NSLog( @"specialConnect--电源接通" ); } @end 客户端(手机): 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @ interface Mobile(){ DataLine *dataLine; } @end @implementation Mobile -(instancetype)initWithDataLine:(DataLine *)line{ self=[super init]; if (self) { dataLine=line; } return self; } -( void )charge{ [dataLine connect]; } @end 客户端调用: 1 2 3 4 EleSocket *socket=[[EleSocket alloc]init]; DataLine *line=[[DataAdapter alloc] initWithEleSocket:socket]; Mobile *moblie=[[Mobile alloc]initWithDataLine:line]; [moblie charge]; 测试结果: 外观模式 外观模式通过引入一个外观角色来简化客户端与子系统之间的交互,为复杂的子系统调用提供一个统一的入口,降低子系统与客户端的耦合度,且客户端调用非常方便。适配器是是接口转换,外观是简化接口,将多个子系统接口转换为一个,最简单的例子就是在饭店吃饭和在家吃饭,如果去饭店吃饭,只需要下单,等个十几二十分钟我们就可以吃饭,在家自己做饭就需要买菜,淘米,炒菜等等一系列动作。 UML类图: 我们简单的模拟一下餐馆点餐的过程需要饭店,服务员,厨师: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @ interface Hotel(){ Waiter *myWaiter; Cook *myCook; } @end @implementation Hotel -(instancetype)initWithCook:(Waiter *)waiter cook:(Cook *)cook{ self=[super init]; if (self) { myWaiter=waiter; myCook=cook; } return self; } -( void )order{ [myWaiter handleOrder]; [myCook cook]; [myCook complete]; } @end 客户端调用: 1 2 Hotel *hotel=[[Hotel alloc]initWithCook:[Waiter new ] cook:[Cook new ]]; [hotel order]; 关于门面模式的简单实现中我们通过一个接口,可以调用子系统的接口,非常简单,外观模式的优势有以下几点: ①对客户屏蔽子系统组件,减少了客户处理的对象数目并使得子系统使用起来更加容易。通过引入外观模式,客户代码将变得很简单,与之关联的对象也很少。 ②实现了子系统与客户之间的松耦合关系,这使得子系统的组件变化不会影响到调用它的客户类,只需要调整外观类即可。 ③ 降低了大型软件系统中的编译依赖性,并简化了系统在不同平台之间的移植过程,因为编译一个子系统一般不需要编译所有其他的子系统。一个子系统的修改对其他子系统没有任何影响,而且子系统内部变化也不会影响到外观对象。 ④提供了一个访问子系统的统一入口,并不影响用户直接使用子系统类。 外观模式的缺点: ① 不能很好地限制客户使用子系统类,如果对客户访问子系统类做太多的限制则减少了可变性和灵活性。 ② 在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。 本文的子系统对象可以从外部传递,如果不希望从外部传递,可以在初始化的时候内部对子系统的进行初始化~ 本文转自Fly_Elephant博客园博客,原文链接:http://www.cnblogs.com/xiaofeixiang/p/5123168.html,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册