...
This commit is contained in:
parent
16640559b3
commit
9f6c424e04
@ -155,6 +155,7 @@ dependencies {
|
|||||||
// implementation 'com.vladsch.flexmark:flexmark-all:0.64.8'
|
// implementation 'com.vladsch.flexmark:flexmark-all:0.64.8'
|
||||||
// implementation("org.opencv:opencv-android:4.11.0")
|
// implementation("org.opencv:opencv-android:4.11.0")
|
||||||
// build.gradle에 추가
|
// build.gradle에 추가
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
|
||||||
// implementation ("com.github.aeonSolutions:FloatingActionButtonMenuDrag:1.1")
|
// implementation ("com.github.aeonSolutions:FloatingActionButtonMenuDrag:1.1")
|
||||||
implementation("io.github.junkfood02.youtubedl-android:library:0.17.4")
|
implementation("io.github.junkfood02.youtubedl-android:library:0.17.4")
|
||||||
implementation("io.github.junkfood02.youtubedl-android:ffmpeg:0.17.4")
|
implementation("io.github.junkfood02.youtubedl-android:ffmpeg:0.17.4")
|
||||||
|
|||||||
@ -91,8 +91,6 @@
|
|||||||
android:screenOrientation="userPortrait"
|
android:screenOrientation="userPortrait"
|
||||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|screenLayout|layoutDirection|navigation"
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|screenLayout|layoutDirection|navigation"
|
||||||
android:windowSoftInputMode="adjustResize"
|
android:windowSoftInputMode="adjustResize"
|
||||||
android:noHistory="true"
|
|
||||||
android:excludeFromRecents="true"
|
|
||||||
android:exported="false">
|
android:exported="false">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|||||||
@ -291,7 +291,9 @@ class AppDrawerBottomSheet : BottomSheetDialogFragment() {
|
|||||||
if (item.type == "APP") {
|
if (item.type == "APP") {
|
||||||
val app = realm.query<AppInfo>("pkgName == $0", item.key).first().find()
|
val app = realm.query<AppInfo>("pkgName == $0", item.key).first().find()
|
||||||
if (app != null && !app.blockRecommend) {
|
if (app != null && !app.blockRecommend) {
|
||||||
unifiedList.add(RecommendationItem.AppItem(realm.copyFromRealm(app)))
|
try { if(pm.getLaunchIntentForPackage(app.pkgName ?: "") != null) {
|
||||||
|
unifiedList.add(RecommendationItem.AppItem(realm.copyFromRealm(app)))
|
||||||
|
}} catch (e: Exception) { }
|
||||||
}
|
}
|
||||||
} else if (item.type == "CONTACT") {
|
} else if (item.type == "CONTACT") {
|
||||||
// 연락처 ID나 전화번호로 조회 (Log 저장 시 key가 무엇인지에 따라 다름)
|
// 연락처 ID나 전화번호로 조회 (Log 저장 시 key가 무엇인지에 따라 다름)
|
||||||
|
|||||||
@ -82,6 +82,40 @@ open class GeckoWeb @JvmOverloads constructor(
|
|||||||
|
|
||||||
// --- 1. Properties & Initialization ---
|
// --- 1. Properties & Initialization ---
|
||||||
|
|
||||||
|
// 1. 세션 상태를 저장할 SharedPreferences 키
|
||||||
|
private val PREF_SESSION_STATE = "gecko_session_state"
|
||||||
|
|
||||||
|
// 2. 현재 세션 상태 저장 메서드
|
||||||
|
fun saveCurrentSessionState() {
|
||||||
|
|
||||||
|
lastSessionState?.let { state ->
|
||||||
|
// SessionState.toString()은 내부적으로 JSON 문자열을 반환합니다.
|
||||||
|
val stateJson = state.toString()
|
||||||
|
|
||||||
|
context.getSharedPreferences("GeckoPrefs", Context.MODE_PRIVATE)
|
||||||
|
.edit()
|
||||||
|
.putString("gecko_session_state", stateJson)
|
||||||
|
.apply()
|
||||||
|
|
||||||
|
Log.d("GeckoWeb", "Session State Saved: $stateJson")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 저장된 세션 상태 복구 메서드
|
||||||
|
fun restoreSessionState(session: GeckoSession) {
|
||||||
|
val stateJson = context.getSharedPreferences("GeckoPrefs", Context.MODE_PRIVATE)
|
||||||
|
.getString("gecko_session_state", null)
|
||||||
|
|
||||||
|
if (!stateJson.isNullOrEmpty()) {
|
||||||
|
// 문자열에서 SessionState 객체 생성
|
||||||
|
val state = GeckoSession.SessionState.fromString(stateJson)
|
||||||
|
if (state != null) {
|
||||||
|
session.restoreState(state)
|
||||||
|
Log.d("GeckoWeb", "Session State Restored")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// UI & State
|
// UI & State
|
||||||
var decoViews = arrayListOf<View>()
|
var decoViews = arrayListOf<View>()
|
||||||
var progress: ProgressBar? = null
|
var progress: ProgressBar? = null
|
||||||
@ -138,8 +172,8 @@ open class GeckoWeb @JvmOverloads constructor(
|
|||||||
override fun onLongPress(targetView: View, fingers: Int) = true
|
override fun onLongPress(targetView: View, fingers: Int) = true
|
||||||
})
|
})
|
||||||
|
|
||||||
class GKCookie { var COOKIES: String? = null }
|
// class GKCookie { var COOKIES: String? = null }
|
||||||
var mGKCookie: GKCookie? = null
|
// var mGKCookie: GKCookie? = null
|
||||||
|
|
||||||
// Markdown/Scraping
|
// Markdown/Scraping
|
||||||
var markdownContents: String? = null
|
var markdownContents: String? = null
|
||||||
@ -192,23 +226,23 @@ open class GeckoWeb @JvmOverloads constructor(
|
|||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
try {
|
try {
|
||||||
val request = YoutubeDLRequest(url)
|
val request = YoutubeDLRequest(url)
|
||||||
mGKCookie?.COOKIES?.let { cookieStr ->
|
// mGKCookie?.COOKIES?.let { cookieStr ->
|
||||||
val cookieFile = File(context.filesDir, "cookies.txt")
|
// val cookieFile = File(context.filesDir, "cookies.txt")
|
||||||
val cookies = cookieStr.split(";").mapNotNull {
|
// val cookies = cookieStr.split(";").mapNotNull {
|
||||||
val p = it.trim().split("=", limit = 2)
|
// val p = it.trim().split("=", limit = 2)
|
||||||
if (p.size == 2) p[0] to p[1] else null
|
// if (p.size == 2) p[0] to p[1] else null
|
||||||
}.toMap()
|
// }.toMap()
|
||||||
val expires = (System.currentTimeMillis() / 1000) + 3600 * 24 * 7
|
// val expires = (System.currentTimeMillis() / 1000) + 3600 * 24 * 7
|
||||||
|
//
|
||||||
val content = buildString {
|
// val content = buildString {
|
||||||
appendLine("# Netscape HTTP Cookie File")
|
// appendLine("# Netscape HTTP Cookie File")
|
||||||
cookies.forEach { (k, v) ->
|
// cookies.forEach { (k, v) ->
|
||||||
appendLine(".${url.toUri().host}\tTRUE\t/\tTRUE\t$expires\t$k\t$v")
|
// appendLine(".${url.toUri().host}\tTRUE\t/\tTRUE\t$expires\t$k\t$v")
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
cookieFile.writeText(content)
|
// cookieFile.writeText(content)
|
||||||
request.addOption("--cookies", cookieFile.absolutePath)
|
// request.addOption("--cookies", cookieFile.absolutePath)
|
||||||
}
|
// }
|
||||||
|
|
||||||
val videoInfo = YoutubeDL.getInstance().getInfo(request)
|
val videoInfo = YoutubeDL.getInstance().getInfo(request)
|
||||||
if (videoInfo != null && !videoInfo.title.isNullOrEmpty()) {
|
if (videoInfo != null && !videoInfo.title.isNullOrEmpty()) {
|
||||||
@ -321,12 +355,14 @@ open class GeckoWeb @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
override fun onPageStop(session: GeckoSession, success: Boolean) {
|
||||||
onPageStopCallback?.invoke(success)
|
onPageStopCallback?.invoke(success)
|
||||||
|
saveCurrentSessionState()
|
||||||
}
|
}
|
||||||
override fun onSessionStateChange(session: GeckoSession, sessionState: GeckoSession.SessionState) {
|
override fun onSessionStateChange(session: GeckoSession, sessionState: GeckoSession.SessionState) {
|
||||||
|
|
||||||
onSessionStateChangeCallback?.invoke(sessionState)
|
onSessionStateChangeCallback?.invoke(sessionState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private var lastSessionState: GeckoSession.SessionState? = null
|
||||||
// [Extension Delegates]
|
// [Extension Delegates]
|
||||||
private val addonManagerDelegate = object : AddonManagerDelegate {
|
private val addonManagerDelegate = object : AddonManagerDelegate {
|
||||||
override fun onReady(extension: WebExtension) { mExtension = extension }
|
override fun onReady(extension: WebExtension) { mExtension = extension }
|
||||||
@ -386,6 +422,7 @@ open class GeckoWeb @JvmOverloads constructor(
|
|||||||
private fun buildWeb() {
|
private fun buildWeb() {
|
||||||
getRuntime()?.let { runtime ->
|
getRuntime()?.let { runtime ->
|
||||||
val session = GeckoSession()
|
val session = GeckoSession()
|
||||||
|
restoreSessionState(session)
|
||||||
session.open(runtime)
|
session.open(runtime)
|
||||||
this.setSession(session)
|
this.setSession(session)
|
||||||
|
|
||||||
|
|||||||
@ -41,12 +41,7 @@ import bums.lunatic.launcher.home.adapters.BookmarkPagerFragment
|
|||||||
import bums.lunatic.launcher.model.RssData
|
import bums.lunatic.launcher.model.RssData
|
||||||
import bums.lunatic.launcher.model.RssDataType
|
import bums.lunatic.launcher.model.RssDataType
|
||||||
import bums.lunatic.launcher.settings.SettingsActivity
|
import bums.lunatic.launcher.settings.SettingsActivity
|
||||||
import bums.lunatic.launcher.home.tokiz.Comics
|
|
||||||
import bums.lunatic.launcher.home.tokiz.Novels
|
|
||||||
import bums.lunatic.launcher.home.tokiz.Perplexity
|
|
||||||
import bums.lunatic.launcher.home.tokiz.TokiFragment
|
import bums.lunatic.launcher.home.tokiz.TokiFragment
|
||||||
import bums.lunatic.launcher.home.tokiz.Webtoons
|
|
||||||
import bums.lunatic.launcher.home.tokiz.YouTube
|
|
||||||
import bums.lunatic.launcher.utils.Blog
|
import bums.lunatic.launcher.utils.Blog
|
||||||
import bums.lunatic.launcher.utils.beforeDay
|
import bums.lunatic.launcher.utils.beforeDay
|
||||||
import bums.lunatic.launcher.workers.WorkersDb
|
import bums.lunatic.launcher.workers.WorkersDb
|
||||||
@ -63,6 +58,7 @@ import org.mozilla.geckoview.ExperimentDelegate
|
|||||||
import org.mozilla.geckoview.GeckoResult
|
import org.mozilla.geckoview.GeckoResult
|
||||||
import org.mozilla.geckoview.GeckoRuntime
|
import org.mozilla.geckoview.GeckoRuntime
|
||||||
import org.mozilla.geckoview.GeckoRuntimeSettings
|
import org.mozilla.geckoview.GeckoRuntimeSettings
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
open class NeoRssActivity : CommonActivity() {
|
open class NeoRssActivity : CommonActivity() {
|
||||||
@ -116,7 +112,7 @@ open class NeoRssActivity : CommonActivity() {
|
|||||||
var onExit = false
|
var onExit = false
|
||||||
var lastAction = MotionEvent.ACTION_HOVER_EXIT
|
var lastAction = MotionEvent.ACTION_HOVER_EXIT
|
||||||
override fun dispatchKeyEvent(ev: KeyEvent): Boolean {
|
override fun dispatchKeyEvent(ev: KeyEvent): Boolean {
|
||||||
val currentFragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
|
Blog.LOGE("dispatchKeyEvent >>> ${ev}")
|
||||||
if (ev?.device?.name?.contains("SM-031N Mouse") == true) {
|
if (ev?.device?.name?.contains("SM-031N Mouse") == true) {
|
||||||
when(ev.action) {
|
when(ev.action) {
|
||||||
ACTION_UP -> {
|
ACTION_UP -> {
|
||||||
@ -162,36 +158,35 @@ open class NeoRssActivity : CommonActivity() {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val currentFragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
|
val currentFragment = supportFragmentManager.findFragmentById(R.id.fragment_container)
|
||||||
when(currentFragment) {
|
Blog.LOGE("currentFragment >>> ${currentFragment} ${currentFragment is TokiFragment && currentFragment.isbooktoki()}")
|
||||||
is Novels -> {
|
if (currentFragment is TokiFragment && currentFragment.isbooktoki()) {
|
||||||
if(MotionEvent.ACTION_UP.equals(ev?.action ?: MotionEvent.ACTION_CANCEL) == true) {
|
if(MotionEvent.ACTION_UP.equals(ev?.action ?: MotionEvent.ACTION_CANCEL) == true) {
|
||||||
return when (ev.keyCode) {
|
return when (ev.keyCode) {
|
||||||
KeyEvent.KEYCODE_VOLUME_DOWN -> {
|
KeyEvent.KEYCODE_VOLUME_DOWN -> {
|
||||||
if(currentFragment is Novels){ currentFragment.actionNextEvent() }
|
if(currentFragment is TokiFragment){ currentFragment.actionNextEvent() }
|
||||||
true
|
true
|
||||||
}
|
|
||||||
KeyEvent.KEYCODE_VOLUME_UP -> {
|
|
||||||
if(currentFragment is Novels){ currentFragment.actionPrevEvent() }
|
|
||||||
true
|
|
||||||
}
|
|
||||||
else -> false
|
|
||||||
}
|
}
|
||||||
} else {
|
KeyEvent.KEYCODE_VOLUME_UP -> {
|
||||||
return when (ev.keyCode) {
|
if(currentFragment is TokiFragment){ currentFragment.actionPrevEvent() }
|
||||||
KeyEvent.KEYCODE_VOLUME_DOWN -> {
|
true
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyEvent.KEYCODE_VOLUME_UP -> {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> false
|
|
||||||
}
|
}
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return when (ev.keyCode) {
|
||||||
|
KeyEvent.KEYCODE_VOLUME_DOWN -> {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyEvent.KEYCODE_VOLUME_UP -> {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> return super.dispatchKeyEvent(ev)
|
|
||||||
}
|
}
|
||||||
|
else { return super.dispatchKeyEvent(ev) }
|
||||||
}
|
}
|
||||||
return super.dispatchKeyEvent(ev)
|
return super.dispatchKeyEvent(ev)
|
||||||
}
|
}
|
||||||
@ -293,67 +288,6 @@ open class NeoRssActivity : CommonActivity() {
|
|||||||
showContents(v.id)
|
showContents(v.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// override fun onNewIntent(intent: Intent) {
|
|
||||||
// Blog.LOGE("onNewIntent intent >> ${intent}")
|
|
||||||
// if(intent?.action?.equals(Intent.ACTION_SEND) == true &&
|
|
||||||
// intent?.hasExtra(Intent.EXTRA_TEXT) == true) {
|
|
||||||
// intent?.getStringExtra(Intent.EXTRA_TEXT)?.let {
|
|
||||||
// if(it.startsWith("http") == false) {
|
|
||||||
// it.split("http").forEach { string ->
|
|
||||||
// if(string.startsWith("http")) {
|
|
||||||
// try {
|
|
||||||
// string.toUri()?.let { uri ->
|
|
||||||
// Blog.LOGE("onNewIntent string uri.lastPathSegment >>>>> ${uri.host}")
|
|
||||||
// Blog.LOGE("onNewIntent string uri.lastPathSegment >>>>> ${uri.lastPathSegment}")
|
|
||||||
// }
|
|
||||||
// } catch (e: Exception) {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// try {
|
|
||||||
// it.toUri()?.let { uri ->
|
|
||||||
// Blog.LOGE("onNewIntent it uri.lastPathSegment >>>>> ${uri.host}")
|
|
||||||
// Blog.LOGE("onNewIntent it uri.lastPathSegment >>>>> ${uri.lastPathSegment}")
|
|
||||||
// }
|
|
||||||
// } catch (e: Exception) {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else if (intent?.action == Intent.ACTION_WEB_SEARCH) {
|
|
||||||
// openWithIntent(intent)
|
|
||||||
// } else {
|
|
||||||
// Blog.LOGE("onNewIntent intent?.hasExtra >> ${intent?.hasExtra(Intent.EXTRA_STREAM)}")
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// if (intent?.action?.equals(Intent.ACTION_MAIN) == true && intent.categories.contains(
|
|
||||||
// Intent.CATEGORY_HOME
|
|
||||||
// ) && intent.hasExtra("android.intent.extra.EXTRA_START_REASON") && intent.getStringExtra(
|
|
||||||
// "android.intent.extra.EXTRA_START_REASON"
|
|
||||||
// ).equals("startDockOrHome")
|
|
||||||
// ) {
|
|
||||||
//
|
|
||||||
// } else {
|
|
||||||
// intent?.extras?.keySet()?.forEach {
|
|
||||||
// try {
|
|
||||||
// Blog.LOGE(
|
|
||||||
// "onNewIntent :: key >> ${it} :: value >> ${
|
|
||||||
// intent?.extras?.getString(
|
|
||||||
// it
|
|
||||||
// )
|
|
||||||
// }"
|
|
||||||
// )
|
|
||||||
// } catch (e: Exception) {
|
|
||||||
// e.printStackTrace()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// super.onNewIntent(intent)
|
|
||||||
// }
|
|
||||||
|
|
||||||
private fun openWithIntent(intent: Intent){
|
private fun openWithIntent(intent: Intent){
|
||||||
Blog.LOGE("intent >> ${intent}")
|
Blog.LOGE("intent >> ${intent}")
|
||||||
@ -528,7 +462,13 @@ open class NeoRssActivity : CommonActivity() {
|
|||||||
private fun initGeckoRuntime() {
|
private fun initGeckoRuntime() {
|
||||||
if (sRuntime == null) {
|
if (sRuntime == null) {
|
||||||
try {
|
try {
|
||||||
|
val profileDir = File(this.filesDir, "geckoview_profile")
|
||||||
|
if (!profileDir.exists()) profileDir.mkdirs()
|
||||||
|
|
||||||
sRuntime = GeckoRuntime.create(this, GeckoRuntimeSettings.Builder()
|
sRuntime = GeckoRuntime.create(this, GeckoRuntimeSettings.Builder()
|
||||||
|
.configFilePath(profileDir.absolutePath)
|
||||||
|
.aboutConfigEnabled(true)
|
||||||
|
.javaScriptEnabled(true)
|
||||||
.extensionsProcessEnabled(true)
|
.extensionsProcessEnabled(true)
|
||||||
.extensionsWebAPIEnabled(true)
|
.extensionsWebAPIEnabled(true)
|
||||||
.experimentDelegate(experimentDelegate)
|
.experimentDelegate(experimentDelegate)
|
||||||
@ -559,16 +499,9 @@ open class NeoRssActivity : CommonActivity() {
|
|||||||
sRuntime = null
|
sRuntime = null
|
||||||
} catch (e: Exception) { e.printStackTrace() }
|
} catch (e: Exception) { e.printStackTrace() }
|
||||||
|
|
||||||
// appWidgetHost?.stopListening() // 이 줄은 제거하고 onStop으로 이동
|
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onUserLeaveHint() {
|
|
||||||
|
|
||||||
showContents(R.id.close)
|
|
||||||
|
|
||||||
super.onUserLeaveHint()
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O_MR1)
|
@RequiresApi(Build.VERSION_CODES.O_MR1)
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
@ -605,12 +538,12 @@ open class NeoRssActivity : CommonActivity() {
|
|||||||
currentFragment.doNextPage()
|
currentFragment.doNextPage()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is YouTube -> {
|
// is YouTube -> {
|
||||||
currentFragment.back()
|
// currentFragment.back()
|
||||||
}
|
// }
|
||||||
is Novels -> {
|
// is Novels -> {
|
||||||
currentFragment.actionNextEvent(false)
|
// currentFragment.actionNextEvent(false)
|
||||||
}
|
// }
|
||||||
else -> {
|
else -> {
|
||||||
showContents(R.id.close)
|
showContents(R.id.close)
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -33,7 +33,6 @@ import androidx.fragment.app.Fragment
|
|||||||
import bums.lunatic.launcher.R
|
import bums.lunatic.launcher.R
|
||||||
import bums.lunatic.launcher.databinding.BooktokiBinding
|
import bums.lunatic.launcher.databinding.BooktokiBinding
|
||||||
import bums.lunatic.launcher.home.GeckoWeb
|
import bums.lunatic.launcher.home.GeckoWeb
|
||||||
import bums.lunatic.launcher.home.GeckoWeb.GKCookie
|
|
||||||
import bums.lunatic.launcher.home.GeckoWeb.JxEvent
|
import bums.lunatic.launcher.home.GeckoWeb.JxEvent
|
||||||
import bums.lunatic.launcher.home.NeoRssActivity
|
import bums.lunatic.launcher.home.NeoRssActivity
|
||||||
import bums.lunatic.launcher.home.NeoRssActivity.Companion.getRuntime
|
import bums.lunatic.launcher.home.NeoRssActivity.Companion.getRuntime
|
||||||
@ -224,6 +223,9 @@ class TokiFragment : Fragment(), PagedTextViewInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isbooktoki() : Boolean {
|
||||||
|
return webcontentsName.contains("booktoki")
|
||||||
|
}
|
||||||
override fun onSwipeLeft(count: Int) {
|
override fun onSwipeLeft(count: Int) {
|
||||||
if (!enableGestures) return
|
if (!enableGestures) return
|
||||||
Blog.LOGD(log = "onSwipeLeft ${count}")
|
Blog.LOGD(log = "onSwipeLeft ${count}")
|
||||||
@ -1060,7 +1062,7 @@ class TokiFragment : Fragment(), PagedTextViewInterface {
|
|||||||
view.visibility = VISIBLE
|
view.visibility = VISIBLE
|
||||||
binding.menuWeb.visibility = GONE
|
binding.menuWeb.visibility = GONE
|
||||||
}
|
}
|
||||||
view.forceUpdateUI()
|
// view.forceUpdateUI()
|
||||||
lastedUrl?.let {
|
lastedUrl?.let {
|
||||||
Uri.parse(it)?.let { uri ->
|
Uri.parse(it)?.let { uri ->
|
||||||
uri.path?.let {
|
uri.path?.let {
|
||||||
|
|||||||
@ -1,336 +0,0 @@
|
|||||||
//package bums.lunatic.launcher.home.tokiz.view
|
|
||||||
//
|
|
||||||
//import android.annotation.SuppressLint
|
|
||||||
//import android.content.Context
|
|
||||||
//import android.content.Intent
|
|
||||||
//import android.os.Build
|
|
||||||
//import android.util.AttributeSet
|
|
||||||
//import android.view.MotionEvent
|
|
||||||
//import android.view.PointerIcon
|
|
||||||
//import android.view.View
|
|
||||||
//import androidx.core.net.toUri
|
|
||||||
//import androidx.core.view.isVisible
|
|
||||||
//import bums.lunatic.launcher.R
|
|
||||||
//import bums.lunatic.launcher.helpers.ForeGroundService
|
|
||||||
//import bums.lunatic.launcher.helpers.ForeGroundService.Companion.ACTION_VIDEO_DOWNLOAD
|
|
||||||
//import bums.lunatic.launcher.helpers.ForeGroundService.Companion.EXTRA_TARGET_URL
|
|
||||||
//import bums.lunatic.launcher.utils.Blog
|
|
||||||
//import bums.lunatic.launcher.utils.SimpleFingerGestures
|
|
||||||
//import com.yausername.youtubedl_android.YoutubeDL
|
|
||||||
//import com.yausername.youtubedl_android.YoutubeDLRequest
|
|
||||||
//import kotlinx.coroutines.CoroutineScope
|
|
||||||
//import kotlinx.coroutines.Dispatchers
|
|
||||||
//import kotlinx.coroutines.launch
|
|
||||||
//import org.mozilla.gecko.util.ThreadUtils.runOnUiThread
|
|
||||||
//import org.mozilla.geckoview.GeckoView
|
|
||||||
//import java.io.File
|
|
||||||
//import java.util.Base64
|
|
||||||
//import kotlin.collections.iterator
|
|
||||||
//
|
|
||||||
//enum class JxEvent {
|
|
||||||
// SCROLL_UP,
|
|
||||||
// SCROLL_DOWN,
|
|
||||||
// SWIPE_LEFT,
|
|
||||||
// SWIPE_RIGHT,
|
|
||||||
// ON_CLICK,
|
|
||||||
//}
|
|
||||||
//typealias JxInteface = (JxEvent)->Unit
|
|
||||||
//open class BWebview : GeckoView {
|
|
||||||
// var decoViews = arrayListOf<View>()
|
|
||||||
// @SuppressLint("ClickableViewAccessibility")
|
|
||||||
// constructor(context: Context?) : super(context) {
|
|
||||||
// this.setOnTouchListener { v, event ->
|
|
||||||
// if (event.device.name?.contains(
|
|
||||||
// "JX-12",
|
|
||||||
// true
|
|
||||||
// ) == true || event.device.name?.equals("J06", true) == true
|
|
||||||
// ) {
|
|
||||||
// return@setOnTouchListener mSimpleFingerGestures.onTouch(v, event)
|
|
||||||
// } else {
|
|
||||||
// return@setOnTouchListener super.onTouchEvent(event)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
||||||
// val nullCursor = PointerIcon.getSystemIcon(context!!, PointerIcon.TYPE_NULL)
|
|
||||||
// this.setPointerIcon(nullCursor)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// @SuppressLint("ClickableViewAccessibility")
|
|
||||||
// constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
|
|
||||||
// this.setOnTouchListener { v,event ->
|
|
||||||
// if (event.device.name?.contains("JX-12",true) == true|| event.device.name?.equals("J06",true) == true) {
|
|
||||||
// return@setOnTouchListener mSimpleFingerGestures.onTouch(v,event)
|
|
||||||
// } else {
|
|
||||||
// return@setOnTouchListener super.onTouchEvent(event)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
||||||
// val nullCursor = PointerIcon.getSystemIcon(context!!, PointerIcon.TYPE_NULL)
|
|
||||||
// this.setPointerIcon(nullCursor)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// fun videoDlownLoad(videoUrl : String) {
|
|
||||||
// val actionIntent = Intent(context, ForeGroundService::class.java).apply {
|
|
||||||
// action = ACTION_VIDEO_DOWNLOAD
|
|
||||||
// putExtra(EXTRA_TARGET_URL, videoUrl) // 전달할 데이터
|
|
||||||
// }
|
|
||||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
// context.startForegroundService(actionIntent)
|
|
||||||
// } else {
|
|
||||||
// context.startService(actionIntent)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// class GKCookie {
|
|
||||||
// var COOKIES : String? = null
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// var mGKCookie : GKCookie? = null
|
|
||||||
//
|
|
||||||
// fun checkIfDownloadable(url: String) {
|
|
||||||
// CoroutineScope(Dispatchers.Main).launch {
|
|
||||||
// runOnUiThread {
|
|
||||||
// decoViews.filter { it.id == R.id.dl_video }.firstOrNull()?.let {
|
|
||||||
// it.setOnClickListener {}
|
|
||||||
// it.visibility = GONE
|
|
||||||
// }}}
|
|
||||||
// Blog.LOGE("checkIfDownloadable ${url}")
|
|
||||||
// CoroutineScope(Dispatchers.IO).launch {
|
|
||||||
// try {
|
|
||||||
// var request = YoutubeDLRequest(url)
|
|
||||||
// (mGKCookie?.COOKIES)?.let{
|
|
||||||
// Blog.LOGE(it)
|
|
||||||
// val cookies = it.split(";")
|
|
||||||
// .map { it.trim() }
|
|
||||||
// .mapNotNull {
|
|
||||||
// val parts = it.split("=", limit = 2)
|
|
||||||
// if (parts.size == 2) parts[0] to parts[1] else null
|
|
||||||
// }
|
|
||||||
// .toMap()
|
|
||||||
// val expires = (System.currentTimeMillis() / 1000) + 3600 * 24 * 7 // 일주일 후 만료 예시
|
|
||||||
//
|
|
||||||
// val cookieFileContent = buildString {
|
|
||||||
// appendLine("# Netscape HTTP Cookie File")
|
|
||||||
// for ((name, value) in cookies) {
|
|
||||||
// appendLine(".${url.toUri().host}\tTRUE\t/\tTRUE\t$expires\t$name\t$value")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// val cookieFile = File(context.filesDir, "cookies.txt")
|
|
||||||
// cookieFile.writeText(cookieFileContent)
|
|
||||||
// request.addOption("--cookies", cookieFile.absolutePath)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// val videoInfo = YoutubeDL.getInstance().getInfo(request)
|
|
||||||
// // videoInfo 가 null 아니고, 필요한 키(예: title, url 등)가 있으면 다운로드 가능
|
|
||||||
// Blog.LOGE("checkIfDownloadable ${url}\n videoInfo : ${videoInfo}")
|
|
||||||
// var canVideoDown = videoInfo != null && !videoInfo.title.isNullOrEmpty()
|
|
||||||
// CoroutineScope(Dispatchers.Main).launch {
|
|
||||||
// runOnUiThread {
|
|
||||||
// decoViews.filter { it.id == R.id.dl_video }.firstOrNull()?.let {
|
|
||||||
// it.setOnClickListener {
|
|
||||||
// videoDlownLoad(url)
|
|
||||||
// }
|
|
||||||
// it.visibility = if (canVideoDown){
|
|
||||||
// VISIBLE
|
|
||||||
// } else{
|
|
||||||
// GONE
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// } catch (e: Exception) {
|
|
||||||
// e.printStackTrace()
|
|
||||||
// Blog.LOGE("checkIfDownloadable ${url} ${e}")
|
|
||||||
// CoroutineScope(Dispatchers.Main).launch {
|
|
||||||
// runOnUiThread {
|
|
||||||
// decoViews.filter { it.id == R.id.dl_video }.firstOrNull()?.let {
|
|
||||||
// it.setOnClickListener {}
|
|
||||||
// it.visibility = GONE
|
|
||||||
// }}}
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// val mSimpleFingerGestures = SimpleFingerGestures(omfgl = object : SimpleFingerGestures.OnFingerGestureListener{
|
|
||||||
//
|
|
||||||
// override fun onSwipeUp(
|
|
||||||
// targetView: View,
|
|
||||||
// fingers: Int,
|
|
||||||
// gestureDuration: Long,
|
|
||||||
// gestureDistance: Double
|
|
||||||
// ): Boolean {
|
|
||||||
// Blog.LOGE("")
|
|
||||||
// jxInteface?.invoke(JxEvent.SCROLL_UP )
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onSwipeDown(
|
|
||||||
// targetView: View,
|
|
||||||
// fingers: Int,
|
|
||||||
// gestureDuration: Long,
|
|
||||||
// gestureDistance: Double
|
|
||||||
// ): Boolean {
|
|
||||||
// Blog.LOGE("")
|
|
||||||
// jxInteface?.invoke(JxEvent.SCROLL_DOWN)
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onSwipeLeft(
|
|
||||||
// targetView: View,
|
|
||||||
// fingers: Int,
|
|
||||||
// gestureDuration: Long,
|
|
||||||
// gestureDistance: Double
|
|
||||||
// ): Boolean {
|
|
||||||
// Blog.LOGE("")
|
|
||||||
// jxInteface?.invoke(JxEvent.SWIPE_LEFT)
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onSwipeRight(
|
|
||||||
// targetView: View,
|
|
||||||
// fingers: Int,
|
|
||||||
// gestureDuration: Long,
|
|
||||||
// gestureDistance: Double
|
|
||||||
// ): Boolean {
|
|
||||||
// Blog.LOGE("")
|
|
||||||
// jxInteface?.invoke(JxEvent.SWIPE_RIGHT)
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onPinch(
|
|
||||||
// targetView: View,
|
|
||||||
// fingers: Int,
|
|
||||||
// gestureDuration: Long,
|
|
||||||
// gestureDistance: Double
|
|
||||||
// ): Boolean {
|
|
||||||
// Blog.LOGE("onPinch")
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onUnpinch(
|
|
||||||
// targetView: View,
|
|
||||||
// fingers: Int,
|
|
||||||
// gestureDuration: Long,
|
|
||||||
// gestureDistance: Double
|
|
||||||
// ): Boolean {
|
|
||||||
// Blog.LOGE("")
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onDoubleTap(
|
|
||||||
// targetView: View,
|
|
||||||
// fingers: Int
|
|
||||||
// ): Boolean {
|
|
||||||
// Blog.LOGE("")
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onLongPress(
|
|
||||||
// targetView: View,
|
|
||||||
// fingers: Int
|
|
||||||
// ): Boolean {
|
|
||||||
// Blog.LOGE("onLongPress")
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onClick(
|
|
||||||
// targetView: View,
|
|
||||||
// fingers: Int
|
|
||||||
// ): Boolean {
|
|
||||||
// Blog.LOGE("onClick")
|
|
||||||
// jxInteface?.invoke(JxEvent.ON_CLICK)
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// })
|
|
||||||
// companion object {
|
|
||||||
// var currentRetryCount = 0
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// var jxInteface : JxInteface? = null
|
|
||||||
//
|
|
||||||
// var lastDomain : String = ""
|
|
||||||
//
|
|
||||||
// open fun loadUrl(url: String, param : String? = null) {
|
|
||||||
// var nUrl = url
|
|
||||||
// Blog.LOGE("url >>>> ${url}")
|
|
||||||
// if (url.endsWith("=")) {
|
|
||||||
// nUrl = String(Base64.getMimeDecoder().decode(url.toByteArray()))
|
|
||||||
// param?.let {
|
|
||||||
// nUrl = nUrl.plus(param)
|
|
||||||
// }
|
|
||||||
// } else if (url.startsWith("http") == false) {
|
|
||||||
// nUrl = lastDomain
|
|
||||||
// }
|
|
||||||
// if (this.isVisible == false) {
|
|
||||||
// this.visibility = VISIBLE
|
|
||||||
// }
|
|
||||||
// Blog.LOGE("nUrl >>>> ${nUrl}")
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// nUrl?.let { url ->
|
|
||||||
// if (url.split("//").size > 1) {
|
|
||||||
// url.replace("//","/").replace("https:/","https://").let {
|
|
||||||
// Blog.LOGE("url >> ${url} , it >>> ${it}")
|
|
||||||
// this.session?.loadUri(it)
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// this.session?.loadUri(url)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// currentRetryCount = 0;
|
|
||||||
// }
|
|
||||||
// private var lastX = 0f
|
|
||||||
// private var lastY = 0f
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// override fun onTouchEvent(event: MotionEvent): Boolean {
|
|
||||||
// Blog.LOGE("event.device.name >>> ${event.device.name}")
|
|
||||||
// if (event.device.name?.contains("JX-12",true) == true || event.device.name?.equals("J06",true) == true) {
|
|
||||||
// Blog.LOGE("BWebview onTouchEvent $event")
|
|
||||||
// when (event.action) {
|
|
||||||
// MotionEvent.ACTION_DOWN -> {
|
|
||||||
// lastX = event.x
|
|
||||||
// lastY = event.y
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// MotionEvent.ACTION_MOVE -> {
|
|
||||||
// val deltaX = event.x - lastX
|
|
||||||
// val deltaY = event.y - lastY
|
|
||||||
// // 상하 이동이 더 크면(즉, 거의 수직 이동이면)만 처리
|
|
||||||
// if (Math.abs(deltaY) > Math.abs(deltaX)) {
|
|
||||||
// // 원하는 감도 적용
|
|
||||||
// val scrollFactor = 0.1f
|
|
||||||
//// scrollBy(0, (-deltaY * scrollFactor).toInt())
|
|
||||||
//
|
|
||||||
// jxInteface?.invoke(if ((-deltaY * scrollFactor).toInt() > 0){
|
|
||||||
// JxEvent.SCROLL_DOWN
|
|
||||||
// } else {
|
|
||||||
// JxEvent.SCROLL_UP
|
|
||||||
// })
|
|
||||||
// lastY = event.y
|
|
||||||
// lastX = event.x
|
|
||||||
// Blog.LOGE("return true for scroll")
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// // 좌우 이동은 무시
|
|
||||||
// lastY = event.y
|
|
||||||
// lastX = event.x
|
|
||||||
// Blog.LOGE("return false")
|
|
||||||
// return false
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// else -> {
|
|
||||||
// Blog.LOGE("call super")
|
|
||||||
// return super.onTouchEvent(event)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// return super.onTouchEvent(event)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
@ -3,11 +3,13 @@ package bums.lunatic.launcher.home.tokiz.view
|
|||||||
import android.annotation.TargetApi
|
import android.annotation.TargetApi
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
|
import android.graphics.Paint
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.text.Layout
|
import android.text.Layout
|
||||||
import android.text.StaticLayout
|
import android.text.StaticLayout
|
||||||
|
import android.text.TextPaint
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@ -19,8 +21,10 @@ import bums.lunatic.launcher.R
|
|||||||
import bums.lunatic.launcher.home.tokiz.TouchArea
|
import bums.lunatic.launcher.home.tokiz.TouchArea
|
||||||
import bums.lunatic.launcher.utils.Blog
|
import bums.lunatic.launcher.utils.Blog
|
||||||
import bums.lunatic.launcher.utils.SimpleFingerGestures
|
import bums.lunatic.launcher.utils.SimpleFingerGestures
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.MainScope
|
import kotlinx.coroutines.MainScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
|
|
||||||
@ -33,248 +37,6 @@ interface PagedTextViewInterface {
|
|||||||
fun onSwipeUp(touchCount : Int)
|
fun onSwipeUp(touchCount : Int)
|
||||||
fun onLongClick()
|
fun onLongClick()
|
||||||
}
|
}
|
||||||
class PagedTextView : AppCompatTextView {
|
|
||||||
|
|
||||||
private var needPaginate = false
|
|
||||||
private var isPaginating = false
|
|
||||||
private val pageList = arrayListOf<CharSequence>()
|
|
||||||
private var pageIndex: Int = 0
|
|
||||||
private var pageHeight: Int = 0
|
|
||||||
private var originalText: CharSequence = ""
|
|
||||||
|
|
||||||
var mPagedTextGenerateInterface : PagedTextGenerateInterface? = null
|
|
||||||
|
|
||||||
|
|
||||||
constructor(context: Context?) : super(context!!){initView(context)}
|
|
||||||
|
|
||||||
constructor(context: Context?, attrs: AttributeSet?) : super(context!!, attrs){initView(context)}
|
|
||||||
|
|
||||||
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context!!, attrs, defStyleAttr){initView(context)}
|
|
||||||
|
|
||||||
fun initView(context: Context?){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun size(): Int = pageList.size
|
|
||||||
fun current() : Int = pageIndex
|
|
||||||
|
|
||||||
fun doPrev() {
|
|
||||||
if (pageIndex > 0 )
|
|
||||||
pageIndex = pageIndex - 1
|
|
||||||
setPageText()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun doNext() {
|
|
||||||
if (pageIndex < pageList.size)
|
|
||||||
pageIndex = pageIndex + 1
|
|
||||||
setPageText()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun next(index: Int) {
|
|
||||||
pageIndex = index
|
|
||||||
setPageText()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setPageText() {
|
|
||||||
if(pageList.size > 0) {
|
|
||||||
isPaginating = true
|
|
||||||
text = pageList[pageIndex]
|
|
||||||
isPaginating = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setTxtF(text: CharSequence?) {
|
|
||||||
needPaginate = true
|
|
||||||
this.setText(text , null)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setText(text: CharSequence?, type: BufferType?) {
|
|
||||||
if (!isPaginating) {
|
|
||||||
needPaginate = true
|
|
||||||
originalText = text ?: ""
|
|
||||||
}
|
|
||||||
super.setText(text, type)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
override fun setTextSize(size: Float) {
|
|
||||||
setTextSize(TypedValue.COMPLEX_UNIT_SP, size)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setTextSize(unit: Int, size: Float) {
|
|
||||||
super.setTextSize(unit, size)
|
|
||||||
paint.textSize = TypedValue.applyDimension(unit, size, context.resources.getDisplayMetrics())
|
|
||||||
needPaginate = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) {
|
|
||||||
super.setPadding(left, top, right, bottom)
|
|
||||||
needPaginate = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setPaddingRelative(start: Int, top: Int, end: Int, bottom: Int) {
|
|
||||||
super.setPaddingRelative(start, top, end, bottom)
|
|
||||||
needPaginate = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setTextScaleX(size: Float) {
|
|
||||||
if (size != textScaleX) {
|
|
||||||
needPaginate = true
|
|
||||||
}
|
|
||||||
super.setTextScaleX(size)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setTypeface(tf: Typeface?) {
|
|
||||||
if (typeface != null && tf != typeface) {
|
|
||||||
needPaginate = true
|
|
||||||
paint.typeface = tf
|
|
||||||
}
|
|
||||||
super.setTypeface(tf)
|
|
||||||
}
|
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
override fun setLetterSpacing(letterSpacing: Float) {
|
|
||||||
if (letterSpacing != this.letterSpacing) {
|
|
||||||
needPaginate = true
|
|
||||||
}
|
|
||||||
super.setLetterSpacing(letterSpacing)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setHorizontallyScrolling(whether: Boolean) {
|
|
||||||
super.setHorizontallyScrolling(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setLineSpacing(add: Float, mult: Float) {
|
|
||||||
if (add != lineSpacingExtra || mult != lineSpacingMultiplier) {
|
|
||||||
needPaginate = true
|
|
||||||
}
|
|
||||||
super.setLineSpacing(add, mult)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setMaxLines(maxLines: Int) {
|
|
||||||
if (maxLines != this.maxLines) {
|
|
||||||
needPaginate = true
|
|
||||||
}
|
|
||||||
|
|
||||||
super.setMaxLines(maxLines)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setLines(lines: Int) {
|
|
||||||
super.setLines(lines)
|
|
||||||
|
|
||||||
if (lines != this.lineCount) {
|
|
||||||
needPaginate = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
|
|
||||||
super.onSizeChanged(w, h, oldw, oldh)
|
|
||||||
pageHeight = h - (paddingTop + paddingBottom) // 마진 제외
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
|
||||||
super.onLayout(changed, left, top, right, bottom)
|
|
||||||
Blog.LOGD(log = "onLayout>> ${this::class.java.name} changed >> ${changed}")
|
|
||||||
if (changed || needPaginate) {
|
|
||||||
paginate()
|
|
||||||
setPageText()
|
|
||||||
needPaginate = false
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
fun doUpdate() {
|
|
||||||
if (needPaginate && layout != null) {
|
|
||||||
paginate()
|
|
||||||
setPageText()
|
|
||||||
needPaginate = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private fun paginate() {
|
|
||||||
if (layout != null) {
|
|
||||||
MainScope().launch {
|
|
||||||
pageList.clear()
|
|
||||||
// Blog.LOGD(log = "paginate>> ${this::class.java.name} && ${layout.text}")
|
|
||||||
val layout = from(layout)
|
|
||||||
val lines = if(min(maxLines, layout.lineCount) > 10) {min(maxLines, layout.lineCount) - 1} else {min(maxLines, layout.lineCount)}
|
|
||||||
var startOffset = 0
|
|
||||||
val heightWithoutPaddings = pageHeight //- (marginTop + marginBottom + paddingTop + paddingBottom)
|
|
||||||
var height = heightWithoutPaddings
|
|
||||||
|
|
||||||
for (i in 0 until lines) {
|
|
||||||
if (height < layout.getLineBottom(i)) {
|
|
||||||
pageList.add(
|
|
||||||
layout.text.subSequence(startOffset, layout.getLineStart(i))
|
|
||||||
)
|
|
||||||
startOffset = layout.getLineStart(i)
|
|
||||||
height = layout.getLineTop(i) + heightWithoutPaddings
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == lines - 1) {
|
|
||||||
pageList.add(
|
|
||||||
if(layout.lineCount > i) {
|
|
||||||
layout.text.subSequence(startOffset, layout.getLineEnd(i + 1))
|
|
||||||
} else {
|
|
||||||
layout.text.subSequence(startOffset, layout.getLineEnd(i))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mPagedTextGenerateInterface?.completePagination(pageList)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun from(layout: Layout): Layout =
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
StaticLayout(
|
|
||||||
originalText,
|
|
||||||
paint,
|
|
||||||
layout.width - paddingLeft - paddingRight, // margin 제외
|
|
||||||
layout.alignment,
|
|
||||||
lineSpacingMultiplier,
|
|
||||||
lineSpacingExtra,
|
|
||||||
includeFontPadding
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
StaticLayout.Builder
|
|
||||||
.obtain(
|
|
||||||
originalText, 0, originalText.length, paint,
|
|
||||||
(layout.width - paddingLeft - paddingRight)
|
|
||||||
)
|
|
||||||
.setAlignment(layout.alignment)
|
|
||||||
.setLineSpacing(lineSpacingExtra, lineSpacingMultiplier)
|
|
||||||
.setIncludePad(includeFontPadding)
|
|
||||||
.setUseLineSpacingFromFallbacks()
|
|
||||||
.setBreakStrategy(breakStrategy)
|
|
||||||
.setHyphenationFrequency(hyphenationFrequency)
|
|
||||||
.setMaxLines(maxLines)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun StaticLayout.Builder.setUseLineSpacingFromFallbacks(): StaticLayout.Builder {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
||||||
this.setUseLineSpacingFromFallbacks(isFallbackLineSpacing)
|
|
||||||
}
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun StaticLayout.Builder.setJustificationMode(): StaticLayout.Builder {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
this.setJustificationMode(justificationMode)
|
|
||||||
}
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
interface PagedTextGenerateInterface {
|
interface PagedTextGenerateInterface {
|
||||||
fun completePagination(pageList: ArrayList<CharSequence>)
|
fun completePagination(pageList: ArrayList<CharSequence>)
|
||||||
@ -297,26 +59,95 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface {
|
|||||||
var mainTextView : TextView? = null
|
var mainTextView : TextView? = null
|
||||||
var sencondTextView : TextView? = null
|
var sencondTextView : TextView? = null
|
||||||
var demp : View? = null
|
var demp : View? = null
|
||||||
var hiddenTextView : PagedTextView? = null
|
// var hiddenTextView : PagedTextView? = null
|
||||||
var guideLine : Guideline? = null
|
var guideLine : Guideline? = null
|
||||||
var pageList: ArrayList<CharSequence>? = null
|
var pageList = mutableListOf<CharSequence>()
|
||||||
var summaryText : String = ""
|
var summaryText : String = ""
|
||||||
var text : String = ""
|
var text : String = ""
|
||||||
set(new) {
|
set(new) {
|
||||||
// Blog.LOGE("field >> ${field}")
|
|
||||||
// Blog.LOGE("new >> ${new}")
|
|
||||||
field = new
|
field = new
|
||||||
val summary = new.replace(" " ,"").replace("\n" ,"").substring(0,Math.min(30,new.length))
|
val summary = new.replace(" " ,"").replace("\n" ,"").substring(0,Math.min(30,new.length))
|
||||||
if (summary.equals(summaryText)) {
|
if (summary.equals(summaryText) && summaryText.length > 100) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Blog.LOGE("field >> ${field}")
|
if (field.length > 0) {
|
||||||
hiddenTextView?.setTxtF(field)
|
post {
|
||||||
hiddenTextView?.visibility = VISIBLE
|
if (width > 0 && height > 0) {
|
||||||
|
MainScope().launch {
|
||||||
|
pageList.clear()
|
||||||
|
val contentWidth =
|
||||||
|
mainTextView!!.width - (mainTextView!!.paddingLeft + mainTextView!!.paddingRight)
|
||||||
|
val contentHeight =
|
||||||
|
mainTextView!!.height - (mainTextView!!.paddingTop + mainTextView!!.paddingBottom)
|
||||||
|
val pages = paginateAsync(text, contentWidth, contentHeight)
|
||||||
|
pageList.addAll(pages)
|
||||||
|
Blog.LOGE("pages >>> ${pages.size}")
|
||||||
|
setPageBy(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
summaryText = summary
|
summaryText = summary
|
||||||
}
|
}
|
||||||
|
suspend fun paginateAsync(text: CharSequence, width: Int, height: Int): List<CharSequence> = withContext(Dispatchers.Default) {
|
||||||
|
val resultPages = ArrayList<CharSequence>()
|
||||||
|
val paint = mainTextView?.paint ?: TextPaint()
|
||||||
|
val lineSpacingMult = mainTextView?.lineSpacingMultiplier ?: 1.0f
|
||||||
|
val lineSpacingAdd = mainTextView?.lineSpacingExtra ?: 1.0f
|
||||||
|
val letterSpacing = mainTextView?.letterSpacing ?: 1.0f
|
||||||
|
val includePad = false
|
||||||
|
Blog.LOGE("text ${text.length}, width $width, height $height")
|
||||||
|
// 1. 전체 텍스트에 대한 StaticLayout 생성 (API 버전에 따른 분기 처리 권장)
|
||||||
|
val layout = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
StaticLayout.Builder.obtain(text, 0, text.length, paint, width)
|
||||||
|
.setAlignment(Layout.Alignment.ALIGN_NORMAL)
|
||||||
|
.setLineSpacing(lineSpacingAdd, lineSpacingMult)
|
||||||
|
.setIncludePad(includePad)
|
||||||
|
.build()
|
||||||
|
} else {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
StaticLayout(text, paint, width, Layout.Alignment.ALIGN_NORMAL, lineSpacingMult, lineSpacingAdd, includePad)
|
||||||
|
}
|
||||||
|
|
||||||
|
val totalLines = layout.lineCount
|
||||||
|
var startLine = 0
|
||||||
|
var startOffset = 0
|
||||||
|
|
||||||
|
// 2. 라인 정보를 순회하며 높이 계산
|
||||||
|
while (startLine < totalLines) {
|
||||||
|
// 현재 페이지의 시작 y 좌표
|
||||||
|
val pageTopY = layout.getLineTop(startLine)
|
||||||
|
// 현재 페이지가 끝날 수 있는 최대 y 좌표
|
||||||
|
val targetBottomY = pageTopY + height
|
||||||
|
|
||||||
|
// 이 페이지에 들어갈 수 있는 마지막 라인 찾기
|
||||||
|
var endLine = layout.getLineForVertical(targetBottomY)
|
||||||
|
|
||||||
|
// getLineForVertical은 정확한 좌표가 없으면 마지막 라인을 반환하므로 검증 필요
|
||||||
|
if (layout.getLineBottom(endLine) > targetBottomY) {
|
||||||
|
endLine--
|
||||||
|
}
|
||||||
|
|
||||||
|
// 한 줄도 못 들어가는 경우(폰트가 뷰보다 큰 경우 등) 방어 코드
|
||||||
|
if (endLine < startLine) endLine = startLine
|
||||||
|
|
||||||
|
// 페이지 범위의 텍스트 추출
|
||||||
|
// endLine의 끝 오프셋을 가져옴
|
||||||
|
val endOffset = layout.getLineEnd(endLine)
|
||||||
|
|
||||||
|
// 텍스트 자르기 (subSequence는 메모리 복사를 최소화함)
|
||||||
|
if (startOffset < endOffset) {
|
||||||
|
resultPages.add(text.subSequence(startOffset, endOffset))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 다음 페이지 준비
|
||||||
|
startOffset = endOffset
|
||||||
|
startLine = endLine + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return@withContext resultPages
|
||||||
|
}
|
||||||
private val hanler = Handler()
|
private val hanler = Handler()
|
||||||
var mPagedTextViewInterface : PagedTextViewInterface? = null
|
var mPagedTextViewInterface : PagedTextViewInterface? = null
|
||||||
val touchTimeover = Runnable {
|
val touchTimeover = Runnable {
|
||||||
@ -328,11 +159,8 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface {
|
|||||||
inflate(context, R.layout.layout_textviewer, this)
|
inflate(context, R.layout.layout_textviewer, this)
|
||||||
mainTextView = findViewById(R.id.first_view)
|
mainTextView = findViewById(R.id.first_view)
|
||||||
sencondTextView = findViewById(R.id.sencond_view)
|
sencondTextView = findViewById(R.id.sencond_view)
|
||||||
demp = findViewById(R.id.demp)
|
|
||||||
currentPageTextView = findViewById(R.id.current_page)
|
currentPageTextView = findViewById(R.id.current_page)
|
||||||
|
|
||||||
hiddenTextView = findViewById(R.id.hidden_view)
|
|
||||||
hiddenTextView?.mPagedTextGenerateInterface = this
|
|
||||||
currentPageTextView?.text = ""
|
currentPageTextView?.text = ""
|
||||||
hanler.removeCallbacks(touchTimeover)
|
hanler.removeCallbacks(touchTimeover)
|
||||||
setOnLongClickListener { v ->
|
setOnLongClickListener { v ->
|
||||||
@ -450,8 +278,7 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface {
|
|||||||
super.onLayout(changed, left, top, right, bottom)
|
super.onLayout(changed, left, top, right, bottom)
|
||||||
Blog.LOGD(log = "onLayout>> ${this::class.java.name} changed >> ${changed}")
|
Blog.LOGD(log = "onLayout>> ${this::class.java.name} changed >> ${changed}")
|
||||||
if(changed) {
|
if(changed) {
|
||||||
hiddenTextView?.text = text
|
// forceUpdateUI()
|
||||||
forceUpdateUI()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
|
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
|
||||||
@ -470,14 +297,12 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface {
|
|||||||
|
|
||||||
var currentPage = 0
|
var currentPage = 0
|
||||||
override fun completePagination(pageList: ArrayList<CharSequence>) {
|
override fun completePagination(pageList: ArrayList<CharSequence>) {
|
||||||
// Blog.LOGD(log = "completePagination>> ${this::class.java.name} >> pageList ${pageList}")
|
|
||||||
if(text.length > 0 && pageList!= null && pageList.size == 0) {
|
if(text.length > 0 && pageList!= null && pageList.size == 0) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this.pageList = pageList
|
this.pageList = pageList
|
||||||
setPageBy(0)
|
setPageBy(0)
|
||||||
}
|
}
|
||||||
hiddenTextView?.visibility = GONE
|
|
||||||
}
|
}
|
||||||
var defaultAlpha = 171
|
var defaultAlpha = 171
|
||||||
fun setColorStyle(colors : Array<String>) {
|
fun setColorStyle(colors : Array<String>) {
|
||||||
@ -490,11 +315,7 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface {
|
|||||||
sencondTextView?.setTextColor(Color.parseColor("#FFFFFF"))
|
sencondTextView?.setTextColor(Color.parseColor("#FFFFFF"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// fun setPagedTextViewInterface(pagedTextViewInterface: PagedTextViewInterface) = hiddenTextView?.setPagedTextViewInterface(pagedTextViewInterface)
|
|
||||||
// fun setText(replace: String) = hiddenTextView?.setText(replace)
|
|
||||||
|
|
||||||
fun setTextSize(fl: Float) {
|
fun setTextSize(fl: Float) {
|
||||||
hiddenTextView?.setTextSize(fl)
|
|
||||||
mainTextView?.setTextSize(fl)
|
mainTextView?.setTextSize(fl)
|
||||||
sencondTextView?.setTextSize(fl)
|
sencondTextView?.setTextSize(fl)
|
||||||
}
|
}
|
||||||
@ -508,22 +329,38 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun setPageBy(num : Int) {
|
fun setPageBy(num : Int) {
|
||||||
this@PagedTextLayout.currentPage = num
|
if (pageList.size > 0) {
|
||||||
var realPage = if(isDualPage()) this@PagedTextLayout.currentPage * 2 else this@PagedTextLayout.currentPage
|
this@PagedTextLayout.currentPage = num
|
||||||
Blog.LOGE("realPage = if(${pageList?.size} ?: 0 > ${realPage}) { realPage} else { ${(pageList?.size ?: 0) - 1 }}")
|
var realPage = if (isDualPage()) this@PagedTextLayout.currentPage * 2 else this@PagedTextLayout.currentPage
|
||||||
realPage = if(pageList?.size ?: 0 > realPage) { realPage} else { (pageList?.size ?: 0) - 1 }
|
Blog.LOGE("realPage = if(${pageList?.size} ?: 0 > ${realPage}) { realPage} else { ${(pageList?.size ?: 0) - 1}}")
|
||||||
currentPageTextView?.text = "${realPage + 1 }/${ pageList?.size ?: 0 + 1}"
|
realPage = if (pageList?.size ?: 0 > realPage) {
|
||||||
|
realPage
|
||||||
|
} else {
|
||||||
|
(pageList?.size ?: 0) - 1
|
||||||
|
}
|
||||||
|
currentPageTextView?.text = "${realPage + 1}/${pageList?.size ?: 0 + 1}"
|
||||||
|
|
||||||
mainTextView?.text = pageList?.get(realPage) ?: "NONE"
|
mainTextView?.text = pageList?.get(realPage) ?: "NONE"
|
||||||
if(isDualPage()) {
|
Blog.LOGE("pageList.get($realPage) ${pageList?.get(realPage)}")
|
||||||
realPage = realPage.inc()
|
if (isDualPage()) {
|
||||||
sencondTextView?.text = if(pageList?.size ?: 0 > realPage) { pageList?.get(realPage)} else { "끝"}
|
realPage = realPage.inc()
|
||||||
} else {
|
sencondTextView?.text = if (pageList?.size ?: 0 > realPage) {
|
||||||
sencondTextView?.text = ""
|
pageList?.get(realPage)
|
||||||
|
} else {
|
||||||
|
"끝"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sencondTextView?.text = ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun size(): Int = if(isDualPage()) Math.round((hiddenTextView?.size() ?:0) * 0.5f) else hiddenTextView?.size() ?: 0
|
fun size(): Int = (if(isDualPage()) {
|
||||||
|
Math.round(pageList.size * 0.5f)
|
||||||
|
}else {
|
||||||
|
pageList.size
|
||||||
|
})
|
||||||
|
|
||||||
fun getFastPageCount() = if(isDualPage()) 3 else 6
|
fun getFastPageCount() = if(isDualPage()) 3 else 6
|
||||||
fun current(): Int = this@PagedTextLayout.currentPage
|
fun current(): Int = this@PagedTextLayout.currentPage
|
||||||
fun doNext(fast : Boolean = false) {
|
fun doNext(fast : Boolean = false) {
|
||||||
@ -547,33 +384,26 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun forceUpdateUI() {
|
|
||||||
hiddenTextView?.doUpdate()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) {
|
override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) {
|
||||||
hiddenTextView?.setPadding(left,top,right, bottom)
|
|
||||||
mainTextView?.setPadding(left,top,right, bottom)
|
mainTextView?.setPadding(left,top,right, bottom)
|
||||||
sencondTextView?.setPadding(left,top,right, bottom)
|
sencondTextView?.setPadding(left,top,right, bottom)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun setTypeface(tf: Typeface?) {
|
fun setTypeface(tf: Typeface?) {
|
||||||
hiddenTextView?.setTypeface(tf)
|
|
||||||
mainTextView?.setTypeface(tf)
|
mainTextView?.setTypeface(tf)
|
||||||
sencondTextView?.setTypeface(tf)
|
sencondTextView?.setTypeface(tf)
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
fun setLetterSpacing(letterSpacing: Float) {
|
fun setLetterSpacing(letterSpacing: Float) {
|
||||||
hiddenTextView?.letterSpacing = letterSpacing.times(0.01f)
|
|
||||||
mainTextView?.letterSpacing = letterSpacing.times(0.01f)
|
mainTextView?.letterSpacing = letterSpacing.times(0.01f)
|
||||||
sencondTextView?.letterSpacing = letterSpacing.times(0.01f)
|
sencondTextView?.letterSpacing = letterSpacing.times(0.01f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun setLineSpacing(mult: Float) {
|
fun setLineSpacing(mult: Float) {
|
||||||
hiddenTextView?.setLineSpacing(1f, 1f.plus(mult.times(0.01f)))
|
|
||||||
mainTextView?.setLineSpacing(1f, 1f.plus(mult.times(0.01f)))
|
mainTextView?.setLineSpacing(1f, 1f.plus(mult.times(0.01f)))
|
||||||
sencondTextView?.setLineSpacing(1f, 1f.plus(mult.times(0.01f)))
|
sencondTextView?.setLineSpacing(1f, 1f.plus(mult.times(0.01f)))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,32 +6,6 @@
|
|||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_margin="5dp"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
<bums.lunatic.launcher.home.tokiz.view.PagedTextView
|
|
||||||
android:layout_margin="5dp"
|
|
||||||
android:id="@+id/hidden_view"
|
|
||||||
android:visibility="visible"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
android:lineSpacingExtra="0dp"
|
|
||||||
style="@style/sss"
|
|
||||||
android:layout_height="match_parent"/>
|
|
||||||
<View
|
|
||||||
android:id="@+id/demp"
|
|
||||||
android:visibility="invisible"
|
|
||||||
android:layout_margin="5dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent"/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_margin="5dp"
|
android:layout_margin="5dp"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
@ -55,7 +29,7 @@
|
|||||||
android:gravity="start"
|
android:gravity="start"
|
||||||
android:includeFontPadding="false"
|
android:includeFontPadding="false"
|
||||||
android:lineSpacingExtra="0dp"
|
android:lineSpacingExtra="0dp"
|
||||||
android:visibility="invisible"
|
android:visibility="gone"
|
||||||
android:id="@+id/sencond_view"
|
android:id="@+id/sencond_view"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user