Создание IDE для Amdroid на Java. #1
Привет, Хабр!
Вступление
В этой статье я буду рассказывать о создании своей IDE для Android. Я не нашел какого-либо материала на эту тему. Хочу разделить статью на несколько подстатей, так как информации будет много. Также буду оставлять ссылки на весь материал который я использовал.
Статья предназначена для новичков, ну и для тех кто хочет создать свою IDE для мобилки. Мы будем делать IDE для языка программирования Lua, но это не имеет особого значения, так как в проект можно будет добавить любой язык. Я лично буду использовать библиотеку Luaj, это очень удоьный и простой в использовании интерпритатор для Lua написаный на Java.
Также нам понадобятся библиотеки MaterialDesign и AndroidX, для создания красивого интерфейса, ну они часто уже есть в проектах по умолчанию, А также SoraEditor для создания удобного редактора с оптимизированой подсветкой синтаксиса.
GitHub — luaj/luaj: Lightweight, fast, Java-centric Lua interpreter written for JME and JSE, with string, table, package, math, io, os, debug, coroutine & luajava libraries, JSR-223 bindings, all metatags, weak tables and unique direct lua-to-java-bytecode compiling.
github.comGitHub — Rosemoe/sora-editor: A multifunctional Android code editor library. (aka CodeEditor)
github.comПодготовка
Для начало подключим все нужные библиотеки. Заходим в файл app/build.gradle, и добавляем нужные зависимости:
dependencies {
implementation("com.google.android.material:material:1.9.0")
implementation("androidx.appcompat:appcompat:1.6.1")
// sora editor API
implementation(platform("io.github.Rosemoe.sora-editor:bom:0.23.2"))
implementation 'io.github.Rosemoe.sora-editor:editor'
implementation 'io.github.Rosemoe.sora-editor:language-textmate'
}
Пока-что зависимости SoraEditor нам не понадобятся, его мы будем использовать при создании самого редактора.
Также нужно поменять версию Java минимум на 17 для работы SoraEditor. В файле app/build.gradle:
android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
...
}
Также, я отключу viewbinding, так как мне не нравится его использовать, но если вам он нравится, можете оставить.
Создадим класс App он будет наследоваться от Application, он будет хранить различные константы и общие данны, такие как путь к папке с проектами.
Мы будем хранить проекты во внутреннем хранилище, которое будт доступно всем приложениям. Конечно можно хранить и во внешнем, но не виду смысла заморачиваться на этот счет, я всеровно сделаю экспорт проекта в формате ZIP архива.
Пример класса App:
public class App extends Application {
private static Context context;
public static Context getContext() {
return context;
}
public static File getProjectsDir() {
File dir = new File(context.getExternalFilesDir(null), "projects/");
if(!dir.exists()) dir.mkdirs();
return dir;
}
}
Далее в манифесте, в
...
Создание меню проектов
Создани активность если вы ее еще не создали, я назову свою ProjectsActivity, и она будет находится в пакете .activitys для большего удобства, там будут находится все активности приложения.
В разметке это активности, мы должны добавить 2 view, это Toolbar и RecyclerView.
Toolbar — это верхняя панель в приложении, которая является более гибкой версией ActionBar и AppBar, так мы может расположить ее в любом месте, но я уже по привычке его использую, вы можете использовать свой Toolbar.
RecyclerView — это улучшеная версия ListView, которая дополнительна оптимизирована для большого массива данных, так как использует минимальное кол-во элементов которые можно показать на экране, его рекомендуется использовать.
Вот пример разметки:
Я храню все цвета в файле colors.xml, чтоб можно было поменять в любой момент нет бегая по файлам, в также чтобы удобно было делать что-то для другой темы, тоже самое с strings.xml, но для языков. Я это написал потому-что многие не соблюдают эти обычаи.
Далее, нужно создать адаптер, а также сам элемент проекта в layout/.
Я создам дирректорию project, там будут все с этим связаные файле. Там создадим класс Project, для удобного использования, там будет хранится название проекта и путь к нему. Пример кода:
public class Project {
private String name;
private File path;
public Project(File path) {
this.path = path;
this.name = path.getName();
}
public Project(String name) {
this.name = name;
this.path = new File(App.getProjectsDir(), name);
}
public boolean create() {
File main = new File(path, "main.lua");
try {
main.createNewFile();
} catch(IOException e) {
e.printStackTrace();
return false;
}
return path.mkdirs();
}
// Другие методы...
}
Далее создаем адаптер. Создадим класс ProjectsAdapter, и наследуем RecyclerView.Adapter
В адаптере нужно переопределить несколько методов, это onCreateViewHolder (ViewGroup, int), onBindViewHolder (VH, int) и getItemCount ().
onCreateViewHolder — в нес воздается поверхность (ViewHolder).
onBindViewHolder — тут обычно идет остальная настрока каждого элемента списка.
getItemCount — возвращает размер списка с элементам.
Пример адаптера
public class ProjectsAdapter extends RecyclerView.Adapter {
public class VH extends RecyclerView.ViewHolder {
private View parent;
public VH(View parent) {
super(parent);
this.parent = parent;
name = parent.findViewById(R.id.name);
more = parent.findViewById(R.id.more);
}
private TextView name;
private ImageView more;
}
private List list;
private Context context;
public ProjectsAdapter(Context context, List list) {
this.context = context;
this.list = list;
}
@Override
public VH onCreateViewHolder(ViewGroup parent, int pos) {
View view = LayoutInflater.from(context).inflate(R.layout.project_item, parent, false);
return new VH(view);
}
@Override
public void onBindViewHolder(VH vh, int pos) {
vh.name = list.get(pos).getName();
}
@Override
public int getItemCount() {
return list.size();
}
public void updateList(List list) {
this.list = list;
notifyDataSetChanged(); // говорим адаптеру что весь список изменился
}
}
В App я добавлю метод getProjects () который будет возвращать List
public static List getProjects() {
List projects = new ArrayList<>();
for(File file : getProjectsDir().listFiles()) {
if(file.isDirectory()) projects.add(file);
}
return projects;
}
В ProjectsActivity в методе onCreate, мы создать адаптер, и применить его к RecyclerVie
Пример
ProjectsAdapter adapter;
RecyclerView rv
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
rv = findViewById(R.id.projects);
adapter = new ProjectsAdapter(this, App.getProjects());
rv.setLayoutManager(new LinearLayoutManager(this));
rv.setAdapter(adapter);
}
public void updateProjects() {
adapter.updateList(App.getProjects());
}
Функциональность кнопке more, а также создание проектов мы сделаем в следующей статье. Если будут вопросы можете задать их в комментариях.
Пока, Хабр! :-)