正如标题所示,我正在尝试从活动中更改片段的视图/按钮的可见性。
片段的代码:
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>
答案 0 :(得分:1)
好的,所以您有几个问题,但是如果我只为您提供详尽的一步,那可能是最好的。因此,让我们从头开始。
那么首先是问题
您引用了错误的内存。首先,您将一个片段放入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>
然后在“活动”中,您只需创建一个成员变量并按如下方式访问它:
//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(或父活动)
//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的发展方向,如果您尚未使用Android,则应该使用Kotlin而不是Java进行学习。如果您使用Java,则可以将其粘贴到Java文件中,我相信它将为您提供将其转换为Java的功能。
快乐编码!
答案 1 :(得分:0)
这最终为我解决了:
private fun updateUI(user: FirebaseUser?) {
if (user != null) {
// tvStatus.text = "Google User email: " + user.email!!
// tvDetail.text = "Firebase User ID: " + user.uid
var fragment = supportFragmentManager.findFragmentByTag("setting") as 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
var fragment = supportFragmentManager.findFragmentByTag("setting") as SettingFragment
fragment.changeVisibility(false)
// btn_sign_in.visibility = View.VISIBLE
// layout_sign_out_and_disconnect.visibility = View.GONE
}
}