admob - How to add admob banner ads after each 3 video items
问题描述
Want to display admob banner ads after each 3 video item
I have the code below which works except it always hides atleast one real item in the listview because the ad displays at that position.
Example of the problem: I have a list of n times, and the adView is displaying at position 3. on the listview I played around with increasing the size of the adapter everytime I return an ad but it didn't work very well.
Any ideas?
class LocalFoldedVideosFragment : SwipeBackFragment(), View.OnClickListener, View.OnLongClickListener,
OnReloadVideosListener, SwipeRefreshLayout.OnRefreshListener, OnBackPressedListener {
private lateinit var mInteractionCallback: InteractionCallback
private var mLifecycleCallback: FragmentPartLifecycleCallback? = null
private var mVideoOpCallback: VideoListItemOpCallback<Video>? = null
private lateinit var mRecyclerView: SlidingItemMenuRecyclerView
private val mAdapter = VideoListAdapter()
private val mVideoDir by lazy {
arguments?.get(KEY_VIDEODIR) as? VideoDirectory
}
private var _mVideos: MutableList<Video>? = null
private inline val mVideos: MutableList<Video>
get() {
if (_mVideos == null) {
_mVideos = mVideoDir?.videos ?: ArrayList(0)
}
return _mVideos!!
}
private var mLoadDirectoryVideosTask: LoadDirectoryVideosTask? = null
private lateinit var mBackButton: ImageButton
private lateinit var mCancelButton: Button
private lateinit var mSelectAllButton: Button
private lateinit var mVideoOptionsFrame: ViewGroup
private lateinit var mDeleteButton: TextView
private lateinit var mRenameButton: TextView
private lateinit var mShareButton: TextView
private lateinit var mDetailsButton: TextView
private lateinit var scrolable_banner_ads : AdView
private var _TOP: String? = null
private inline val TOP: String
get() {
if (_TOP == null) {
_TOP = getString(R.string.top)
}
return _TOP!!
}
private var _CANCEL_TOP: String? = null
private inline val CANCEL_TOP: String
get() {
if (_CANCEL_TOP == null) {
_CANCEL_TOP = getString(R.string.cancelTop)
}
return _CANCEL_TOP!!
}
private var _SELECT_ALL: String? = null
private inline val SELECT_ALL: String
get() {
if (_SELECT_ALL == null) {
_SELECT_ALL = getString(R.string.selectAll)
}
return _SELECT_ALL!!
}
private var _SELECT_NONE: String? = null
private inline val SELECT_NONE: String
get() {
if (_SELECT_NONE == null) {
_SELECT_NONE = getString(R.string.selectNone)
}
return _SELECT_NONE!!
}
fun setVideoOpCallback(callback: VideoListItemOpCallback<Video>?) {
mVideoOpCallback = callback
}
override fun onAttach(context: Context) {
super.onAttach(context)
val parent = parentFragment
mInteractionCallback = when {
parent is InteractionCallback -> parent
context is InteractionCallback -> context
parent != null -> throw RuntimeException("Neither $parent nor $context " +
"has implemented LocalFoldedVideosFragment.InteractionCallback")
else -> throw RuntimeException(
"$context must implement LocalFoldedVideosFragment.InteractionCallback")
}
if (parent is FragmentPartLifecycleCallback) {
mLifecycleCallback = parent
} else if (context is FragmentPartLifecycleCallback) {
mLifecycleCallback = context
}
mLifecycleCallback?.onFragmentAttached(this)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mLifecycleCallback?.onFragmentViewCreated(this)
}
override fun onDestroyView() {
super.onDestroyView()
mLifecycleCallback?.onFragmentViewDestroyed(this)
val task = mLoadDirectoryVideosTask
if (task != null) {
mLoadDirectoryVideosTask = null
task.cancel(false)
}
if (mVideoOptionsFrame.visibility == View.VISIBLE) {
for (video in mVideos) {
video.isChecked = false
}
mInteractionCallback.isRefreshLayoutEnabled = true
}
}
override fun onDestroy() {
super.onDestroy()
App.getInstanceUnsafe()?.refWatcher?.watch(this)
}
override fun onDetach() {
super.onDetach()
mLifecycleCallback?.onFragmentDetached(this)
targetFragment?.onActivityResult(targetRequestCode, RESULT_CODE_LOCAL_FOLDED_VIDEOS_FRAGMENT,
Intent().putExtra(KEY_DIRECTORY_PATH, mVideoDir?.path)
.putParcelableArrayListExtra(KEY_VIDEOS,
mVideos as? ArrayList<Video> ?: ArrayList(mVideos)))
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_local_folded_videos, container, false)
initViews(view)
return attachViewToSwipeBackLayout(view)
}
private fun initViews(contentView: View) {
val actionbar = mInteractionCallback.getActionBar(this)
val titleText = actionbar.findViewById<TextView>(R.id.text_title)
titleText.text = mVideoDir?.name
mRecyclerView = contentView.findViewById(R.id.simrv_foldedVideoList)
mRecyclerView.layoutManager = LinearLayoutManager(contentView.context)
mRecyclerView.adapter = mAdapter
mRecyclerView.addItemDecoration(
DividerItemDecoration(contentView.context, DividerItemDecoration.VERTICAL))
mRecyclerView.setHasFixedSize(true)
mBackButton = actionbar.findViewById(R.id.btn_back)
mCancelButton = actionbar.findViewById(R.id.btn_cancel)
mSelectAllButton = actionbar.findViewById(R.id.btn_selectAll)
mVideoOptionsFrame = contentView.findViewById(R.id.frame_videoOptions)
mDeleteButton = contentView.findViewById(R.id.btn_delete_videoListOptions)
mRenameButton = contentView.findViewById(R.id.btn_rename)
mShareButton = contentView.findViewById(R.id.btn_share)
mDetailsButton = contentView.findViewById(R.id.btn_details)
mBackButton.setOnClickListener(this)
mCancelButton.setOnClickListener(this)
mSelectAllButton.setOnClickListener(this)
mDeleteButton.setOnClickListener(this)
mRenameButton.setOnClickListener(this)
mShareButton.setOnClickListener(this)
mDetailsButton.setOnClickListener(this)
contentView.post {
if (Utils.isLayoutRtl(contentView)) {
swipeBackLayout.enabledEdges = SwipeBackLayout.EDGE_RIGHT
}
}
}
override fun onBackPressed() =
if (mVideoOptionsFrame.visibility == View.VISIBLE) {
hideMultiselectVideoControls()
true
} else false
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
REQUEST_CODE_PLAY_VIDEO -> if (resultCode == RESULT_CODE_PLAY_VIDEO) {
val video = data?.getParcelableExtra<Video>(KEY_VIDEO) ?: return
if (video.id == NO_ID) return
for ((i, v) in mVideos.withIndex()) {
if (v != video) continue
if (v.progress != video.progress) {
v.progress = video.progress
mAdapter.notifyItemChanged(i, PAYLOAD_REFRESH_VIDEO_PROGRESS_DURATION)
}
break
}
}
REQUEST_CODE_PLAY_VIDEOS -> if (resultCode == RESULT_CODE_PLAY_VIDEOS) {
val parcelables = data?.getParcelableArrayExtra(KEY_VIDEOS) ?: return
val videos = Array(parcelables.size) { parcelables[it] as Video }
for (video in videos) {
val index = mVideos.indexOf(video)
val v = if (index != -1) mVideos[index] else null
if (v != null && v.progress != video.progress) {
v.progress = video.progress
mAdapter.notifyItemChanged(index, PAYLOAD_REFRESH_VIDEO_PROGRESS_DURATION)
}
}
}
}
}
override fun onClick(v: View) {
when (v.id) {
R.id.btn_back -> swipeBackLayout.scrollToFinishActivityOrPopUpFragment()
R.id.itemVisibleFrame -> {
val position = v.tag as Int
if (mVideoOptionsFrame.visibility == View.VISIBLE) {
val video = mVideos[position]
video.isChecked = !video.isChecked
mAdapter.notifyItemChanged(position, PAYLOAD_REFRESH_CHECKBOX_WITH_ANIMATOR)
onVideoCheckedChange()
} else {
if (mVideos.size == 1) {
playVideo(mVideos[0])
} else {
playVideos(*mVideos.toTypedArray(), selection = position)
}
}
}
R.id.checkbox -> {
val video = mVideos[v.tag as Int]
video.isChecked = !video.isChecked
onVideoCheckedChange()
}
R.id.btn_top -> {
val index = v.tag as Int
val video = mVideos[index]
val topped = !video.isTopped
video.isTopped = topped
VideoListItemDao.getInstance(v.context).setVideoListItemTopped(video, topped)
val newIndex = mVideos.reordered().indexOf(video)
if (newIndex == index) {
mAdapter.notifyItemChanged(index, PAYLOAD_CHANGE_ITEM_LPS_AND_BG)
} else {
mVideos.add(newIndex, mVideos.removeAt(index))
mAdapter.notifyItemRemoved(index)
mAdapter.notifyItemInserted(newIndex)
mAdapter.notifyItemRangeChanged(min(index, newIndex),
abs(newIndex - index) + 1)
}
}
R.id.btn_delete -> {
val video = mVideos[v.tag as Int]
mVideoOpCallback?.showDeleteItemDialog(video) {
onVideoDeleted(video)
}
}
R.id.btn_cancel -> hideMultiselectVideoControls()
R.id.btn_selectAll -> {
if (mSelectAllButton.text == SELECT_ALL) {
for ((index, video) in mVideos.withIndex())
if (!video.isChecked) {
video.isChecked = true
mAdapter.notifyItemChanged(index, PAYLOAD_REFRESH_CHECKBOX_WITH_ANIMATOR)
}
} else {
for (video in mVideos) video.isChecked = false
mAdapter.notifyItemRangeChanged(0, mAdapter.itemCount,
PAYLOAD_REFRESH_CHECKBOX_WITH_ANIMATOR)
}
onVideoCheckedChange()
}
R.id.btn_delete_videoListOptions -> {
val videos = checkedVideos ?: return
if (videos.size == 1) {
mVideoOpCallback?.showDeleteItemsPopupWindow(videos[0]) {
hideMultiselectVideoControls()
onVideoDeleted(videos[0])
}
} else {
mVideoOpCallback?.showDeleteItemsPopupWindow(*videos.toTypedArray()) {
hideMultiselectVideoControls()
var start = -1
var index = 0
val it = mVideos.iterator()
while (it.hasNext()) {
if (videos.contains(it.next())) {
if (start == -1) {
start = index
}
it.remove()
mAdapter.notifyItemRemoved(index)
index--
}
index++
}
mAdapter.notifyItemRangeChanged(start, mAdapter.itemCount - start)
}
}
}
R.id.btn_rename -> {
val video = checkedVideos?.get(0) ?: return
hideMultiselectVideoControls()
mVideoOpCallback?.showRenameItemDialog(video) {
val index = mVideos.indexOf(video)
val newIndex = mVideos.reordered().indexOf(video)
if (newIndex == index) {
mAdapter.notifyItemChanged(index, PAYLOAD_REFRESH_ITEM_NAME)
} else {
mVideos.add(newIndex, mVideos.removeAt(index))
mAdapter.notifyItemRemoved(index)
mAdapter.notifyItemInserted(newIndex)
mAdapter.notifyItemRangeChanged(min(index, newIndex),
abs(newIndex - index) + 1)
}
}
}
R.id.btn_share -> {
val video = checkedVideos?.get(0) ?: return
hideMultiselectVideoControls()
shareVideo(video)
}
R.id.btn_details -> {
val video = checkedVideos?.get(0) ?: return
hideMultiselectVideoControls()
mVideoOpCallback?.showItemDetailsDialog(video)
}
}
}
override fun onLongClick(v: View) = when (v.id) {
R.id.itemVisibleFrame ->
if (mVideoOptionsFrame.visibility == View.VISIBLE
|| mInteractionCallback.isRefreshLayoutRefreshing) {
false
} else {
mBackButton.visibility = View.GONE
mCancelButton.visibility = View.VISIBLE
mSelectAllButton.visibility = View.VISIBLE
mVideoOptionsFrame.visibility = View.VISIBLE
mRecyclerView.isItemDraggable = false
mInteractionCallback.isRefreshLayoutEnabled = false
mRecyclerView.post {
val itemBottom = (v.parent as View).bottom
val listHeight = mRecyclerView.height
if (itemBottom > listHeight) {
mRecyclerView.scrollBy(0, itemBottom - listHeight)
}
}
val selection = v.tag as Int
mAdapter.run {
notifyItemRangeChanged(0, selection,
PAYLOAD_CHANGE_CHECKBOX_VISIBILITY or PAYLOAD_REFRESH_CHECKBOX)
notifyItemRangeChanged(selection + 1, itemCount - selection - 1,
PAYLOAD_CHANGE_CHECKBOX_VISIBILITY or PAYLOAD_REFRESH_CHECKBOX)
mVideos[selection].isChecked = true
notifyItemChanged(selection,
PAYLOAD_CHANGE_CHECKBOX_VISIBILITY or PAYLOAD_REFRESH_CHECKBOX_WITH_ANIMATOR)
onVideoCheckedChange()
}
true
}
else -> false
}
private fun onVideoCheckedChange() {
var checkedVideosCount = 0
for (video in mVideos) {
if (video.isChecked) checkedVideosCount++
}
when (checkedVideosCount) {
mVideos.size -> mSelectAllButton.text = SELECT_NONE
else -> mSelectAllButton.text = SELECT_ALL
}
mDeleteButton.isEnabled = checkedVideosCount > 0
val enabled = checkedVideosCount == 1
mRenameButton.isEnabled = enabled
mShareButton.isEnabled = enabled
mDetailsButton.isEnabled = enabled
}
private inline val checkedVideos: List<Video>?
get() {
var videos: MutableList<Video>? = null
for (video in mVideos) {
if (video.isChecked) {
if (videos == null) videos = mutableListOf()
videos.add(video)
}
}
return videos
}
private fun hideMultiselectVideoControls() {
mBackButton.visibility = View.VISIBLE
mCancelButton.visibility = View.GONE
mSelectAllButton.visibility = View.GONE
mVideoOptionsFrame.visibility = View.GONE
mRecyclerView.isItemDraggable = true
mInteractionCallback.isRefreshLayoutEnabled = true
for (video in mVideos) {
video.isChecked = false
}
mAdapter.notifyItemRangeChanged(0, mAdapter.itemCount,
PAYLOAD_CHANGE_CHECKBOX_VISIBILITY or PAYLOAD_REFRESH_CHECKBOX)
}
private fun onVideoDeleted(video: Video) {
val index = mVideos.indexOf(video)
if (index != -1) {
mVideos.removeAt(index)
mAdapter.notifyItemRemoved(index)
mAdapter.notifyItemRangeChanged(index, mAdapter.itemCount - index)
}
}
override fun onReloadVideos(videos: List<Video>?) =
if (videos == null || videos.isEmpty()) {
onReloadDirectoryVideos(null)
} else {
onReloadDirectoryVideos(
videos.filter {
it.path.substring(0, it.path.lastIndexOf(File.separatorChar))
.equals(mVideoDir?.path, ignoreCase = true)
}.reordered())
}
private fun onReloadDirectoryVideos(videos: List<Video>?) {
if (videos == null || videos.isEmpty()) {
if (mVideos.isNotEmpty()) {
mVideos.clear()
mAdapter.notifyDataSetChanged()
if (mVideoOptionsFrame.visibility == View.VISIBLE) {
hideMultiselectVideoControls()
}
}
} else
if (videos.size == mVideos.size) {
var changedIndices: MutableList<Int>? = null
for (i in videos.indices) {
if (!videos[i].allEqual(mVideos[i])) {
if (changedIndices == null) changedIndices = LinkedList()
changedIndices.add(i)
}
}
if (changedIndices != null) {
for (index in changedIndices) {
mVideos[index] = videos[index]
mAdapter.notifyItemChanged(index) // without payload
}
if (mVideoOptionsFrame.visibility == View.VISIBLE) {
hideMultiselectVideoControls()
}
}
} else {
mVideos.set(videos)
mAdapter.notifyDataSetChanged()
if (mVideoOptionsFrame.visibility == View.VISIBLE) {
hideMultiselectVideoControls()
}
}
}
override fun onRefresh() {
if (mVideoOpCallback?.isAsyncDeletingItems == true) {
mInteractionCallback.isRefreshLayoutRefreshing = false
return
}
if (mVideoOptionsFrame.visibility == View.VISIBLE) {
hideMultiselectVideoControls()
}
if (mLoadDirectoryVideosTask == null) {
mLoadDirectoryVideosTask = LoadDirectoryVideosTask()
mLoadDirectoryVideosTask!!.executeOnExecutor(ParallelThreadExecutor.getInstance())
}
}
@SuppressLint("StaticFieldLeak")
private inner class LoadDirectoryVideosTask : AsyncTask<Void, Void, List<Video>?>() {
override fun onPreExecute() {
mRecyclerView.isItemDraggable = false
mRecyclerView.releaseItemView(false)
}
override fun doInBackground(vararg params: Void?): List<Video>? {
val dao = VideoListItemDao.getInstance(contextRequired)
var videos: MutableList<Video>? = null
val videoCursor = dao.queryAllVideosInDirectory(mVideoDir?.path) ?: return null
while (!isCancelled && videoCursor.moveToNext()) {
val video = dao.buildVideo(videoCursor) ?: continue
if (videos == null)
videos = LinkedList()
videos.add(video)
}
videoCursor.close()
return videos?.reordered()
}
override fun onPostExecute(videos: List<Video>?) {
onReloadDirectoryVideos(videos)
mRecyclerView.isItemDraggable = true
mInteractionCallback.isRefreshLayoutRefreshing = false
mLoadDirectoryVideosTask = null
}
override fun onCancelled(result: List<Video>?) {
if (mLoadDirectoryVideosTask == null) {
mRecyclerView.isItemDraggable = true
mInteractionCallback.isRefreshLayoutRefreshing = false
}
}
}
private inner class VideoListAdapter : RecyclerView.Adapter<VideoListAdapter.ViewHolder>() {
override fun getItemCount() = mVideos.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
ViewHolder(
LayoutInflater.from(parent.context)
.inflate(R.layout.video_list_item_video, parent, false))
override fun onBindViewHolder(holder: ViewHolder, position: Int, payloads: List<Any>) {
if (payloads.isEmpty()) {
onBindViewHolder(holder, position)
} else {
val video = mVideos[position]
val payload = payloads[0] as Int
if (payload and PAYLOAD_CHANGE_ITEM_LPS_AND_BG != 0) {
separateToppedItemsFromUntoppedOnes(holder, position)
}
if (payload and PAYLOAD_CHANGE_CHECKBOX_VISIBILITY != 0) {
holder.checkBox.visibility = mVideoOptionsFrame.visibility
}
if (payload and PAYLOAD_REFRESH_CHECKBOX != 0) {
holder.checkBox.isChecked = video.isChecked
} else if (payload and PAYLOAD_REFRESH_CHECKBOX_WITH_ANIMATOR != 0) {
holder.checkBox.setChecked(video.isChecked, true)
}
if (payload and PAYLOAD_REFRESH_ITEM_NAME != 0) {
holder.videoNameText.text = video.name
}
if (payload and PAYLOAD_REFRESH_VIDEO_PROGRESS_DURATION != 0) {
holder.videoProgressAndDurationText.text =
VideoUtils2.concatVideoProgressAndDuration(video.progress, video.duration)
}
}
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.itemVisibleFrame.tag = position
holder.checkBox.tag = position
holder.topButton.tag = position
holder.deleteButton.tag = position
separateToppedItemsFromUntoppedOnes(holder, position)
val video = mVideos[position]
holder.checkBox.run {
visibility = mVideoOptionsFrame.visibility
isChecked = video.isChecked
}
VideoUtils2.loadVideoThumbnailIntoImageView(holder.videoImage, video)
holder.videoNameText.text = video.name
holder.videoSizeText.text = FileUtils2.formatFileSize(video.size.toDouble())
holder.videoProgressAndDurationText.text =
VideoUtils2.concatVideoProgressAndDuration(video.progress, video.duration)
}
private fun separateToppedItemsFromUntoppedOnes(holder: ViewHolder, position: Int) {
val context = contextThemedFirst
val lp = holder.topButton.layoutParams
if (mVideos[position].isTopped) {
ViewCompat.setBackground(holder.itemVisibleFrame,
ContextCompat.getDrawable(context, R.drawable.selector_topped_recycler_item))
lp.width = DensityUtils.dp2px(context, 120f)
holder.topButton.layoutParams = lp
holder.topButton.text = CANCEL_TOP
} else {
ViewCompat.setBackground(holder.itemVisibleFrame,
ContextCompat.getDrawable(context, R.drawable.default_selector_recycler_item))
lp.width = DensityUtils.dp2px(context, 90f)
holder.topButton.layoutParams = lp
holder.topButton.text = TOP
}
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val itemVisibleFrame: ViewGroup = itemView.findViewById(R.id.itemVisibleFrame)
val checkBox: CircularCheckBox = itemView.findViewById(R.id.checkbox)
val videoImage: ImageView = itemView.findViewById(R.id.image_video)
val videoNameText: TextView = itemView.findViewById(R.id.text_videoName)
val videoSizeText: TextView = itemView.findViewById(R.id.text_videoSize)
val videoProgressAndDurationText: TextView = itemView.findViewById(R.id.text_videoProgressAndDuration)
val topButton: TextView = itemView.findViewById(R.id.btn_top)
val deleteButton: TextView = itemView.findViewById(R.id.btn_delete)
init {
itemVisibleFrame.setOnClickListener(this@LocalFoldedVideosFragment)
checkBox.setOnClickListener(this@LocalFoldedVideosFragment)
topButton.setOnClickListener(this@LocalFoldedVideosFragment)
deleteButton.setOnClickListener(this@LocalFoldedVideosFragment)
itemVisibleFrame.setOnLongClickListener(this@LocalFoldedVideosFragment)
}
}
}
interface InteractionCallback : ActionBarCallback, RefreshLayoutCallback
}
解决方案
推荐阅读
- powershell - 当命令行参数提供变量时,Powershell 命令调用不起作用
- mongodb - 构建多个索引,其中一个在 Mongo 中是唯一的
- python - 是否有 python 函数来颜色/样式多索引级别?
- reactjs - 带有可变路径的图像需要不起作用
- delphi - Delphi 网络打印机访问路径
- swift - 如何将 ViewModel 绑定到 Collationview?
- oracle - plsql这个代码错误有什么问题'INTO列表类型错误'
- ios - PencilKit 的 Xcode 项目的 .drawing 扩展文件?
- entity-framework - 尝试激活“Controllers.HomeController”时无法解析“IRepositoryPMS.IProductRepository”类型的服务
- python - 如何检测使用 webapp2 单击了哪个图像按钮(输入类型 = 图像)?