Listview OnItemClickListener работает с MainActivity, но не с аналогичным TaskActivity - PullRequest
0 голосов
/ 20 сентября 2018

В MainActivity у меня есть и ContextMenu, который отвечает на длинные щелчки, и обычный OnItemClickListener, который отвечает на обычные клики.

В TaskActivity, который практически аналогичен MainActivity, у меня также есть ContextMenu, который отвечаетДля длинных щелчков, однако при попытке установить OnItemClickListener элементы в представлении списка не отвечают (они реагируют на длинные щелчки).

Чего мне не хватает?Я пробовал различные методы, такие как изменение кликабельного статуса на false и т. Д. - ни один из них не работает.И это имеет смысл, потому что у меня их нет в XML MainActivity, но он там работает.

Код MainActivity:

открытый класс MainActivity расширяет AppCompatActivity {

final Context context = this;
public static final int SIGN_IN = 1;
public static String currentTaskListId;
public static String currentUserId;
private TaskListAdapter mTaskListAdapter;
//TextView that is displayed when the list is empty//
private TextView mEmptyStateTextView;
//The loading indicator //
private View loadingIndicator;


// Firebase instance variables

private FirebaseAuth mFirebaseAuth;
private FirebaseAuth.AuthStateListener mAuthStateListener;
private FirebaseDatabase mFirebaseDatabase;
private DatabaseReference mTaskListDatabaseReference;
private ChildEventListener mChildEventListener;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Set the content of the activity to use the activity_main.xml layout file - the task lists
    setContentView(R.layout.activity_main);

    // Initialize Firebase components
    mFirebaseAuth = FirebaseAuth.getInstance();
    mFirebaseDatabase = FirebaseDatabase.getInstance();




    //Initialize firebase authentication
    mAuthStateListener = new FirebaseAuth.AuthStateListener() {
        @Override
        public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
            FirebaseUser user = firebaseAuth.getCurrentUser();
            if (user != null) {
                // user is signed in
                currentUserId=user.getUid();
                onSignedInInitialize(user.getUid());

            } else {
                // user is signed out
                onSignedOutCleanup();
                startActivityForResult(
                        AuthUI.getInstance()
                                .createSignInIntentBuilder()
                                .setIsSmartLockEnabled(false)
                                .setAvailableProviders(Arrays.asList(
                                        new AuthUI.IdpConfig.EmailBuilder().build(),
                                        new AuthUI.IdpConfig.GoogleBuilder().build()))
                                .setTosAndPrivacyPolicyUrls("https://superapp.example.com/terms-of-service.html",
                                        "https://superapp.example.com/privacy-policy.html")
                                .build(),
                        SIGN_IN);
            }
        }
    };


    //Initialize task list Array, ListView and Adapter.
    final ArrayList<TaskList> taskLists = new ArrayList<TaskList>();

    // Create an {@link TaskListAdapter}, whose data source is a list of {@link TaskList}s.
    mTaskListAdapter = new TaskListAdapter(this, taskLists);

    // Locate the {@link ListView} object in the view hierarchy of the {@link Activity}.
    ListView listView = (ListView) findViewById(R.id.task_list_view);

    //Set the empty view
    mEmptyStateTextView = (TextView) findViewById(R.id.empty_view);
    listView.setEmptyView(mEmptyStateTextView);

    //Initialize the loading indicator
    loadingIndicator = findViewById(R.id.loading_indicator);
    loadingIndicator.setVisibility(View.INVISIBLE);

    // Make the {@link ListView} use the {@link TaskListAdapter} defined above, so that the
    // {@link ListView} will display list items for each {@link TaskList} in the list.
    listView.setAdapter(mTaskListAdapter);

    //Set and create the FAB and it's action listener
    FloatingActionButton fab = findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            // Get add_list.xml view
            LayoutInflater li = LayoutInflater.from(context);
            View addTaskListView = li.inflate(R.layout.add_list, null);

            //Create the prompt to enable the user to create a new task list
            AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
                    context);

            // Set add_list.xml as the layout for alertdialog builder
            alertDialogBuilder.setView(addTaskListView);

            //Set the user input box
            final EditText userInput = (EditText) addTaskListView
                    .findViewById(R.id.edit_list_name);

            // Set dialog message
            alertDialogBuilder
                    .setCancelable(false)
                    .setPositiveButton("Create",
                            new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog,int id) {
                                    // Get list title from user and create a new task list
                                    //Also fetch the FireBase ID and connect it to the new task list.
                                    String mTaskListId = mTaskListDatabaseReference.push().getKey();
                                    TaskList taskList = new TaskList(userInput.getText().toString(),mTaskListId);
                                    mTaskListDatabaseReference.child(mTaskListId).setValue(taskList);
                                }
                            })
                    .setNegativeButton("Cancel",
                            new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog,int id) {
                                    dialog.cancel();
                                }
                            });

            // Create the dialog
            AlertDialog alertDialog = alertDialogBuilder.create();

            // Show the dialog
            alertDialog.show();
        }
    });
    // Set an item click listener on the ListView, which creates an intent to open
    //the relevant task list and show the tasks inside.
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
            // Find the current task list that was clicked on
            TaskList currentTaskList = mTaskListAdapter.getItem(position);

            //get the current task list's ID
            currentTaskListId=currentTaskList.getId();


            // Create a new intent to view the tasks in the chosen list
            Intent taskIntent = new Intent(MainActivity.this, TaskActivity.class);

            // Send the intent to launch a new activity
            startActivity(taskIntent);
        }
    });

    listView.setLongClickable(true);
    registerForContextMenu(listView);

}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == SIGN_IN) {
        if (resultCode == RESULT_OK) {
            // Sign-in succeeded, set up the UI
            Toast.makeText(this, "Signed in!", Toast.LENGTH_SHORT).show();
        } else if (resultCode == RESULT_CANCELED) {
            // Sign in was canceled by the user, finish the activity
            Toast.makeText(this, "Sign in canceled", Toast.LENGTH_SHORT).show();
            finish();
        }
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.mini_menu,menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.sign_out:
            AuthUI.getInstance().signOut(this);
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }

}

@Override
protected void onResume() {
    super.onResume();
    mFirebaseAuth.addAuthStateListener(mAuthStateListener);
}
@Override
protected void onPause() {
    super.onPause();
    if (mAuthStateListener != null) {
        mFirebaseAuth.removeAuthStateListener(mAuthStateListener);
    }
    mTaskListAdapter.clear();
    detachDatabaseReadListener();

}

private void onSignedInInitialize(final String userId) {

    //Get reference for the task list for the logged in user and attach the database listener
    mTaskListDatabaseReference=mFirebaseDatabase.getReference().child("users").child(userId);
    loadingIndicator.setVisibility(View.VISIBLE);
    attachDatabaseReadListener();
    mEmptyStateTextView.setText("No task lists, add a new one!");
    loadingIndicator.setVisibility(View.GONE);


}

private void onSignedOutCleanup() {
    mTaskListAdapter.clear();
    detachDatabaseReadListener();
}
private void attachDatabaseReadListener() {
    if (mChildEventListener == null) {
        mChildEventListener = new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                TaskList taskList = dataSnapshot.getValue(TaskList.class);
                mTaskListAdapter.add(taskList);
            }
            public void onChildChanged(DataSnapshot dataSnapshot, String s) {}
            public void onChildRemoved(DataSnapshot dataSnapshot) {}
            public void onChildMoved(DataSnapshot dataSnapshot, String s) {}
            public void onCancelled(DatabaseError databaseError) {}
        };

    }
    mTaskListDatabaseReference.addChildEventListener(mChildEventListener);

}
private void detachDatabaseReadListener() {
    if (mChildEventListener != null) {
        mTaskListDatabaseReference.removeEventListener(mChildEventListener);
        mChildEventListener = null;
    }
}

public static String getCurrentTaskListId() {
    return currentTaskListId;
}
public static String getCurrentUserId() {
    return currentUserId;
}

/**
 * MENU
 */

@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo){
    if (v.getId() == R.id.task_list_view){
        AdapterView.AdapterContextMenuInfo info =(AdapterView.AdapterContextMenuInfo)menuInfo;
        menu.add(0,0,0,"Delete");
    }
}

@Override
public boolean onContextItemSelected(MenuItem menuItem){
    AdapterView.AdapterContextMenuInfo info=(AdapterView.AdapterContextMenuInfo)menuItem.getMenuInfo();
    TaskList taskListClicked=mTaskListAdapter.getItem(info.position);
    Log.d("check","" +taskListClicked.getTitle());
    switch (menuItem.getItemId()) {
        case 0:
            mTaskListDatabaseReference.child(taskListClicked.getId()).removeValue();
            mTaskListAdapter.remove(taskListClicked);
            Toast.makeText(this, "Task List deleted!", Toast.LENGTH_LONG).show();
            break;

        default:
            break;

    }
    return true;
}

}

Код TaskActivity:

public class TaskActivity extends AppCompatActivity {
    final Context context = this;
    private TaskAdapter mTaskAdapter;
    private int taskCount;
    // TextView that is displayed when the list is empty //
    private TextView mEmptyStateTextView;
    //The loading indicator //
    private View loadingIndicator;
    //Edit text and button for creating new tasks quickly
    private EditText mTaskEditText;
    private Button mTaskCreateButton;

// Firebase instance variables
private FirebaseDatabase mFirebaseDatabase;
private DatabaseReference mTaskDatabaseReference;
private DatabaseReference mTaskNumDatabaseReference;
private ChildEventListener mChildEventListener;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Set the content of the activity to use the activity_main.xml layout file - the task lists
    setContentView(R.layout.task_activity);

    //Set up to allow Up navigation to parent activity
    this.getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    // Initialize Firebase components
    mFirebaseDatabase = FirebaseDatabase.getInstance();

    // Initialize references to views
    mTaskEditText = (EditText) findViewById(R.id.task_edit_text);
    mTaskCreateButton = (Button) findViewById(R.id.create_task_button);

    // Enable Send button when there's text to send
    mTaskEditText.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            if (charSequence.toString().trim().length() > 0) {
                mTaskCreateButton.setEnabled(true);
            } else {
                mTaskCreateButton.setEnabled(false);
            }
        }

        @Override
        public void afterTextChanged(Editable editable) {
        }
    });

    // Create button creates a new task and clears the EditText
    mTaskCreateButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            // Get task title from user and create a new task
            //Also fetch the FireBase ID and connect it to the new task.
            //And finally get the task's creation date
            String creationDate ="Created: " + new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new Date());
            String taskId = mTaskDatabaseReference.push().getKey();
            Task task = new Task(mTaskEditText.getText().toString(),false,taskId,creationDate);
            mTaskDatabaseReference.child(taskId).setValue(task);

            //add that task to the list's task count
            mTaskNumDatabaseReference.child("taskNum").setValue(taskCount+1);



            // Clear input box
            mTaskEditText.setText("");
        }
    });


    //Initialize task Array, ListView and Adapter.
    final ArrayList<Task> tasks = new ArrayList<Task>();

    // Create an {@link TaskAdapter}, whose data source is a list of {@link Task}s.
    mTaskAdapter = new TaskAdapter(this, tasks);

    // Locate the {@link ListView} object in the view hierarchy of the {@link Activity}.
    ListView listView = (ListView) findViewById(R.id.task_list_view);

    //Set the empty view
    mEmptyStateTextView = (TextView) findViewById(R.id.empty_view);
    listView.setEmptyView(mEmptyStateTextView);

    //Initialize the loading indicator
    loadingIndicator = findViewById(R.id.loading_indicator);
    loadingIndicator.setVisibility(View.INVISIBLE);

    // Make the {@link ListView} use the {@link TaskAdapter} defined above, so that the
    // {@link ListView} will display list items for each {@link Task} in the list.
    listView.setAdapter(mTaskAdapter);

    //Set a regular click - opening the TaskInfoFragment
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
            // Find the current task list that was clicked on
            Log.d("clicked here bro","clicikcckckc");
            Task currentTask = mTaskAdapter.getItem(position);

            //Open the TaskInfoFragment for this task
            TaskInfoFragment taskInfo = new TaskInfoFragment();
            taskInfo.setCurrentTask(currentTask);
            android.support.v4.app.FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            // Replace whatever is in the fragment_container view with this fragment,
            // and add the transaction to the back stack
            transaction.replace(R.id.frag_container, taskInfo);
            transaction.addToBackStack(null);

            // Commit the transaction
            transaction.commit();


        }
    });

    //Set context menu for ListView
    listView.setLongClickable(true);
    registerForContextMenu(listView);



    //Get reference for the task list for the logged in user and attach the database listener
    mTaskDatabaseReference=mFirebaseDatabase.getReference().child("users")
            .child(MainActivity.getCurrentUserId())
            .child(MainActivity.getCurrentTaskListId()).child("tasks");
    mTaskNumDatabaseReference=mFirebaseDatabase.getReference().child("users")
            .child(MainActivity.getCurrentUserId())
            .child(MainActivity.getCurrentTaskListId());


    //add listener to get the current task count in this specific task list
    mTaskNumDatabaseReference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            TaskList taskList = dataSnapshot.getValue(TaskList.class);
            taskCount=taskList.getTaskNum();
            Log.d("post count: ", "" + taskCount);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            System.out.println("The read failed: " + databaseError.getCode());
        }
    });
}

@Override
protected void onResume() {
    super.onResume();
    loadingIndicator.setVisibility(View.VISIBLE);
    attachDatabaseReadListener();
    mEmptyStateTextView.setText("No tasks, add a new one!");
    loadingIndicator.setVisibility(View.GONE);

}
@Override
protected void onPause() {
    super.onPause();

    mTaskAdapter.clear();
    detachDatabaseReadListener();

}

private void attachDatabaseReadListener() {
    if (mChildEventListener == null) {
        mChildEventListener = new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                Task task = dataSnapshot.getValue(Task.class);
                mTaskAdapter.add(task);
            }
            public void onChildChanged(DataSnapshot dataSnapshot, String s) {
                //Task task = dataSnapshot.getValue(Task.class);
                //mTaskAdapter.add(task);
            }
            public void onChildRemoved(DataSnapshot dataSnapshot) {
                mTaskNumDatabaseReference.child("taskNum").setValue(taskCount-1);
            }
            public void onChildMoved(DataSnapshot dataSnapshot, String s) {}
            public void onCancelled(DatabaseError databaseError) {}
        };

    }
    mTaskDatabaseReference.addChildEventListener(mChildEventListener);

}
private void detachDatabaseReadListener() {
    if (mChildEventListener != null) {
        mTaskDatabaseReference.removeEventListener(mChildEventListener);
        mChildEventListener = null;
    }
}

/**
 * MENU
 */

@Override
public void onCreateContextMenu(ContextMenu menu,View v, ContextMenu.ContextMenuInfo menuInfo){
    if (v.getId() == R.id.task_list_view){
        AdapterView.AdapterContextMenuInfo info =(AdapterView.AdapterContextMenuInfo)menuInfo;
        menu.add(0,0,0,"Delete");
        menu.add(0,1,1,"info");
    }
}

@Override
public boolean onContextItemSelected(MenuItem menuItem){
    AdapterView.AdapterContextMenuInfo info=(AdapterView.AdapterContextMenuInfo)menuItem.getMenuInfo();
    Task taskClicked=mTaskAdapter.getItem(info.position);
    Log.d("check","" +taskClicked.getTitle());
    switch (menuItem.getItemId()) {
        case 0:
            mTaskDatabaseReference.child(taskClicked.getId()).removeValue();
            mTaskAdapter.remove(taskClicked);
            Toast.makeText(this, "Task deleted!", Toast.LENGTH_LONG).show();
            break;

        case 1:
            //Open the TaskInfoFragment for this task
            TaskInfoFragment taskInfo = new TaskInfoFragment();
            taskInfo.setCurrentTask(taskClicked);
            android.support.v4.app.FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            // Replace whatever is in the fragment_container view with this fragment,
            // and add the transaction to the back stack
            transaction.replace(R.id.frag_container, taskInfo);
            transaction.addToBackStack(null);

            // Commit the transaction
            transaction.commit();
            break;

        default:
            break;

    }
    return true;
}


//set up the back button - to navigate to the parent activity
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        // Respond to the action bar's Up/Home button
        case android.R.id.home:
            //Check if the call came from the TaskInfoFragment or the activity
            Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.frag_container);
            if(currentFragment!=null && currentFragment.isVisible()){
                this.onBackPressed();
            }
            else{
                NavUtils.navigateUpFromSameTask(this);

            }
            return true;

    }
    return super.onOptionsItemSelected(item);
}

}

TaskAdapter - адаптер TaskActivity

    package com.example.guyerez.todotiger;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;

import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;

import java.util.ArrayList;
import java.util.Locale;

/**
 * {@link TaskAdapter} is an {@link ArrayAdapter} that can provide the layout for each task item
 * based on a data source, which is a list of {@link Task} objects.
 */

public class TaskAdapter extends ArrayAdapter<Task> {

//Define FireBase instance variables
private DatabaseReference mTaskDatabaseReference;
private FirebaseDatabase mFirebaseDatabase;
/**
 * Create a new {@link TaskAdapter} object.
 *
 * @param context is the current context (i.e. Activity) that the adapter is being created in.
 * @param tasks is the list of {@link Task}s to be displayed.
 */


public TaskAdapter(Context context, ArrayList<Task> tasks) {
    super(context, 0, tasks);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // Check if an existing view is being reused, otherwise inflate the view
    View listItemView = convertView;
    if (listItemView == null) {
        listItemView = LayoutInflater.from(getContext()).inflate(
                R.layout.task_item, parent, false);
    }
    // Get the {@link Task} object located at this position in the list
    final Task currentTask = getItem(position);

    // Locate the TextView in the task_item.xml layout with the ID task_title.
    final TextView titleTextView = (TextView) listItemView.findViewById(R.id.task_title);
    // Get the task's title from the currentTask object and set it in the text view
    titleTextView.setText(currentTask.getTitle());
    //If the task is completed - title Strikethrough
    titleTextView.setBackgroundResource(strikeCompleted(currentTask.getCompleted()));

    //Initialize the check box and check it if the task was completed.
    CheckBox checkBox = (CheckBox) listItemView.findViewById(R.id.check_box);
    checkBox.setOnCheckedChangeListener(null);
    checkBox.setChecked(currentTask.getCompleted());

    //Initialize the creation date TextView in the task_item.xml layout with the ID creation_date
    TextView creationDateTextView = (TextView) listItemView.findViewById(R.id.creation_date);
    //Get the task's creation date from the currentTask object and set it in the text view
    creationDateTextView.setText(currentTask.getCreationDate());

    // Initialize Firebase DB
    mFirebaseDatabase = FirebaseDatabase.getInstance();
    //Get the task DB reference to edit task completion status

    // Find the CheckBox in the task_item.xml layout with the ID check_box.

    checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
            mTaskDatabaseReference=mFirebaseDatabase.getReference()
                    .child("users").child(MainActivity.getCurrentUserId())
                    .child(MainActivity.getCurrentTaskListId()).child("tasks").child(currentTask.getId());
                if (isChecked) {
                    titleTextView.setBackgroundResource(R.drawable.strike_through);
                    mTaskDatabaseReference.child("completed").setValue(true);
                } else {
                    titleTextView.setBackgroundResource(0);
                    mTaskDatabaseReference.child("completed").setValue(false);
                }

        }
        }
    );
    // Return the whole list item layout (containing 1 text view and 1 checkbox) so that it can be shown in the ListView.
    return listItemView;
}
private int strikeCompleted(boolean completed){
    if (completed){
        return R.drawable.strike_through;
    }
    else{
        return 0;
    }
}

} ​​

1 Ответ

0 голосов
/ 21 сентября 2018

После нескольких рекомендуемых обходных путей (например, здесь ) для ListView строк, содержащих CheckBox, безуспешно, я хотел бы предложить другой подход:

Использованиедругой, прозрачный View, который охватывает весь ряд, за исключением небольшой области вокруг CheckBox.Пусть это View имеет OnClickListener, которое запускает открытие TaskInfoFragment.

В идеале можно было бы использовать интерфейс, чтобы TaskAdapter мог передать нажатый Task в TaskActivity, который в свою очередь показал бы Fragment.

Несколько часов спустя ... (@Guy, ваш намек на то, что вы «пытались удалить весь код, связанный с флажками и xml, и проблема с обычными щелчками сохранялась» заставила меня обмениваться одним компонентом за другим, пока я не сузил егов строку xml) Я нашел причину, по которой ListView s OnItemClickListener в TaskActivity не срабатывает.Корень ConstraintLayout списка Task имеет атрибут, которого у корня списка TaskList нет: android:longClickable="true"

Удаление этого атрибута заставляет ListView вести себя нормально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...