android - 如何从活动中更改片段的视图/按钮的可见性?
问题描述
正如标题所示,我正在尝试从活动中更改片段的视图/按钮的可见性。
片段代码:
package nus.is3261.kotlinapp
import android.content.Context
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
*
*/
class SettingFragment : Fragment() {
private var listener:SettingFragment.OnFragmentInteractionListener? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_setting, container, false)
val signIn = view.findViewById<View>(R.id.btn_sign_in)
signIn.setOnClickListener {
onButtonPressed("signIn")
}
val signOut = view.findViewById<Button>(R.id.btn_sign_out)
signOut.setOnClickListener {
onButtonPressed("signOut")
}
return view
}
fun changeVisibility(isSignedIn : Boolean){
if (isSignedIn) {
val signIn = view?.findViewById<View>(R.id.btn_sign_in)
signIn?.visibility = View.GONE
val signOut = view?.findViewById<View>(R.id.btn_sign_out)
signOut?.visibility = View.VISIBLE
} else {
val signIn = view?.findViewById<View>(R.id.btn_sign_in)
signIn?.visibility = View.VISIBLE
val signOut = view?.findViewById<View>(R.id.btn_sign_out)
signOut?.visibility = View.GONE
}
}
fun onButtonPressed(str: String) {
listener?.onFragmentInteraction(str)
}
override fun onAttach(context: Context) {
super.onAttach(context)
if (context is SettingFragment.OnFragmentInteractionListener) {
listener = context
} else {
throw RuntimeException(context.toString() + " must implement OnFragmentInteractionListener")
}
}
override fun onDetach() {
super.onDetach()
listener = null
}
interface OnFragmentInteractionListener {
fun onFragmentInteraction(str: String)
}
}
如您所见,我有 changeVisibility 函数来更改已设置按钮的可见性。现在,我如何从主要活动中调用这些函数?我从主要活动中尝试了这个,但遗憾的是它不起作用:
private fun updateUI(user: FirebaseUser?) {
if (user != null) {
// tvStatus.text = "Google User email: " + user.email!!
// tvDetail.text = "Firebase User ID: " + user.uid
val fragment = SettingFragment()
fragment.changeVisibility(true)
// btn_sign_in.visibility = View.GONE
// layout_sign_out_and_disconnect.visibility = View.VISIBLE
} else {
// tvStatus.text = "Signed Out"
// tvDetail.text = null
val fragment = SettingFragment()
fragment.changeVisibility(false)
// btn_sign_in.visibility = View.VISIBLE
// layout_sign_out_and_disconnect.visibility = View.GONE
}
}
这是我的xml文件:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/dracula"
tools:context=".SettingFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.gms.common.SignInButton
android:id="@+id/btn_sign_in"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="0dp"
android:visibility="visible"
tools:visibility="gone" />
<Button
android:id="@+id/btn_sign_out"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:visibility="gone"
tools:visibility="visible"
android:backgroundTint="@color/draculalight"
android:textColor="@color/green"
android:text="@string/signout" />
</LinearLayout>
</FrameLayout>
解决方案
好的,所以你有几个问题,但最好是我为你一步一步地提供一个完整的步骤。所以让我们从头开始。
所以首先是问题
你引用了错误的内存。首先,您将一个片段放入您的 xml 中,然后创建一个不同的实例,这就像倒一杯咖啡,然后从一个新的空杯子中喝水,然后想知道为什么咖啡没有在里面。
现在寻求解决方案。
首先,您的 MainActivity(或片段的父活动)必须包含您尝试包含的片段的元素。你有几个选择来做到这一点。让我们从最简单的方法开始,假设它是一个不会被换出的静态片段。
选项 1(固定片段)
<ParentActivityLayoutOfYourChoice>
<fragment
android:name="com.yourpath.FooFragment"
android:id="@+id/fooFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</ParentActivityLayoutOfYourChoice>
然后在 Activity 中,您只需创建一个成员变量并像这样访问它:
//lateinit only if you guarantee it will be there in the oncreate
private lateinit var fooFragment: FooFragment
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
fooFragment = findViewById(R.id.fooFragment)
}
fun btnSignIn_onClick(){
//onSuccess
fooFragment.isSignedIn(true)
}
选项 2(动态片段)
<ParentActivityLayoutOfYourChoice>
<FrameLayout
android:id="@+id/fragPlaceholder"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</ParentActivityLayoutOfYourChoice>
然后当然可以在你的 onCreate 或者合适的地方(比如抽屉切换片段)创建 Fragment 并交换到占位符中。
例子:
//MainActivity(或父Activity)内部
//lazy will new it up the first time you use it.
private val mFooFragment by lazy {
FooFragment()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
swapFragment(mFooFragment) //will auto new the fragment with lazy
}
//Let's start simple before I show you thorough
fun swapFragment(fragment: Fragment){
val fragmentManager = supportFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()
fragmentTransaction.replace(R.id.fragPlaceholder, fragment)
fragmentTransaction.commit() //puts the fragment into the placeholder
}
fun btnSignIn_onClick(){
//onSuccess
mFooFragment.isSignedIn(true)
}
*现在,在我们走得更远之前,我觉得重要的是我告诉你,如果你动态交换片段,那么它还有更多。你应该处理捆绑,你应该知道你是否在隐藏、显示、替换等。处理事务有很多方法。更改片段时,您必须决定是隐藏还是删除。当你把它们放回去时,它会影响 onResume 和 onCreate 的生命周期,所以要明智地管理它。
我已经构建了一个简单的 swapFragment 方法,我在 BaseActivity 中的几乎所有项目中都使用了该方法。我现在将分享,只是为了彻底。
在基础活动中存储所选片段并动态控制片段交换的示例
private var mSelectedFragment: BaseFragment? = null
protected fun swapFragment(fragment: BaseFragment, @Nullable bundle: Bundle?, hideCurrentFrag: Boolean = false) {
if (fragment.isVisible) {
A35Log.e(mClassTag, "swapFragment called on already visible fragment")
return
}
A35Log.v(mClassTag, "swapFragment( ${fragment.javaClass.simpleName} )")
val currentFragBundle = fragment.arguments
if (currentFragBundle == null && bundle != null) {
fragment.arguments = bundle
A35Log.v(mClassTag, "current bundle is null, so setting new bundle passed in")
} else if (bundle != null) {
fragment.arguments?.putAll(bundle)
A35Log.v(mClassTag, "current fragment bundle was not null, so add new bundle to it")
}
//make sure no pending transactions are still floating and not complete
val fragmentManager = supportFragmentManager
fragmentManager.executePendingTransactions()
val fragmentTransaction = fragmentManager.beginTransaction()
//Make sure the requested fragment isn't already on the screen before adding it
if (fragment.isAdded) {
A35Log.v(mClassTag, "Fragment is already added")
if (fragment.isHidden) {
A35Log.v(mClassTag, "Fragment is hidden, so show it")
fragmentTransaction.show(fragment)
if(hideCurrentFrag) {
A35Log.v(mClassTag, "hideCurrentFlag = true, hiding current fragment $mSelectedFragment")
fragmentTransaction.hide(mSelectedFragment!!)
}else{
A35Log.v(mClassTag, "hideCurrentFlag = false, removing current fragment $mSelectedFragment")
fragmentTransaction.remove(mSelectedFragment!!)
}
}else{
A35Log.v(mClassTag, "Fragment is already visible")
}
}else if(mSelectedFragment == null){
A35Log.v(mClassTag,"mSelectedFragment = null, so replacing active fragment with new one ${fragment.javaClass.simpleName}")
fragmentTransaction.replace(R.id.fragPlaceholder, fragment)
}else{
A35Log.v(mClassTag, "Fragment is not added, so adding to the screen ${fragment.javaClass.simpleName}")
fragmentTransaction.add(R.id.fragPlaceholder, fragment)
if(hideCurrentFrag) {
A35Log.v(mClassTag, "hideCurrentFlag = true, hiding current fragment $mSelectedFragment")
fragmentTransaction.hide(mSelectedFragment!!)
}else{
A35Log.v(mClassTag, "hideCurrentFlag = false, removing current fragment $mSelectedFragment")
fragmentTransaction.remove(mSelectedFragment!!)
}
}
A35Log.v(mClassTag, "committing swap fragment transaction")
fragmentTransaction.commit()
A35Log.v(mClassTag, "mSelectedFragment = ${fragment.javaClass.simpleName}")
mSelectedFragment = fragment
}
所有示例都在 Kotlin 中提供,因为这是 Android 的发展方向,如果您还没有学习的话,您应该使用 Kotlin 而不是 Java。如果您正在使用 Java,那么您可以将其粘贴到 Java 文件中,我相信它会为您提供将其翻译成 Java 的功能。
快乐编码!
推荐阅读
- java - 将数据从对话框片段返回到调用它的 Activity
- docker - Docker osTicket HTTP 错误
- itext7 - 如何从 PDF 文件中获取图像?
- machine-learning - 在java中加载张量流模型
- math - 这个符号( <> )是什么意思?
- javascript - 笑话测试总是在导入'./environment/validate'时失败;
- python-3.x - 输入类名并从列表中删除该类的对象
- python - 当定时器不在等待阶段时如何取消定时器
- python - OpenCV 3.4.1:未找到 KNearest 函数
- reactjs - 样式组件不使用道具