Feature: Full Screen Mode
This commit is contained in:
@ -8,7 +8,6 @@
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
|
||||
<application
|
||||
android:name=".NeoApp"
|
||||
android:allowBackup="true"
|
||||
android:extractNativeLibs="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
|
@ -1,21 +0,0 @@
|
||||
package io.neoterm;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
|
||||
public class NeoApp extends Application {
|
||||
private static NeoApp app;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
app = this;
|
||||
}
|
||||
|
||||
public static NeoApp get() {
|
||||
return app;
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
package io.neoterm.customize.font
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Typeface
|
||||
import io.neoterm.NeoApp
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
@ -9,10 +9,11 @@ import io.neoterm.NeoApp
|
||||
object FontManager {
|
||||
private var DEFAULT_FONT: Typeface? = null
|
||||
|
||||
fun init(context: Context) {
|
||||
DEFAULT_FONT = Typeface.createFromAsset(context.assets, "font.ttf")
|
||||
}
|
||||
|
||||
fun getDefaultFont(): Typeface {
|
||||
if (DEFAULT_FONT == null) {
|
||||
DEFAULT_FONT = Typeface.createFromAsset(NeoApp.get().assets, "font.ttf")
|
||||
}
|
||||
return DEFAULT_FONT!!
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import android.content.*
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Bundle
|
||||
import android.os.IBinder
|
||||
import android.preference.PreferenceManager
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v4.view.OnApplyWindowInsetsListener
|
||||
import android.support.v4.view.ViewCompat
|
||||
@ -15,10 +16,11 @@ import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.ImageButton
|
||||
import android.widget.Toast
|
||||
import de.mrapp.android.tabswitcher.*
|
||||
import de.mrapp.android.tabswitcher.view.TabSwitcherButton
|
||||
import io.neoterm.R
|
||||
import io.neoterm.backend.TerminalSession
|
||||
import io.neoterm.customize.font.FontManager
|
||||
import io.neoterm.customize.shortcut.ShortcutConfigLoader
|
||||
import io.neoterm.customize.shortcut.builtin.BuiltinShortcutKeys
|
||||
import io.neoterm.installer.BaseFileInstaller
|
||||
@ -26,63 +28,24 @@ import io.neoterm.preference.NeoPermission
|
||||
import io.neoterm.preference.NeoTermPreference
|
||||
import io.neoterm.services.NeoTermService
|
||||
import io.neoterm.ui.settings.SettingActivity
|
||||
import io.neoterm.utils.NeoTermFullScreen
|
||||
import io.neoterm.view.tab.*
|
||||
import android.content.Intent
|
||||
|
||||
|
||||
class NeoTermActivity : AppCompatActivity(), ServiceConnection {
|
||||
|
||||
|
||||
class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
lateinit var tabSwitcher: TabSwitcher
|
||||
var systemShell = true
|
||||
var termService: NeoTermService? = null
|
||||
|
||||
override fun onServiceDisconnected(name: ComponentName?) {
|
||||
if (termService != null) {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
|
||||
termService = (service as NeoTermService.NeoTermBinder).service
|
||||
if (termService == null) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
|
||||
var resultListener: BaseFileInstaller.ResultListener? = null
|
||||
resultListener = BaseFileInstaller.ResultListener { error ->
|
||||
if (error == null) {
|
||||
initShortcutKeys()
|
||||
systemShell = false
|
||||
if (!termService!!.sessions.isEmpty()) {
|
||||
for (session in termService!!.sessions) {
|
||||
addNewSession(session)
|
||||
}
|
||||
switchToSession(getStoredCurrentSessionOrLast())
|
||||
} else {
|
||||
tabSwitcher.showSwitcher()
|
||||
addNewSession("NeoTerm #0", systemShell, createRevealAnimation())
|
||||
}
|
||||
} else {
|
||||
AlertDialog.Builder(this@NeoTermActivity)
|
||||
.setTitle("Error")
|
||||
.setMessage(error.toString())
|
||||
.setNegativeButton("System Shell", { _, _ ->
|
||||
tabSwitcher.showSwitcher()
|
||||
addNewSession("NeoTerm #0", systemShell, createRevealAnimation())
|
||||
})
|
||||
.setPositiveButton("Retry", { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
BaseFileInstaller.installBaseFiles(this@NeoTermActivity, resultListener)
|
||||
}).show()
|
||||
}
|
||||
}
|
||||
|
||||
BaseFileInstaller.installBaseFiles(this, resultListener)
|
||||
}
|
||||
var restartRequired = false
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
NeoPermission.initAppPermission(this, NeoPermission.REQUEST_APP_PERMISSION)
|
||||
FontManager.init(this)
|
||||
NeoTermPreference.init(this)
|
||||
|
||||
if (NeoTermPreference.loadBoolean(R.string.key_ui_fullscreen, false)) {
|
||||
@ -92,6 +55,17 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection {
|
||||
|
||||
setContentView(R.layout.tab_main)
|
||||
|
||||
val fullScreenHelper = NeoTermFullScreen.injectActivity(this)
|
||||
fullScreenHelper.setKeyBoardListener({ isShow, _ ->
|
||||
if (NeoTermPreference.loadBoolean(R.string.key_ui_fullscreen, false)
|
||||
|| NeoTermPreference.loadBoolean(R.string.key_ui_hide_toolbar, false)) {
|
||||
if (tabSwitcher.selectedTab is TermTab) {
|
||||
val tab = tabSwitcher.selectedTab as TermTab
|
||||
tab.toolbar?.visibility = if (isShow) View.GONE else View.VISIBLE
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
tabSwitcher = findViewById(R.id.tab_switcher) as TabSwitcher
|
||||
tabSwitcher.decorator = TermTabDecorator(this)
|
||||
ViewCompat.setOnApplyWindowInsetsListener(tabSwitcher, createWindowInsetsListener())
|
||||
@ -114,6 +88,13 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection {
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (restartRequired) {
|
||||
restartRequired = false
|
||||
this.recreate()
|
||||
}
|
||||
|
||||
PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.registerOnSharedPreferenceChangeListener(this)
|
||||
tabSwitcher.addListener(object : TabSwitcherListener {
|
||||
private var tabSwitcherButtonInit = false
|
||||
|
||||
@ -162,6 +143,8 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection {
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.unregisterOnSharedPreferenceChangeListener(this)
|
||||
if (termService != null) {
|
||||
if (termService!!.sessions.isEmpty()) {
|
||||
termService!!.stopSelf()
|
||||
@ -189,7 +172,7 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection {
|
||||
NeoPermission.REQUEST_APP_PERMISSION -> {
|
||||
if (grantResults.isEmpty()
|
||||
|| grantResults[0] != PackageManager.PERMISSION_GRANTED) {
|
||||
AlertDialog.Builder(this).setMessage("应用无法取得必须的权限,正在退出")
|
||||
AlertDialog.Builder(this).setMessage(R.string.permission_denied)
|
||||
.setPositiveButton(android.R.string.ok, { _: DialogInterface, _: Int ->
|
||||
finish()
|
||||
})
|
||||
@ -200,6 +183,58 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onServiceDisconnected(name: ComponentName?) {
|
||||
if (termService != null) {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
|
||||
termService = (service as NeoTermService.NeoTermBinder).service
|
||||
if (termService == null) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
|
||||
var resultListener: BaseFileInstaller.ResultListener? = null
|
||||
resultListener = BaseFileInstaller.ResultListener { error ->
|
||||
if (error == null) {
|
||||
initShortcutKeys()
|
||||
systemShell = false
|
||||
if (!termService!!.sessions.isEmpty()) {
|
||||
for (session in termService!!.sessions) {
|
||||
addNewSession(session)
|
||||
}
|
||||
switchToSession(getStoredCurrentSessionOrLast())
|
||||
} else {
|
||||
tabSwitcher.showSwitcher()
|
||||
addNewSession("NeoTerm #0", systemShell, createRevealAnimation())
|
||||
}
|
||||
} else {
|
||||
AlertDialog.Builder(this@NeoTermActivity)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(error.toString())
|
||||
.setNegativeButton(R.string.use_system_shell, { _, _ ->
|
||||
tabSwitcher.showSwitcher()
|
||||
addNewSession("NeoTerm #0", systemShell, createRevealAnimation())
|
||||
})
|
||||
.setPositiveButton(R.string.retry, { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
BaseFileInstaller.installBaseFiles(this@NeoTermActivity, resultListener)
|
||||
}).show()
|
||||
}
|
||||
}
|
||||
|
||||
BaseFileInstaller.installBaseFiles(this, resultListener)
|
||||
}
|
||||
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||
if (key == getString(R.string.key_ui_fullscreen)) {
|
||||
Toast.makeText(this, R.string.fullscreen_mode_changed, Toast.LENGTH_SHORT).show()
|
||||
restartRequired = true
|
||||
}
|
||||
}
|
||||
|
||||
private fun addNewSession(session: TerminalSession?) {
|
||||
if (session == null) {
|
||||
return
|
||||
|
112
app/src/main/java/io/neoterm/utils/NeoTermFullScreen.java
Normal file
112
app/src/main/java/io/neoterm/utils/NeoTermFullScreen.java
Normal file
@ -0,0 +1,112 @@
|
||||
package io.neoterm.utils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
/**
|
||||
* Helper class to "adjustResize" Activity when we are in full screen mode and check IME status.
|
||||
* Android Bug 5497: https://code.google.com/p/android/issues/detail?id=5497
|
||||
* author @kiva
|
||||
*/
|
||||
public class NeoTermFullScreen {
|
||||
public static NeoTermFullScreen injectActivity(Activity activity) {
|
||||
return new NeoTermFullScreen(activity);
|
||||
}
|
||||
|
||||
public interface KeyBoardListener {
|
||||
/**
|
||||
* call back
|
||||
*
|
||||
* @param isShow true is show else hidden
|
||||
* @param keyboardHeight keyboard height
|
||||
*/
|
||||
void onKeyboardChange(boolean isShow, int keyboardHeight);
|
||||
}
|
||||
|
||||
private View mChildOfContent;
|
||||
private int usableHeightPrevious;
|
||||
private FrameLayout.LayoutParams frameLayoutParams;
|
||||
|
||||
private int mOriginHeight;
|
||||
private int mPreHeight;
|
||||
private KeyBoardListener mKeyBoardListener;
|
||||
|
||||
public void setKeyBoardListener(KeyBoardListener mKeyBoardListener) {
|
||||
this.mKeyBoardListener = mKeyBoardListener;
|
||||
}
|
||||
|
||||
private NeoTermFullScreen(Activity activity) {
|
||||
FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
|
||||
mChildOfContent = content.getChildAt(0);
|
||||
mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
public void onGlobalLayout() {
|
||||
possiblyResizeChildOfContent();
|
||||
monitorImeStatus();
|
||||
}
|
||||
});
|
||||
frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
|
||||
}
|
||||
|
||||
private void monitorImeStatus() {
|
||||
int currHeight = mChildOfContent.getHeight();
|
||||
if (currHeight == 0) {
|
||||
// First time
|
||||
return;
|
||||
}
|
||||
boolean hasChange = false;
|
||||
if (mPreHeight == 0) {
|
||||
mPreHeight = currHeight;
|
||||
mOriginHeight = currHeight;
|
||||
} else {
|
||||
if (mPreHeight != currHeight) {
|
||||
hasChange = true;
|
||||
mPreHeight = currHeight;
|
||||
} else {
|
||||
hasChange = false;
|
||||
}
|
||||
}
|
||||
if (hasChange) {
|
||||
boolean isShow;
|
||||
int keyboardHeight = 0;
|
||||
if (Math.abs(mOriginHeight - currHeight) < 100) {
|
||||
//hidden
|
||||
isShow = false;
|
||||
} else {
|
||||
//show
|
||||
keyboardHeight = mOriginHeight - currHeight;
|
||||
isShow = true;
|
||||
}
|
||||
|
||||
if (mKeyBoardListener != null) {
|
||||
mKeyBoardListener.onKeyboardChange(isShow, keyboardHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void possiblyResizeChildOfContent() {
|
||||
int usableHeightNow = computeUsableHeight();
|
||||
if (usableHeightNow != usableHeightPrevious) {
|
||||
int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
|
||||
int heightDifference = usableHeightSansKeyboard - usableHeightNow;
|
||||
if (heightDifference > (usableHeightSansKeyboard/4)) {
|
||||
// keyboard probably just became visible
|
||||
frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
|
||||
} else {
|
||||
// keyboard probably just became hidden
|
||||
frameLayoutParams.height = usableHeightSansKeyboard;
|
||||
}
|
||||
mChildOfContent.requestLayout();
|
||||
usableHeightPrevious = usableHeightNow;
|
||||
}
|
||||
}
|
||||
|
||||
private int computeUsableHeight() {
|
||||
Rect r = new Rect();
|
||||
mChildOfContent.getWindowVisibleDisplayFrame(r);
|
||||
return (r.bottom - r.top);
|
||||
}
|
||||
|
||||
}
|
@ -36,7 +36,6 @@ class TermTabDecorator(val context: NeoTermActivity) : TabSwitcherDecorator() {
|
||||
}
|
||||
context.tabSwitcher.showSwitcher()
|
||||
})
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,8 @@
|
||||
<string name="pref_ui_color_scheme">配色方案</string>
|
||||
<string name="pref_ui_font">字体</string>
|
||||
<string name="pref_ui_fullscreen">全屏</string>
|
||||
<string name="pref_ui_hide_toolbar">隐藏标题栏</string>
|
||||
<string name="pref_ui_hide_toolbar_desc">键盘显示时隐藏标题栏</string>
|
||||
<string name="pref_ui_suggestions">显示建议 (需要 oh-my-zsh)</string>
|
||||
<string name="pref_ui_suggestions_desc">使用一些软件时,屏幕下方显示快捷键</string>
|
||||
<string name="pref_ui_wide_char_weight_explicit">为宽字符设置权重</string>
|
||||
@ -31,4 +33,9 @@
|
||||
<string name="ui_settings">界面设置</string>
|
||||
<string name="shell_not_found">Shell %s 未找到, 请先安装.</string>
|
||||
<string name="installer_message">正在安装</string>
|
||||
<string name="fullscreen_mode_changed">全屏模式已改变,请重启 NeoTerm</string>
|
||||
<string name="permission_denied">NeoTerm 无法取得必需的权限,正在退出</string>
|
||||
<string name="error">还有这种操作?</string>
|
||||
<string name="use_system_shell">使用系统Shell</string>
|
||||
<string name="retry">重试</string>
|
||||
</resources>
|
@ -6,6 +6,7 @@
|
||||
<string name="key_general_shell" translatable="false">neoterm_general_shell</string>
|
||||
|
||||
<string name="key_ui_fullscreen" translatable="false">neoterm_ui_fullscreen</string>
|
||||
<string name="key_ui_hide_toolbar" translatable="false">neoterm_ui_hide_toolbar</string>
|
||||
<string name="key_ui_font" translatable="false">neoterm_ui_font</string>
|
||||
<string name="key_ui_color_scheme" translatable="false">neoterm_ui_color_scheme</string>
|
||||
<string name="key_ui_next_tab_anim" translatable="false">neoterm_ui_next_tab_anim</string>
|
||||
|
@ -24,6 +24,8 @@
|
||||
<string name="pref_general_shell" translatable="false">Shell</string>
|
||||
<string name="pref_general_shell_desc">Which shell should we use when login</string>
|
||||
<string name="pref_ui_fullscreen">Full Screen</string>
|
||||
<string name="pref_ui_hide_toolbar">Hide Toolbar</string>
|
||||
<string name="pref_ui_hide_toolbar_desc">Hide toolbar when keyboard is showing</string>
|
||||
<string name="pref_ui_font">Font</string>
|
||||
<string name="pref_ui_color_scheme">Color Scheme</string>
|
||||
<string name="pref_ui_close_tab_anim_next_tab">Next tab animation</string>
|
||||
@ -35,6 +37,11 @@
|
||||
<string name="pref_package_source">Source</string>
|
||||
<string name="toggle_ime">Toggle IME</string>
|
||||
<string name="shell_not_found">Shell %s not found, please install it first.</string>
|
||||
<string name="fullscreen_mode_changed">FullScreen mode changed, please restart NeoTerm.</string>
|
||||
<string name="permission_denied">NeoTerm cannot get essential permissions, exiting.</string>
|
||||
<string name="error">Error</string>
|
||||
<string name="use_system_shell">System Shell</string>
|
||||
<string name="retry">Retry</string>
|
||||
|
||||
<string-array name="pref_ui_color_scheme_entries" translatable="false">
|
||||
<item>Default</item>
|
||||
|
@ -6,6 +6,12 @@
|
||||
android:key="@string/key_ui_fullscreen"
|
||||
android:title="@string/pref_ui_fullscreen" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="@string/key_ui_hide_toolbar"
|
||||
android:summary="@string/pref_ui_hide_toolbar_desc"
|
||||
android:title="@string/pref_ui_hide_toolbar" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="@string/key_ui_next_tab_anim"
|
||||
|
@ -52,6 +52,7 @@ import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import de.mrapp.android.tabswitcher.layout.AbstractTabSwitcherLayout;
|
||||
import de.mrapp.android.tabswitcher.layout.AbstractTabSwitcherLayout.LayoutListenerWrapper;
|
||||
@ -207,7 +208,8 @@ public class TabSwitcher extends FrameLayout implements TabSwitcherLayout, Model
|
||||
@AttrRes final int defaultStyle,
|
||||
@StyleRes final int defaultStyleResource) {
|
||||
pendingActions = new LinkedList<>();
|
||||
listeners = new LinkedHashSet<>();
|
||||
// listeners = new LinkedHashSet<>();
|
||||
listeners = new CopyOnWriteArraySet<>(new LinkedHashSet<TabSwitcherListener>());
|
||||
model = new TabSwitcherModel(this);
|
||||
model.addListener(createModelListener());
|
||||
getViewTreeObserver().addOnGlobalLayoutListener(
|
||||
|
Reference in New Issue
Block a user