我正在使用模板构建一个标签式应用,该应用使用自定义类(extends Fragment
)和
如何将值从第一个片段传递到第二个片段?
描述的: 在一个包中,三个类控制标签和视图的创建:
标签: package com.research.fragmenttabstudy.base;
public class AppConstants {
public static final String TAB_A = "tab_a_identifier";
public static final String TAB_B = "tab_b_identifier";
//Your other constants, if you have them..
}
片段:
package com.research.fragmenttabstudy.base;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
public class BaseFragment extends Fragment {
public AppMainTabActivity mActivity;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivity = (AppMainTabActivity) this.getActivity();
}
public boolean onBackPressed(){
return false;
}
public void onActivityResult(int requestCode, int resultCode, Intent data){
}
}
主要活动:
package com.research.fragmenttabstudy.base;
import java.util.HashMap;
import java.util.Stack;
import com.research.fragmenttabstudy.R;
import com.research.fragmenttabstudy.tabA.AppTabAFirstFragment;
import com.research.fragmenttabstudy.tabB.AppTabBFirstFragment;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TabHost;
public class AppMainTabActivity extends FragmentActivity {
/* Your Tab host */
private TabHost mTabHost;
/* A HashMap of stacks, where we use tab identifier as keys..*/
private HashMap<String, Stack<Fragment>> mStacks;
/*Save current tabs identifier in this..*/
private String mCurrentTab;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.app_main_tab_fragment_layout);
/*
* Navigation stacks for each tab gets created..
* tab identifier is used as key to get respective stack for each tab
*/
mStacks = new HashMap<String, Stack<Fragment>>();
mStacks.put(AppConstants.TAB_A, new Stack<Fragment>());
mStacks.put(AppConstants.TAB_B, new Stack<Fragment>());
mTabHost = (TabHost)findViewById(android.R.id.tabhost);
mTabHost.setOnTabChangedListener(listener);
mTabHost.setup();
initializeTabs();
//Receive intent from Fragment AppTabBFirstFragment
Intent intent = getIntent();
String url = intent.getStringExtra("URLone");
//Send data to AppTabBSecondFragment
Bundle bundle=new Bundle();
bundle.putString("urlToSecond", url);
AppTabBSecondFragment objFragment = new AppTabBSecondFragment();
objFragment.setArguments(bundle); }
private View createTabView(final int id) {
View view = LayoutInflater.from(this).inflate(R.layout.tabs_icon, null);
ImageView imageView = (ImageView) view.findViewById(R.id.tab_icon);
imageView.setImageDrawable(getResources().getDrawable(id));
return view;
}
public void initializeTabs(){
/* Setup your tab icons and content views.. Nothing special in this..*/
TabHost.TabSpec spec = mTabHost.newTabSpec(AppConstants.TAB_A);
mTabHost.setCurrentTab(-3);
spec.setContent(new TabHost.TabContentFactory() {
public View createTabContent(String tag) {
return findViewById(R.id.realtabcontent);
}
});
spec.setIndicator(createTabView(R.drawable.tab_a_state_btn));
mTabHost.addTab(spec);
spec = mTabHost.newTabSpec(AppConstants.TAB_B);
spec.setContent(new TabHost.TabContentFactory() {
public View createTabContent(String tag) {
return findViewById(R.id.realtabcontent);
}
});
spec.setIndicator(createTabView(R.drawable.tab_b_state_btn));
mTabHost.addTab(spec);
}
/*Comes here when user switch tab, or we do programmatically*/
TabHost.OnTabChangeListener listener = new TabHost.OnTabChangeListener() {
public void onTabChanged(String tabId) {
/*Set current tab..*/
mCurrentTab = tabId;
if(mStacks.get(tabId).size() == 0){
/*
* First time this tab is selected. So add first fragment of that tab.
* Dont need animation, so that argument is false.
* We are adding a new fragment which is not present in stack. So add to stack is true.
*/
if(tabId.equals(AppConstants.TAB_A)){
pushFragments(tabId, new AppTabAFirstFragment(), false,true);
}else if(tabId.equals(AppConstants.TAB_B)){
pushFragments(tabId, new AppTabBFirstFragment(), false,true);
}
}else {
/*
* We are switching tabs, and target tab is already has atleast one fragment.
* No need of animation, no need of stack pushing. Just show the target fragment
*/
pushFragments(tabId, mStacks.get(tabId).lastElement(), false,false);
}
}
};
/* Might be useful if we want to switch tab programmatically, from inside any of the fragment.*/
public void setCurrentTab(int val){
mTabHost.setCurrentTab(val);
}
/*
* To add fragment to a tab.
* tag -> Tab identifier
* fragment -> Fragment to show, in tab identified by tag
* shouldAnimate -> should animate transaction. false when we switch tabs, or adding first fragment to a tab
* true when when we are pushing more fragment into navigation stack.
* shouldAdd -> Should add to fragment navigation stack (mStacks.get(tag)). false when we are switching tabs (except for the first time)
* true in all other cases.
*/
public void pushFragments(String tag, Fragment fragment,boolean shouldAnimate, boolean shouldAdd){
if(shouldAdd)
mStacks.get(tag).push(fragment);
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
if(shouldAnimate)
ft.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left);
ft.replace(R.id.realtabcontent, fragment);
ft.commit();
}
public void popFragments(){
/*
* Select the second last fragment in current tab's stack..
* which will be shown after the fragment transaction given below
*/
Fragment fragment = mStacks.get(mCurrentTab).elementAt(mStacks.get(mCurrentTab).size() - 2);
/*pop current fragment from stack.. */
mStacks.get(mCurrentTab).pop();
/* We have the target fragment in hand.. Just show it.. Show a standard navigation animation*/
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
ft.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);
ft.replace(R.id.realtabcontent, fragment);
ft.commit();
}
@Override
public void onBackPressed() {
if(((BaseFragment)mStacks.get(mCurrentTab).lastElement()).onBackPressed() == false){
/*
* top fragment in current tab doesn't handles back press, we can do our thing, which is
*
* if current tab has only one fragment in stack, ie first fragment is showing for this tab.
* finish the activity
* else
* pop to previous fragment in stack for the same tab
*
*/
if(mStacks.get(mCurrentTab).size() == 1){
super.onBackPressed(); // or call finish..
}else{
popFragments();
}
}else{
//do nothing.. fragment already handled back button press.
}
}
/*
* Imagine if you wanted to get an image selected using ImagePicker intent to the fragment. Ofcourse I could have created a public function
* in that fragment, and called it from the activity. But couldn't resist myself.
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(mStacks.get(mCurrentTab).size() == 0){
return;
}
/*Now current fragment on screen gets onActivityResult callback..*/
mStacks.get(mCurrentTab).lastElement().onActivityResult(requestCode, resultCode, data);
}
}
现在,新包中包含与选项卡关联的类,使此选项卡始终可见:
package com.research.fragmenttabstudy.tabB;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import com.research.fragmenttabstudy.R;
import com.research.fragmenttabstudy.base.AppConstants;
import com.research.fragmenttabstudy.base.BaseFragment;
public class AppTabBFirstFragment extends BaseFragment {
private Button itemOne;
String itemOneUrl = "http://url”;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.app_tab_b_first_screen, container, false);
itemOne = (Button) view.findViewById(R.id.itemOne);
itemOne.setOnClickListener(listener);
return view;
}
private OnClickListener listener = new View.OnClickListener(){
@Override
public void onClick(View v){
// Go to next fragment in navigation stack
//Callback
Intent intent = new Intent (getActivity().getBaseContext(), AppMainTabActivity.class);
intent.putExtra("URLone", itemOneUrl);
getActivity().startActivity(intent);
mActivity.pushFragments(AppConstants.TAB_B, new AppTabBSecondFragment(),true,true);
}
};
}
这是第二个片段的类:
package com.research.fragmenttabstudy.tabB;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.research.fragmenttabstudy.R;
import com.research.fragmenttabstudy.base.BaseFragment;
public class AppTabBSecondFragment extends BaseFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.app_tab_b_second_screen, container, false);
TextView tab = (TextView) view.findViewById(R.id.tab);
String urlOne = getArguments().getString("urlToSecond");
tab.setText(urlOne);
return view;
}
}
答案 0 :(得分:0)
使用回调接口将数据从Fragment传递到其Activity。然后,Activity找到Fragment以接收数据,并且(如果Fragment存在)调用该Fragment中的方法来传递数据(或者如果片段尚不存在则创建片段)。