Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin RecyclerView如何选择活动加载后的第一个列表项?已尝试(下面的代码)失败:(_Kotlin_Android Recyclerview - Fatal编程技术网

Kotlin RecyclerView如何选择活动加载后的第一个列表项?已尝试(下面的代码)失败:(

Kotlin RecyclerView如何选择活动加载后的第一个列表项?已尝试(下面的代码)失败:(,kotlin,android-recyclerview,Kotlin,Android Recyclerview,我可以在回收视图中选择第一个项目(下面的工作代码,单击“电子邮件”工厂按钮-boom!第一个选中) 但是,当应用程序启动时,我无法在代码中获得第一次RecyclerView点击 我寻找了override fun onViewCreated(),但在activity中找不到类似的内容 活动和回收视图完全呈现后,在哪里可以调用selectFirstOnList()? 在活动完全呈现/加载时触发什么事件? 还是我的noob kotlin思维方式有缺陷?其99.9%的有效性:( 提前感谢您的帮助:) 解

我可以在回收视图中选择第一个项目(下面的工作代码,单击“电子邮件”工厂按钮-boom!第一个选中)

但是,当应用程序启动时,我无法在代码中获得第一次RecyclerView点击

我寻找了override fun onViewCreated(),但在activity中找不到类似的内容

活动和回收视图完全呈现后,在哪里可以调用selectFirstOnList()? 在活动完全呈现/加载时触发什么事件?

还是我的noob kotlin思维方式有缺陷?其99.9%的有效性:(

提前感谢您的帮助:)

解决方案(编辑到本文底部的代码将替换ItemListActivity.kt中的代码)

ItemListActivity.kt

package ie.dpsystems.asm.list

import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.graphics.Color
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.snackbar.Snackbar
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import ie.dpsystems.asm.R
import ie.dpsystems.asm.data.Orientation
import ie.dpsystems.asm.data.State
import ie.dpsystems.asm.data.State.Companion.trackLog
import ie.dpsystems.asm.detail.ItemDetailActivity
import ie.dpsystems.asm.detail.ItemDetailFragment

import kotlinx.android.synthetic.main.activity_item_list.*
import kotlinx.android.synthetic.main.item_list_content.view.*
import kotlinx.android.synthetic.main.item_list.*
import android.os.Handler


class ItemListActivity : AppCompatActivity() {
    private var twoPane: Boolean = false
    private var showToastEvents: Boolean = true

    private fun uiIsTwoPane():Boolean{
        try{
            if (item_detail_container != null) {
                // The detail container view will be present only in the
                // large-screen layouts (res/values-w900dp).
                // If this view is present, then the
                // activity should be in two-pane mode.
                return true
            }
        }catch(e:Exception)
        {
            Toast.makeText(this,"E: ${e.toString()}",Toast.LENGTH_SHORT).show()
        }
        return false
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        trackLog(this,"onCreate()")
        setContentView(R.layout.activity_item_list)

        twoPane = uiIsTwoPane()
        setSupportActionBar(toolbar)
        toolbar.title = title
        fab.setOnClickListener { view -> onListFabClick(view) }
        setupRecyclerView(recycleview_list)
        refreshUI()
    }

    private fun setupRecyclerView(recyclerView: RecyclerView) {
        trackLog(this,"setupRecyclerView()")
        State.dataRows = ListContent.ITEMS
        recyclerView.adapter = SimpleItemRecyclerViewAdapter(
            this,
            twoPane,
            this
        )

        var recycleViewUI = recycleview_list
        postAndNotifyAdapter(Handler(), recycleViewUI)
    }

    override fun onConfigurationChanged(newConfig: Configuration?) {
        super.onConfigurationChanged(newConfig)
        trackLog(this,"onConfigurationChanged()")
    }

    override fun onStart() {
        super.onStart()
        trackLog(this,"onStart()")
    }

    override fun onResume() {
        super.onResume()
        trackLog(this,"onResume() A")
        checkOrientationChange()
        refreshUI()
        trackLog(this,"onResume() B")

    }

    private fun checkOrientationChange() {
        trackLog(this,"checkOrientationChange()")
        if (State.lastOrientation != null) {
            val thisOrientation = if (twoPane) Orientation.landscape else Orientation.portrate
            if (thisOrientation != State.lastOrientation) {
                putDetailFragmentOnDetailFragmentHolder()
            }
        }
    }

    private fun putDetailFragmentOnDetailFragmentHolder() {
        trackLog(this,"putDetailFragmentOnDetailFragmentHolder()")
        if(item_detail_container!=null){
            val fragment = ItemDetailFragment()   //val fragment = ItemDetailFragment().apply {arguments = Bundle().apply {putInt("SOME UNIQUE TAG", selectedItemUniqueID)}}
            val container = item_detail_container
            container.removeAllViewsInLayout()
            supportFragmentManager.beginTransaction().replace(R.id.item_detail_container, fragment).commit()
        }
    }

    override fun onPause() {
        super.onPause()
        trackLog(this,"onPause()")
    }

    override fun onStop() {
        super.onStop()
        trackLog(this,"onStop()")
    }

    class SimpleItemRecyclerViewAdapter( private val parentActivity: ItemListActivity
                                         ,private val twoPane: Boolean
                                         ,private val context: Context //private val context = parentActivity.applicationContext
    ) : RecyclerView.Adapter<SimpleItemRecyclerViewAdapter.ViewHolder>() {

        override fun getItemCount(): Int {
            return State.dataRows.size
        }

        override fun onBindViewHolder(recyclerViewRow: ViewHolder, position: Int) {
            trackLog(context, "onBindViewHolder()")
            val dataThisRow = State.dataRows[position]
            dataThisRow.listRowIndex = position
            setDataToRecyclerRow(recyclerViewRow, dataThisRow)

            recyclerViewRow.itemView.setOnClickListener {
                onListItemClick(dataThisRow.uniqueID)
            }

            if (dataThisRow.uniqueID == State.selectedListItemUniqueId) {
                recyclerViewRow.idRow.setBackgroundColor(Color.parseColor("#009688"))
            } else {
                recyclerViewRow.idRow.setBackgroundColor(Color.WHITE)
            }
        }

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
            trackLog(context, "onCreateViewHolder()")
            val view = LayoutInflater.from(parent.context)
                .inflate(R.layout.item_list_content, parent, false)
            return ViewHolder(view, 1)
        }

        override fun onViewAttachedToWindow(holder: ViewHolder) {
            super.onViewAttachedToWindow(holder)
            trackLog(context, "onViewAttachedToWindow()")
        }

        inner class ViewHolder(itemView: View, position: Int) : RecyclerView.ViewHolder(itemView) {
            val idView: TextView = itemView.id_text
            val contentView: TextView = itemView.content
            val idRow = itemView.id_row_linear_layout
        }

        private fun setDataToRecyclerRow(recyclerViewRow: ViewHolder, data: ListContent.ListItem) {
            trackLog(context, "setDataToRecyclerRow(id: ${data.id})")
            recyclerViewRow.idView.text = data.id
            recyclerViewRow.contentView.text = data.itemTitle
            recyclerViewRow.itemView.tag = data
        }

        private fun onListItemClick(selectedItemUniqueID: Int) {
            trackLog(context, "onListItemClick($selectedItemUniqueID)")
            State.selectedListItemUniqueId = selectedItemUniqueID

            if (twoPane) {
                State.lastOrientation = Orientation.landscape
                putDetailFragmentOnDetailActivity()
            } else {
                State.lastOrientation = Orientation.portrate
                launchDetailActivity()
            }
            notifyDataSetChanged()
        }

        private fun launchDetailActivity() {
            trackLog(context, "launchDetailActivity()")
            val intent = Intent(
                context,
                ItemDetailActivity::class.java
            )   //val intent = Intent(context, ItemDetailActivity::class.java).apply {putExtra(ItemDetailFragment.ARG_ITEM_ID, selectedItemUniqueID)}
            context.startActivity(intent)
        }

        private fun putDetailFragmentOnDetailActivity() {
            trackLog(context, "putDetailFragmentOnDetailFragmentHolder()")
            val fragment =
                ItemDetailFragment()   //val fragment = ItemDetailFragment().apply {arguments = Bundle().apply {putInt("SOME UNIQUE TAG", selectedItemUniqueID)}}
            val container = parentActivity.item_detail_container
            container.removeAllViewsInLayout()
            parentActivity.supportFragmentManager.beginTransaction()
                .replace(R.id.item_detail_container, fragment).commit()
        }
    }




    private fun onListFabClick(view: View) {
        trackLog(this, "onListFabClick()")
        selectFirstOnList()
        Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
            .setAction("Action", null).show()
    }

    private fun refreshUI() {
        trackLog(this, "refreshUI()")
        var recycleViewUI = recycleview_list

        if (State.selectedListItemUniqueId == null) {
            selectFirstOnList()
        } else {
            val selectedListItem: ListContent.ListItem? =
                State.findDataRowByUniqueId(State.selectedListItemUniqueId)
            if (selectedListItem == null) {
                selectFirstOnList()
                recycleViewUI.findViewHolderForAdapterPosition(0)?.itemView?.performClick()
            } else {
                recycleViewUI.getLayoutManager()
                    ?.scrollToPosition(selectedListItem.listRowIndex)
            }

        }
    }

    private fun selectFirstOnList() {
        trackLog(this, "selectFirstOnList()")
        if (twoPane) {
            var recycleViewUI = recycleview_list
            //recycleViewUI.getLayoutManager()?.scrollToPosition(0)
            recycleViewUI.findViewHolderForAdapterPosition(0)?.itemView?.performClick()
        }
    }

    protected fun postAndNotifyAdapter(handler: Handler, recyclerView: RecyclerView) {
        trackLog(this, "postAndNotifyAdapter()")
/*
        handler.post(Runnable {
            if (!recyclerView.isComputingLayout) {
                // This will call first item by calling "performClick()" of view.
                (recyclerView.findViewHolderForLayoutPosition(0) as RecyclerView.ViewHolder).itemView.performClick()
            } else {
                postAndNotifyAdapter(handler, recyclerView) //, adapter
            }
        })
*/
    }
}
<?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="match_parent"
    android:layout_marginLeft="16dp"
    android:layout_marginRight="16dp"
    android:baselineAligned="false"
    android:divider="?android:attr/dividerHorizontal"
    android:orientation="horizontal"
    android:showDividers="middle"
    tools:context=".list.ItemListActivity">

    <!--
    This layout is a two-pane layout for list / detail
    -->

    <androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/recycleview_list"
        android:name="ie.dpsystems.asm.ItemListFragment"
        android:layout_width="@dimen/item_width"
        android:layout_height="match_parent"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        app:layoutManager="LinearLayoutManager"
        tools:context="ie.dpsystems.asm.list.ItemListActivity"
        tools:listitem="@layout/item_list_content" />

    <FrameLayout
        android:id="@+id/item_detail_container"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="3" />

</LinearLayout>
import java.util.ArrayList
import java.util.HashMap

/**
 * Helper class for providing sample itemTitle for user interfaces created by
 * Android template wizards.
 *
 * TODO: Replace all uses of this class before publishing your app.
 */
object ListContent {

    /**
     * An array of sample (dummy) items.
     */
    val ITEMS: MutableList<ListItem> = ArrayList()

    /**
     * A map of sample (dummy) items, by ID.
     */
    val ITEM_MAP: MutableMap<String, ListItem> = HashMap()

    private val COUNT = 25

    init {
        // Add some sample items.
        for (i in 1..COUNT) {
            addItem(fakeGetRecordFromSqlite(i))
        }
    }

    private fun addItem(item: ListItem) {
        ITEMS.add(item)
        ITEM_MAP.put(item.id, item)
    }

    private fun fakeGetRecordFromSqlite(position: Int): ListItem {
        return ListItem(position, -1, position.toString(), "Item " + position, fakeGetRecordCollectionFromSqlite(position))
    }

    private fun fakeGetRecordCollectionFromSqlite(position: Int): String {
        val builder = StringBuilder()
        builder.append("Details about Item: ").append(position)
        for (i in 0..position - 1) {
            builder.append("\nMore details information here.")
        }
        return builder.toString()
    }

    /**
     * A dummy item representing a piece of itemTitle.
     */
    data class ListItem(val uniqueID:Int, var listRowIndex:Int, val id: String, val itemTitle: String, val details: String) {
        override fun toString(): String = itemTitle
    }
}

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import ie.dpsystems.asm.R
import ie.dpsystems.asm.data.State
import ie.dpsystems.asm.list.ListContent
import kotlinx.android.synthetic.main.activity_item_detail.*
import kotlinx.android.synthetic.main.item_detail.view.*

/**
 * A fragment representing a single Item detail screen.
 * This fragment is either contained in a [ItemListActivity]
 * in two-pane mode (on tablets) or a [ItemDetailActivity]
 * on handsets.
 */
class ItemDetailFragment : Fragment() {

    /**
     * The dummy itemTitle this fragment is presenting.
     */
    private var item: ListContent.ListItem? = null
    private var selectedItemUniqueID:Int? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //arguments?.let { if (it.containsKey(ARG_ITEM_ID)) {val uniqueID = it.getInt(ARG_ITEM_ID)}}
        item = State.findDataRowByUniqueId(State.selectedListItemUniqueId)
        activity?.toolbar_layout?.title = item?.itemTitle
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {
        val rootView = inflater.inflate(R.layout.item_detail, container, false)
        item?.let {rootView.item_detail.text = it.details}
        return rootView
    }
}
class ItemDetailActivity(适用于单窗格屏幕大小的设备)

解决方案 postdelay先选择(您可以从原始代码中看到我已经尝试过类似的东西!)呸!希望这对某人有所帮助:)


我已经编辑了我的原始文章以上是完整的答案

我建议您使用一个界面来通知recyclerview何时完成对其项目的渲染

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/id_row_linear_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/id_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/text_margin"
        android:textAppearance="?attr/textAppearanceListItem" />

    <TextView
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/text_margin"
        android:textAppearance="?attr/textAppearanceListItem" />
</LinearLayout>
import java.util.ArrayList
import java.util.HashMap

/**
 * Helper class for providing sample itemTitle for user interfaces created by
 * Android template wizards.
 *
 * TODO: Replace all uses of this class before publishing your app.
 */
object ListContent {

    /**
     * An array of sample (dummy) items.
     */
    val ITEMS: MutableList<ListItem> = ArrayList()

    /**
     * A map of sample (dummy) items, by ID.
     */
    val ITEM_MAP: MutableMap<String, ListItem> = HashMap()

    private val COUNT = 25

    init {
        // Add some sample items.
        for (i in 1..COUNT) {
            addItem(fakeGetRecordFromSqlite(i))
        }
    }

    private fun addItem(item: ListItem) {
        ITEMS.add(item)
        ITEM_MAP.put(item.id, item)
    }

    private fun fakeGetRecordFromSqlite(position: Int): ListItem {
        return ListItem(position, -1, position.toString(), "Item " + position, fakeGetRecordCollectionFromSqlite(position))
    }

    private fun fakeGetRecordCollectionFromSqlite(position: Int): String {
        val builder = StringBuilder()
        builder.append("Details about Item: ").append(position)
        for (i in 0..position - 1) {
            builder.append("\nMore details information here.")
        }
        return builder.toString()
    }

    /**
     * A dummy item representing a piece of itemTitle.
     */
    data class ListItem(val uniqueID:Int, var listRowIndex:Int, val id: String, val itemTitle: String, val details: String) {
        override fun toString(): String = itemTitle
    }
}

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import ie.dpsystems.asm.R
import ie.dpsystems.asm.data.State
import ie.dpsystems.asm.list.ListContent
import kotlinx.android.synthetic.main.activity_item_detail.*
import kotlinx.android.synthetic.main.item_detail.view.*

/**
 * A fragment representing a single Item detail screen.
 * This fragment is either contained in a [ItemListActivity]
 * in two-pane mode (on tablets) or a [ItemDetailActivity]
 * on handsets.
 */
class ItemDetailFragment : Fragment() {

    /**
     * The dummy itemTitle this fragment is presenting.
     */
    private var item: ListContent.ListItem? = null
    private var selectedItemUniqueID:Int? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //arguments?.let { if (it.containsKey(ARG_ITEM_ID)) {val uniqueID = it.getInt(ARG_ITEM_ID)}}
        item = State.findDataRowByUniqueId(State.selectedListItemUniqueId)
        activity?.toolbar_layout?.title = item?.itemTitle
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {
        val rootView = inflater.inflate(R.layout.item_detail, container, false)
        item?.let {rootView.item_detail.text = it.details}
        return rootView
    }
}
import android.content.Intent
import android.os.Bundle
import com.google.android.material.snackbar.Snackbar
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.NavUtils
import android.view.MenuItem
import android.view.View
import ie.dpsystems.asm.list.ItemListActivity
import ie.dpsystems.asm.R
import kotlinx.android.synthetic.main.activity_item_detail.*
import kotlinx.android.synthetic.main.activity_item_detail.fab

/**
 * An activity representing a single Item detail screen. This
 * activity is only used on narrow width devices. On tablet-size devices,
 * item details are presented side-by-side with a list of items
 * in a [ItemListActivity].
 */
class ItemDetailActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_item_detail)
        setSupportActionBar(detail_toolbar)

        fab.setOnClickListener { view -> onListFabClick(view) }
        supportActionBar?.setDisplayHomeAsUpEnabled(true) // Show the Up button in the action bar.
        putDetailFragmentOnDetailActivity(savedInstanceState)
    }

    private fun putDetailFragmentOnDetailActivity(savedInstanceState: Bundle?){    // Create the detail fragment and add it to the activity using a fragment transaction.
        // savedInstanceState is non-null when there is fragment state
        // saved from previous configurations of this activity
        // (e.g. when rotating the screen from portrait to landscape).
        // In this case, the fragment will automatically be re-added
        // to its container so we don't need to manually add it.
        // For more information, see the Fragments API guide at:
        // http://developer.android.com/guide/components/fragments.html
        if (savedInstanceState == null) {
            val fragment = ItemDetailFragment()             //val fragment = ItemDetailFragment().apply {arguments = Bundle().apply {putString("SOME UNIQUE TAG",intent.getStringExtra("SOME UNIQUE TAG"))}}
            supportFragmentManager.beginTransaction().add(R.id.item_detail_container, fragment).commit()
        }
    }

    private fun onListFabClick(view: View?) {
        if(view!=null) Snackbar.make(view, "Replace with your own detail action", Snackbar.LENGTH_LONG).setAction("Action", null).show()
    }

    override fun onOptionsItemSelected(item: MenuItem) =
        when (item.itemId) {
            android.R.id.home -> {
                // This ID represents the Home or Up button. In the case of this
                // activity, the Up button is shown. Use NavUtils to allow users
                // to navigate up one level in the application structure. For
                // more details, see the Navigation pattern on Android Design:
                //
                // http://developer.android.com/design/patterns/navigation.html#up-vs-back

                NavUtils.navigateUpTo(this, Intent(this, ItemListActivity::class.java))
                true
            }
            else -> super.onOptionsItemSelected(item)
        }
}
    protected fun postAndNotifyAdapter(handler: Handler, recyclerView: RecyclerView) {
        trackLog(this, "postAndNotifyAdapter() ${State.selectedListItemUniqueId}")
        if (twoPane && State.selectedListItemUniqueId==null) {
            Handler().postDelayed({
                if (!recyclerView.isComputingLayout) {
                    trackLog(this, "postAndNotifyAdapter() !recyclerView.isComputingLayout ${State.selectedListItemUniqueId}")
                    selectFirstOnList()
                } else {
                    postAndNotifyAdapter(handler, recyclerView) //, adapter
                }
            }, 1000)
        }
    }