ImageVerifierCode 换一换
格式:DOCX , 页数:12 ,大小:122.74KB ,
资源ID:6825218      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/6825218.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(打造酷炫AndroidStudio插件剖析.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

打造酷炫AndroidStudio插件剖析.docx

1、打造酷炫AndroidStudio插件剖析打造酷炫AndroidStudio插件这篇文章打算开发一个酷炫一点的插件。因为会用到前面的基础,所以如果没有看前面系列文章的话,请先返回。当然,如果有基础的可以忽略之。先看看本文实现的最终效果如下(好吧,很多人说看的眼花):虽然并没有什么实际用途,但是作为学习插件开发感觉挺有意思的。1. 基本思路基本思路可以归结如下几步:通过Editor对象可以拿到封装代码编辑框的JComponent对象,即调用如下函数:JComponent component = editor.getContentComponent();获取输入或删除的字符(或字符串。通过选中多个

2、字符删除或粘贴则为字符串)。可以通过添加DocumentListener,监听文本变化。重写beforeDocumentChange函数,并通过DocumentEvent对象取得新的字符和旧的字符。分别通过函数:documentEvent.getNewFragment()、documentEvent.getOldFragment()。它们代表着输入的字符串和删除的字符串。将输入或删除的字符串在编辑框中显示出来。只需将各个字符串分别封装到Jlabel中,并将JLabel加入到JComponent中即可显示出输入或删除的字符串(或字符)。获取用于显示各个字符串的Jlabel对象在JComponen

3、t中的坐标位置。添加CaretListener,监听光标的位置。每次光标位置发生变化,就刷新到临时变量中。当要添加一个JLabel时,获取当前的临时变量中保存的位置即为Jlabel应存放的位置。动画效果。开启一个线程,对于输入的字符串,只需不断修改字体大小。对于删除的字符串,不断修改JLabel的位置和字体大小。插件状态保存到本地。用户点击开启或者关闭插件以及其他开关选项,需要保存起来,下一次开启AndroidStudio时可以恢复。只需实现PersistentStateComponent接口即可。用户未点击Action时,能自动注册DocumentListener。这主要是考虑到,用户开启了

4、插件,下一次打开AndroidStudio时无需点击Aciton,直接输入时就能自动注册监听Document变化。由于注册DocumentListener需要Editor对象,而想要取得Editor对象只有两种方式:通过AnActionEvent对象的getData函数;另一种是通过DataContext对象,使用 PlatformDataKeys.EDITOR.getData(dataContext)方法。显然第一种方法只能在AnAction类的actionPerformed和update方法中才能取得。因此只能考虑用第二种方法,而在前面文章中介绍过,监听键盘字符输入时,可以取得DataCo

5、ntext对象。即重写TypedActionHandler接口的execute函数,execute参数中传递了DataContext对象。可以看到,以上用到的知识都是前面3篇文章中介绍过的内容,并不复杂。只有第6条没有介绍,本文中会学习本地持久化数据。2. 插件状态本地持久化先看看如何实现本地持久化。首先定义一个全局共享变量类GlobalVar,使之实现PersistentStateComponent接口。先来个视觉上的认识,直接看代码。/* * 配置文件 * Created by huachao on 2016/12/27. */State( name = amazing-mode, sto

6、rages = Storage( id = amazing-mode, file = $APP_CONFIG$/amazing-mode_setting.xml ) )public class GlobalVar implements PersistentStateComponent public static final class State public boolean IS_ENABLE; public boolean IS_RANDOM; Nullable Override public State getState() return this.state; Override pub

7、lic void loadState(State state) this.state = state; public State state = new State(); public GlobalVar() state.IS_ENABLE = false; state.IS_RANDOM = false; public static GlobalVar getInstance() return ServiceManager.getService(GlobalVar.class); 使用State注解指定本地存储位置、id等。具体实现基本可以参照这个模板写,就是重写loadState()和ge

8、tState()两个函数。另外需要注意一下getInstance()函数的写法。基本模板就这样,没有什么特别的地方,依葫芦画瓢就行。还有一点特别重要,一定要记得在plugin.xml中注册这个持久化类。找到标签,加入子标签,如下: 这样写完以后,在获取数据的时候,直接如下:private GlobalVar.State state = GlobalVar.getInstance().state;/state.IS_ENABLE/state.IS_RANDOM3. 编写Action主要包含2个Action:EnableAction和RandomColorAction。EnableAction用于

9、设置插件的开启或关闭,RandomColorAction用于设置是否使用随机颜色。由于二者功能类似,我们只看看EnableAction的实现:/* * Created by huachao on 2016/12/27. */public class EnableAction extends AnAction private GlobalVar.State state = GlobalVar.getInstance().state; Override public void update(AnActionEvent e) Project project = e.getData(PlatformD

10、ataKeys.PROJECT); Editor editor = e.getData(PlatformDataKeys.EDITOR); if (editor = null | project = null) e.getPresentation().setEnabled(false); else JComponent component = editor.getContentComponent(); if (component = null) e.getPresentation().setEnabled(false); else e.getPresentation().setEnabled(

11、true); updateState(e.getPresentation(); Override public void actionPerformed(AnActionEvent e) Project project = e.getData(PlatformDataKeys.PROJECT); Editor editor = e.getData(PlatformDataKeys.EDITOR); if (editor = null | project = null) return; JComponent component = editor.getContentComponent(); if

12、 (component = null) return; state.IS_ENABLE = !state.IS_ENABLE; updateState(e.getPresentation(); /只要点击Enable项,就把缓存中所有的文本清理 CharPanel.getInstance(component).clearAllStr(); GlobalVar.registerDocumentListener(project, editor, state.IS_ENABLE); private void updateState(Presentation presentation) if (sta

13、te.IS_ENABLE) presentation.setText(Enable); presentation.setIcon(AllIcons.General.InspectionsOK); else presentation.setText(Disable); presentation.setIcon(AllIcons.Actions.Cancel); 代码比较简单,跟前面几篇文章中写的很相似。只需注意一下actionPerformed函数中调用了两个函数:CharPanel.getInstance(component).clearAllStr();GlobalVar.registerD

14、ocumentListener(project, editor, state.IS_ENABLE);CharPanel对象中的clearAllStr()函数后面介绍,只需知道它是将缓存中的所有动画对象清除。GlobalVar对象中的registerDocumentListener ()函数是添加DocumentListener监听器。实现本文效果的中枢是DocumentListener监听器,是通过监听文本内容发生变化来获取实现字符动画效果的数据。因此应应可能早地将DocumentListener监听器加入,而DocumentListener监听器加入的时刻包括:用户点击Action、用户敲入

15、字符。也就是说,多个地方都存在添加DocumentListener监听器的可能。因此把这个函数抽出来,加入到GlobalVar中,具体实现如下:private static AmazingDocumentListener amazingDocumentListener = null;public static void registerDocumentListener(Project project, Editor editor, boolean isFromEnableAction) if (!hasAddListener | isFromEnableAction) hasAddListen

16、er = rue; JComponent component = editor.getContentComponent(); if (component = null) return; if (amazingDocumentListener = null) amazingDocumentListener = new AmazingDocumentListener(project); Document document = editor.getDocument(); document.addDocumentListener(amazingDocumentListener); Thread thr

17、ead = new Thread(CharPanel.getInstance(component); thread.start(); 可以看到,一旦DocumentListener监听器被加入,就会开启一个线程,这个线程是一直执行,实现动画效果。DocumentListener监听器只需加入一次即可。4. 实现动画前面多次使用到了CharPanel对象,CharPanel对象就是用于实现动画效果。先源码:package com.huachao.plugin.util;import com.huachao.plugin.Entity.CharObj;import javax.swing.*;im

18、port java.awt.*;import java.util.*;import java.util.List;/* * Created by huachao on 2016/12/27. */public class CharPanel implements Runnable private JComponent mComponent; private Point mCurPosition; private Set charSet = new HashSet(); private List bufferList = new ArrayList(); private GlobalVar.St

19、ate state = GlobalVar.getInstance().state; public void setComponent(JComponent component) mComponent = component; public void run() while (state.IS_ENABLE) if (GlobalVar.font != null) synchronized (bufferList) charSet.addAll(bufferList); bufferList.clear(); draw(); int minFontSize = GlobalVar.font.g

20、etSize(); /修改各个Label的属性,使之能以动画形式出现和消失 Iterator it = charSet.iterator(); while (it.hasNext() CharObj obj = it.next(); if (obj.isAdd() /如果是添加到文本框 if (obj.getSize() = minFontSize) /当字体大小到达最小后,使之消失 mComponent.remove(obj.getLabel(); it.remove(); else /否则,继续减小 int size = obj.getSize() - 6 minFontSize ? mi

21、nFontSize : (obj.getSize() - 6); obj.setSize(size); else /如果是从文本框中删除 Point p = obj.getPosition(); if (p.y = 0 | obj.getSize() = 0) /如果到达最底下,则清理 mComponent.remove(obj.getLabel(); it.remove(); else p.y = p.y - 10; int size = obj.getSize() - 1 0 ? 0 : (obj.getSize() - 1); obj.setSize(size); try if (cha

22、rSet.isEmpty() synchronized (charSet) charSet.wait(); Thread.currentThread().sleep(50); catch (InterruptedException e) e.printStackTrace(); /绘制文本,本质上只是修改各个文本的位置和字体大小 private void draw() if (mComponent = null) return; for (CharObj obj : charSet) JLabel label = obj.getLabel(); Font font = new Font(Glo

23、balVar.font.getName(), GlobalVar.font.getStyle(), obj.getSize(); label.setFont(font); FontMetrics metrics = label.getFontMetrics(label.getFont(); int textH = metrics.getHeight(); /字符串的高, 只和字体有关 int textW = metrics.stringWidth(label.getText(); /字符串的宽 label.setBounds(obj.getPosition().x, obj.getPositi

24、on().y - (textH - GlobalVar.minTextHeight), textW, textH); mComponent.invalidate(); public void clearAllStr() synchronized (bufferList) bufferList.clear(); charSet.clear(); Iterator setIt = charSet.iterator(); while (setIt.hasNext() CharObj obj = setIt.next(); mComponent.remove(obj.getLabel(); Itera

25、tor bufferIt = bufferList.iterator(); while (bufferIt.hasNext() CharObj obj = bufferIt.next(); mComponent.remove(obj.getLabel(); /单例模式,静态内部类 private static class SingletonHolder /静态初始化器,由JVM来保证线程安全 private static CharPanel instance = new CharPanel(); /返回单例对象 public static CharPanel getInstance(JComp

26、onent component) if (nent != null) SingletonHolder.instance.mComponent = component; return SingletonHolder.instance; /由光标监听器回调,由此可动态获取当前光标位置 public void setPosition(Point position) this.mCurPosition = position; /* * 将字符串添加到列表中。 * * isAdd 如果为true表示十新增字符串,否则为被删除字符串 * str 字符串 */ public void addStrToLis

27、t(String str, boolean isAdd) if (mComponent != null & mCurPosition != null) CharObj charObj = new CharObj(mCurPosition.y); JLabel label = new JLabel(str); charObj.setStr(str); charObj.setAdd(isAdd); charObj.setLabel(label); if (isAdd) charObj.setSize(60); else charObj.setSize(GlobalVar.font.getSize(

28、); charObj.setPosition(mCurPosition); if (state.IS_RANDOM) label.setForeground(randomColor(); else label.setForeground(GlobalVar.defaultForgroundColor); synchronized (bufferList) bufferList.add(charObj); if (charSet.isEmpty() synchronized (charSet) charSet.notify(); mComponent.add(label); /以下用于产生随机颜

29、色 private static final Color COLORS = Color.GREEN, Color.BLACK, Color.BLUE, Color.ORANGE, Color.YELLOW, Color.RED, Color.CYAN, Color.MAGENTA; private Color randomColor() int max = COLORS.length; int index = new Random().nextInt(max); return COLORSindex; 解释一下两个关键函数run()和draw()。run()函数是开启新线程开始执行的函数,它的实现是一个循环,当插件开启时会一直循环运行。CharPanel使用了2个集合来保持用户删除或者添加的字符串

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1