kopia lustrzana https://github.com/TeamNewPipe/NewPipe
Moved import/export options to menu
rodzic
5b435c586e
commit
1d69bd48be
|
@ -1,24 +1,24 @@
|
|||
package org.schabi.newpipe.local.subscription
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.SubMenu
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.ActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import com.xwray.groupie.Group
|
||||
import com.xwray.groupie.GroupAdapter
|
||||
|
@ -34,7 +34,9 @@ import org.schabi.newpipe.databinding.FeedItemCarouselBinding
|
|||
import org.schabi.newpipe.databinding.FragmentSubscriptionBinding
|
||||
import org.schabi.newpipe.error.ErrorInfo
|
||||
import org.schabi.newpipe.error.UserAction
|
||||
import org.schabi.newpipe.extractor.NewPipe
|
||||
import org.schabi.newpipe.extractor.channel.ChannelInfoItem
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException
|
||||
import org.schabi.newpipe.fragments.BaseStateFragment
|
||||
import org.schabi.newpipe.ktx.animate
|
||||
import org.schabi.newpipe.local.subscription.SubscriptionViewModel.SubscriptionState
|
||||
|
@ -45,13 +47,10 @@ import org.schabi.newpipe.local.subscription.item.EmptyPlaceholderItem
|
|||
import org.schabi.newpipe.local.subscription.item.FeedGroupAddItem
|
||||
import org.schabi.newpipe.local.subscription.item.FeedGroupCardItem
|
||||
import org.schabi.newpipe.local.subscription.item.FeedGroupCarouselItem
|
||||
import org.schabi.newpipe.local.subscription.item.FeedImportExportItem
|
||||
import org.schabi.newpipe.local.subscription.item.HeaderWithMenuItem
|
||||
import org.schabi.newpipe.local.subscription.item.HeaderWithMenuItem.Companion.PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM
|
||||
import org.schabi.newpipe.local.subscription.services.SubscriptionsExportService
|
||||
import org.schabi.newpipe.local.subscription.services.SubscriptionsExportService.EXPORT_COMPLETE_ACTION
|
||||
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService
|
||||
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.IMPORT_COMPLETE_ACTION
|
||||
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_MODE
|
||||
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_VALUE
|
||||
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.PREVIOUS_EXPORT_MODE
|
||||
|
@ -65,6 +64,7 @@ import org.schabi.newpipe.util.external_communication.ShareUtils
|
|||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import java.util.function.Supplier
|
||||
|
||||
class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
||||
private var _binding: FragmentSubscriptionBinding? = null
|
||||
|
@ -74,12 +74,9 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
|||
private lateinit var subscriptionManager: SubscriptionManager
|
||||
private val disposables: CompositeDisposable = CompositeDisposable()
|
||||
|
||||
private var subscriptionBroadcastReceiver: BroadcastReceiver? = null
|
||||
|
||||
private val groupAdapter = GroupAdapter<GroupieViewHolder<FeedItemCarouselBinding>>()
|
||||
private val feedGroupsSection = Section()
|
||||
private var feedGroupsCarousel: FeedGroupCarouselItem? = null
|
||||
private lateinit var importExportItem: FeedImportExportItem
|
||||
private lateinit var feedGroupsSortMenuItem: HeaderWithMenuItem
|
||||
private val subscriptionsSection = Section()
|
||||
|
||||
|
@ -94,9 +91,6 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
|||
@State
|
||||
@JvmField
|
||||
var feedGroupsListState: Parcelable? = null
|
||||
@State
|
||||
@JvmField
|
||||
var importExportItemExpandedState: Boolean? = null
|
||||
|
||||
init {
|
||||
setHasOptionsMenu(true)
|
||||
|
@ -120,20 +114,10 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
|||
return inflater.inflate(R.layout.fragment_subscription, container, false)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
setupBroadcastReceiver()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
itemsListState = binding.itemsList.layoutManager?.onSaveInstanceState()
|
||||
feedGroupsListState = feedGroupsCarousel?.onSaveInstanceState()
|
||||
importExportItemExpandedState = importExportItem.isExpanded
|
||||
|
||||
if (subscriptionBroadcastReceiver != null && activity != null) {
|
||||
LocalBroadcastManager.getInstance(activity).unregisterReceiver(subscriptionBroadcastReceiver!!)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
@ -150,28 +134,75 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
|||
|
||||
activity.supportActionBar?.setDisplayShowTitleEnabled(true)
|
||||
activity.supportActionBar?.setTitle(R.string.tab_subscriptions)
|
||||
|
||||
buildImportExportMenu(menu)
|
||||
}
|
||||
|
||||
private fun setupBroadcastReceiver() {
|
||||
if (activity == null) return
|
||||
private fun buildImportExportMenu(menu: Menu) {
|
||||
// -- Import --
|
||||
|
||||
if (subscriptionBroadcastReceiver != null) {
|
||||
LocalBroadcastManager.getInstance(activity).unregisterReceiver(subscriptionBroadcastReceiver!!)
|
||||
val importSubMenu = menu.addSubMenu(R.string.import_from)
|
||||
|
||||
addMenuItem(importSubMenu, R.string.previous_export) {
|
||||
onImportPreviousSelected()
|
||||
}
|
||||
|
||||
val filters = IntentFilter()
|
||||
filters.addAction(EXPORT_COMPLETE_ACTION)
|
||||
filters.addAction(IMPORT_COMPLETE_ACTION)
|
||||
subscriptionBroadcastReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
_binding?.itemsList?.post {
|
||||
importExportItem.isExpanded = false
|
||||
importExportItem.notifyChanged(FeedImportExportItem.REFRESH_EXPANDED_STATUS)
|
||||
val services = requireContext().resources.getStringArray(R.array.service_list)
|
||||
for (serviceName in services) {
|
||||
try {
|
||||
val service = NewPipe.getService(serviceName)
|
||||
|
||||
val subscriptionExtractor = service.subscriptionExtractor ?: continue
|
||||
|
||||
val supportedSources = subscriptionExtractor.supportedSources
|
||||
if (supportedSources.isEmpty()) continue
|
||||
|
||||
addMenuItem(importSubMenu, serviceName) {
|
||||
onImportFromServiceSelected(service.serviceId)
|
||||
}
|
||||
} catch (e: ExtractionException) {
|
||||
throw RuntimeException(
|
||||
"Services array contains an entry that it's not a valid service name ($serviceName)",
|
||||
e
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
LocalBroadcastManager.getInstance(activity).registerReceiver(subscriptionBroadcastReceiver!!, filters)
|
||||
// -- Export --
|
||||
|
||||
val exportSubMenu = menu.addSubMenu(R.string.export_to)
|
||||
|
||||
addMenuItem(exportSubMenu, R.string.file) { onExportSelected() }
|
||||
}
|
||||
|
||||
private fun addMenuItem(
|
||||
subMenu: SubMenu,
|
||||
@StringRes title: Int,
|
||||
onClick: Runnable
|
||||
): MenuItem {
|
||||
return addMenuItem({ subMenu.add(title) }, onClick)
|
||||
}
|
||||
|
||||
private fun addMenuItem(
|
||||
subMenu: SubMenu,
|
||||
title: String,
|
||||
onClick: Runnable
|
||||
): MenuItem {
|
||||
return addMenuItem({ subMenu.add(title) }, onClick)
|
||||
}
|
||||
|
||||
private fun addMenuItem(
|
||||
menuItemSupplier: Supplier<MenuItem>,
|
||||
onClick: Runnable
|
||||
): MenuItem {
|
||||
val item = menuItemSupplier.get()
|
||||
|
||||
item.setOnMenuItemClickListener { _ ->
|
||||
onClick.run()
|
||||
true
|
||||
}
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
private fun onImportFromServiceSelected(serviceId: Int) {
|
||||
|
@ -263,13 +294,14 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
|||
subscriptionsSection.setPlaceholder(EmptyPlaceholderItem())
|
||||
subscriptionsSection.setHideWhenEmpty(true)
|
||||
|
||||
importExportItem = FeedImportExportItem(
|
||||
{ onImportPreviousSelected() },
|
||||
{ onImportFromServiceSelected(it) },
|
||||
{ onExportSelected() },
|
||||
importExportItemExpandedState ?: false
|
||||
groupAdapter.add(
|
||||
Section(
|
||||
HeaderWithMenuItem(
|
||||
getString(R.string.tab_subscriptions)
|
||||
),
|
||||
listOf(subscriptionsSection)
|
||||
)
|
||||
)
|
||||
groupAdapter.add(Section(importExportItem, listOf(subscriptionsSection)))
|
||||
}
|
||||
|
||||
override fun initViews(rootView: View, savedInstanceState: Bundle?) {
|
||||
|
@ -371,13 +403,6 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
|||
subscriptionsSection.update(result.subscriptions)
|
||||
subscriptionsSection.setHideWhenEmpty(false)
|
||||
|
||||
if (result.subscriptions.isEmpty() && importExportItemExpandedState == null) {
|
||||
binding.itemsList.post {
|
||||
importExportItem.isExpanded = true
|
||||
importExportItem.notifyChanged(FeedImportExportItem.REFRESH_EXPANDED_STATUS)
|
||||
}
|
||||
}
|
||||
|
||||
if (itemsListState != null) {
|
||||
binding.itemsList.layoutManager?.onRestoreInstanceState(itemsListState)
|
||||
itemsListState = null
|
||||
|
|
|
@ -1,122 +0,0 @@
|
|||
package org.schabi.newpipe.local.subscription.item
|
||||
|
||||
import android.graphics.Color
|
||||
import android.graphics.PorterDuff
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.DrawableRes
|
||||
import com.xwray.groupie.viewbinding.BindableItem
|
||||
import com.xwray.groupie.viewbinding.GroupieViewHolder
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.databinding.FeedImportExportGroupBinding
|
||||
import org.schabi.newpipe.extractor.NewPipe
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException
|
||||
import org.schabi.newpipe.ktx.animateRotation
|
||||
import org.schabi.newpipe.util.ServiceHelper
|
||||
import org.schabi.newpipe.util.ThemeHelper
|
||||
import org.schabi.newpipe.views.CollapsibleView
|
||||
|
||||
class FeedImportExportItem(
|
||||
val onImportPreviousSelected: () -> Unit,
|
||||
val onImportFromServiceSelected: (Int) -> Unit,
|
||||
val onExportSelected: () -> Unit,
|
||||
var isExpanded: Boolean = false
|
||||
) : BindableItem<FeedImportExportGroupBinding>() {
|
||||
companion object {
|
||||
const val REFRESH_EXPANDED_STATUS = 123
|
||||
}
|
||||
|
||||
override fun bind(viewBinding: FeedImportExportGroupBinding, position: Int, payloads: MutableList<Any>) {
|
||||
if (payloads.contains(REFRESH_EXPANDED_STATUS)) {
|
||||
viewBinding.importExportOptions.apply { if (isExpanded) expand() else collapse() }
|
||||
return
|
||||
}
|
||||
|
||||
super.bind(viewBinding, position, payloads)
|
||||
}
|
||||
|
||||
override fun getLayout(): Int = R.layout.feed_import_export_group
|
||||
|
||||
override fun bind(viewBinding: FeedImportExportGroupBinding, position: Int) {
|
||||
if (viewBinding.importFromOptions.childCount == 0) setupImportFromItems(viewBinding.importFromOptions)
|
||||
if (viewBinding.exportToOptions.childCount == 0) setupExportToItems(viewBinding.exportToOptions)
|
||||
|
||||
expandIconListener?.let { viewBinding.importExportOptions.removeListener(it) }
|
||||
expandIconListener = CollapsibleView.StateListener { newState ->
|
||||
viewBinding.importExportExpandIcon.animateRotation(
|
||||
250, if (newState == CollapsibleView.COLLAPSED) 0 else 180
|
||||
)
|
||||
}
|
||||
|
||||
viewBinding.importExportOptions.currentState = if (isExpanded) CollapsibleView.EXPANDED else CollapsibleView.COLLAPSED
|
||||
viewBinding.importExportExpandIcon.rotation = if (isExpanded) 180F else 0F
|
||||
viewBinding.importExportOptions.ready()
|
||||
|
||||
viewBinding.importExportOptions.addListener(expandIconListener)
|
||||
viewBinding.importExport.setOnClickListener {
|
||||
viewBinding.importExportOptions.switchState()
|
||||
isExpanded = viewBinding.importExportOptions.currentState == CollapsibleView.EXPANDED
|
||||
}
|
||||
}
|
||||
|
||||
override fun unbind(viewHolder: GroupieViewHolder<FeedImportExportGroupBinding>) {
|
||||
super.unbind(viewHolder)
|
||||
expandIconListener?.let { viewHolder.binding.importExportOptions.removeListener(it) }
|
||||
expandIconListener = null
|
||||
}
|
||||
|
||||
override fun initializeViewBinding(view: View) = FeedImportExportGroupBinding.bind(view)
|
||||
|
||||
private var expandIconListener: CollapsibleView.StateListener? = null
|
||||
|
||||
private fun addItemView(title: String, @DrawableRes icon: Int, container: ViewGroup): View {
|
||||
val itemRoot = View.inflate(container.context, R.layout.subscription_import_export_item, null)
|
||||
val titleView = itemRoot.findViewById<TextView>(android.R.id.text1)
|
||||
val iconView = itemRoot.findViewById<ImageView>(android.R.id.icon1)
|
||||
|
||||
titleView.text = title
|
||||
iconView.setImageResource(icon)
|
||||
|
||||
container.addView(itemRoot)
|
||||
return itemRoot
|
||||
}
|
||||
|
||||
private fun setupImportFromItems(listHolder: ViewGroup) {
|
||||
val previousBackupItem = addItemView(
|
||||
listHolder.context.getString(R.string.previous_export),
|
||||
R.drawable.ic_backup, listHolder
|
||||
)
|
||||
previousBackupItem.setOnClickListener { onImportPreviousSelected() }
|
||||
|
||||
val iconColor = if (ThemeHelper.isLightThemeSelected(listHolder.context)) Color.BLACK else Color.WHITE
|
||||
val services = listHolder.context.resources.getStringArray(R.array.service_list)
|
||||
for (serviceName in services) {
|
||||
try {
|
||||
val service = NewPipe.getService(serviceName)
|
||||
|
||||
val subscriptionExtractor = service.subscriptionExtractor ?: continue
|
||||
|
||||
val supportedSources = subscriptionExtractor.supportedSources
|
||||
if (supportedSources.isEmpty()) continue
|
||||
|
||||
val itemView = addItemView(serviceName, ServiceHelper.getIcon(service.serviceId), listHolder)
|
||||
val iconView = itemView.findViewById<ImageView>(android.R.id.icon1)
|
||||
iconView.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN)
|
||||
|
||||
itemView.setOnClickListener { onImportFromServiceSelected(service.serviceId) }
|
||||
} catch (e: ExtractionException) {
|
||||
throw RuntimeException("Services array contains an entry that it's not a valid service name ($serviceName)", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupExportToItems(listHolder: ViewGroup) {
|
||||
val previousBackupItem = addItemView(
|
||||
listHolder.context.getString(R.string.file),
|
||||
R.drawable.ic_save, listHolder
|
||||
)
|
||||
previousBackupItem.setOnClickListener { onExportSelected() }
|
||||
}
|
||||
}
|
|
@ -1,114 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="14dp"
|
||||
android:background="?attr/contrast_background_color">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="5dp"
|
||||
android:background="?attr/toolbar_shadow" />
|
||||
</FrameLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/separator_color" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/import_export"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<org.schabi.newpipe.views.NewPipeTextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:text="@string/tab_subscriptions"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/import_export_expand_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginRight="16dp"
|
||||
app:srcCompat="@drawable/ic_expand_more"
|
||||
tools:ignore="ContentDescription,RtlHardcoded" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<org.schabi.newpipe.views.CollapsibleView
|
||||
android:id="@+id/import_export_options"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="6dp"
|
||||
tools:ignore="RtlSymmetry">
|
||||
|
||||
<org.schabi.newpipe.views.NewPipeTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/subscription_import_export_title_height"
|
||||
android:gravity="left|center"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="36dp"
|
||||
android:text="@string/import_from"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="13sp"
|
||||
tools:ignore="RtlHardcoded" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/import_from_options"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="36dp"
|
||||
android:layout_marginLeft="36dp"
|
||||
android:orientation="vertical" />
|
||||
|
||||
<org.schabi.newpipe.views.NewPipeTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/subscription_import_export_title_height"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="left|center"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="36dp"
|
||||
android:text="@string/export_to"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="13sp"
|
||||
tools:ignore="RtlHardcoded" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/export_to_options"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="36dp"
|
||||
android:orientation="vertical" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="2dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="?attr/separator_color" />
|
||||
</org.schabi.newpipe.views.CollapsibleView>
|
||||
</LinearLayout>
|
|
@ -1,32 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@android:id/icon1"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="@dimen/subscription_import_export_item_icon_size"
|
||||
android:layout_marginTop="@dimen/subscription_import_export_item_icon_margin"
|
||||
android:layout_marginBottom="@dimen/subscription_import_export_item_icon_margin"
|
||||
android:scaleType="fitCenter"
|
||||
tools:ignore="ContentDescription,RtlHardcoded"
|
||||
tools:src="@drawable/place_holder_youtube" />
|
||||
|
||||
<org.schabi.newpipe.views.NewPipeTextView
|
||||
android:id="@android:id/text1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/subscription_import_export_item_height"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="6dp"
|
||||
android:paddingRight="6dp"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="13sp"
|
||||
tools:text="@string/youtube" />
|
||||
</LinearLayout>
|
Ładowanie…
Reference in New Issue