回收器查看单击在使用导航抽屉时停止工作(无碎片)



我遇到了这篇文章,其中讨论了如何在不使用片段的情况下创建导航抽屉。撇开我不想使用片段的动机不谈,我现在面临着一个问题,即我的RecyclerView项的 onClick 事件不再被触发。

TL;DR:如果我从布局 xml 中删除DrawerLayout部分,onClick 事件将按预期触发。在我的活动布局 xml 中定义DrawerLayout似乎会导致回收器视图的所有事件(如滚动/单击(停止工作。我的另一个观察结果是,包括DrawerLaout会导致我RecyclerView的第一个元素根本不显示。我无法弄清楚可能导致onClick事件被阻止的原因。


以下是我的代码的相关部分:

1. 导航活动,将由希望显示导航抽屉的其他活动扩展

public class NavigationActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
protected void onCreateDrawer() {
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.navigation, 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_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_todays_goals) {
} else if (id == R.id.nav_freetime) {
Intent intent = new Intent(this,FreeTimeActivity.class);
startActivity(intent);
} else if (id == R.id.nav_goaltime) {
Intent intent = new Intent(this,GoalTimeActivity.class);
startActivity(intent);
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
@Override
public void setContentView(@LayoutRes int layoutResID)
{
super.setContentView(layoutResID);
onCreateDrawer();
}
}

2. 使用有问题的回收器视图扩展导航活动的活动之一(仅显示相关代码(:

public class FreeTimeActivity extends NavigationActivity implements FreeTimeAdapter.FreeTimeAdapterOnClickHandler, LoaderManager.LoaderCallbacks<Cursor> {
private RecyclerView mRecyclerView;
private ProgressBar mLoadingIndicator;
private FreeTimeAdapter mFreeTimeAdapter;
private int mPosition = RecyclerView.NO_POSITION;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_freetime);
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview_seasons);
mLoadingIndicator = (ProgressBar) findViewById(R.id.pb_loading_indicator);
mFreeTimeAdapter = new FreeTimeAdapter(this, this);
LinearLayoutManager layoutManager =
new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setAdapter(mFreeTimeAdapter);
showLoading();
getSupportLoaderManager().initLoader(FREETIME_LOADER_ID, null, this);
}
@Override
public void onClickFreeTimeListItem(String name) {
Intent intent = new Intent(this, FreeTimeDetailsActivity.class);
//TODO uri should be set as freetime_goals rather than goals.
Uri uri = LifeTimeContract.FreeTimeGoalEntry.CONTENT_URI;
uri = uri.buildUpon().appendPath(name).build();
intent.setData(uri);
intent.putExtra("freezone_name",name);
startActivity(intent);
}
}

onClickFreeTimeListItem方法是在单击mRecyclerView实例中的项时应调用的方法。我尝试调试 RecyclerView 使用的FreeTimeAdapter类,它似乎按预期注册了侦听器,但稍后单击RecyclerView中的项目时永远不会调用onClick方法。以下是FreeTimeAdapter类的代码:

public class FreeTimeAdapter extends RecyclerView.Adapter<FreeTimeAdapter.FreeTimeAdapterViewHolder> {
private final Context mContext;
final private FreeTimeAdapterOnClickHandler mClickHandler;
/**
* The interface that receives onClickFreeTimeListItem messages.
*/
public interface FreeTimeAdapterOnClickHandler {
void onClickFreeTimeListItem(String name);
}
private Cursor mCursor;
/**
* Creates a ForecastAdapter.
*
* @param context      Used to talk to the UI and app resources
* @param clickHandler The on-click handler for this adapter. This single handler is called
*                     when an item is clicked.
*/
public FreeTimeAdapter(@NonNull Context context, FreeTimeAdapterOnClickHandler clickHandler) {
mContext = context;
mClickHandler = clickHandler;
}
@Override
public FreeTimeAdapterViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
int layoutId = R.layout.freetime_list_items;
View view = LayoutInflater.from(mContext).inflate(layoutId, viewGroup, false);
view.setFocusable(true);
return new FreeTimeAdapterViewHolder(view);
}
@Override
public void onBindViewHolder(FreeTimeAdapterViewHolder freeTimeAdapterViewHolder, int position) {
mCursor.moveToPosition(position);
String freeTimeName = mCursor.getString(FreeTimeActivity.INDEX_FREETIME_NAME);
int id = mCursor.getInt(FreeTimeActivity.INDEX_FREETIME_ID);
String startTime = mCursor.getString(FreeTimeActivity.INDEX_FREETIME_START_TIME);
String endTime = mCursor.getString(FreeTimeActivity.INDEX_FREETIME_END_TIME);
String endDate = mCursor.getString(FreeTimeActivity.INDEX_FREETIME_END_DATE);
freeTimeAdapterViewHolder.tvFreeTimeName.setText(freeTimeName);
freeTimeAdapterViewHolder.tvStartTime.setText(startTime);
freeTimeAdapterViewHolder.tvEndTime.setText(endTime);
freeTimeAdapterViewHolder.tvEndDate.setText(endDate);
/*FreeTimeItemDataHolder freeTimeItemDataHolder = new FreeTimeItemDataHolder(id,freeTimeName);*/
freeTimeAdapterViewHolder.itemView.setTag(R.string.tag_freetime_id,id);
freeTimeAdapterViewHolder.itemView.setTag(R.string.tag_freetime_name,freeTimeName);

}

@Override
public int getItemCount() {
if (null == mCursor) return 0;
return mCursor.getCount();
}
void swapCursor(Cursor newCursor) {
mCursor = newCursor;
notifyDataSetChanged();
}
class FreeTimeAdapterViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
final TextView tvFreeTimeName;
final TextView tvStartTime;
final TextView tvEndTime;
final TextView tvEndDate;
FreeTimeAdapterViewHolder(View view) {
super(view);
//TODO add additional views to each item in the recyclerview such as delete button etc
tvFreeTimeName = (TextView) view.findViewById(R.id.tv_freetime_name);
tvStartTime = (TextView) view.findViewById(R.id.tv_freetime_start_time);
tvEndTime = (TextView) view.findViewById(R.id.tv_freetime_end_time);
tvEndDate = (TextView) view.findViewById(R.id.tv_freetime_end_date);
view.setOnClickListener(this);
}
/**
* This gets called by the child views during a click. We fetch the date that has been
* selected, and then call the onClickFreeTimeListItem handler registered with this adapter
*
* @param v the View that was clicked
*/
@Override
public void onClick(View v) {
int adapterPosition = getAdapterPosition();
mCursor.moveToPosition(adapterPosition);
String name = mCursor.getString(FreeTimeActivity.INDEX_FREETIME_NAME);
mClickHandler.onClickFreeTimeListItem(name);
}
}
}

包含回收程序视图的活动的布局 XML 文件

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<ProgressBar
android:id="@+id/pb_loading_indicator"
android:layout_width="42dp"
android:layout_height="42dp"
android:layout_gravity="center"
android:visibility="invisible" />
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview_seasons"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="8dp" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:src="@drawable/ic_add_box_black_24dp"
android:layout_margin="48dp"
android:onClick="onClickAddFreeTime"/>
<!-- Temporariliy added to navigate to goal time screen. Remove this when app navigation bar is coded -->
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_all_goals"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|bottom"
android:src="@drawable/ic_add_box_black_24dp"
android:layout_margin="48dp"
android:onClick="onClickAllGoals"/>
<android.support.v4.widget.DrawerLayout 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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="@layout/app_bar_navigation"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header_navigation"
app:menu="@menu/activity_navigation_drawer" />
</android.support.v4.widget.DrawerLayout>
</FrameLayout>

在我引入NavigationActivity和相关导航抽屉代码之前,相同的代码库工作正常。

嗨,实际上我不知道您的代码中到底出了什么问题,但您可以查看我的代码,我做了同样的事情,它工作正常
,这是包含导航抽屉的基本活动

public class BaseActivity extends AppCompatActivity implements
NavigationView.OnNavigationItemSelectedListener {
private NavigationView navigationView;
private DrawerLayout fullLayout;
private Toolbar toolbar;
private ActionBarDrawerToggle drawerToggle;
private int selectedNavItemId;
List<User> userInfoList = new ArrayList<>();
private TextView headerText;
private TextView pointsTextView;
private TextView groupTextView;
String access;
String client;
String expiry;
String uid;
String type;
String url;
ArrayList<String> categories;
View parentVeiw;
@Override
public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
super.onCreate(savedInstanceState, persistentState);
}
boolean doubleBackToExitPressedOnce = false;
@Override
public void onBackPressed() {
parentVeiw=findViewById(R.id.activity_container);
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
return;
}
this.doubleBackToExitPressedOnce = true;
Snackbar.make(parentVeiw,"الرجاء اضغط مرة أخرى للخروج من البرنامج",Snackbar.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
doubleBackToExitPressedOnce = false;
}
}, 2000);
}
@Override
public void setContentView(@LayoutRes int layoutResID) {
access = ((GlobalVAriables) this.getApplication()).getAccessToken();
client = ((GlobalVAriables) this.getApplication()).getClient();
expiry = ((GlobalVAriables) this.getApplication()).getExpiry();
uid = ((GlobalVAriables) this.getApplication()).getUid();
type = ((GlobalVAriables) this.getApplication()).getType();
url = ((GlobalVAriables) this.getApplication()).getUrl();
getCategories(url, access, type, client, expiry, uid);
sendJsonRequestgetUserInfo(url, access, type, client, expiry, uid);

/**
* This is going to be our actual root layout.
*/
fullLayout = (DrawerLayout) getLayoutInflater().inflate(R.layout.activity_base, null);
/**
* {@link FrameLayout} to inflate the child's view. We could also use a {@link android.view.ViewStub}
*/
FrameLayout activityContainer = (FrameLayout) fullLayout.findViewById(R.id.activity_content);
getLayoutInflater().inflate(layoutResID, activityContainer, true);
/**
* Note that we don't pass the child's layoutId to the parent,
* instead we pass it our inflated layout.
*/
super.setContentView(fullLayout);
toolbar = (Toolbar) findViewById(R.id.toolbar);
navigationView = (NavigationView) findViewById(R.id.navigationView); //        int currentapiVersion = android.os.Build.VERSION.SDK_INT; //        if (currentapiVersion == Build.VERSION_CODES.KITKAT){ //            toolbar.setPadding(0, getStatusBarHeight(), 0, 0);  } //
if (useToolbar())
{
setSupportActionBar(toolbar);
}
else
{
toolbar.setVisibility(View.GONE);
}
setUpNavView();
}
/**
* Helper method that can be used by child classes to
* specify that they don't want a {@link Toolbar}
* @return true
*/
protected boolean useToolbar()
{
return true;
}
protected void setUpNavView()
{
navigationView.setNavigationItemSelectedListener(this);
if( useDrawerToggle()) { // use the hamburger menu
drawerToggle = new ActionBarDrawerToggle(this, fullLayout, toolbar,
R.string.drawer_open,
R.string.drawer_close);
fullLayout.setDrawerListener(drawerToggle);
drawerToggle.syncState();
} else if(useToolbar() && getSupportActionBar() != null) {
// Use home/back button instead
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(getResources()
.getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha));
}
}
/**
* Helper method to allow child classes to opt-out of having the
* hamburger menu.
* @return
*/
protected boolean useDrawerToggle()
{
return true;
}

@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
fullLayout.closeDrawer(GravityCompat.START);
selectedNavItemId = menuItem.getItemId();
return onOptionsItemSelected(menuItem);
}

@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
switch (id)
{
case R.id.main:
Intent mainac = new Intent(this, MainActivity.class);
startActivity(mainac);
finish();

break;
case R.id.Categories:
Intent Categories=new Intent(this,CategoryActivity.class);
Categories.putExtra("categories", categories);
startActivity(Categories);
finish();
break;
case R.id.notifications:
Intent notificationIntent=new Intent(this,NotificationsActivity.class);
startActivity(notificationIntent);
finish();
break;
case R.id.change_password:
Intent changePassIntent=new Intent(this,changePassword.class);
startActivity(changePassIntent);
finish();
break;
case R.id.log_out:

SharedPreferences sharedPrefs = getSharedPreferences(SignInActivity.PREFS_NAME, MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPrefs.edit();
editor.clear();
editor.commit(); //                user = "";
//show login form
Intent intent = new Intent(this, First_Activity.class);
startActivity(intent);
finish();
break;
case R.id.about_them:
Intent aboutThemIntent=new Intent(this,AboutThem.class);
startActivity(aboutThemIntent);
finish();
break;
case R.id.about_us:
Intent aboutUsIntent=new Intent(this,AboutUs.class);
startActivity(aboutUsIntent);
finish();
break;


default:
}
return super.onOptionsItemSelected(item);
}}

这是扩展基本活动的活动

public class MainActivity extends BaseActivity {
public static final int detail_id = 1;
private bookListAdapter booklistadapter;
List<book> aksarEste3araList = new ArrayList<>();
RecyclerView aksarEste3araRecyclerView;
List<book> sanfMofadalList = new ArrayList<>();
RecyclerView sanfMofadalRecyclerView;
String user;
String access;
String client;
String expiry;
String uid;
String type;
String url;
TextView mostEste3aeaNmae, sanfMofadalName;
ProgressDialog progressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mostEste3aeaNmae = (TextView) findViewById(R.id.most_este3ara_name);
sanfMofadalName = (TextView) findViewById(R.id.sanf_mofadal_name);
Typeface custom_font = Typeface.createFromAsset(getAssets(), "fonts/GE_SS_Three_Light_0.otf");
mostEste3aeaNmae.setTypeface(custom_font);
sanfMofadalName.setTypeface(custom_font);

access = ((GlobalVAriables) this.getApplication()).getAccessToken();
client = ((GlobalVAriables) this.getApplication()).getClient();
expiry = ((GlobalVAriables) this.getApplication()).getExpiry();
uid = ((GlobalVAriables) this.getApplication()).getUid();
type = ((GlobalVAriables) this.getApplication()).getType();
url = ((GlobalVAriables) this.getApplication()).getUrl();

//Toast.makeText(getBaseContext(),access,Toast.LENGTH_SHORT).show();

// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
// If you want to send messages to this application instance or
// manage this apps subscriptions on the server side, send the
// Instance ID token to your app server.
sendRegistrationToServer(refreshedToken);

//        aksar este3ara
aksarEste3araRecyclerView = (RecyclerView) findViewById(R.id.aksar_este3ara_recycler_view);
sendJsonRequestAksarEste3ara(url, access, type, client, expiry, uid);
aksarEste3araRecyclerView.addOnItemTouchListener(new RecyclerTouchListener(getBaseContext(), aksarEste3araRecyclerView, new RecyclerTouchListener.ClickListener() {
@Override
public void onClick(View view, int position) {
Intent i = new Intent(getBaseContext(), BookDetailsActivity.class);
i.putExtra("goo", aksarEste3araList.get(position).getCategoryId());
i.putExtra("bookId", aksarEste3araList.get(position).getBookId());
startActivityForResult(i, detail_id);
}
@Override
public void onLongClick(View view, int position) {
Intent i = new Intent(getBaseContext(), BookDetailsActivity.class);
i.putExtra("goo", aksarEste3araList.get(position).getCategoryId());
i.putExtra("bookId", aksarEste3araList.get(position).getBookId());
startActivityForResult(i, detail_id);
}
}));

//        sanf mofadal
sanfMofadalRecyclerView = (RecyclerView) findViewById(R.id.sanf_mofadal_recycler_view);
sendJsonRequestSanfMofadal(url, access, type, client, expiry, uid);
sanfMofadalRecyclerView.addOnItemTouchListener(new RecyclerTouchListener(getBaseContext(), sanfMofadalRecyclerView, new RecyclerTouchListener.ClickListener() {
@Override
public void onClick(View view, int position) {
Intent i = new Intent(getBaseContext(), BookDetailsActivity.class);
i.putExtra("goo", sanfMofadalList.get(position).getCategoryId());
i.putExtra("bookId", sanfMofadalList.get(position).getBookId());
startActivityForResult(i, detail_id);
}
@Override
public void onLongClick(View view, int position) {
Intent i = new Intent(getBaseContext(), BookDetailsActivity.class);
i.putExtra("goo", sanfMofadalList.get(position).getCategoryId());
i.putExtra("bookId", sanfMofadalList.get(position).getBookId());
startActivityForResult(i, detail_id);
}
}));
}

如果您需要任何澄清,请随时询问

最新更新