前言
目前为止,Android使用的插件的已经很多了,但是自己在这块确实空白的,之前写过了ViewInject博客了,在优化findViewById之后,考虑到不需要手写问题的情况下,采用插件辅助来开发,网上目前已经有了ButterKnife的辅助的插件,为自己开发ViewInject插件,个人建议不要光看我写的一部分我用到的方法,需要你自己看IDE Plugin API刚好这段时间有空闲时间。
使用
在使用本插件之前,请使用https://blog.csdn.net/u012127961/article/details/70195693
插件下载
插件项目
插件导入方法
技术
IDE Plugin API : http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/publishing_plugin.html
(1)创建插件项目(http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/creating_plugin_project.html)
(2)创建Action (http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/creating_an_action.html)
(3)获取当前项目、编辑器、文档对象
@Override
public void actionPerformed(AnActionEvent e) {
Project project = e.getProject();
Editor editor = e.getData(CommonDataKeys.EDITOR);
Document document = editor.getDocument();
}
(4)显示提示信息
Messages.showMessageDialog("信息内容", "提示", Messages.getInformationIcon());
(5)获取鼠标选中文字
SelectionModel selectionMode = editor.getSelectionModel();
String selectText = selectionMode.getSelectedText();
(6)获取当前打开的文件
PsiFile psiFile = e.getData(LangDataKeys.PSI_FILE);//e--->AnActionEvent
String content = psiFile.getViewProvider().getContents().toString();//文件内容
(7)文件写入信息
Document document = editor.getDocument();
WriteCommandAction.runWriteCommandAction(project, new Runnable() {
@Override
public void run() {
document.insertString(xx, xxxxx);
}
});
(8)替换文字
Document document = editor.getDocument();
SelectionModel selectionModel = editor.getSelectionModel();
int start = selectionModel.getSelectionStart();
int end = selectionModel.getSelectionEnd();
WriteCommandAction.runWriteCommandAction(project, () ->
document.replaceString(start, end, "Replacement")
);
selectionModel.removeSelection();
(9)获取当前类
protected PsiClass getTargetClass(Editor editor, PsiFile file) {
int offset = editor.getCaretModel().getOffset();
PsiElement element = file.findElementAt(offset);
if (element == null) {
return null;
} else {
PsiClass target = (PsiClass) PsiTreeUtil.getParentOfType(element, PsiClass.class);
return target instanceof SyntheticElement ? null : target;
}
}
(10)获取ElementFactory
ElementFactory ElementFactory = JavaPsiFacade.getElementFactory(project);
(11)类操作
PsiClass psiClass = getTargetClass(editor, psiFile);
//添加字段 --- [其他方式可以更改createFieldFromText这里,还可以对方法、包都可以操作]
psiClass.add(JavaPsiFacade.getElementFactory(project).createFieldFromText("private Editext etxtUser;", psiClass));
ViewInject Plugin
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileSystemItem;
import com.intellij.psi.PsiManager;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import org.apache.http.util.TextUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ViewInject extends AnAction {
@Override
public void actionPerformed(AnActionEvent e) {
Project project = e.getProject();
Editor editor = e.getData(CommonDataKeys.EDITOR);
Document document = editor.getDocument();
//获取选中文字
SelectionModel selectionMode = editor.getSelectionModel();
String selectText = selectionMode.getSelectedText();
if (TextUtils.isEmpty(selectText)) {
Messages.showMessageDialog("Select the layout name, such as: R.layout. Aty_main, and select aty_main", "提示", Messages.getInformationIcon());
return;
}
//当前文件
PsiFile psiFile = e.getData(LangDataKeys.PSI_FILE);
String currentContent = psiFile.getViewProvider().getContents().toString();
String current[] = currentContent.split("\n");
StringBuffer packageSb = new StringBuffer();
packageSb.append("import android.widget.*;");
packageSb.append("\n");
packageSb.append("import com.android.annotation.ViewInject;");
packageSb.append("\n");
StringBuffer sbPackage = new StringBuffer();
for (int i = 0; i < current.length; i++) {
if (current[i].contains("import")) {
break;
} else {
sbPackage.append(current[i] + "\n");
}
}
WriteCommandAction.runWriteCommandAction(project, new Runnable() {
@Override
public void run() {
document.insertString(sbPackage.length(), packageSb.toString());
}
});
List<Map<String, String>> list = findViewIdByXmlName(project, selectText);
StringBuffer fieldSb = new StringBuffer("\n");
for (int i = 0; i < list.size(); i++) {
Map<String, String> map = list.get(i);
String id = map.get("id");
String name = map.get("name");
fieldSb.append(" @ViewInject(R.id." + id + ")");
fieldSb.append("\n");
fieldSb.append(" private " + name + " " + id + ";");
fieldSb.append("\n");
}
StringBuffer sbTop = new StringBuffer();
for (int i = 0; i < current.length; i++) {
sbTop.append(current[i] + "\n");
if (current[i].contains("{")) {
break;
}
}
WriteCommandAction.runWriteCommandAction(project, new Runnable() {
@Override
public void run() {
document.insertString(sbTop.length() + packageSb.toString().length(), fieldSb.toString());
}
});
}
@Override
public void update(AnActionEvent e) {
super.update(e);
//Get required data keys
final Project project = e.getProject();
final Editor editor = e.getData(CommonDataKeys.EDITOR);
//Set visibility only in case of existing project and editor and if some text in the editor is selected
e.getPresentation().setEnabled(project != null && editor != null);
}
/**
* 全局搜索xml文件
*
* @param project 项目
* @param xmlName xml名字
* @return
*/
private List<Map<String, String>> findViewIdByXmlName(Project project, String xmlName) {
List<Map<String, String>> idList = new ArrayList<>();
PsiFileSystemItem[] items = FilenameIndex.getFilesByName(project, xmlName + ".xml", GlobalSearchScope.allScope(project), false);
if (items.length == 1) {
XmlFile xmlFile = (XmlFile) PsiManager.getInstance(project).findFile(items[0].getVirtualFile());
XmlTag tag = xmlFile.getRootTag();
findViewByXmlTag(project, tag, idList);
}
return idList;
}
private List<Map<String, String>> findViewByXmlTag(Project project, XmlTag tag, List<Map<String, String>> idList) {
putMap(project, tag, idList);
XmlTag[] xmlTags = tag.getSubTags();
for (int i = 0; i < xmlTags.length; i++) {
XmlTag xmlTag = xmlTags[i];
putMap(project, xmlTag, idList);
XmlTag[] subTags = xmlTag.getSubTags();
if (subTags.length != 0) {
for (int j = 0; j < subTags.length; j++) {
findViewByXmlTag(project, subTags[j], idList);
}
}
}
return idList;
}
private void putMap(Project project, XmlTag xmlTag, List<Map<String, String>> idList) {
if (xmlTag.getAttributeValue("android:id") != null) {
Map<String, String> map = new HashMap<>();
map.put("name", xmlTag.getName());
map.put("id", xmlTag.getAttributeValue("android:id").replace("@+id/", ""));
idList.add(map);
}
if (xmlTag.getName().equals("include") && xmlTag.getAttributeValue("layout") != null) {
String name = xmlTag.getAttributeValue("layout").replace("@layout/", "");
idList.addAll(findViewIdByXmlName(project, name));
}
}
}