Как установить рисование перехода в представлении элементов представления Recycler, не сталкиваясь с исключением NullPointerException? - PullRequest
0 голосов
/ 27 апреля 2020

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

Теперь здесь возникает проблема . Я хочу, чтобы представление элемента, которое соответствует запросу, не только прокручивалось, но и выделялось. Когда я пытаюсь поместить анимацию в любой вид элемента, который не отображается на экране, я получаю NPE , что понятно, поскольку представление Recycler создает только часть всего списка. У меня вопрос, как мне обойти это?

Один из способов (я думал) - сначала прокрутить вниз, а затем применить анимацию. Но, как выясняется, анимация начинает происходить первой (, может быть, прокрутка происходит в фоновом потоке? ) и сразу же выбрасывает NPE. Как мне это решить?

Полный код фрагмента, о котором я говорю, приведен ниже, а код анимации - последний (, где проблема ):

package com.coffeetech.kittycatch;

import android.animation.ObjectAnimator;
import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.TransitionDrawable;
import android.os.Bundle;

import androidx.annotation.Nullable;
import androidx.cardview.widget.CardView;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.Toast;

import com.google.android.material.floatingactionbutton.FloatingActionButton;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

public class InventoryFragment extends Fragment {

    //GLOBAL VARIABLES
    File file;

    RecyclerView recyclerView;
    FoodAdapter foodAdapter;
    FloatingActionButton add_button, search_button;

    FoodViewModel foodViewModel;

    public static final int REQUEST_NEW_FOOD = 25;
    public static final int REQUEST_OLD_FOOD = 21;

    //FOOD LIST
    private List<Food> foodList = new ArrayList<>();

    Food food;

    CardView search_space;
    EditText search_text;
    ImageButton upSearchButton, downSearchButton;
    private ArrayList<Integer> searchedPositions = new ArrayList<>();
    String substring;
    int iterator;
    LinearLayoutManager linearLayoutManager;
    ObjectAnimator animator;


    public InventoryFragment() {}

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        //GETTING THE FOOD VIEW MODEL
        foodViewModel = new ViewModelProvider(getActivity(),ViewModelProvider.AndroidViewModelFactory.getInstance(getActivity().getApplication())).get(FoodViewModel.class); //TODO:HERE
        foodViewModel.getFoods().observe(getViewLifecycleOwner(), new Observer<List<Food>>() {
            @Override
            public void onChanged(List<Food> foods) {
                foodList = foods;
                foodAdapter.setFoods(foods);
                foodAdapter.notifyDataSetChanged();  //TODO:MAKE THIS BETTER
            }
        });
        recyclerView.setAdapter(foodAdapter);
    }



    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View v = inflater.inflate(R.layout.fragment_inventory, container, false);

        search_button = v.findViewById(R.id.search_foods_button);
        search_space = v.findViewById(R.id.search_space);
        search_text = v.findViewById(R.id.search_text);
        upSearchButton = v.findViewById(R.id.up_search_button);
        downSearchButton = v.findViewById(R.id.down_search_button);

        search_space.setVisibility(View.GONE);
        //GETTING THE FOOD VIEW MODEL
        //foodAdapter = new FoodAdapter();
        recyclerView=v.findViewById(R.id.recycler_view);
        recyclerView.setHasFixedSize(true);
        linearLayoutManager = new LinearLayoutManager(getContext());
        recyclerView.setLayoutManager(linearLayoutManager);


        //setting up the Add button
        add_button=v.findViewById(R.id.add_button);
        add_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {  //for new food addition to list
                Intent intent = new Intent(getActivity(),FoodEditorActivity.class);
                startActivityForResult(intent,REQUEST_NEW_FOOD);
            }
        });

        //BELOW CODE FOR SEARCH BUTTON
        search_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(search_space.getVisibility() == View.GONE){
                    search_space.setVisibility(View.VISIBLE);
                }else{
                    search_space.setVisibility(View.GONE);
                    linearLayoutManager.scrollToPositionWithOffset(0,0);
                }
            }
        });

        search_text.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                substring = s.toString().trim().toLowerCase();
                searchedPositions.clear();
                if(substring!=""){
                    iterator=0;
                    for(Food f : foodList){
                        if(f.getName().toLowerCase().contains(substring)){
                            searchedPositions.add(iterator);
                        }
                        iterator+=1;
                    }
                }
                iterator=0;
                if(searchedPositions.size() !=0){
                    //linearLayoutManager.scrollToPositionWithOffset(searchedPositions.get(0),0);
                    findItemAndHighlight(searchedPositions.get(0));
                }else{
                    linearLayoutManager.scrollToPositionWithOffset(0,0);
                    Toast.makeText(getContext(),"Not found",Toast.LENGTH_SHORT).show();
                }
            }

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

        downSearchButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(!substring.trim().isEmpty()){
                    if(iterator == searchedPositions.size()-1) { //IF LAST OF SEARCHED LIST IS REACHED
                        iterator=0;
                    }else{ //IF THERE ARE STILL SOME ITEMS LEFT
                        iterator+=1;
                    }
                    //linearLayoutManager.scrollToPositionWithOffset(searchedPositions.get(iterator),0);
                    findItemAndHighlight(searchedPositions.get(iterator));
                    //recyclerView.smoothScrollToPosition(searchedPositions.get(iterator));
                }
            }
        });

        upSearchButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(!substring.trim().isEmpty()){
                    if(iterator == 0) { //IF LAST OF SEARCHED LIST IS REACHED
                        iterator = searchedPositions.size()-1;
                    }else{ //IF THERE ARE STILL SOME ITEMS LEFT
                        iterator-=1;
                    }
                    //linearLayoutManager.scrollToPositionWithOffset(searchedPositions.get(iterator),0);
                    findItemAndHighlight(searchedPositions.get(iterator));
                    //recyclerView.smoothScrollToPosition(searchedPositions.get(iterator));
                }
            }
        });

        foodAdapter = new FoodAdapter(1);
        foodAdapter.setOnFoodcardClickListener(new FoodAdapter.OnFoodcardClickListener() {
            @Override
            public void deleteFood(int position) { //code that deletes current food
                if(position!=RecyclerView.NO_POSITION){
                    //DELETE IMAGE
                    if(foodList.get(position).getPhoto() != "null" && foodList.get(position).getThumbnail() != "null"){
                        file = new File (foodList.get(position).getPhoto());
                        if (file.exists()){file.delete();}
                        file = new File (foodList.get(position).getThumbnail());
                        if (file.exists()){file.delete();}
                    }

                    //delete from database
                    foodViewModel.delete(foodList.get(position));
                }
            }

            @Override
            public void onEdit(int position) { //code that runs the edit of each food
                if(position!=RecyclerView.NO_POSITION) {
                    Intent intent = new Intent(getActivity(),FoodEditorActivity.class);
                    //PUT THE DATA CORRECTLY
                    intent.putExtra(FoodEditorActivity.EXTRA_NAME, foodList.get(position).getName());
                    intent.putExtra(FoodEditorActivity.EXTRA_ID, foodList.get(position).getID());
                    intent.putExtra(FoodEditorActivity.EXTRA_TYPE, foodList.get(position).getType());
                    intent.putExtra(FoodEditorActivity.EXTRA_THUMBNAIL, foodList.get(position).getThumbnail());
                    intent.putExtra(FoodEditorActivity.EXTRA_PHOTO, foodList.get(position).getPhoto());
                    intent.putExtra(FoodEditorActivity.EXTRA_QUANTITY, foodList.get(position).getQuantity());
                    intent.putExtra(FoodEditorActivity.EXTRA_MIN_QUANTITY, foodList.get(position).getMin_quantity());

                    startActivityForResult(intent,REQUEST_OLD_FOOD);
                }
            }

            @Override
            public void increaseValue(int position) {
                if(position!=RecyclerView.NO_POSITION){
                    foodList.get(position).increase();
                    foodList.get(position).setDate(new Date());
                    foodViewModel.update(foodList.get(position));
                }
            }

            @Override
            public void decreaseValue(int position) {
                if(position!=RecyclerView.NO_POSITION){
                    foodList.get(position).decrease();
                    foodList.get(position).setDate(new Date());
                    foodViewModel.update(foodList.get(position));
                }
            }


            @Override
            public void setSeekBar(int position,int progress) {
                if(position!=RecyclerView.NO_POSITION) {
                    foodList.get(position).setQuantity(progress);
                    foodList.get(position).setDate(new Date());
                    foodViewModel.update(foodList.get(position));
                    Toast.makeText(getContext(),"Quantity set to "+progress+"%",Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void setCheckBoxTrue() {

            }

            @Override
            public void setCheckBoxFalse() {

            }
        });
        return v;
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if(requestCode == REQUEST_NEW_FOOD && resultCode == Activity.RESULT_OK){
            food = new Food();
            food.setID(data.getIntExtra(FoodEditorActivity.EXTRA_ID,-1));
            food.setName(data.getStringExtra(FoodEditorActivity.EXTRA_NAME));
            food.setType(data.getIntExtra(FoodEditorActivity.EXTRA_TYPE,0));
            food.setQuantity(data.getIntExtra(FoodEditorActivity.EXTRA_QUANTITY,0));
            food.setMin_quantity(data.getIntExtra(FoodEditorActivity.EXTRA_MIN_QUANTITY,0));
            food.setPhoto(data.getStringExtra(FoodEditorActivity.EXTRA_PHOTO));
            food.setThumbnail(data.getStringExtra(FoodEditorActivity.EXTRA_THUMBNAIL));
            food.setDate(new Date());

            foodViewModel.insert(food);

            Toast.makeText(getContext(),"Saved",Toast.LENGTH_SHORT).show();


        }else if(requestCode == REQUEST_OLD_FOOD && resultCode == Activity.RESULT_OK){
            food = new Food();
            food.setID(data.getIntExtra(FoodEditorActivity.EXTRA_ID,-1));
            food.setName(data.getStringExtra(FoodEditorActivity.EXTRA_NAME));
            food.setType(data.getIntExtra(FoodEditorActivity.EXTRA_TYPE,0));
            food.setQuantity(data.getIntExtra(FoodEditorActivity.EXTRA_QUANTITY,0));
            food.setMin_quantity(data.getIntExtra(FoodEditorActivity.EXTRA_MIN_QUANTITY,0));
            food.setPhoto(data.getStringExtra(FoodEditorActivity.EXTRA_PHOTO));
            food.setThumbnail(data.getStringExtra(FoodEditorActivity.EXTRA_THUMBNAIL));
            food.setDate(new Date());

            foodViewModel.update(food);

            Toast.makeText(getContext(),"Saved",Toast.LENGTH_SHORT).show();
        }else if(resultCode == FoodEditorActivity.PHOTO_DELETED){
            food = new Food();
            food.setID(data.getIntExtra(FoodEditorActivity.EXTRA_ID,-1));
            food.setName(data.getStringExtra(FoodEditorActivity.EXTRA_NAME));
            food.setType(data.getIntExtra(FoodEditorActivity.EXTRA_TYPE,0));
            food.setQuantity(data.getIntExtra(FoodEditorActivity.EXTRA_QUANTITY,0));
            food.setMin_quantity(data.getIntExtra(FoodEditorActivity.EXTRA_MIN_QUANTITY,0));
            food.setPhoto(data.getStringExtra(FoodEditorActivity.EXTRA_PHOTO));
            food.setThumbnail(data.getStringExtra(FoodEditorActivity.EXTRA_THUMBNAIL));
            food.setDate(new Date());  //TODO: REMOVE THIS AFTER WRITING CODE TO FIND FOOD BY ID


            foodViewModel.update(food);
        }
    }


    void findItemAndHighlight(int position){
        linearLayoutManager.scrollToPositionWithOffset(position,0);
        ColorDrawable[] color = {new ColorDrawable(getResources().getColor(R.color.colorAlternateTwo)),new ColorDrawable(getResources().getColor(R.color.elevatedBackgroundColor))};
        TransitionDrawable transitionDrawable = new TransitionDrawable(color);
        //recyclerView.getChildAt(position).setBackground(transitionDrawable);
        recyclerView.findViewHolderForAdapterPosition(position).itemView.setBackground(transitionDrawable);
        transitionDrawable.startTransition(1000);

    }

}

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