Saving dynamically added Views(pages) of Viewpager in SharedPreferences - java

Hi friends I am trying from long time to save dynamically added views of Viewpager in shardepreferences. So that when user next time open the app , his added pages or views should be there. But I have no success. I am trying to save the size of ArrayList in sharedpreferences and then trying to call regenerate the size of ArrayList next time when user open app. what I am doing is i am adding number of pages in pager with for loop that are equal to size of ArrayList. I dont know is this a right way or i am completely wrong. Please guide me someone through this. Thanks in advance. I am uploading the pic of my UI also enter image description here.I am pasting my code here. First below is code of my adapter.
import android.content.Context;
import android.content.SharedPreferences;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.ArrayList;
public class MainPagerAdapter extends PagerAdapter
{
private ArrayList<View> views = new ArrayList<View>();
SharedPreferences preferences;
Context context;
LayoutInflater inflater;
final static String PREF_COUNT="com.savesampledata";
final static String PREF_KEY="com.savesampledata.key";
final static String PREF_LIST="com.savesampledata.list";
final static String PREF_LIST_KEY="com.savesampledata.listkey";
int numberofview;
public MainPagerAdapter(Context c){
context=c;
}
#Override
public int getItemPosition (Object object)
{
int index = views.indexOf (object);
if (index == -1)
return POSITION_NONE;
else
return index;
}
#Override
public Object instantiateItem (ViewGroup container, int position)
{
Log.v("instantiate is called","now");
View v;
v = views.get(position);
if(v.getParent()!=null)
((ViewGroup)v.getParent()).removeView(v);
container.addView(v);
return v;
}
#Override
public void destroyItem (ViewGroup container, int position, Object object)
{
container.removeView (views.get (position));
}
#Override
public int getCount ()
{
Log.d("view list size",views.size()+"");
Log.d("numofViews before save",numberofview+"");
return views.size();
}
#Override
public boolean isViewFromObject (View view, Object object)
{
return view == object;
}
public int addView (View v)
{
return addView (v, views.size());
}
public int addView (View v, int position)
{
views.add (position, v);
return position;
}
public int removeView (ViewPager pager, View v)
{
return removeView (pager, views.indexOf (v));
}
public int removeView (ViewPager pager, int position)
{
if (numberofview > 1)
position = numberofview - 1;
if(position>0) {
pager.setAdapter(null);
views.remove(position);
pager.setAdapter(this);
}
return position;
}
public View getView (int position)
{
return views.get (position);
}
public void setCount(){
//storing size of views list
SharedPreferences preferences=context.getSharedPreferences(PREF_COUNT,Context.MODE_PRIVATE);
SharedPreferences.Editor editor=preferences.edit();
editor.putInt(PREF_KEY,views.size());
Log.d("shared stored val :",views.size()+"");
editor.apply();
}
public int getNumberOfView(){
//getting size of views list
SharedPreferences preferences=context.getSharedPreferences(PREF_COUNT, Context.MODE_PRIVATE);
numberofview=preferences.getInt(PREF_KEY,0);
return numberofview;
}
}
Code of my Activity:
import android.content.Context;
import android.content.SharedPreferences;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
public class ViewPagerActivity extends AppCompatActivity implements View.OnClickListener {
private ViewPager pager =null;
private MainPagerAdapter pageradapter=null;
Button addpagebtn,removebtn;
final static String PREF_COUNT="com.savesampledata";
final static String PREF_KEY="com.savesampledata.key";
int numberofview;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_pager_activity);
addpagebtn=(Button)findViewById(R.id.addbtn) ;
removebtn=(Button)findViewById(R.id.removeButton);
removebtn.setOnClickListener(this);
addpagebtn.setOnClickListener(this);
pageradapter= new MainPagerAdapter(this);
pager=(ViewPager)findViewById(R.id.view_pager);
pager.setAdapter(pageradapter);
pager.setOffscreenPageLimit(3);
numberofview=pageradapter.getNumberOfView();//here i am getting the value
Log.d("value after saving",pageradapter.getNumberOfView()+"");
LayoutInflater inflater=getLayoutInflater();
FrameLayout v0=(FrameLayout)inflater.inflate(R.layout.sample_layout_page,null);
pageradapter.addView(v0,0);
pageradapter.notifyDataSetChanged();
if(numberofview>1) {
Log.d("ManyView","added");
for (int i = 1; i <= numberofview; i++) {
pageradapter.addView(v0,i);
pageradapter.notifyDataSetChanged();
}
}
}
public void addView(View newpage){
int pageIndex=pageradapter.addView(newpage);
Log.d("page added at",pageIndex+"");
pageradapter.notifyDataSetChanged();
pageradapter.setCount();
pager.setCurrentItem(pageIndex,true);
}
public void removeView(View defunctPage){
int pageindex=pageradapter.removeView(pager,defunctPage);
Log.d("page removed at",pageindex+"");
pageradapter.notifyDataSetChanged();
pageradapter.setCount();
if(pageindex==pageradapter.getCount())
pageindex--;
pager.setCurrentItem(pageindex);
}
public View getCurrentPage(){
return pageradapter.getView(pager.getCurrentItem());
}
public void setCurrentPage(View pageToShow){
pager.setCurrentItem(pageradapter.getItemPosition(pageToShow),true);
}
#Override
public void onClick(View v) {
if(v.getId()==R.id.addbtn) {
LayoutInflater inflater=getLayoutInflater();
FrameLayout v0=(FrameLayout)inflater.inflate(R.layout.sample_layout_page,null);
addView(v0);
pageradapter.setCount();
}
if(v.getId()==R.id.removeButton){
View v1=getCurrentPage();
removeView(v1);
pageradapter.setCount();
}
}
#Override
protected void onStop() {
//here I am storing value
super.onStop();
pageradapter.setCount();
}
}

Related

Why isn't onBindViewHolder getting called when I make a selection?

My scrolling list is displaying properly.
OnBindViewHolder is called for each item in initial display and when scrolling brings new items into view.
When I click on an item, I do see my ItemDetailsLookup and getItemDetails functions getting called, HOWEVER it doesn't call the OnBindViewHolder, and so setActivated isn't getting run.
The documentation for androidx.recyclerview.selection says "... When the user selects an item the library will record that in SelectionTracker then notify RecyclerView that the state of the item has changed. This will ultimately cause the value to be rebound by way of RecyclerView.Adapter#onBindViewHolder..." and I think I've done everything up to this point, but I must have missed something...
Any ideas?
Thanks
Here's my fragment:
package com.example.smartflashcards;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.selection.ItemDetailsLookup;
import androidx.recyclerview.selection.SelectionPredicates;
import androidx.recyclerview.selection.SelectionTracker;
import androidx.recyclerview.selection.StableIdKeyProvider;
import androidx.recyclerview.selection.StorageStrategy;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class StackSelectionFragment extends Fragment {
private static final String ARG_COLUMN_COUNT = "column-count";
private int mColumnCount = 1;
static SelectionTracker<Long> tracker;
public StackSelectionFragment() {
}
#SuppressWarnings("unused")
public static StackSelectionFragment newInstance(int columnCount) {
StackSelectionFragment fragment = new StackSelectionFragment();
Bundle args = new Bundle();
args.putInt(ARG_COLUMN_COUNT, columnCount);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mColumnCount = getArguments().getInt(ARG_COLUMN_COUNT);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_stack_selection_list, container, false);
File directory = getActivity().getFilesDir();
List<String> filesList = new ArrayList(Arrays.asList(directory.list()));
if (view instanceof RecyclerView) {
Context context = view.getContext();
RecyclerView recyclerView = (RecyclerView) view;
if (mColumnCount <= 1) {
recyclerView.setLayoutManager(new LinearLayoutManager(context));
} else {
recyclerView.setLayoutManager(new GridLayoutManager(context, mColumnCount));
}
recyclerView.setAdapter(new MyItemRecyclerViewAdapter(filesList));
recyclerView.getAdapter().hasStableIds();
this.tracker = new SelectionTracker.Builder<Long>(
"stack_selector",
recyclerView,
new StableIdKeyProvider(recyclerView),
new MyDetailsLookup(recyclerView),
StorageStrategy.createLongStorage()
).withSelectionPredicate(SelectionPredicates.<Long>createSelectAnything()).build();
}
return view;
}
final class MyDetailsLookup extends ItemDetailsLookup {
private final RecyclerView mRecyclerView;
MyDetailsLookup(RecyclerView recyclerView) {
mRecyclerView = recyclerView;
}
public #Nullable
ItemDetails getItemDetails(#NonNull MotionEvent e) {
View view = mRecyclerView.findChildViewUnder(e.getX(), e.getY());
if (view != null) {
RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(view);
if (holder instanceof MyItemRecyclerViewAdapter.ViewHolder) {
return ((MyItemRecyclerViewAdapter.ViewHolder)holder).getItemDetails();
}
}
return null;
}
}
}
Here's my adapter:
package com.example.smartflashcards;
import androidx.annotation.Nullable;
import androidx.recyclerview.selection.ItemDetailsLookup;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.TextView;
import com.example.smartflashcards.databinding.FragmentStackSelectionBinding;
import java.util.List;
public class MyItemRecyclerViewAdapter extends RecyclerView.Adapter<MyItemRecyclerViewAdapter.ViewHolder> {
private final List<String> mValues;
public MyItemRecyclerViewAdapter(List<String> items) {
setHasStableIds(true);
mValues = items;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(FragmentStackSelectionBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mItem = getItemId(position);
holder.mContentView.setText(mValues.get(position));
holder.mContentView.setActivated(StackSelectionFragment.tracker.isSelected((long) position));
}
#Override
public int getItemCount() {
return mValues.size();
}
#Override
public long getItemId(int position) {
return (long)position;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public final TextView mIdView;
public final TextView mContentView;
public Long mItem;
public ViewHolder(FragmentStackSelectionBinding binding) {
super(binding.getRoot());
mIdView = binding.itemNumber;
mContentView = binding.content;
}
#Override
public String toString() {
return super.toString() + " '" + mContentView.getText() + "'";
}
public ItemDetailsLookup.ItemDetails<Long> getItemDetails() {
return new ItemDetailsLookup.ItemDetails<Long>() {
#Override
public int getPosition() {
return getAbsoluteAdapterPosition();
}
#Nullable
#Override
public Long getSelectionKey() {
return mItem;
}
};
}
}
}
By following the example at https://github.com/Thumar/recyclerview-selection/tree/master/app
I was able to get it working. See my working code below.
But I still don't know which of the changes made it work and why.
If anyone figures out what was causing my problem, please post a comment or answer.
Any and all other feedback is welcome as well.
THANKS
Here's my new fragment:
package com.example.smartflashcards;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.selection.ItemDetailsLookup;
import androidx.recyclerview.selection.Selection;
import androidx.recyclerview.selection.SelectionPredicates;
import androidx.recyclerview.selection.SelectionTracker;
import androidx.recyclerview.selection.StableIdKeyProvider;
import androidx.recyclerview.selection.StorageStrategy;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class StackSelectionFragment extends Fragment {
// TODO: Customize parameter argument names
private static final String ARG_COLUMN_COUNT = "column-count";
// TODO: Customize parameters
private int mColumnCount = 1;
SelectionTracker<Long> tracker; //TODO: add private?
private StackSelectionListener listener;
public interface StackSelectionListener {
public void onSelectStack(String stack);
}
String selections = "";
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public StackSelectionFragment() {
}
// TODO: Customize parameter initialization
#SuppressWarnings("unused")
public static StackSelectionFragment newInstance(int columnCount) {
StackSelectionFragment fragment = new StackSelectionFragment();
Bundle args = new Bundle();
args.putInt(ARG_COLUMN_COUNT, columnCount);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mColumnCount = getArguments().getInt(ARG_COLUMN_COUNT);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_stack_selection_list, container, false);
File directory = getActivity().getFilesDir();
List<String> filesList = new ArrayList(Arrays.asList(directory.list()));
// Set the adapter
if (view instanceof RecyclerView) {
Context context = view.getContext();
RecyclerView recyclerView = (RecyclerView) view;
if (mColumnCount <= 1) {
recyclerView.setLayoutManager(new LinearLayoutManager(context));
} else {
recyclerView.setLayoutManager(new GridLayoutManager(context, mColumnCount));
}
MyItemRecyclerViewAdapter adapter = new MyItemRecyclerViewAdapter(filesList);
recyclerView.setAdapter(adapter);
adapter.hasStableIds();
this.tracker = new SelectionTracker.Builder<Long>(
"stack_selector",
recyclerView,
new StableIdKeyProvider(recyclerView),
new MyDetailsLookup(recyclerView),
StorageStrategy.createLongStorage()
).withSelectionPredicate(SelectionPredicates.<Long>createSelectAnything()).build();
adapter.injectTracker(this.tracker);
SelectionTracker.SelectionObserver<Long> observer = new SelectionTracker.SelectionObserver<Long>() {
#Override
public void onSelectionChanged() {
super.onSelectionChanged();
//TODO: replace this placeholder action with something useful
selections = "";
tracker.getSelection().forEach(item -> selections += adapter.getContent(item.intValue()));//selections += item);
//listener.onSelectStack("selections"); //This causes an error???
Context context = getContext();
Toast toast = Toast.makeText(context, selections, Toast.LENGTH_LONG);
toast.show();
}
};
this.tracker.addObserver(observer);
}
return view;
}
final class MyDetailsLookup extends ItemDetailsLookup {
private final RecyclerView mRecyclerView;
MyDetailsLookup(RecyclerView recyclerView) {
mRecyclerView = recyclerView;
}
public #Nullable
ItemDetails getItemDetails(#NonNull MotionEvent e) {
View view = mRecyclerView.findChildViewUnder(e.getX(), e.getY());
if (view != null) {
RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(view);
if (holder instanceof MyItemRecyclerViewAdapter.ViewHolder) {
return ((MyItemRecyclerViewAdapter.ViewHolder)holder).getItemDetails();
}
}
return null;
}
}
Here's my new adapter:
package com.example.smartflashcards;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.selection.ItemDetailsLookup;
import androidx.recyclerview.selection.SelectionTracker;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
public class MyItemRecyclerViewAdapter extends RecyclerView.Adapter<MyItemRecyclerViewAdapter.ViewHolder> {
private final List<String> mValues;
private SelectionTracker<Long> selectionTracker;
public MyItemRecyclerViewAdapter(List<String> items) {
setHasStableIds(true); //TODO: remove redundancy between this and "recyclerView.getAdapter().hasStableIds()" in the Fragment
mValues = items;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_stack_selection, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
String item = this.mValues.get(position);
holder.bind(item, selectionTracker.isSelected((long) position));
}
#Override
public int getItemCount() {
return mValues.size();
}
#Override
public long getItemId(int position) {
return (long)position;
}
public String getContent(int position) {
return mValues.get(position);
}
public void injectTracker(SelectionTracker<Long> tracker)
{
this.selectionTracker = tracker;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public final TextView mContentView;
public ViewHolder(#NonNull View itemView) {
super(itemView);
mContentView = itemView.findViewById(R.id.content);
}
#Override
public String toString() {
return super.toString() + " '" + mContentView.getText() + "'";
}
public void bind(String item, Boolean activate) {
this.mContentView.setText(item);
itemView.setActivated(activate); //TODO: understand how "itemView" exists outside of the constructor
}
public ItemDetailsLookup.ItemDetails<Long> getItemDetails() {
return new ItemDetailsLookup.ItemDetails<Long>() {
#Override
public int getPosition() {
return getAbsoluteAdapterPosition();
}
#Nullable
#Override
public Long getSelectionKey() {
return (long) getAbsoluteAdapterPosition();
}
};
}
}
}

Index out of Bound on Item deletion in a Recycler View's adapter

I am trying to create a note-taking app focusing on color-changing.
In one of the activity, I am trying to implement item addition and deletion to the note
picture_of_the_activity.
Item addition obviously works as intended.
The problem is with the deletion, it is very inconsistent: when I delete all the item starting from the last one upward, everything work fine; if I delete items in another order the adapter mess up, do not always delete the correct one and crashes when removing the last item.
I looked it up and found some possible solution (here or in other websites) but couldn't find a solution, or, so I thought.
I created methods inside the adapter addItem() and removeItem() so any changes is done within the class.
Maybe I am misunderstanding a concept or missing something?
Thank you in advance!
some interfaces or protion of the code are missing because I didn't implement some features yet
Activity Code
package com.example.colornoteplus;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;
public class CheckListNoteActivity extends AppCompatActivity{
// note editable views
private EditText titleView;
private TextView titleCharacterCount;
private ImageButton colorView;
private RecyclerView contentView;
private FloatingActionButton fab;
CheckListAdapter adapter;
// toolbar
private Toolbar toolbar;
// Current note
private CheckListNote note;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getNoteFromIntent();
note.getContent().add(new CheckListItem("ONE"));
note.getContent().add(new CheckListItem("TWO"));
note.getContent().add(new CheckListItem("THREE"));
note.getContent().add(new CheckListItem("FOUR"));
note.getContent().add(new CheckListItem("FIVE"));
changeViewsColor(0);
}
// Method used to add menus and configure button action
// like OnClickListeners ...
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Create a submenu for sorting purpose
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_check_list_activity,menu);
return super.onCreateOptionsMenu(menu);
}
// get note from the intent
private void getNoteFromIntent(){
if (!getIntent().getStringExtra(Statics.KEY_NOTE_ACTIVITY).equals(Statics.NOTE_DEFAULT_UID)){
note = MySharedPreferences.LoadCheckListNoteFromSharedPreferences(getIntent().getStringExtra(Statics.KEY_NOTE_ACTIVITY),getApplicationContext());
} else {
note = new CheckListNote();
}
}
private void changeViewsColor(int color){
// set the global theme
setTheme(StyleManager.getTheme(color));
// set the appropriate layout
setContentView(R.layout.activity_check_list_note);
// change status bar color
getWindow().setStatusBarColor(getResources().getColor(StyleManager.getThemeColor(color)));
// set up FAB action
fab = findViewById(R.id.fab_add_item);
fab.setOnClickListener(view -> onFabClickListener());
// setting the toolbar
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setBackgroundColor(getResources().getColor(StyleManager.getThemeColor(color)));
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
// setting the note title
titleView = findViewById(R.id.note_title_view);
titleView.setText("");
titleView.setTextColor(getResources().getColor(StyleManager.getThemeColorDark(color)));
titleView.setHintTextColor(getResources().getColor(StyleManager.getThemeColorLight(color)));
// setting the character counter for the note title
titleCharacterCount = findViewById(R.id.note_title_characters);
String m = titleView.getText().toString().trim().length()+ getString(R.string.text_divider)+ getResources().getInteger(R.integer.title_max_length);
titleCharacterCount.setText(m);
titleCharacterCount.setTextColor(getResources().getColor(StyleManager.getThemeColor(color)));
titleView.addTextChangedListener(new TextWatcher()
{
#Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int aft)
{
}
#Override
public void afterTextChanged(Editable s)
{
// this will show characters remaining
String msg = titleView.getText().toString().length()+ getString(R.string.text_divider)+ getResources().getInteger(R.integer.title_max_length);
titleCharacterCount.setText(msg);
}
});
// setting the color view
colorView = findViewById(R.id.note_color_view);
colorView.setOnClickListener(view -> buildColorPickDialog());
colorView.setBackgroundResource(StyleManager.getBackground(color));
adapter = new CheckListAdapter(getApplicationContext(),note.getContent(),color);
adapter.setOnItemClickListener(new CheckListAdapter.OnItemClickListener() {
#Override
public void onChecked(int position) {
Toast.makeText(CheckListNoteActivity.this, "Checked item: " +position, Toast.LENGTH_SHORT).show();
}
#Override
public void onUnchecked(int position) {
Toast.makeText(CheckListNoteActivity.this, "Unchecked item: " +position, Toast.LENGTH_SHORT).show();
}
#Override
public void onSetPriority(int position) {
}
#Override
public void onSetReminder(int position) {
}
#Override
public void onDelete(int position) {
adapter.removeItem(position);
Toast.makeText(CheckListNoteActivity.this, "List has "+note.getContent().size()+" elements", Toast.LENGTH_SHORT).show();
}
});
contentView = findViewById(R.id.note_content_view);
contentView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
contentView.setAdapter(adapter);
}
private void switchColor(int color){
String tempTitle = titleView.getText().toString().trim();
changeViewsColor(color);
titleView.setText(tempTitle);
}
// build the color picker dialog
private void buildColorPickDialog(){
FragmentPickColor fragment = new FragmentPickColor(new ColorAdapter(),5,note.getColor());
fragment.show(getSupportFragmentManager(),Statics.TAG_FRAGMENT_COLOR_PICK);
fragment.setOnItemClickListener(new ColorAdapter.OnItemClickListener() {
#Override
public void OnClickListener(int position) {
note.setColor(position);
switchColor(position);
fragment.dismiss();
}
#Override
public void OnLongClickListener(int position) {
}
});
}
private void onFabClickListener(){
FragmentAddCheckListItem fragment = new FragmentAddCheckListItem(note.getColor());
fragment.show(getSupportFragmentManager(),Statics.TAG_FRAGMENT_ADD_CHECK_LIST_ITEM);
fragment.setOnClickListener(new FragmentAddCheckListItem.OnClickListener() {
#Override
public void onConfirmClickListener() {
fragment.getItem().setDescription(fragment.getInputText());
adapter.addItem(fragment.getItem(),0);
fragment.dismiss();
}
#Override
public void onSetPriorityClickListener() {
}
#Override
public void onSetDueTimeClickListener() {
FragmentDatePicker datePicker = new FragmentDatePicker();
datePicker.show(getSupportFragmentManager(),Statics.TAG_FRAGMENT_DATE_PICKER);
datePicker.setOnDateSet((year, month, day) -> {
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR,year);
c.set(Calendar.MONTH,month);
c.set(Calendar.DAY_OF_MONTH,day);
fragment.getItem().setDueDate(c.getTime().getTime());
fragment.setDueTimeText(DateFormat.getDateInstance().format(new Date(fragment.getItem().getDueDate())));
});
}
});
}
}
Adapter
package com.example.colornoteplus;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.recyclerview.widget.RecyclerView;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
public class CheckListAdapter extends RecyclerView.Adapter<CheckListAdapter.MyViewHolder> {
public CheckListAdapter(Context context,ArrayList<CheckListItem> list, int color) {
this.list = list;
this.color = color;
this.context = context;
}
final private ArrayList<CheckListItem> list;
final private int color;
final private Context context;
private OnItemClickListener listener;
#NonNull
#Override
public CheckListAdapter.MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new CheckListAdapter.MyViewHolder(LayoutInflater.
from(parent.getContext()).
inflate(R.layout.item_check_list,parent,false));
}
#Override
public void onBindViewHolder(#NonNull CheckListAdapter.MyViewHolder holder, int position) {
CheckListItem currentItem = list.get(position);
holder.background.setBackgroundResource(StyleManager.getBackgroundLight(color));
holder.checkBox.setOnCheckedChangeListener((compoundButton, b) -> {
if (b) listener.onChecked(position);
else listener.onUnchecked(position);
});
holder.title.setTextColor(context.getResources().getColor(StyleManager.getThemeColorDark(color)));
holder.title.setHintTextColor(context.getResources().getColor(StyleManager.getThemeColor(color)));
assert currentItem != null;
holder.title.setText(currentItem.getDescription().trim());
holder.dueTimeText.setTextColor(context.getResources().getColor(StyleManager.getThemeColor(color)));
holder.dueTimeText.setText(currentItem.getDoneDate() != -1 ? DateFormat.getDateInstance().format(new Date(currentItem.getDueDate())) : context.getString(R.string.set_reminder));
holder.dueTimeText.setOnClickListener(view -> listener.onSetReminder(position));
holder.priorityText.setTextColor(context.getResources().getColor(StyleManager.getThemeColor(color)));
holder.priorityText.setText(currentItem.priorityToString(context));
holder.priorityText.setOnClickListener(view -> listener.onSetPriority(position));
holder.delete.setBackgroundResource(StyleManager.getBackground(color));
holder.delete.setOnClickListener(view -> {
// listener.onDelete(position);
removeItem(position);
});
}
#Override
public int getItemCount() {
return list.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder{
CheckBox checkBox;
ConstraintLayout background;
EditText title;
ImageButton delete;
TextView priorityText,dueTimeText;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
checkBox = itemView.findViewById(R.id.item_check_box);
title = itemView.findViewById(R.id.item_title);
dueTimeText = itemView.findViewById(R.id.item_due_time_text);
priorityText = itemView.findViewById(R.id.item_priority_text);
delete = itemView.findViewById(R.id.item_delete);
background = itemView.findViewById(R.id.item_background);
}
}
public void addItem(CheckListItem item,int position){
if (position < 0){
list.add(item);
notifyItemInserted(list.size()-1);
}
else {
list.add(position,item);
notifyItemInserted(position);
}
}
public void removeItem(int position){
list.remove(position);
notifyItemRemoved(position);
}
public void setOnItemClickListener(OnItemClickListener listener){
this.listener = listener;
}
public interface OnItemClickListener{
void onChecked(int position);
void onUnchecked(int position);
void onSetPriority(int position);
void onSetReminder(int position);
void onDelete(int position);
}
}
public void addItem(CheckListItem item, int position) {
if (position >= 0) {
list.add(position, item);
notifyItemInserted(position);
}
}
public void removeItem(int position) {
if (position >= 0) {
list.remove(position);
notifyItemRemoved(position);
}
}
And in onBindViewHolder use holder.getAdapterPosition() instead of position in your listeners like this:
holder.delete.setOnClickListener(view -> {
// listener.onDelete(position);
removeItem(holder.getAdapterPosition());
});

ListView custom adapter for Android 9.0 - NullPointerException

I have a ListView that displays a custom view when the user clicks in the search button. Each custom view is a checkbox. When the user selects a checkbox, the object in that position goes to a list. What I need to do is: if the user clicks again in the search button, the view that was already checked (is on the list), can't appear in the ListView again.
I did a code that is working perfectly in Android 6.0, my problem is at Android 9.0 that is returning:
java.lang.NullPointerException: Attempt to invoke virtual method 'int
android.view.View.getImportantForAccessibility()' on a null object
reference
This is the adapter code:
package com.example.nerasexpert.adapter;
import android.app.Activity;
import android.net.wifi.ScanResult;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import com.example.nerasexpert.R;
import java.util.ArrayList;
import java.util.List;
public class ListaDevicesAdapter extends BaseAdapter {
private List<ScanResult> devices;
private final Activity activity;
private ArrayList<ScanResult> selectedDevices = new ArrayList<>();
public ListaDevicesAdapter(Activity activity, List<ScanResult> nerasList) {
this.activity = activity;
this.devices = nerasList;
}
#Override
public int getCount() {
return devices.size();
}
#Override
public Object getItem(int position) {
return devices.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
LayoutInflater inflater = activity.getLayoutInflater();
View viewCriada = inflater.inflate(R.layout.item_install, viewGroup, false);
Log.i("lista devices", "" + devices);
Log.i("item", "" + devices.get(position));
Log.i("selected devices", "" + selectedDevices);
for (ScanResult device :
selectedDevices){
if(device.SSID.equals(devices.get(position).SSID)) {
return null;
}
}
populaView(position, viewCriada);
return viewCriada;
}
private void populaView(int position, View viewCriada) {
CheckBox deviceName = viewCriada.findViewById(R.id.checkBox);
ScanResult deviceDevolvido = devices.get(position);
deviceName.setText(deviceDevolvido.SSID);
deviceName.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked) {
selectedDevices.add(deviceDevolvido);
} else {
selectedDevices.remove(deviceDevolvido);
}
}
});
}
public ArrayList<ScanResult> getSelectedDevicesList() {
return this.selectedDevices;
}
public void update(List<ScanResult> list) {
this.devices.clear();
this.devices.addAll(list);
notifyDataSetChanged();
}
}
I know that the problem is in returning null when the objects exists in the list, but what can I do to have the same result without the NullPointException in Android 9.0?

In Android, how to achieve snap effect on a listview while respecting acceleration caused by fling?

For demonstration, I have a ListView displaying a list of numbers. I would like to achieve the effect that when the user scrolls the ListView and the scrolling ends, it will only stop at certain positions so that the first visible item is always shown completely. I've attached my attempted code below. It works when users drag to scroll the ListView. But when there's fling, the normal acceleration is interrupted, causing an unnatural stop. My question is, how can I take acceleration caused by fling into account while achieving the same effect?
package com.example.snaptest;
import android.content.Context;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends ActionBarActivity {
private static class TestListViewAdapter extends BaseAdapter {
private Context mContext;
public TestListViewAdapter(Context context) {
mContext = context;
}
#Override
public int getCount() {
return 100;
}
#Override
public Object getItem(int position) {
return Integer.toString(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView textView = new TextView(mContext);
textView.setText(Integer.toString(position));
AbsListView.LayoutParams params = new AbsListView.LayoutParams(ViewGroup.LayoutParams
.MATCH_PARENT, 180);
textView.setLayoutParams(params);
return textView;
}
}
private static class TestListView extends ListView {
public TestListView(Context context) {
super(context);
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) {
View itemView = getChildAt(0);
int top = Math.abs(itemView.getTop()); // top is a negative value
int bottom = Math.abs(itemView.getBottom());
if (top >= bottom){
smoothScrollToPositionFromTop
(getFirstVisiblePosition() + 1, 0);
} else {
smoothScrollToPositionFromTop
(getFirstVisiblePosition(), 0);
}
}
return super.onTouchEvent(ev);
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TestListView listView = new TestListView(this);
listView.setAdapter(new TestListViewAdapter(this));
setContentView(listView);
}
}
I would try with an OnScrollListener rather than extending ListView.
Something like this:
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == AbsListView.SCROLL_STATE_IDLE) {
// snap the listview according to the top/bottom items' visibility
}
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});

"Set wallpaper" button function, Android

I've created a custom gallery; however, the "Set wallpaper" button will not set the wallpaper. Here's the wallpaper.java I have. I'm just lost on how to implement OnClickListener and then set my button to use an onclicklistener like so:
buttonName.setOnClickListener(this);
package com.totem;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.Gallery.LayoutParams;
import java.io.IOException;
import java.io.InputStream;
public class Wallpaper extends Activity implements
AdapterView.OnItemSelectedListener, AdapterView.OnItemClickListener {
private static final String LOG_TAG = "Home";
private static final Integer[] THUMB_IDS = {
R.drawable.andy_small,
};
private static final Integer[] IMAGE_IDS = {
R.drawable.andy,
};
private Gallery mGallery;
private boolean mIsWallpaperSet;
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.wallpaper_chooser);
mGallery = (Gallery) findViewById(R.id.gallery);
mGallery.setAdapter(new ImageAdapter(this));
mGallery.setOnItemSelectedListener(this);
mGallery.setOnItemClickListener(this);
}
#Override
protected void onResume() {
super.onResume();
mIsWallpaperSet = false;
}
#SuppressWarnings("unchecked")
public void onItemSelected(AdapterView parent, View v, int position, long id) {
getWindow().setBackgroundDrawableResource(IMAGE_IDS[position]);
}
#SuppressWarnings("unchecked")
public void onItemClick(AdapterView parent, View v, int position, long id) {
selectWallpaper(position);
}
private synchronized void selectWallpaper(int position) {
if (mIsWallpaperSet) {
return;
}
mIsWallpaperSet = true;
try {
InputStream stream = getResources().openRawResource(IMAGE_IDS[position]);
setWallpaper(stream);
setResult(RESULT_OK);
finish();
} catch (IOException e) {
Log.e(LOG_TAG, "Failed to set wallpaper " + e);
}
}
#SuppressWarnings("unchecked")
public void onNothingSelected(AdapterView parent) {
}
public boolean onTouchEvent(MotionEvent event, Object Action_Down) {
getAction(Action_Down);
selectWallpaper(mGallery.getSelectedItemPosition());
return true;
}
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter(Context c) {
mContext = c;
}
public int getCount() {
return THUMB_IDS.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(final int position, View convertView, ViewGroup parent) {
ImageView i = new ImageView(mContext);
i.setImageResource(THUMB_IDS[position]);
i.setAdjustViewBounds(true);
i.setLayoutParams(new Gallery.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
i.setBackgroundResource(android.R.drawable.picture_frame);
return i;
}
}
}
Parsed in 0.242 seconds, using GeSHi 1.0.8.4
Go to http://www.xtensivearts.com/topics/tutorials/ there are video tutorials that will help you with the onclicklisteners
are you set user permission in androidmanifest file for set Wallpaper?
<uses-permission android:name="android.permission.SET_WALLPAPER" />

Categories

Resources