片段如何将自身附加到活动?

时间:2015-12-01 01:49:47

标签: java android

当我所做的只是跟随代码时,片段如何将自身附加到活动上。

    public class FragmentA extends Fragment{
       @Override
       public View onCreateView(Layout inflater,ViewGroup container, Bundle  savedInstanceState){
          return inflater.inflate(R.layout.fragment_b, container, false);
       }
       @Override
       public void onActivityCreated(Bundle savedInstanceState){
           Button test = (Button) getActivity().findViewById(R.id.fragBtn1);
       }

     }

我对上面的代码感到困惑,因为我不太确定当我声明的是上面的代码并将片段添加到main_activity.XMl布局文件中时,片段是如何绑定到活动的。

所以我唯一的假设是XML布局引用了主要活动,因为它是由活动中的setContentView()调用的。作为此引用的结果,XMl文件能够将活动的上下文传递给片段,直到片段,从而允许片段绑定到活动上。

我在这个假设中是否正确?

2 个答案:

答案 0 :(得分:2)

如果您在布局XML中添加了<fragment>标记,则表明应该实例化具有指定类名的片段,并将其添加到Activity的视图层次结构中,同时保留其余部分视图层次结构正在实例化。这就产生了所谓的“硬连线”片段,它消除了片段所要提供的大量功能和灵活性。一个严重的限制是该片段无法删除或替换为同一活动UI中的​​另一个片段。

另一种方法是自己实例化片段,通常在宿主活动的onCreate()方法中,并使用FragmentManager将片段添加到活动中。这是使用一个名为FragmentTransaction的东西完成的。

FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();

transaction.add(R.id.frame_layout_container, new FragmentA());
transaction.commit();

此处R.id.frame_layout_container指的是您的UI中的小部件,通常是FrameLayout,您已经专门添加了该小部件以包含该片段。这类似于将任何其他小部件添加到RelativeLayoutLinearLayout。 FrameLayouts专门用于阻止部分UI关闭以保存一个组件,如片段。

为了清晰起见,我将此代码扩展了一些。 FragmentTransaction是一个流体构建器接口,这意味着大多数transaciton方法返回更新的FragmentTransaction,以便您可以将它们链接在一起。看到这样的事情更常见:

getFragmentManager().beginTransaction().add(R.id.frame_layout_container, 
  new FragmentA()).commit();

以这种方式使用片段管理器会创建一个“动态片段”,它可以替代硬连线片段。这些类型的碎片更加灵活。例如,它们可以交换进出UI,也可以保留它们(这意味着当主机活动由于配置更改(如旋转屏幕)而创建和销毁时保留)。大多数开发人员认为这是更好的方法,即使最初的硬接线片段看起来更容易。

在任何一种情况下,片段都有一个特殊的生命周期方法,当它附加到主机活动时被调用。这种名为onAttach(Activity a)的方法是您以某种方式与主机活动进行交互的机会。

在任何情况下,片段都不会“绑定”自己的活动。相反,它是隐式创建的(在硬连线片段的情况下)或显式(通过片段管理器)附加到主机活动。

答案 1 :(得分:1)

-160 - &gt;你刚回答了自己的问题:)

有关详细信息,请粘贴 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. timerAudio = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "checkTime", userInfo: nil, repeats: true) self.audioPlayer?.meteringEnabled playAudio( false, SongNumber: 2) } func checkTime() { self.audioPlayer?.updateMeters() self.audioPlayer?.numberOfChannels let normalizedValue = self.audioPlayer?.averagePowerForChannel(0) print(normalizedValue) self.waveformView.updateWithLevel(CGFloat(normalizedValue!)) } func playAudio( stopAudio:Bool, SongNumber: Int) { let songNumber = SongsArray let songNumberMediaPlayer = SongsArray nameSong(songNumber[SongNumber]) do { try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback) //print("AVAudioSession Category Playback OK") do { try AVAudioSession.sharedInstance().setActive(true) //print("AVAudioSession is Active") } catch let error as NSError { print(error.localizedDescription) } } catch let error as NSError { print(error.localizedDescription) } let dispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) dispatch_async(dispatchQueue, { let mainBundle = NSBundle.mainBundle() /* Find the location of our file to feed to the audio player */ let filePath = mainBundle.pathForResource(songNumber[SongNumber], ofType:"mp3") if let path = filePath{ let fileData = NSData(contentsOfFile: path) do { /* Start the audio player */ self.audioPlayer = try AVAudioPlayer(data: fileData!) guard let player = self.audioPlayer else{ return } /* Set the delegate and start playing */ player.delegate = self if player.prepareToPlay() && player.play(){ /* Successfully started playing */ } else { /* Failed to play */ } } catch{ self.audioPlayer = nil return } if stopAudio == true { self.audioPlayer?.pause() self.timerAudio.invalidate() }else { self.audioPlayer?.play() } } }) } ,我假设您拥有硬编码(仅限容器)片段参考。所以,是的,Android将找到该类(或者如果找不到类-fragment-则抛出异常)。

根据经验,我通常认为这是练习(直接在XML中硬编码片段),因为它有一些限制(特别是当涉及到嵌套碎片)它使得更难找到“这个片段来自何处”。 ;)

我忘了提到:硬编码片段的另一个缺点是你不能替换它们。因此,如果您尝试将Fragment替换为另一个片段,如果前者是XML格式的Harcoded,则不能,因为added the fragment into the main_activity.XMl layout file.需要 Container (如FrameLayout或类似)放置片段,而不是之前的片段。

来源http://developer.android.com/training/basics/fragments/creating.html

提取

  

注意:通过在布局XML文件中定义片段将片段添加到活动布局时,无法在运行时删除片段。如果您计划在用户交互期间将片段交换进出,则必须在活动首次启动时将片段添加到活动中

更新了澄清说明:

  1.   

    片段将自身绑定到布局资源文件让我感到困惑

  2. 确定。片段不会将其自身绑定到任何东西。您告诉Android(通过XML)活动“Main”具有main_activity.xml中指定的布局。当活动需要设置其内容时,它会解析此XML并发现有FragmentManager#replace(id)的引用,其main_activity.xml属于Fragment类型。这会自动解决(如果找到这样的类)。

    然后片段(并且您粘贴了此代码)正在其class方法(您提供的方法)中加载其内容。然后,一旦活动可以,这个硬连线片段就会生效。

    1. 什么是FragmentA?这通常在JavaDocs中用于分隔Type和Method / Function。示例:onCreateView#