无法将上下文转换为片段的 FragmentAdapter 中的 CustomCallBack 接口
Can't cast context to CustomCallBack interface in FragmentAdapter of a Fragment
我在 Fragment 的 FragmentAdapter 中投射上下文时遇到问题。我的应用程序流程是:
- 当我点击导航列表项 (Nav One) 时,它将显示带有 recyclerview 和 cardview 的片段。
- 当我单击 cardview 列表项的图像时,我想要一个操作来显示 Toast 消息或使用名为 (CustomCallBack) 的自定义接口执行某些操作。
这是我的代码:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private ListView lvNavigation;
private DrawerLayout mDrawer;
private NavigationView mNavigation;
private LinearLayout llMianContain;
String[] navigation = new String[]{"Nav One","Nav Two", "Nav Three","Nav Four"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
lvNavigation = (ListView) findViewById(R.id.lv_listView);
mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
mNavigation= (NavigationView) findViewById(R.id.navigation_view);
llMianContain = (LinearLayout) findViewById(R.id.ll_main_content);
setSupportActionBar(toolbar);
lvNavigation.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, navigation));
lvNavigation.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
replaceFragment(i);
lvNavigation.setItemChecked(i, true);
hideDrawer();
}
});
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, mDrawer, toolbar, R.string.open, R.string.close);
mDrawer.setDrawerListener(toggle);
toggle.syncState();
}
private void replaceFragment(int position){
Fragment fragment = null;
switch (position){
case 0:
fragment = new OneFragment();
break;
case 1:
fragment = new TwoFragment();
break;
case 2:
fragment = new ThreeFragment();
break;
case 3:
fragment= new FourFragment();
break;
default:
fragment = new OneFragment();
break;
}
if(null!= fragment){
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.ll_main_content, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
}
private void hideDrawer(){
mDrawer.closeDrawer(GravityCompat.START);
}
private void showDrawer(){
mDrawer.openDrawer(GravityCompat.START);
}
@Override
public void onBackPressed() {
if (mDrawer.isDrawerOpen(GravityCompat.START))
hideDrawer();
else
super.onBackPressed();
}
}
OneFragment.java
public class OneFragment extends Fragment implements FragmentOneAdapter.CustomCallBack{
private ArrayList<ListItem> listItems;
private RecyclerView recyclerView;
private FragmentOneAdapter adapter;
public OneFragment() { }
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view =inflater.inflate(R.layout.fragment_one, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
LinearLayoutManager manager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(manager);
listItems = new ArrayList<>();
for(int i=0;i<40;i++){
listItems.add(new ListItem(R.drawable.ic_account_circle_black_48dp, "MY NAME "+ i));
}
adapter = new FragmentOneAdapter(listItems, getActivity());
recyclerView.setAdapter(adapter);
return view;
}
@Override
public void onProfileClick(int position) {
Toast.makeText(getActivity(), "position "+ position, Toast.LENGTH_SHORT).show();
}
}
FragmentAdapter.java
public class FragmentOneAdapter extends RecyclerView.Adapter<FragmentOneAdapter.FragmentOneViewHolder> {
private ArrayList<ListItem> listItems;
private Context context;
final CustomCallBack customCallBack;
public FragmentOneAdapter(ArrayList<ListItem> listItems, Context context){
this.listItems = listItems;
this.context = context;
this.customCallBack = (CustomCallBack) context;
}
@Override
public FragmentOneViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_one_item, parent,false);
FragmentOneViewHolder holder = new FragmentOneViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(FragmentOneViewHolder holder, int position) {
holder.tvName.setText(listItems.get(position).getName());
holder.ivProfile.setImageResource(listItems.get(position).getProfile());
}
@Override
public int getItemCount() {
return listItems.size();
}
class FragmentOneViewHolder extends RecyclerView.ViewHolder{
TextView tvName;
ImageView ivProfile;
LinearLayout llFooter;
public FragmentOneViewHolder(View itemView) {
super(itemView);
tvName = (TextView) itemView.findViewById(R.id.tv_name);
ivProfile = (ImageView) itemView.findViewById(R.id.iv_profile);
llFooter= (LinearLayout) itemView.findViewById(R.id.ll_footer);
ivProfile.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
customCallBack.onProfileClick(getAdapterPosition());
}
});
}
}
// MY Custom CallBack
interface CustomCallBack{
void onProfileClick(int position);
}
}
嗯,
所以你的 Fragment 正在实现 CustomCallBack 接口
为什么不直接将 Fragment 对象本身传递给适配器?
例如,在 FragmentOneAdapter.java、
变化:
public FragmentOneAdapter(ArrayList<ListItem> listItems, Context context) ===> public FragmentOneAdapter(ArrayList<ListItem> listItems, CustomCallBack callback)
然后:
this.customCallBack = (CustomCallBack) context; ===> this.customCallBack = callback;
显然,现在 OneFragment.java,
只需将 'this' 作为参数传递,因为 Fragment 本身就是 CustomCallBack:
adapter = new FragmentOneAdapter(listItems, getActivity()); ===> adapter = new FragmentOneAdapter(listItems, this);
我在 Fragment 的 FragmentAdapter 中投射上下文时遇到问题。我的应用程序流程是: - 当我点击导航列表项 (Nav One) 时,它将显示带有 recyclerview 和 cardview 的片段。 - 当我单击 cardview 列表项的图像时,我想要一个操作来显示 Toast 消息或使用名为 (CustomCallBack) 的自定义接口执行某些操作。 这是我的代码:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private ListView lvNavigation;
private DrawerLayout mDrawer;
private NavigationView mNavigation;
private LinearLayout llMianContain;
String[] navigation = new String[]{"Nav One","Nav Two", "Nav Three","Nav Four"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
lvNavigation = (ListView) findViewById(R.id.lv_listView);
mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
mNavigation= (NavigationView) findViewById(R.id.navigation_view);
llMianContain = (LinearLayout) findViewById(R.id.ll_main_content);
setSupportActionBar(toolbar);
lvNavigation.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, navigation));
lvNavigation.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
replaceFragment(i);
lvNavigation.setItemChecked(i, true);
hideDrawer();
}
});
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, mDrawer, toolbar, R.string.open, R.string.close);
mDrawer.setDrawerListener(toggle);
toggle.syncState();
}
private void replaceFragment(int position){
Fragment fragment = null;
switch (position){
case 0:
fragment = new OneFragment();
break;
case 1:
fragment = new TwoFragment();
break;
case 2:
fragment = new ThreeFragment();
break;
case 3:
fragment= new FourFragment();
break;
default:
fragment = new OneFragment();
break;
}
if(null!= fragment){
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.ll_main_content, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
}
private void hideDrawer(){
mDrawer.closeDrawer(GravityCompat.START);
}
private void showDrawer(){
mDrawer.openDrawer(GravityCompat.START);
}
@Override
public void onBackPressed() {
if (mDrawer.isDrawerOpen(GravityCompat.START))
hideDrawer();
else
super.onBackPressed();
}
}
OneFragment.java
public class OneFragment extends Fragment implements FragmentOneAdapter.CustomCallBack{
private ArrayList<ListItem> listItems;
private RecyclerView recyclerView;
private FragmentOneAdapter adapter;
public OneFragment() { }
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view =inflater.inflate(R.layout.fragment_one, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
LinearLayoutManager manager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(manager);
listItems = new ArrayList<>();
for(int i=0;i<40;i++){
listItems.add(new ListItem(R.drawable.ic_account_circle_black_48dp, "MY NAME "+ i));
}
adapter = new FragmentOneAdapter(listItems, getActivity());
recyclerView.setAdapter(adapter);
return view;
}
@Override
public void onProfileClick(int position) {
Toast.makeText(getActivity(), "position "+ position, Toast.LENGTH_SHORT).show();
}
}
FragmentAdapter.java
public class FragmentOneAdapter extends RecyclerView.Adapter<FragmentOneAdapter.FragmentOneViewHolder> {
private ArrayList<ListItem> listItems;
private Context context;
final CustomCallBack customCallBack;
public FragmentOneAdapter(ArrayList<ListItem> listItems, Context context){
this.listItems = listItems;
this.context = context;
this.customCallBack = (CustomCallBack) context;
}
@Override
public FragmentOneViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_one_item, parent,false);
FragmentOneViewHolder holder = new FragmentOneViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(FragmentOneViewHolder holder, int position) {
holder.tvName.setText(listItems.get(position).getName());
holder.ivProfile.setImageResource(listItems.get(position).getProfile());
}
@Override
public int getItemCount() {
return listItems.size();
}
class FragmentOneViewHolder extends RecyclerView.ViewHolder{
TextView tvName;
ImageView ivProfile;
LinearLayout llFooter;
public FragmentOneViewHolder(View itemView) {
super(itemView);
tvName = (TextView) itemView.findViewById(R.id.tv_name);
ivProfile = (ImageView) itemView.findViewById(R.id.iv_profile);
llFooter= (LinearLayout) itemView.findViewById(R.id.ll_footer);
ivProfile.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
customCallBack.onProfileClick(getAdapterPosition());
}
});
}
}
// MY Custom CallBack
interface CustomCallBack{
void onProfileClick(int position);
}
}
嗯,
所以你的 Fragment 正在实现 CustomCallBack 接口
为什么不直接将 Fragment 对象本身传递给适配器?
例如,在 FragmentOneAdapter.java、
变化:
public FragmentOneAdapter(ArrayList<ListItem> listItems, Context context) ===> public FragmentOneAdapter(ArrayList<ListItem> listItems, CustomCallBack callback)
然后:
this.customCallBack = (CustomCallBack) context; ===> this.customCallBack = callback;
显然,现在 OneFragment.java,
只需将 'this' 作为参数传递,因为 Fragment 本身就是 CustomCallBack:
adapter = new FragmentOneAdapter(listItems, getActivity()); ===> adapter = new FragmentOneAdapter(listItems, this);