[Android Studio]如何从Fragment中嵌套的Recycleview启动一个Activity?

Posted

技术标签:

【中文标题】[Android Studio]如何从Fragment中嵌套的Recycleview启动一个Activity?【英文标题】:[Android Studio]How to start an Activity from a nested Recycleview in a Fragment? 【发布时间】:2021-09-05 21:50:15 【问题描述】:

我想在我的 RecycleView 中单击一个自定义对象,然后它会启动一个新的 Activity 包含有关所单击对象的数据,但单击时我没有得到任何响应。

我尝试关注this 问题,但要么我做错了,要么它不起作用。

笑话类别

package com.example.jokestarapplication;

import android.os.Parcel;
import android.os.Parcelable;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class JokeCategory  implements Parcelable
    private String name;
    private List<Joke> jokes;

    public JokeCategory(String name) 
        this.name = name;
        this.jokes= new ArrayList<>();
    

    protected JokeCategory(Parcel in)
        name=in.readString();
        in.readList(jokes,List.class.getClassLoader());
    

    public JokeCategory(String name, List<Joke> jokes) 
        this.name = name;
        this.jokes = jokes;
    

    public static final Creator<JokeCategory> CREATOR = new Creator<JokeCategory>() 
        @Override
        public JokeCategory createFromParcel(Parcel in) 
            return new JokeCategory(in);
        

        @Override
        public JokeCategory[] newArray(int size) 
            return new JokeCategory[size];
        
    ;

    public String getName() 
        return name;
    

    public String getJokeNumString() 
        return String.valueOf(jokes.size());
    

    public List<Joke> getJokes() 
        return jokes;
    

    @Override
    public String toString() 
        return name;
    

    public void addJoke(Joke joke) 
        jokes.add(joke);
    

    @Override
    public int describeContents() 
        return 0;
    

    @Override
    public void writeToParcel(Parcel dest, int flags) 
        dest.writeString(name);
        dest.writeList(jokes);
    

CategoryListAdapter

package com.example.jokestarapplication;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.List;

public class CategoryListAdapter extends RecyclerView.Adapter<CategoryListAdapter.CategoryViewHolder> 

    private List<JokeCategory> mItems;
    private Context mContext;
    private ListItemClickListener mListItemClickListener;

    public CategoryListAdapter(List<JokeCategory> mItems, Context mContext, ListItemClickListener mListItemClickListener) 
        this.mItems = mItems;
        this.mContext = mContext;
        this.mListItemClickListener = mListItemClickListener;
    

    @Override
    public int getItemViewType(final int position) 
        return R.layout.category_list_item;
    

    @NonNull
    @Override
    public CategoryViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) 

        Context context = parent.getContext();
        mContext = context;
        LayoutInflater inflater = LayoutInflater.from(context);

        View view = inflater.inflate(R.layout.category_list_item, parent, false);

        return new CategoryViewHolder(view);
    

    @Override
    public void onBindViewHolder(@NonNull CategoryViewHolder holder, int position) 
        holder.bind(position);
    

    @Override
    public int getItemCount() 
        return (mItems==null) ? 0 : mItems.size();
    

    interface ListItemClickListener 
        void onListItemClick(JokeCategory item);
    

    public void setOnListItemClickListener(ListItemClickListener listItemClickListener) 
        mListItemClickListener = listItemClickListener;
    

    public class CategoryViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener

        private TextView tvCatName, tvCatNum;

        public CategoryViewHolder(@NonNull View itemView) 
            super(itemView);
            tvCatName = itemView.findViewById(R.id.tvCatName);
            tvCatNum = itemView.findViewById(R.id.tvCatNum);
        

        public TextView getTvCatName() 
            return tvCatName;
        

        public TextView getTvCatNum() 
            return tvCatNum;
        

        public void bind(int position) 
            tvCatName.setText(mItems.get(position).getName());
            tvCatNum.setText(mItems.get(position).getJokeNumString());
        

        @Override
        public void onClick(View v) 
            if (mListItemClickListener!=null)
                int clickedIndex = getAdapterPosition();
                JokeCategory jokeCategory = mItems.get(clickedIndex);
                mListItemClickListener.onListItemClick(jokeCategory);
            
        
    


主片段


import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.util.LinkedList;
import java.util.List;

public class MainFragment extends Fragment implements CategoryListAdapter.ListItemClickListener 

    private CategoryListAdapter mAdapter;
    private RecyclerView rvcategories;
    private List<JokeCategory> categories;

    private onCategoryITemSelected listener;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) 
        View view = inflater.inflate(R.layout.fragment_main, container, false);

        categories = (List<JokeCategory>) getArguments().getSerializable("Categories");

        // Add the following lines to create RecyclerView
        rvcategories = view.findViewById(R.id.rvcategories);
        rvcategories.setHasFixedSize(true);
        rvcategories.setLayoutManager(new LinearLayoutManager(view.getContext()));
        mAdapter = new CategoryListAdapter(categories, getContext(), this);
        rvcategories.setAdapter(mAdapter);

        return view;
    

    @Override
    public void onResume() 
        categories = (List<JokeCategory>) getArguments().getSerializable("Categories");
        rvcategories.getAdapter().notifyDataSetChanged();
        super.onResume();
    

    @Override
    public void onAttach(@NonNull Context context) 
        super.onAttach(context);

        if (context instanceof onCategoryITemSelected)
            listener = (onCategoryITemSelected) context;
        else
            throw new ClassCastException(context.toString() + "must implement listener");
    

    @Override
    public void onListItemClick(JokeCategory item) 
        Intent i = new Intent(getContext(), ActivityCategory.class);
        i.putExtra(ActivityCategory.KEY_EXTRACATEGORY, item);
        startActivity(i);
    


    public interface onCategoryITemSelected 
        void onListItemClick(JokeCategory item);
    

    private List<JokeCategory> DemoData() 
        List<JokeCategory> data = new LinkedList<>();
        data.add(new JokeCategory("Short Jokes"));
        data.add(new JokeCategory("Long Jokes"));
        data.add(new JokeCategory("One Liner"));
        data.add(new JokeCategory("Dumb Jokes"));
        data.add(new JokeCategory("Chuck Norris"));

        return data;
    

MainActivity


import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.material.navigation.NavigationView;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;


public class    MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener


    //global available user data
    public static String displayUserName;
    public static String displayUserEmail;
    GoogleSignInClient mGoogleSignInClient;
    private TextView displayName;
    private TextView displayEmail;
    private DrawerLayout drawerLayout;
    private ActionBarDrawerToggle actionBarDrawerToggle;
    private Toolbar toolbar;
    private NavigationView navigationView;
    private FragmentManager fragmentManager;
    private FragmentTransaction fragmentTransaction;

    private List<JokeCategory> categories;
    private Bundle bundle;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        drawerLayout = findViewById(R.id.drawer);
        navigationView = findViewById(R.id.navigationView);
        navigationView.setNavigationItemSelectedListener(this);

        actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.open, R.string.close);
        drawerLayout.addDrawerListener(actionBarDrawerToggle);
        actionBarDrawerToggle.setDrawerIndicatorEnabled(true);
        actionBarDrawerToggle.syncState();

        categories = DemoData();
        bundle = new Bundle();
        bundle.putSerializable("Categories", (Serializable) categories);

        //load default fragment

        fragmentManager = getSupportFragmentManager();
        fragmentTransaction = fragmentManager.beginTransaction();
        MainFragment mainFragment = new MainFragment();
        mainFragment.setArguments(bundle);
        fragmentTransaction.replace(R.id.container_fragment, mainFragment);
        fragmentTransaction.commit();

        // Configure sign-in to request the user's ID, email address, and basic
        // profile. ID and basic profile are included in DEFAULT_SIGN_IN.
        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestIdToken(getString(R.string.default_web_client_id))
                .requestEmail()
                .build();

        // Build a GoogleSignInClient with the options specified by gso.
        mGoogleSignInClient = GoogleSignIn.getClient(this, gso);

        // Side navigation elements (needs headerView since sidenav can be hidden (null)
        View headerView = navigationView.getHeaderView(0);
        displayName = (TextView) headerView.findViewById(R.id.displayName);
        displayEmail = (TextView) headerView.findViewById(R.id.displayEmail);

        GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
        if (account != null) 
            //account.getDisplayName()
            Log.d("AUTH", "User is logged-in automatically");
            Toast.makeText(this, "Google Login automatically (already signed in previously)",
                    Toast.LENGTH_LONG).show();

            updateMainActivityUI(account);
         else 
            Log.d("AUTH", "User is NOT logged-in automatically");
        


    

    public void updateMainActivityUI(GoogleSignInAccount account) 
        // Global vars
        displayUserName = account.getDisplayName();
        displayUserEmail = account.getEmail();
        //Side nav vars
        Log.d("AUTH", "side nav vars: " + displayUserName);
        Log.d("AUTH", "side nav vars: " + displayUserEmail);
       // if (displayUserName != null) 
            displayName.setText(displayUserName);
       // 
       // if (displayUserEmail != null) 
            displayEmail.setText(displayUserEmail);
      //  


    


    //move to new Fragment

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) 

        drawerLayout.closeDrawer(GravityCompat.START);


        bundle = new Bundle();
        bundle.putSerializable("Categories", (Serializable) categories);

        fragmentManager = getSupportFragmentManager();
        fragmentTransaction = fragmentManager.beginTransaction();

        switch (item.getItemId()) 
            case R.id.home:
                MainFragment mainFragment = new MainFragment();
                mainFragment.setArguments(bundle);
                fragmentTransaction.replace(R.id.container_fragment, mainFragment);
                break;

            case R.id.newJoke:
                NewJokeFragment newJokeFragment = new NewJokeFragment();
                newJokeFragment.setArguments(bundle);
                fragmentTransaction.replace(R.id.container_fragment, newJokeFragment);
                break;

            case R.id.logInOut:
                fragmentTransaction.replace(R.id.container_fragment, new LogInOutFragment());
                break;
            case R.id.aboutUs:
                fragmentTransaction.replace(R.id.container_fragment, new AboutUsFragment());
                break;

            case R.id.register:
                fragmentTransaction.replace(R.id.container_fragment, new RegisterFragment());
                break;

        
        fragmentTransaction.commit();

        return true;
    

    private List<JokeCategory> DemoData() 
        List<JokeCategory> data = new ArrayList<>();
        data.add(new JokeCategory("Short Jokes"));
        data.add(new JokeCategory("Long Jokes"));
        data.add(new JokeCategory("One Liner"));
        data.add(new JokeCategory("Dumb Jokes"));
        data.add(new JokeCategory("Chuck Norris"));

        return data;
    

    public void updateCategories(List<JokeCategory> list)
        categories = list;
    


【问题讨论】:

【参考方案1】:

看起来itemView.onClickListener 从未注册过。

将以下行添加到构造函数中。

itemView.setOnClickListener(this);

看起来像:

       public CategoryViewHolder(@NonNull View itemView) 
            super(itemView);
            itemView.setOnClickListener(this);
            tvCatName = itemView.findViewById(R.id.tvCatName);
            tvCatNum = itemView.findViewById(R.id.tvCatNum);
        

【讨论】:

以上是关于[Android Studio]如何从Fragment中嵌套的Recycleview启动一个Activity?的主要内容,如果未能解决你的问题,请参考以下文章

如何从Mac从android studio中的fabric注销? [复制]

如何向Android Studio里导入从Github上面下载的Project?

如何从 Android Studio 运行单个 Kotlin 类

如何强制 Android Studio 从欢迎屏幕开始?

如何从android studio启动firefox焦点

如何从 Android Studio 为 Flutter 构建签名的 apk