Как получить доступ к компонентам представления фрагментов внутри/из активности

Я использую навигационный ящик с новым компонентом NavController, у меня есть семь фрагментов, каждый фрагмент представляет пункт меню навигационного ящика.

Мне нужно получить доступ к некоторым компонентам представления в каждом фрагменте, например, к Recyclerview и адаптеру из MainActivity, чтобы использовать его на onOptionsItemSelected, как это

 @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        if (item.getItemId() == R.id.change_layout) {
            android.app.AlertDialog.Builder builder
                    = new android.app.AlertDialog.Builder(getContext());

            builder.setTitle(getString(R.string.choose_layout));

            String[] recyclerViewLayouts = getResources().getStringArray(R.array.RecyclerViewLayouts);
            SharedPreferences.Editor editor = sharedPreferences.edit();


            builder.setItems(recyclerViewLayouts, (dialog, index) -> {
                switch (index) {
                    case 0: // Card List Layout
                        adapter.setViewType(0);
                        recyclerView.setLayoutManager(layoutManager);
                        recyclerView.setAdapter(adapter);
                        editor.putString("recyclerViewLayout", "cardLayout");
                        editor.apply();
                        break;
                    case 1: // Cards Magazine Layout
                        adapter.setViewType(1);
                        recyclerView.setLayoutManager(layoutManager);
                        recyclerView.setAdapter(adapter);
                        editor.putString("recyclerViewLayout", "cardMagazineLayout");
                        editor.apply();
                        break;
                    case 2: // PostTitle Layout
                        adapter.setViewType(2);
                        recyclerView.setLayoutManager(titleLayoutManager);
                        recyclerView.setAdapter(adapter);
                        editor.putString("recyclerViewLayout", "titleLayout");
                        editor.apply();
                        break;
                    case 3: //Grid Layout
                        adapter.setViewType(3);
                        recyclerView.setLayoutManager(gridLayoutManager);
                        recyclerView.setAdapter(adapter);
                        editor.putString("recyclerViewLayout", "gridLayout");
                        editor.apply();

                }
            });

            android.app.AlertDialog alertDialog = builder.create();
            alertDialog.show();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

Мне нужно реализовать этот метод для всех фрагментов активности, а не переопределять его в каждом фрагменте отдельно.

XML-файл mobile_navigation

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mobile_navigation"
    app:startDestination="@id/nav_home">

    <fragment
        android:id="@+id/nav_home"
        android:name="com.test.dummyappv3.ui.home.HomeFragment"
        android:label="@string/home"
        tools:layout="@layout/fragment_home" />

    <fragment
        android:id="@+id/nav_Accessory"
        android:name="com.test.dummyappv3.ui.accessory.AccessoryFragment"
        android:label="@string/accessory"
        tools:layout="@layout/fragment_accessory" />

    <fragment
        android:id="@+id/nav_Arcade"
        android:name="com.test.dummyappv3.ui.arcade.ArcadeFragment"
        android:label="@string/arcade"
        tools:layout="@layout/fragment_arcade" />

    <fragment
        android:id="@+id/nav_Fashion"
        android:name="com.test.dummyappv3.ui.fashion.FashionFragment"
        android:label="@string/fashion"
        tools:layout="@layout/fashion_fragment" />
    <fragment
        android:id="@+id/nav_Food"
        android:name="com.test.dummyappv3.ui.food.FoodFragment"
        android:label="@string/food"
        tools:layout="@layout/food_fragment" />
    <fragment
        android:id="@+id/nav_Heath"
        android:name="com.test.dummyappv3.ui.heath.HeathFragment"
        android:label="@string/heath"
        tools:layout="@layout/heath_fragment" />
    <fragment
        android:id="@+id/nav_Lifestyle"
        android:name="com.test.dummyappv3.ui.lifestyle.LifestyleFragment"
        android:label="@string/lifestyle"
        tools:layout="@layout/lifestyle_fragment" />
    <fragment
        android:id="@+id/nav_Sports"
        android:name="com.test.dummyappv3.ui.sports.SportsFragment"
        android:label="@string/sports"
        tools:layout="@layout/sports_fragment" />
</navigation>

В MainActivtiy этот метод должен контролировать фрагменты

navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
            @Override
            public void onDestinationChanged(@NonNull NavController controller, @NonNull NavDestination destination, @Nullable Bundle arguments) {
                switch (destination.getId()){
                    case R.id.nav_home:
                        Toast.makeText(MainActivity.this,
                                "Home clicked",Toast.LENGTH_LONG).show();
                        

                        break;
                    case R.id.nav_Accessory:
                        Toast.makeText(MainActivity.this,
                                "Accessory clicked",Toast.LENGTH_LONG).show();
                        break;

                    case R.id.nav_Arcade:
                        Toast.makeText(MainActivity.this,
                                "Arcade clicked",Toast.LENGTH_LONG).show();
                        break;

                }
            }
        });

Класс PostAdapter

public class PostAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private Context context;
    private List<Item> items;

    private static final int CARD = 0;
    private static final int CARD_MAGAZINE = 1;
    private static final int TITLE = 2;
    private static final int GRID = 3;
    private static final int SDK_VERSION = Build.VERSION.SDK_INT;
    public static final String TAG = "POST ADAPTER";

    private int viewType;

    public PostAdapter(Context context, List<Item> items) {
        this.context = context;
        this.items = items;
    }

    public void setViewType(int viewType) {
        this.viewType = viewType;
        notifyDataSetChanged();
    }

    public int getViewType() {
        return this.viewType;
    }


    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(context);
        View view;

        if (this.viewType == CARD) {
            view = inflater.inflate(R.layout.card, parent, false);
            return new CardViewHolder(view);
        } else if (this.viewType == CARD_MAGAZINE) {
            view = inflater.inflate(R.layout.card_magazine, parent, false);
            return new CardMagazineViewHolder(view);
        } else if (this.viewType == TITLE) {
            if(SDK_VERSION < Build.VERSION_CODES.LOLLIPOP){
                view = inflater.inflate(R.layout.title_layout_v15,parent,false);
            }else {
                view = inflater.inflate(R.layout.title_layout, parent, false);
            }
            return new TitleViewHolder(view);
        } else {
            if(SDK_VERSION < Build.VERSION_CODES.LOLLIPOP){
                view = inflater.inflate(R.layout.grid_layout_v15,parent,false);
            }else {
                view = inflater.inflate(R.layout.grid_layout, parent, false);
            }
            return new GridViewHolder(view);
        }

    }


    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        int itemType = getViewType();
        Item item = items.get(holder.getAdapterPosition());
        final Document document = Jsoup.parse(item.getContent());
        final Elements elements = document.select("img");

//        Log.e("IMAGE", document.getAllElements().select("img").get(0).attr("src"));

        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat
                ("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
        Intent intent = new Intent(context, DetailsActivity.class);

        switch (itemType) {
            case CARD:
                if (holder instanceof CardViewHolder) {
                    CardViewHolder cardViewHolder = (CardViewHolder) holder;
                    cardViewHolder.postTitle.setText(item.getTitle());

                    try {
                        Log.e("IMAGE", elements.get(0).attr("src"));
                        Glide.with(context).load(elements.get(0).attr("src"))
                                .into(cardViewHolder.postImage);
                    }catch (IndexOutOfBoundsException e){
                        cardViewHolder.postImage.setImageResource(R.mipmap.ic_launcher);
                        Log.e(TAG,e.toString());
                    }


                    cardViewHolder.postDescription.setText(document.text());
                    try {
                        date = format.parse(items.get(position).getPublished());

                    } catch (ParseException e) {
                        e.printStackTrace();
                    }

                    PrettyTime prettyTime = new PrettyTime();

                    cardViewHolder.postDate.setText(prettyTime.format(date));

                    cardViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {


                            intent.putExtra("url", item.getUrl());
                            intent.putExtra("title", item.getTitle());
                            intent.putExtra("content", item.getContent());
                            int youtubeThumbnailImagesetVisibility = 0;

                            Element element = document.body();

                            String youtubeThumbnailImageSrc = "";
                            String youTubeLink = "";
                            for (Element e : element.getElementsByClass
                                    ("YOUTUBE-iframe-video")) {
                                youtubeThumbnailImageSrc = e.attr("data-thumbnail-src");
                                youTubeLink = e.attr("src");
                                Log.e("YouTube thumbnail", youtubeThumbnailImageSrc);
                                Log.e("Youtube link", youTubeLink);
                            }

                            if (youtubeThumbnailImageSrc.isEmpty()) {
                                youtubeThumbnailImagesetVisibility = 8;
                                intent.putExtra("youtubeThumbnailImagesetVisibility",
                                        youtubeThumbnailImagesetVisibility);
                            } else {
                                intent.putExtra("youtubeThumbnailImageSrc", youtubeThumbnailImageSrc);
                                intent.putExtra("youTubeLink", youTubeLink);
                            }

//             String imageSrc = elements.get(0).attr("src");
//             intent.putExtra("blogImage",imageSrc);

                            view.getContext().startActivity(intent);
                        }
                    });
                }
                break;

            case CARD_MAGAZINE:
                if (holder instanceof CardMagazineViewHolder) {
                    CardMagazineViewHolder cardMagazineViewHolder = (CardMagazineViewHolder) holder;
                    cardMagazineViewHolder.postTitle.setText(item.getTitle());


                    try {
                        Log.e("IMAGE", elements.get(0).attr("src"));
                        Glide.with(context).load(elements.get(0).attr("src"))
                                .into(cardMagazineViewHolder.postImage);
                    }catch (IndexOutOfBoundsException e){
                        cardMagazineViewHolder.postImage.setImageResource(R.mipmap.ic_launcher);
                        Log.e(TAG,e.toString());
                    }

                    try {
                        date = format.parse(items.get(position).getPublished());

                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                    PrettyTime prettyTime = new PrettyTime();

                    cardMagazineViewHolder.postDate.setText(prettyTime.format(date));

                    cardMagazineViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            intent.putExtra("url", item.getUrl());
                            intent.putExtra("title", item.getTitle());
                            intent.putExtra("content", item.getContent());
                            int youtubeThumbnailImagesetVisibility = 0;

                            Element element = document.body();

                            String youtubeThumbnailImageSrc = "";
                            String youTubeLink = "";
                            for (Element e : element.getElementsByClass
                                    ("YOUTUBE-iframe-video")) {
                                youtubeThumbnailImageSrc = e.attr("data-thumbnail-src");
                                youTubeLink = e.attr("src");
                                Log.e("YouTube thumbnail", youtubeThumbnailImageSrc);
                                Log.e("Youtube link", youTubeLink);
                            }

                            if (youtubeThumbnailImageSrc.isEmpty()) {
                                youtubeThumbnailImagesetVisibility = 8;
                                intent.putExtra("youtubeThumbnailImagesetVisibility",
                                        youtubeThumbnailImagesetVisibility);
                            } else {
                                intent.putExtra("youtubeThumbnailImageSrc", youtubeThumbnailImageSrc);
                                intent.putExtra("youTubeLink", youTubeLink);
                            }

//             String imageSrc = elements.get(0).attr("src");
//             intent.putExtra("blogImage",imageSrc);

                            view.getContext().startActivity(intent);
                        }
                    });
                }
                break;
            case TITLE:
                if (holder instanceof TitleViewHolder) {
                    TitleViewHolder titleViewHolder = (TitleViewHolder) holder;
                    titleViewHolder.postTitle.setText(item.getTitle());

                    Log.d("TITLE", "title layout called");


                    try {
                        Log.e("IMAGE", elements.get(0).attr("src"));
                        Glide.with(context).load(elements.get(0).attr("src"))
                                .into(titleViewHolder.postImage);
                    }catch (IndexOutOfBoundsException e){
                        titleViewHolder.postImage.setImageResource(R.mipmap.ic_launcher);
                        Log.e(TAG,e.toString());
                    }

                    if(position == getItemCount() -1)
                        if(context instanceof MainActivity){
//                            ((MainActivity)context).getMainPagePosts();
                        }

                    titleViewHolder.itemView.setOnClickListener(view -> {
                        intent.putExtra("url", item.getUrl());
                        intent.putExtra("title", item.getTitle());
                        intent.putExtra("content", item.getContent());
                        int youtubeThumbnailImagesetVisibility = 0;

                        Element element = document.body();

                        String youtubeThumbnailImageSrc = "";
                        String youTubeLink = "";
                        for (Element e : element.getElementsByClass
                                ("YOUTUBE-iframe-video")) {
                            youtubeThumbnailImageSrc = e.attr("data-thumbnail-src");
                            youTubeLink = e.attr("src");
                            Log.e("YouTube thumbnail", youtubeThumbnailImageSrc);
                            Log.e("Youtube link", youTubeLink);
                        }

                        if (youtubeThumbnailImageSrc.isEmpty()) {
                            youtubeThumbnailImagesetVisibility = 8;
                            intent.putExtra("youtubeThumbnailImagesetVisibility",
                                    youtubeThumbnailImagesetVisibility);
                        } else {
                            intent.putExtra("youtubeThumbnailImageSrc", youtubeThumbnailImageSrc);
                            intent.putExtra("youTubeLink", youTubeLink);
                        }

//             String imageSrc = elements.get(0).attr("src");
//             intent.putExtra("blogImage",imageSrc);

                        view.getContext().startActivity(intent);
                    });

                }
                break;
            case GRID:
                if (holder instanceof GridViewHolder) {
                    GridViewHolder gridViewHolder = (GridViewHolder) holder;
                    gridViewHolder.postTitle.setText(item.getTitle());


                    try {
                        Log.e("IMAGE", elements.get(0).attr("src"));
                        Glide.with(context).load(elements.get(0).attr("src"))
                                .into(gridViewHolder.postImage);
                    }catch (IndexOutOfBoundsException e){
                        gridViewHolder.postImage.setImageResource(R.mipmap.ic_launcher);
                        Log.e(TAG,e.toString());
                    }

                    if(position == getItemCount() -1)
                    if(context instanceof MainActivity){
//                        ((MainActivity)context).getMainPagePosts();
                    }

                    gridViewHolder.itemView.setOnClickListener(view -> {
                        intent.putExtra("url", item.getUrl());
                        intent.putExtra("title", item.getTitle());
                        intent.putExtra("content", item.getContent());
                        int youtubeThumbnailImagesetVisibility;

                        Element element = document.body();

                        String youtubeThumbnailImageSrc = "";
                        String youTubeLink = "";
                        for (Element e : element.getElementsByClass
                                ("YOUTUBE-iframe-video")) {
                            youtubeThumbnailImageSrc = e.attr("data-thumbnail-src");
                            youTubeLink = e.attr("src");
                            Log.e("YouTube thumbnail", youtubeThumbnailImageSrc);
                            Log.e("Youtube link", youTubeLink);
                        }

                        if (youtubeThumbnailImageSrc.isEmpty()) {
                            youtubeThumbnailImagesetVisibility = 8;
                            intent.putExtra("youtubeThumbnailImagesetVisibility",
                                    youtubeThumbnailImagesetVisibility);
                        } else {
                            intent.putExtra("youtubeThumbnailImageSrc", youtubeThumbnailImageSrc);
                            intent.putExtra("youTubeLink", youTubeLink);
                        }

//             String imageSrc = elements.get(0).attr("src");
//             intent.putExtra("blogImage",imageSrc);

                        view.getContext().startActivity(intent);
                    });
                }
        }
    }


    @Override
    public int getItemCount() {
        return items.size();
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    public class CardViewHolder extends RecyclerView.ViewHolder {

        ImageView postImage;
        TextView postTitle,postDescription, postDate;

        private CardViewHolder(View itemView) {
            super(itemView);
            postImage = itemView.findViewById(R.id.postImage);
            postTitle = itemView.findViewById(R.id.postTitle);
            postDescription = itemView.findViewById(R.id.postDescription);
            postDate = itemView.findViewById(R.id.postDate);

        }
    }

    public class CardMagazineViewHolder extends RecyclerView.ViewHolder {

        ImageView postImage;
        TextView postTitle, postDate;

        private CardMagazineViewHolder(View itemView) {
            super(itemView);
            postImage = itemView.findViewById(R.id.postImage);
            postTitle = itemView.findViewById(R.id.postTitle);
            postDate = itemView.findViewById(R.id.postDate);

        }
    }

    public class TitleViewHolder extends RecyclerView.ViewHolder {
        TextView postTitle;
        MyImageview postImage;


        private TitleViewHolder(@NonNull View itemView) {
            super(itemView);
            postTitle = itemView.findViewById(R.id.postTitle);
            postImage = itemView.findViewById(R.id.postImage);
        }
    }


    public class GridViewHolder extends RecyclerView.ViewHolder {
        TextView postTitle;
        MyImageview postImage;


        private GridViewHolder(@NonNull View itemView) {
            super(itemView);
            postTitle = itemView.findViewById(R.id.postTitle);
            postImage = itemView.findViewById(R.id.postImage);
        }
    }
}



Ответы (1)


Я не думаю, что есть простой способ сделать это, но в моем случае я связываю представления с помощью интерфейса, вот пример того, как я получаю доступ к TextView из действия:

это деятельность:

public class MainActivity4 extends AppCompatActivity implements OnFragmentViewCreated {

    private TextView fragmentTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);
        getSupportFragmentManager().beginTransaction().add(R.id.fragment, new TestFragment()).commit();

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = new MenuInflater(this);
        inflater.inflate(R.menu.test, menu);
        return super.onCreateOptionsMenu(menu);
    }

    /**
     * this method called each time a fragment Created. you can initialize the view on in
     *
     * @param fragment the instance of the fragment that called it
     * @param view the view that has bonded
     */
    @Override
    public void onBindView(Fragment fragment, View view) {
        if (fragment instanceof TestFragment) {
            // here i know that i sent a TextView
            fragmentTextView = ((TextView) view);
        }

    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {

        if (fragmentTextView != null) {
            switch (item.getItemId()) {
                case R.id.home:
                    fragmentTextView.setText("this is only a Test: Option Selected 0");
                    break;
                case R.id.nav_bus:
                    fragmentTextView.setText("this is only a Test: Option Selected  1");
                    break;
            }
        }
        return super.onOptionsItemSelected(item);
    }
}

а это Фрагмент

public class TestFragment extends Fragment {


    private TextView textView;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_first, container, false);
        textView = v.findViewById(R.id.textview_first);
        return v;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        // initialize the interface for each fragment
        OnFragmentViewCreated viewFragmentCreated = (OnFragmentViewCreated) requireActivity();

        // call the method in the activity
        viewFragmentCreated.onBindView(this, textView);
    }
}

и, наконец, это интерфейс

public interface OnFragmentViewCreated{
     void onBindView(Fragment fragment, View view);
}

ОБНОВИТЬ

Для примера @Dr Mido, если вы хотите получить доступ к RecyclerView и Apdapter, вы должны изменить интерфейс следующим образом.

public interface OnFragmentViewCreated {
    void onBindView(Fragment fragment, RecyclerView view, RecyclerView.Adapter<? extends RecyclerView.ViewHolder> adapter);
}

И добавьте это в свой Frgament внутри onViewCreated()

 @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        /*
                rest of your code here 
         */
        RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
        // initialize the interface
        OnFragmentViewCreated viewFragmentCreated = (OnFragmentViewCreated) requireActivity();
        // call the method in the activity
        viewFragmentCreated.onBindView(this, recyclerView, userAdapter);
    }

И когда вы реализуете этот интерфейс в своей деятельности, он выглядит следующим образом, где вам нужно инициализировать свое представление для их использования в методе onOptionsItemSelected:

/**
 * this method called each time a fragment Created. you can initialize the recyclerView on in
 *
 * @param fragment     the instance of the fragment that called it
 * @param recyclerView your recycler recyclerView in the fragment
 * @param adapter      your adapter
 */

@Override
public void onBindView(Fragment fragment, RecyclerView recyclerView, RecyclerView.Adapter<? extends RecyclerView.ViewHolder> adapter) {
    if (fragment instanceof TestFragment) {
        this.recyclerView = recyclerView;
        //replace the UserAdapter by your Adapter
        this.adapter = (UserAdapter) adapter;
    }
}

И совсем просто, как и в своем вопросе, вы можете использовать их в своем onOptionsItemSelected, как в приведенном ниже коде:

  @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {

        if (recyclerView != null && adapter != null) {
            switch (item.getItemId()) {
                case R.id.home:
                    recyclerView.setLayoutManager(new LinearLayoutManager(this));
                    recyclerView.setAdapter(adapter);
                    break;
                case R.id.nav_bus:

                    break;
            }
        }
        return super.onOptionsItemSelected(item);
    }

А тут все должно работать

person Shay Kin    schedule 15.03.2021
comment
AS не примет переопределение этого интерфейса, а также, когда я запускаю приложение, оно требует его от меня, я думаю, что это ошибка в AS, и я думаю, что адаптер не может транслировать для просмотра - person Dr Mido; 17.03.2021
comment
Нет, просто я приведу вам пример, если вы хотите получить доступ к адаптеру, вам нужно изменить подпись интерфейсов, таких как void onBindView(Recyclerview recyclerview, yourAdapter adapter, Fragment fragment) - person Shay Kin; 17.03.2021
comment
Если я правильно понял, вы имеете в виду Android Studio под AS, ну, может быть, вы неправильно использовали интерфейс - person Shay Kin; 17.03.2021
comment
да AS ярлык для Android studio, интерфейс конечно не промахнулся, попробовал сделать в этом же классе и в отдельном файле, попробую еще раз - person Dr Mido; 17.03.2021
comment
вопрос перед изменением моего ответа - это адаптеры recyclerView того же класса? - person Shay Kin; 17.03.2021
comment
Я редактирую свой вопрос и добавляю полный код класса адаптера - person Dr Mido; 17.03.2021
comment
хорошо, я обновил свой ответ, добавив более подробную информацию, пожалуйста, перепроверьте его - person Shay Kin; 17.03.2021
comment
В этот раз все заработало нормально, но как я и ожидал, к сожалению, метод onOptionsItemSelected не распознал адаптер от onBindView Таким образом выдал мне java.lang.NullPointerException: Attempt to invoke virtual method 'void com.test.dummyappv3.ui.PostAdapter.setViewType(int)' on a null object reference при попытке изменить раскладку из меню - person Dr Mido; 18.03.2021
comment
Давайте продолжим это обсуждение в чате. - person Shay Kin; 18.03.2021