插件開發系列
Android Studio插件開發1之插件介紹與環境搭建
Android Studio插件開發2之Action System
Android Studio插件開發3之Extensions And Extension Points(擴展與擴展點)
Action System包含最基礎的Action,還有Action Group
Action
什么是Action
我們自己的代碼邏輯,在IDE的運行環境下執行,我們的代碼便成了它的“插件”,可是怎樣才能讓IDE執行我們的代碼邏輯?Intellij提供了一個很基礎的組件 -- Action。
Action,直譯就是動作,是我們最常見到的組件,也是最普通的代碼執行的入口。
所有菜單和工具欄的點擊按鈕背后就是一個Action
所以我一般都把它想象成Android里的OnClickListener。同樣地,要自定義自己的Action,只需要繼承AnAction
類并把邏輯放在actionPerformed
方法即可。
最簡單的Action
public class SimpleAction extends AnAction {
@Override
public void actionPerformed(AnActionEvent e) {
// TODO: insert action logic here
System.out.println("This is an action");
}
}
上一篇文章說過,Action是需要在plugin.xml注冊的,所以,要讓這個Action跑起來,還需要在plugin.xml的actions
標簽添加以下內容
<action id="MyPlugin.SimpleAction" class="SimpleAction" text="logAction" description="just log to console">
<add-to-group group-id="HelpMenu" anchor="first"/>
</action>
解釋一下action
標簽的屬性的含義
- id:這個Action的唯一標識,所有的id不能重復,IDE通過id區分不同的Action
- class:這個Action的類
- text:這個Action顯示在菜單或工具欄上的文字
- description:這個Action的描述
然后編譯運行:
- 如果沒有用gradle點擊運行按鈕即可
- 使用了gradle
- 點擊gradle的tool window,找到Tasks / intellij / runIdea,雙擊
runIdea
- 命令行執行
gradle runIdea
(gradle得在你的PATH里)
- 點擊gradle的tool window,找到Tasks / intellij / runIdea,雙擊
后文將默認使用gradle
一切正常的話,一個新的IDE實例便會運行起來,運行的版本取決于你在build.gradle指定的版本
現在,在Help菜單欄的第一個條目就是我們的Action
點擊logAction,在控制臺(我們編譯插件的IDE實例)就能看到輸出
新建Action向導
新建一個Action那么麻煩,Intellij那些聰明的工程師怎么會無動于衷!
Plugin Dev插件提供了一個新建Action的向導,好像新建Activity那樣方便簡單,填寫好相關信息,Action類和plugin.xml就還幫我們建好啦
更新Action的狀態
Action中除了actionPerformed
外也值得關注的就是update
方法了,系統通過調用Action的update方法得到Action的狀態,從而決定怎樣在菜單上顯示Action
@Override
public void update(AnActionEvent e) {
Editor editor = e.getData(PlatformDataKeys.EDITOR);
if (editor != null) {
int lineCount = editor.getDocument().getLineCount();
if (lineCount > 20) {
e.getPresentation().setEnabled(true);
} else {
e.getPresentation().setEnabled(false);
}
}
}
上面的代碼塊意思是當前editor打開的文件的行數大于20行才使Action可用,否則不可用,Action不可用的話是會變灰色的
Presentation還有一系列方法改變Action的“外貌”:
presentation.setDescription();
presentation.setIcon();
presentation.setText();
presentation.setVisible();
Action Group
Action Group含有一個或幾個Action Item,每一個Action都屬于一個Action Group。Action Group可以被添加到菜單欄的最頂層,也可以被添加到其他Action Group,預設的Action Group非常多,除了菜單欄上的File、Edit、View等等外,還有很多Intellij已經定義的Action Group,如上圖New Action向導所示,Groups滾動框下拉,可以看到非常多的Action Group。
現在,手動定義一個Action Group
<actions>
<group id="com.example.actiongroup" text="Action Group" description="this is a action group">
</group>
</actions>
<group>
標簽同樣要被包裹在actions
標簽內,id是注冊Action時的要添加進的Group的id,現在往com.example.actiongroup
的Group里加入Action
<group id="com.example.actiongroup" text="Action Group" description="this is a action group">
<action class="GroupAction" id="com.example.actiongroup.groupaction" text="A Action in Group" />
<add-to-group group-id="MainMenu"/>
</group>
<action>
直接寫在<group>
內的話就默認是加入這個group了,同樣,group也要add到已有的group里面,才能讓它在菜單里顯示出來。這里加入的是主菜單,也就是最頂層的菜單,運行效果如下
次級菜單展開
現在添加次級菜單如下
<group id="com.example.actiongroup" text="Action Group" description="this is a action group">
<action class="GroupAction" id="com.example.actiongroup.groupaction" text="A Action in Group"/>
<group id="com.example.subgroup" text="Sub Group">
<action class="GroupAction2" id="com.example.actiongroup.groupaction2" text="A Action2 in Group"/>
</group>
<add-to-group group-id="MainMenu"/>
</group>
可是結果是這樣的
運行結果和我們的直覺不一樣啊!!要如我們所愿,像次級菜單展開的話,還需要設置一個popup屬性,把subgroup的popup屬性設置為true即可破之
添加分隔線
為相似功能的菜單項添加分隔線很簡單,在<group>
下添加<separator/>
標簽即可
引用Action
<group id="com.example.actiongroup" text="Action Group" description="this is a action group">
<action class="GroupAction" id="com.example.actiongroup.groupaction" text="A Action in Group"/>
<group id="com.example.subgroup" text="Sub Group" popup="true">
<action class="GroupAction2" id="com.example.actiongroup.groupaction2" text="A Action2 in Group"/>
</group>
<separator/>
<reference ref="$Cut"/>
<add-to-group group-id="MainMenu"/>
</group>
<reference>
用于引用已有的Action,包括系統定義的和插件定義的Action,如上所示添加了剪切的Action
同級的Action不可引用
與<reference>
定義在同一個級別的Action不可以被引用,上面的代碼塊中GroupAction是不可以被引用的,但是GroupAction2可以被引用
更新Action Group狀態
Action Group同樣通過update
方法更新狀態,不過首先先要給Action Group指定一個class,class繼承DefaultActionGroup
<group id="com.example.actiongroup" class="MyActionGroup" text="Action Group" description="this is a action group">
<action class="GroupAction" id="com.example.actiongroup.groupaction" text="A Action in Group"/>
<group id="com.example.subgroup" text="Sub Group" popup="true">
<action class="GroupAction2" id="com.example.actiongroup.groupaction2" text="A Action2 in Group"/>
</group>
<separator/>
<reference ref="$Cut"/>
<reference ref="com.example.actiongroup.groupaction2"/>
<add-to-group group-id="MainMenu"/>
</group>
改變text和可用性
@Override
public void update(AnActionEvent e) {
e.getPresentation().setText("disable group");
e.getPresentation().setEnabled(false);
}
動態添加Action
如果需要Action Group的Action隨條件的不同而不同,同樣需要設置group的class,不過擴展于ActionGroup
類,并復寫getChildren
方法,即可動態的提供Action
@NotNull
@Override
public AnAction[] getChildren(AnActionEvent anActionEvent) {
return new AnAction[]{new MyAction()};
}