简体   繁体   中英

How do I use buttons inside fragments in Kotlin for android development?

I am new to android development and created a new project from android studio with a bottom navigation activity in Kotlin. Besides MainActivity.kt also dashboard, home and notifications Fragments and its ViewModels were generated. When I handle the button click inside the MainActivity class, everything works fine.

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val navView: BottomNavigationView = findViewById(R.id.nav_view)

        val navController = findNavController(R.id.nav_host_fragment)
        // Passing each menu ID as a set of Ids because each
        // menu should be considered as top level destinations.
        val appBarConfiguration = AppBarConfiguration(setOf(
                R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications))
        setupActionBarWithNavController(navController, appBarConfiguration)
        navView.setupWithNavController(navController)

        //handle button click
        val temporary_button = findViewById<Button>(R.id.temporary_button)
        temporary_button.setOnClickListener{
            makeText(this, "You clicked the button", LENGTH_LONG).show()
        }
    }
}

Here is the screenshot of a working button Button works fine

However I do not understand how to use the buttons inside different fragments. I tried to create a functionality for the second button inside a dashboard fragment Screenshot of a second button but I haven't found a solution. I have tried

class DashboardFragment : Fragment() {

    private lateinit var dashboardViewModel: DashboardViewModel

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        dashboardViewModel =
            ViewModelProviders.of(this).get(DashboardViewModel::class.java)
        val root = inflater.inflate(R.layout.fragment_dashboard, container, false)
        val textView: TextView = root.findViewById(R.id.text_dashboard)
        dashboardViewModel.text.observe(this, Observer {
            textView.text = it
        })
        //handle button click
        val temporary_button = findViewById<Button>(R.id.temporary_button2)
        temporary_button2.setOnClickListener{
            makeText(this, "You clicked the button", LENGTH_LONG).show()
        }
        return root
    }

}

but apperently this piece of code

//handle button click
    val temporary_button = findViewById<Button>(R.id.temporary_button2)
    temporary_button2.setOnClickListener{
        makeText(this, "You clicked the button", LENGTH_LONG).show()
    }

is wrong. Another thing that I have tried is changing the fragment_dashboard.xml file and setting the onClick property to a function name ( android:onClick="button2click" ). Here is the entire xml:

    <androidx.constraintlayout.widget.ConstraintLayout
    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" >

    <TextView
        android:id="@+id/text_dashboard"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:textAlignment="center"
        android:textSize="20sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <Button
        android:id="@+id/temporary_button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="192dp"
        android:layout_marginBottom="248dp"
        android:onClick="button2click"
        android:text="Button2"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent" />

I tried to use the function like this:

class DashboardFragment : Fragment() {

    private lateinit var dashboardViewModel: DashboardViewModel

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        dashboardViewModel =
            ViewModelProviders.of(this).get(DashboardViewModel::class.java)
        val root = inflater.inflate(R.layout.fragment_dashboard, container, false)
        val textView: TextView = root.findViewById(R.id.text_dashboard)
        dashboardViewModel.text.observe(this, Observer {
            textView.text = it
        })

        return root
    }
    fun button2click (view: View){
        println("Button clicked")
    }

}

but this way it doesn't work and the application crashes when I click the button.

Any help on how to use the buttons inside fragments would be appreceated.

Try your inside onViewCreated instead of onCreateView using getView()/view.

eg:

override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
   val temporary_button = getView().findViewById<Button>(R.id.temporary_button2)
   temporary_button2.setOnClickListener{
   makeText(this, "You clicked the button", LENGTH_LONG).show()
   }
 }

There is no findViewById in fragment, normally inside a fragment you should override the onCreateView method, inflate your own layout and try to get views from the view you inflated. For example:

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (mContentView == null){
            mContentView = inflater.inflate(R.layout.family_fragment_scene_list, container, false);
        }

        type = getArguments().getInt(ARGS_KEY_TYPE);

        adapter = new SceneAdapter(getContext());
        // get views from mContentView
        mSceneList = (RecyclerView) mContentView.findViewById(R.id.swipe_target);
        mSceneList.setLayoutManager(new LinearLayoutManager(getContext()));
        mSceneList.setAdapter(adapter);

        return mContentView;
    }

This is what worked out for me in the end:

class DashboardFragment : Fragment() {

private lateinit var dashboardViewModel: DashboardViewModel

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    dashboardViewModel =
        ViewModelProviders.of(this).get(DashboardViewModel::class.java)
    val root = inflater.inflate(R.layout.fragment_dashboard, container, false)
    val textView: TextView = root.findViewById(R.id.text_dashboard)
    dashboardViewModel.text.observe(this, Observer {
        textView.text = it
    })
    val button2 : Button = root.findViewById<Button>(R.id.temporary_button2)
    button2.setOnClickListener{
        println("clicked button 2")
        Toast.makeText(view?.context, "Button Clicked", Toast.LENGTH_LONG).show()
    }
    return root
}

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM