Как получить доступ к дочерним представлениям фрагмента внутри родительской части фрагмента?
У меня есть поддерживаемая функция фрагмента, которая будет загружать diff-фрагменты. У фрагмента есть textView
с id = "score"
, и я хочу получить его дескриптор, но findViewById
для score textView
возвращает null. Почему так?
textView помещается в фрагмент
public class MyActivity extends extends ActionBarActivity
implements NavigationDrawerFragment.NavigationDrawerCallbacks{
private TextView scoreBoardTextView = null;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
mNavigationDrawerFragment = (NavigationDrawerFragment)
getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
scoreBoardTextView = (TextView) findViewById(R.id.score); //this returns null
}
@Override
public void onNavigationDrawerItemSelected(int position) {
//set fragment
}
}
Ответы
Ответ 1
Примечание:
Непосредственный доступ к представлениям фрагментов вне фрагмента - не очень хорошая идея. Вы должны использовать интерфейсы обратного вызова для обработки таких случаев и избегать ошибок. Следующий способ работает, но он не рекомендуется, так как это не очень хорошая практика.
Если вы хотите получить доступ к TextView
из Fragment
внутри родительского Activity
, то вы должны определить метод внутри вашего класса Fragment
следующим образом:
public class MyFragment extends Fragment {
TextView mTextView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_main, container, false);
mTextView = (TextView) view.findViewById(R.id.textView1);
return view;
}
public void setTextViewText(String value){
mTextView.setText(value);
}
}
Теперь вы можете использовать это внутри своего Activity
следующим образом:
myFragment.setTextViewText("foo");
здесь myFragment имеет тип MyFragment
.
Если вы хотите получить доступ ко всему TextView
, вы можете определить такой метод внутри MyFragment.java
:
public TextView getTextView1(){
return mTextView;
}
Таким образом вы можете получить доступ к самому TextView
.
Надеюсь, что это поможет.:)
Ответ 2
Это возможно следующим образом:
Держите ссылку на раздутый вид в Фрагменте следующим образом:
public class MyFragment extends SherlockFragment{
MainMenuActivity activity;
public View view;
public MyFragment(){
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if ( getActivity() instanceof MainMenuActivity){
activity = (MainMenuActivity) getActivity();
}
view = inflater.inflate(R.layout.aboutus, container, false);
return view;
}
}
Создайте функцию в Activity, например:
public class MainMenuActivity extends SherlockFragmentActivity {
SherlockFragment fragment = null;
public void switchContent(SherlockFragment fragment) {
this.fragment = fragment;
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.mainmenu, fragment)
.commit();
invalidateOptionsMenu();
}
Его цель - сохранить ссылку на текущий фрагмент. Всякий раз, когда вы хотите сменить фрагмент, вы вызываете выше функцию, как это (из фрагмента):
activity.switchContent( new MyFragment_2());
Теперь у вас есть ссылка на текущий фрагмент. Таким образом, вы можете напрямую обращаться к представлениям фрагментов в Activity следующим образом: this.fragment.view
Ответ 3
Вам не нужно ссылаться на представление Фрагмент, чтобы получить его компоненты в Деятельности. Поскольку вы можете напрямую обращаться к компонентам компоновки Фрагмент в родительском Деятельности.
Просто вы можете получить доступ к любому компоненту с помощью этого
findViewById(R.id.child_of_fragment_layout);
Ответ 4
Вы можете получить доступ с помощью метода getView класса Fragment.
Например, у вас есть TextView в вашем MyFragment с идентификатором "text_view"
В вашей деятельности сделайте свой фрагмент:
MyFragment myFragment = new MyFragment();
И когда вам нужен ребенок, просто вызовите getView, а затем найдите свой childView.
View view = myFragment.getView();
if (view !=null) {
view.findViewById(R.id.text_view).setText("Child Accessed :D");
}
Ответ 5
Если ваш TextView размещен внутри фрагмента в этом случае, вы не можете получить доступ к TextView внутри вашего Фрагмент Родительского действия, вы можете установить интерфейс для взаимодействия между фрагментом и Activity и отправить данные, когда вы нажимаете TextView или любую другую вещь, которая вы хотите выполнить
Ответ 6
Только это:
((Your_Activity) this.getActivity()).YouyActivityElements;
Ответ 7
Просто поместите фрагмент вместо того, чтобы вводить в действие:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_new_work_order,
container, false);
TextView scoreBoardTextView = (TextView) rootView.findViewById(R.id.score);
return rootView;
}
Ответ 8
Оценка textView находится в макете фрагмента, это не в макете MyActivity, т.е. R.layout.activity_home. Таким образом, вы можете найти текстовое представление в этом фрагменте после раздувания соответствующего файла макета.
Ответ 9
Он возвращает null
, потому что TextView
является элементом Fragment
, а не Activity
.
Обратите внимание, что идея использования Fragment
заключается в инкапсуляции модуля внутри Fragment
, что означает, что Activity
не должен иметь прямого доступа к его свойствам. Подумайте о перемещении своей логики, когда вы получите ссылку TextView
внутри Fragment
Ответ 10
Вы не можете получить доступ к элементу Fragment
в Parent Activity
, но вы можете передать значения в Fragment
следующим образом.
в вашем методе onNavigationDrawerItemSelected
MyActivity
выполните следующие действия
int myScore = 100;
@Override
public void onNavigationDrawerItemSelected(int position) {
// update the main content by replacing fragments
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager
.beginTransaction()
.replace(R.id.container,
MyFragment.newInstance(myScore)).commit();
}
И в классе MyFragment
создайте метод под названием newInstance
, например, следующий
private static final String SCORE = "score";
public static MyFragment newInstance(int score) {
MyFragment fragment = new MyFragment();
Bundle args = new Bundle();
args.putInt(SCORE, score);
fragment.setArguments(args);
return fragment;
}
И в MyFragment
onCreateView()
метод
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
TextView textView = (TextView) rootView
.findViewById(R.id.score);
textView.setText(Integer.toString(getArguments().getInt(
SCORE)));
return rootView;
}
Это все, надеюсь, это вам поможет. Если нет, сообщите мне.
Ответ 11
Просто объявите TextView общедоступным в фрагменте, инициализируйте его findViewById() в фрагменте onCreateView(). Теперь, используя объект фрагмента, который вы добавили в действие, вы можете получить доступ к TextView.
Ответ 12
Вам нужно вызвать метод findViewById из представления фрагмента.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
mNavigationDrawerFragment = (NavigationDrawerFragment)
getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
scoreBoardTextView = (TextView) mNavigationDrawerFragment.getView().findViewById(R.id.score);
}
Этот способ работает для меня.
Ответ 13
Я предлагаю вам сделать часть текста в вашем макете деятельности. В качестве альтернативы вы можете иметь текстовое представление как фрагмент separete. Посмотрите на мой question здесь. Он похож на ваш, но в обратном направлении. Здесь урезанная версия кода, которую я использовал в моем проекте. Объяснение приведено в коде.
Класс активности
public class MainActivity extends ActionBarActivity {
PlaceFragment fragment;
TextView fragmentsTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Bundle bundle = new Bundle();
bundle.putString("score", "1000");
fragment = PlaceFragment.newInstance(bundle);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.container, fragment);
ft.addToBackStack(null);
ft.commit();
// method 1
// fragment is added some ways to access views
// get the reference of fragment textview
if (fragment.getTextView() != null) {
fragmentsTextView = fragment.getTextView();
}
// method 2
// using static method dont use in production code
// PlaceFragment.textViewInFragment.setText("2000");
// method 3
// let the fragment handle update its own text this is the recommended
// way wait until fragment transaction is complete before calling
//fragment.updateText("2000");
}
}
Класс фрагмента:
public class PlaceFragment extends Fragment {
public TextView textViewInFragment;// to access via object.field same to
// string.length
// public static TextView textViewInFragment;//to access via
// PlaceFragment.textView dont try this in production code
public PlaceFragment() {
}
public static PlaceFragment newInstance(Bundle bundle) {
PlaceFragment fragment = new PlaceFragment();
fragment.setArguments(bundle);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.fragment_place, container, false);
textViewInFragment = (TextView) view
.findViewById(R.id.textViewInFragment);
return view;
}
@Override
public void onStart() {
// TODO Auto-generated method stub
super.onStart();
if (getArguments() != null) {
textViewInFragment.setText(getArguments().getString("score"));
}
}
public TextView getTextView() {
if (textViewInFragment != null) {
return textViewInFragment;// returns instance of inflated textview
}
return null;// return null and check null
}
public void updateText(String text) {
textViewInFragment.setText(text);// this is recommended way to alter
// view property of fragment in
// activity
}
}
Связь от активности к фрагменту является прямой. Это связано с тем, что активность содержит фрагмент. Храните объект фрагмента и получите доступ к его свойству через сеттеры и геттеры или публичные поля внутри него. Но для связи от фрагмента к активности требуется интерфейс.
Ответ 14
почему вы не обращаетесь к нему напрямую со своего FragmentPagerAdapter,
SubAccountFragment subAccountFragment = (SubAccountFragment) mSectionsPagerAdapter.getItem(1);
subAccountFragment.requestConnectPressed(view);
и вот полный пример:
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.Locale;
public class TabsActivity extends ActionBarActivity implements ActionBar.TabListener {
/**
* The {@link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {@link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {@link android.support.v4.app.FragmentStatePagerAdapter}.
*/
SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {@link ViewPager} that will host the section contents.
*/
ViewPager mViewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tabs);
// Set up the action bar.
final ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
// When swiping between different sections, select the corresponding
// tab. We can also use ActionBar.Tab#select() to do this if we have
// a reference to the Tab.
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
// Create a tab with text corresponding to the page title defined by
// the adapter. Also specify this Activity object, which implements
// the TabListener interface, as the callback (listener) for when
// this tab is selected.
ActionBar.Tab tab = actionBar.newTab();
View tabView = this.getLayoutInflater().inflate(R.layout.activity_tab, null);
ImageView icon = (ImageView) tabView.findViewById(R.id.tab_icon);
icon.setImageDrawable(getResources().getDrawable(mSectionsPagerAdapter.getPageIcon(i)));
TextView title = (TextView) tabView.findViewById(R.id.tab_title);
title.setText(mSectionsPagerAdapter.getPageTitle(i));
tab.setCustomView(tabView);
tab.setTabListener(this);
actionBar.addTab(tab);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_tabs, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_logout) {
finish();
gotoLogin();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
@Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
/**
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public ProfileFragment profileFragment;
public SubAccountFragment subAccountFragment;
public ChatFragment chatFragment;
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
profileFragment = new ProfileFragment();
subAccountFragment = new SubAccountFragment();
chatFragment = new ChatFragment();
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return profileFragment;
case 1:
return subAccountFragment;
case 2:
return chatFragment;
}
return null;
}
@Override
public int getCount() {
// Show 3 total pages.
return 3;
}
@Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return getString(R.string.title_section1).toUpperCase(l);
case 1:
return getString(R.string.title_section2).toUpperCase(l);
case 2:
return getString(R.string.title_section3).toUpperCase(l);
}
return null;
}
public int getPageIcon(int position) {
switch (position) {
case 0:
return R.drawable.tab_icon_0;
case 1:
return R.drawable.tab_icon_1;
case 2:
return R.drawable.tab_icon_2;
}
return 0;
}
}
public void gotoLogin() {
Intent intent = new Intent(this, LoginActivity.class);
this.startActivity(intent);
}
public void requestConnectPressed(View view){
SubAccountFragment subAccountFragment = (SubAccountFragment) mSectionsPagerAdapter.getItem(1);
subAccountFragment.requestConnectPressed(view);
}
}
Ответ 15
Если представление уже завышено (например, видимо) на экране, вы можете просто использовать findViewById (R.id.yourTextView) в действии как обычно, и оно вернет дескриптор в текстовое представление или null, если представление было не найден.
Ответ 16
Чтобы получить доступ к TextView или Button или что-то еще в вашем фрагменте, вам необходимо сделать следующее:
public class BlankFragment extends Fragment {
public View view;
public TextView textView;
public Button button;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view =inflater.inflate(R.layout.fragment_blank, container, false);
textView = (TextView)view.getRootView().findViewById(R.id.textView_fragment1);
return view;
}
public void changeTextOfFragment(String text){
textView.setText(text);
view.setBackgroundResource(R.color.colorPrimaryDark);
}
Как только это будет сделано в вашем MainActivity или любом другом, где вы хотите получить доступ к TextView из вашего фрагмента, вы должны убедиться, что этот фрагмент в вашем методе OnCreate() будет другим способом, который, скорее всего, вызовет nullPointer. Таким образом, ваша деятельность, в которой вы хотите изменить TextView, должна выглядеть так:
public class MainActivity extends AppCompatActivity {
private Button button1;
private FragmentManager fragmentManager;
private FragmentTransaction fragmentTransaction;
BlankFragment blankFragment = new BlankFragment();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button1 = (Button)findViewById(R.id.button1);
changeFragment();
fragmentManager = getFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment1,blankFragment);
fragmentTransaction.commit();
}
private void changeFragment(){
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
blankFragment.changeTextOfFragment("Enter here the text which you want to be displayed on your Updated Fragment");
}
});
}
Надеюсь, что это поможет:)