I am working on my java code to call a function when I click on the RelativeLayout.
When I click on a RelativeLayout, I am calling toggleSelection function to insert the index in the array list and delete the index in the array list.
Adapter:
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
holder.iconContainer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int pos = holder.getAdapterPosition();
toggleSelection(holder, pos);
}
});
public void toggleSelection(ViewHolder holder, int pos) {
currentSelectedIndex = pos;
if (selectedItems.get(pos, false)) {
selectedItems.delete(pos);
animationItemsIndex.delete(pos);
} else {
selectedItems.put(pos, true);
animationItemsIndex.put(pos, true);
}
Log.e("getSelectedItem...." + getSelectedItemCount, " ");
if (selectedItems.size() == 1) {
if (mInboxes.get(pos).getRead().equals("read")) {
Log.e("passed...5", " ");
}
if (holder.action_archive == null) {
Log.e("passed...6", " ");
//holder.action_archive.setVisible(true);
}
if (holder.action_delete == null) {
//holder.action_delete.setVisible(true);
}
}
notifyItemChanged(pos);
}
}
I want to set the menu items to visible when I click on RelativeLayout, but when I tried this:
MenuItem action_read = menu.findItem(R.id.action_mark_read);
if (action_read.isVisible() == true) {
...
}
It give me an error: java.lang.NullPointerException: Attempt to invoke interface method 'android.view.MenuItem android.view.Menu.findItem(int)' on a null object reference.
Here is the full code:
public class InboxAdapter extends RecyclerView.Adapter<InboxAdapter.ViewHolder> {
public static List<inbox> mInboxes;
private Context mContext;
public String mailbox = "inbox";
public Window window;
public InboxAdapter adapter;
public Fragment _fragment;
public Menu menu;
public InboxAdapter(Context mContext, List<inbox> inboxes, Fragment fragment) {
this.mContext = mContext;
_fragment = fragment;
mInboxes = inboxes;
selectedItems = new SparseBooleanArray();
}
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
holder.iconContainer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int pos = holder.getAdapterPosition();
toggleSelection(holder, pos);
}
});
#SuppressLint({"LongLogTag", "ResourceType"})
public void toggleSelection(ViewHolder holder, int pos) {
currentSelectedIndex = pos;
if (selectedItems.get(pos, false)) {
selectedItems.delete(pos);
animationItemsIndex.delete(pos);
} else {
selectedItems.put(pos, true);
animationItemsIndex.put(pos, true);
}
Log.e("getSelectedItem...." + getSelectedItemCount, " ");
MenuItem action_read = menu.findItem(R.id.action_mark_read);
MenuItem action_unread = menu.findItem(R.id.action_mark_unread);
if (selectedItems.size() == 1) {
if (mInboxes.get(pos).getRead().equals("read")) {
if (action_read.isVisible() == true) {
Log.e("passed...5", " ");
}
}
if (holder.action_archive == null) {
if (action_unread.isVisible() == true) {
Log.e("passed...6", " ");
}
}
if (holder.action_delete == null) {
Log.e("passed...7", " ");
//holder.action_delete.setVisible(true);
}
}
notifyItemChanged(pos);
}
}
Do you know how I can set the menu items to visible in the adapter function??
Related
For some reason the only thing displayed in my RecyclerView is com.stu54259.plan2cook.Model.Shopping_list#5cb7482 repeated with various end codes not the contents of the ArrayList. Any suggestions must be something with the recylerview adapter. Can add xml etc if need be but i'm sure I've just missed something stupid.
Shopping_List class
package com.stu54259.plan2cook.Model;
public class Shopping_List {
private int id;
private String ingredient_type;
private String ingredient_name;
private Double quantity;
private String measurement_name;
public Shopping_List() {
}
public Shopping_List(String ingredient_type, String ingredient_name, Double quantity, String measurement_name) {
this.ingredient_type = ingredient_type;
this.ingredient_name = ingredient_name;
this.quantity = quantity;
this.measurement_name = measurement_name;
}
public Shopping_List(int id, String ingredient_type, String ingredient_name, Double quantity, String measurement_name) {
this.id = id;
this.ingredient_type = ingredient_type;
this.ingredient_name = ingredient_name;
this.quantity = quantity;
this.measurement_name = measurement_name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getIngredient_type() {
return ingredient_type;
}
public void setIngredient_type(String ingredient_type) {
this.ingredient_type = ingredient_type;
}
public String getIngredient_name() {
return ingredient_name;
}
public void setIngredient_name(String ingredient_name) {
this.ingredient_name = ingredient_name;
}
public Double getQuantity() {
return quantity;
}
public void setQuantity(Double quantity) {
this.quantity = quantity;
}
public String getMeasurement_name() {
return measurement_name;
}
public void setMeasurement_name(String measurement_name) {
this.measurement_name = measurement_name;
}
}
Activity
public class ShoppingList extends MainActivity {
ShoppingListAdapter adapterRecipe;
List<Shopping_List> shopList = new ArrayList<>();
RecyclerView listIngredient;
SQLiteDatabase db;
Cursor c;
EditText edittext;
String search;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.shopping_list);
edittext = findViewById(R.id.editPlanName);
edittext.setOnKeyListener(new View.OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
search = edittext.getText().toString();
Log.d("Search value", search);
if ((event.getAction() == KeyEvent.ACTION_DOWN) &&
(keyCode == KeyEvent.KEYCODE_ENTER)) {
loadIngredient();
adapterRecipe.notifyDataSetChanged();
return true;
}
return false;
}
});
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.home:
Intent a = new Intent(ShoppingList.this,MainActivity.class);
startActivity(a);
break;
case R.id.recipes:
Intent b = new Intent(ShoppingList.this,RecipeSearch.class);
startActivity(b);
break;
case R.id.shoppingList:
Intent c = new Intent(ShoppingList.this, ShoppingList.class);
startActivity(c);
break;
case R.id.mealPlan:
Intent d = new Intent(ShoppingList.this, MenuPlan.class);
startActivity(d);
break;
case R.id.reminder:
Intent e = new Intent(ShoppingList.this, Reminders.class);
startActivity(e);
break;
}
return false;
}
});
adapterRecipe = new ShoppingListAdapter(this, shopList);
listIngredient = findViewById(R.id.listIngredient);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(this,
LinearLayoutManager.VERTICAL, false);
listIngredient.setLayoutManager(mLayoutManager);
listIngredient.setItemAnimator(new DefaultItemAnimator());
listIngredient.setAdapter(adapterRecipe);
}
public void loadIngredient() {
shopList.clear();
db = (new DatabaseManager(this).getWritableDatabase());
String RECIPE_SEARCH =
"SELECT SUM(A.ingredient_quantity) quantity, A.ingredient ingredient_name, A.recipe, B.ingredient_type, B.measurement_name, C.id, D.plan_name " +
"FROM " + DatabaseManager.TABLE_QUANTITY + " AS A JOIN " + DatabaseManager.TABLE_INGREDIENTS + " AS B ON A.ingredient = B.ingredient_name " +
"JOIN " + DatabaseManager.TABLE_PLAN_RECIPES + " AS C ON A.recipe = C.recipe_name " +
"JOIN " + DatabaseManager.TABLE_MEAL_PLAN + " AS D ON C.id = D.plan_recipe " +
"WHERE D.plan_name LIKE ? GROUP BY A.ingredient";
Log.d("Search query", RECIPE_SEARCH);
c = db.rawQuery(RECIPE_SEARCH, new String[]{"%" + search + "%"});
if (c.moveToFirst()) {
do {
Shopping_List shopping_list = new Shopping_List();
shopping_list.setQuantity(c.getDouble(c.getColumnIndex("quantity")));
shopping_list.setIngredient_name(c.getString(c.getColumnIndex("ingredient_name")));
shopping_list.setIngredient_type(c.getString(c.getColumnIndex("ingredient_type")));
shopping_list.setMeasurement_name(c.getString(c.getColumnIndex("measurement_name")));
shopList.add(shopping_list);
} while (c.moveToNext());
}
c.close();
db.close();
}
}
Adapter
public class ShoppingListAdapter extends RecyclerView.Adapter<com.stu54259.plan2cook.Adapters.ShoppingListAdapter.ViewHolder> {
private List<Shopping_List> shopList;
private LayoutInflater mInflater;
private com.stu54259.plan2cook.Adapters.RecyclerViewAdapter.ItemClickListener mClickListener;
// data is passed into the constructor
public ShoppingListAdapter(Context context, List<Shopping_List> data) {
this.mInflater = LayoutInflater.from(context);
this.shopList = data;
}
// inflates the row layout from xml when needed
#Override
public com.stu54259.plan2cook.Adapters.ShoppingListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.fragment_item, parent, false);
return new com.stu54259.plan2cook.Adapters.ShoppingListAdapter.ViewHolder(view);
}
// binds the data to the TextView in each row
#Override
public void onBindViewHolder(com.stu54259.plan2cook.Adapters.ShoppingListAdapter.ViewHolder holder, int position) {
if(shopList.get(position) != null)
{
holder.myTextView.setText(shopList.get(position).toString());
}
}
// total number of rows
#Override
public int getItemCount() {
return shopList.size();
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView myTextView;
ViewHolder(View itemView) {
super(itemView);
myTextView = itemView.findViewById(R.id.quantity);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
}
}
// allows clicks events to be caught
void setClickListener(com.stu54259.plan2cook.Adapters.RecyclerViewAdapter.ItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
// parent activity will implement this method to respond to click events
public interface ItemClickListener {
void onItemClick(View view, int position);
}
}
Add this method in your Shopping_List class, so when you use toString() for a Shopping_List instance you will get all its properties separated by spaces:
public String toString() {
return ingredient_name + " " + ingredient_type + " " + quantity + " " + measurement_name;
}
You can change the order of the properties.
You have wrong code in onBindViewHolder method. You should set text with some field from Shopping_List object:
#Override
public void onBindViewHolder(com.stu54259.plan2cook.Adapters.ShoppingListAdapter.ViewHolder holder, int position) {
if(shopList.get(position) != null)
{
holder.myTextView.setText(shopList.get(position).toString());
}
}
You haven't put the Shopping_List object here, but if you have something like this:
public class Shopping_List {
public String title;
public String getTitle() {
return title;
}
}
Then you should do something like this:
#Override
public void onBindViewHolder(com.stu54259.plan2cook.Adapters.ShoppingListAdapter.ViewHolder holder, int position) {
if(shopList.get(position) != null)
{
holder.myTextView.setText(shopList.get(position).getTitle());
}
}
Although it doesn't give a direct solution, I would suggest that you use the groupie library. It will most likely remove your error and reduce boilerplate code and complexity.
here is my recyclerview adapter classs
public class WebsiteAdapter extends RecyclerView.Adapter<WebsiteAdapter.WebsiteHolder> {
private List<Website> websites = new ArrayList<>();
private WebsiteViewModel websiteViewModel;
WebsiteAdapter(WebsiteViewModel viewModel){
this.websiteViewModel = viewModel;
}
#NonNull
#Override
public WebsiteHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.website_item, parent, false);
return new WebsiteHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull final WebsiteHolder holder, final int position) {
final Website currentWebsite = websites.get(position);
final Boolean bookmarkStatus = currentWebsite.getFavourite();
final List<WebPage> webPages = websiteViewModel.getRepository().getAllWebPagesForWebsite(currentWebsite.getWebsite_id());
holder.textViewTitle.setText(currentWebsite.getWebsiteName());
if(currentWebsite.getDescription() != null){
holder.textViewDescription.setText(currentWebsite.getDescription());
holder.textViewDescription.setVisibility(View.VISIBLE);
}
if(webPages!=null && !webPages.isEmpty()) {
holder.secondaryAdapter.setWebPages(webPages);
holder.expandCollapse.setVisibility(View.VISIBLE);
}
if(bookmarkStatus){
holder.isBookmarked = true;
holder.bookmarkButton.setBackgroundResource(R.drawable.ic_bookmark_24px);
} else {
holder.isBookmarked = false;
holder.bookmarkButton.setBackgroundResource(R.drawable.ic_bookmark_border_24px);
}
holder.cardViewWebsite.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String websiteUrl = currentWebsite.getWebsite_url();
System.out.println("Description = " + currentWebsite.getDescription() + ", boomarked : " + currentWebsite.getFavourite());
List<WebPage> webPages = websiteViewModel.getRepository().getAllWebPagesForWebsite(currentWebsite.getWebsite_id());
for(WebPage webPage : webPages){
System.out.println("Web pages: ");
System.out.println(webPage.toString() + ", ");
}
launchWebsite(v.getContext(), websiteUrl);
}
});
holder.bookmarkButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
System.out.println("Website bookmarked before click : " + bookmarkStatus + ", Description is : " + currentWebsite.getDescription());
currentWebsite.setFavourite(!bookmarkStatus);
System.out.println("Website bookmark clicked, status has been set to : " + currentWebsite.getFavourite());
websiteViewModel.getRepository().websiteDao.updateWebsite(currentWebsite);
notifyItemChanged(position);
}
});
}
private void launchWebsite(Context context, String URL) {
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
builder.setStartAnimations(context, R.anim.push_off_screen_left, R.anim.push_onto_screen_from_right);
builder.setExitAnimations(context, R.anim.push_onto_screen_from_left, R.anim.push_off_screen_right);
CustomTabsIntent customTabsIntent = builder.build();
customTabsIntent.launchUrl(context,Uri.parse(URL));
}
#Override
public int getItemCount() {
return websites.size();
}
public void setWebsites(List<Website> websites) {
this.websites = websites;
notifyDataSetChanged();
}
class WebsiteHolder extends RecyclerView.ViewHolder {
private TextView textViewTitle;
private TextView textViewDescription;
private CardView cardViewWebsite;
private boolean isBookmarked; // ALSO FAVOURITED
private boolean isExpanded = false;
private Button expandCollapse;
private Button bookmarkButton;
private SecondaryAdapter secondaryAdapter;
private RecyclerView childRecyclerView;
public WebsiteHolder(View itemView) {
super(itemView);
textViewTitle = itemView.findViewById(R.id.text_view_title);
textViewDescription = itemView.findViewById(R.id.text_view_description);
cardViewWebsite = itemView.findViewById(R.id.cardViewWebsite);
bookmarkButton = itemView.findViewById(R.id.bookmarkButton);
childRecyclerView = itemView.findViewById(R.id.childRecyclerview);
expandCollapse = itemView.findViewById(R.id.expandCollapse);
expandCollapse.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (isExpanded) {
collapseView();
} else {
expandView();
}
}
});
childRecyclerView.setLayoutManager(new LinearLayoutManager(itemView.getContext(), LinearLayoutManager.HORIZONTAL, false));
LayoutAnimationController animation = AnimationUtils.loadLayoutAnimation(itemView.getContext(), R.anim.layout_animation_slide_in);
childRecyclerView.setLayoutAnimation(animation);
childRecyclerView.setHasFixedSize(true);
secondaryAdapter = new SecondaryAdapter();
childRecyclerView.setAdapter(secondaryAdapter);
}
private void collapseView() {
isExpanded = false;
childRecyclerView.setVisibility(View.GONE);
}
private void expandView() {
isExpanded = true;
childRecyclerView.setVisibility(View.VISIBLE);
}
}
}
The issue I am having is, when I press the bookmark button on item A: the expand button on a different item will appear when it should not. B: The secondaryRecyclerView gets set to some other website. How do I go about debugging this? Is there anything that jumps out as a culpit? I feel like I am setting somethings in the wrong place. Thanks very much
wrong item changes in recyclerview
Thanks to this post, I one, added in a bindView method, and 2: added ELSE statements to negate the if statements. Problems solved :) For now :)
I get the Latitude and Longtitude from my Database and I calculate the distance between two persons in the RecyclerView Adapter.
I want to sort these items by distance, but I have no clue how I can do this.
My Adapter:
public class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.ViewHolder>{
Context context;
List<HomeGetter> homeGetters;
HomeCallback homeCallback;
public HomeAdapter(Context context, List<HomeGetter> homeGetters, HomeCallback homeCallback) {
this.context = context;
this.homeGetters = homeGetters;
this.homeCallback = homeCallback;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.custom_home_profil,parent,false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
calculate_age calculate_age = new calculate_age();
final HomeGetter homeGetter = homeGetters.get(position);
String[] splittedAge = homeGetter.getBirthday().split("\\.");
try {
String age = calculate_age.getAge(context,Integer.valueOf(splittedAge[0]),Integer.valueOf(splittedAge[1]),Integer.valueOf(splittedAge[2]));
String username = homeGetter.getUsername().substring(0,1).toUpperCase() + homeGetter.getUsername().substring(1);
holder.textViewUsername.setText(username + "," + age);
} catch (ParseException e) {
e.printStackTrace();
}
Picasso.with(context).load(homeGetter.getImageURL()).resize(600,700).centerCrop().into(holder.imageView);
holder.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
homeCallback.getPosition(position);
}
});
holder.textViewLocation.setText(homeGetter.getLocation());
if(homeGetter.getStatus().equals("0")){
holder.status.setImageDrawable(context.getResources().getDrawable(R.drawable.offline));
}else {
holder.status.setImageDrawable(context.getResources().getDrawable(R.drawable.online));
}
}
#Override
public int getItemCount() {
return homeGetters.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
TextView textViewUsername;
CardView cardView;
TextView textViewLocation;
ImageView status;
public ViewHolder(View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.imageViewThumb);
textViewUsername = itemView.findViewById(R.id.textViewProfilUsername);
cardView = itemView.findViewById(R.id.cardViewProfil);
textViewLocation = itemView.findViewById(R.id.textViewLocation);
status = itemView.findViewById(R.id.imageViewOnlinestatus);
}
}
}
On this line I get the distance in km:
holder.textViewLocation.setText(homeGetter.getLocation());
e.g 544
Is it possible to sort the list in the adapter?
Or how can I sort this?
So, how can I achive this?
The Activity
pullData.getData(USERNAME, "1", new Pullcallback() {
#Override
public void getSingleData(String data) {
}
#Override
public void getMultipleData(String[] multipledatas) {
GENDER = multipledatas[5];
GENDERSEARCH = multipledatas[6];
GetStrangers getStrangers = new GetStrangers(Home.this);
Map<String,String> map = new HashMap<>();
map.put("USERNAME",USERNAME);
map.put("GENDER",GENDER);
map.put("SEARCH",GENDERSEARCH);
getStrangers.strangers(map, "7", new Pullcallback() {
#Override
public void getSingleData(String data) {
}
#Override
public void getMultipleData(final String[] multipledatas) {
// username,imagelink,position,birthday
// imageURL,username,birthday,location
pullData.getData(USERNAME, "2", new Pullcallback() {
#Override
public void getSingleData(String data) {
}
#Override
public void getMultipleData(String[] multipledatas2) {
String[] split1 = multipledatas2[1].split(",");
String[] split2 = multipledatas[2].split(",");
float lat1 = Float.valueOf(split1[0]);
float lng1 = Float.valueOf(split1[1]);
float lat2 = Float.valueOf(split2[0]);
float lng2 = Float.valueOf(split2[1]);
Collections.sort(getterList, new Comparator<HomeGetter>() {
public int compare(HomeGetter s1, HomeGetter s2) {
return Integer.compare(Integer.parseInt(s1.getLocation()), Integer.parseInt(s2.getLocation()));
}
});
homeGetter = new HomeGetter(multipledatas[1],multipledatas[0],multipledatas[3],String.valueOf(Math.round(Calculator.calculateDistance(lat1,lng1,lat2,lng2))),multipledatas[4]);
getterList.add(homeGetter);
homeAdapter.notifyDataSetChanged();
loading.setVisibility(View.GONE);
content.setVisibility(View.VISIBLE);
}
#Override
public void onError(String errormessage) {
}
});
}
#Override
public void onError(String errormessage) {
}
});
}
#Override
public void onError(String errormessage) {
}
});
pullData.getData(USERNAME, "2", new Pullcallback() {
#Override
public void getSingleData(String data) {
}
#Override
public void getMultipleData(String[] multipledatas) {
if(multipledatas[7].equals("0")){
Intent intentFirststep = new Intent(Home.this,Firststep.class);
startActivity(intentFirststep);
finish();
}else {
}
}
#Override
public void onError(String errormessage) {
}
});
recyclerViewHome = findViewById(R.id.recyclerViewHome);
homeAdapter = new HomeAdapter(Home.this, getterList, new HomeCallback() {
#Override
public void getPosition(int position) {
Intent stranger = new Intent(Home.this,Stranger.class);
stranger.putExtra("USERNAME",getterList.get(position).getUsername());
startActivity(stranger);
finish();
}
});
recyclerViewHome.setHasFixedSize(true);
recyclerViewHome.setLayoutManager(new GridLayoutManager(Home.this,3));
recyclerViewHome.setItemAnimator(new DefaultItemAnimator());
recyclerViewHome.setAdapter(homeAdapter);
}
But it is not working correctly it shows me 4,14,507 and 12
but it shoild sort 4,12,14,507
In your activity where you are passing your ArrayList just do this before passing it.
Collections.sort(homeGetter, new Comparator<HomeGetter>() {
public int compare(HomeGetter s1, HomeGetter s2) {
return Integer.compare(Integer.parseInt(s1.getLocation()), Integer.parseInt(s2.getLocation()));
}
});
P.S. Don't use parse if you are already storing as integers.
Happy to help.
EDIT:
Put it here-
getterList.add(homeGetter);
Collections.sort(homeGetter, new Comparator<HomeGetter>() {
public int compare(HomeGetter s1, HomeGetter s2) {
return Integer.compare(Integer.parseInt(s1.getLocation()), Integer.parseInt(s2.getLocation()));
}
});
homeAdapter.notifyDataSetChanged();
You can also sort the List<HomeGetter> homegetters using a Comparator & then initialize HomeAdapter with sorted homegetters list.
An Example:
homegetters.sort((hG1, hG2) -> hG1.getLocation().compareTo(hG2.getLocation()));
Above line will sort homegetters list based on getLocation().
Edit:
In your activity, you are sorting the List first and then adding an item into it.
You should instead add all the items first & then sort the List.
I have a list of threads which I have paginated to use an endless scroll the issue I'm having (well my users) is an OutOfMemoryError: Failed to allocate a [x] byte allocation with [y] free bytes and [z] until OOM. the x, y and z attribute is different per user but the cause of the bug is always in the same place and it's when I refresh the posts. I'm completely out of my depth here as I have no idea how to optimise my code or make it so this doesn't happen. As it's the biggest crash on my app at the moment. I've posted my PostFragment below please see the refreshPosts(ArrayList<Posts> newObjects) method as this is where the crash is happening.
public class PostFragment extends Fragment implements View.OnClickListener {
private View mRootView;
private GridLayoutManager mLayoutManager;
private ThreadItem mThreads;
private PostItem mPost;
private PostAdapter mAdapter;
private PostResponse mData;
private EmoticonResponse mEmoticon;
private PostFeedDataFactory mDataFactory;
private EmoticonFeedDataFactory mEmoticonDataFactory;
private static PostFragment mCurrentFragment;
private int REQUEST_CODE;
//Flip
private boolean isFlipped = false;
private Animation flipAnimation;
#BindView(R.id.postsRecyclerView)
RecyclerView mRecyclerView;
#BindView(R.id.toolbarForPosts)
Toolbar mToolbar;
#BindView(R.id.threadText)
TextView mThreadText;
#BindView(R.id.flipText)
TextView mFlipTextView;
#BindView(R.id.shareText)
TextView mShareTextView;
#BindView(R.id.replyText)
TextView mReplyTextView;
#BindView(R.id.scrimColorView)
View mBackgroundView;
#BindView(R.id.fabMenu)
FloatingActionButton mFabMenu;
#BindView(R.id.flipFab)
FloatingActionButton mFlipFab;
#BindView(R.id.shareFab)
FloatingActionButton mShareFab;
#BindView(R.id.replyFab)
FloatingActionButton mReplyFab;
//Collapsing Toolbar
#BindView(R.id.postParentAppBarLayout)
AppBarLayout postAppBarLayout;
#BindView(R.id.postCollapseToolbar)
CollapsingToolbarLayout postCollapseToolbarLayout;
#BindView(R.id.mainImageContainer)
ViewGroup mainContainer;
//Back to top
#BindView(R.id.backToTopButton)
Button mBackToTop;
public static boolean isFromReply;
//FAB
private boolean mIsFabOpen = false;
private Animation fab_open, fab_close, rotate_forward, rotate_backward;
//Pagination
private int mCurrentPage = 1;
private ArrayList<Posts> postList = new ArrayList<>();
private boolean mIsLoading = false;
private boolean mIsLastPage = false;
public static PostFragment newInstance(#NonNull ThreadItem threadItem) {
Bundle args = new Bundle();
args.putParcelable("ThreadItem", Parcels.wrap(threadItem));
mCurrentFragment = new PostFragment();
mCurrentFragment.setArguments(args);
isFromReply = false;
return mCurrentFragment;
}
public static PostFragment newPostInstance(#NonNull PostItem postItem) {
Bundle args = new Bundle();
args.putParcelable("PostItemFromCompose", Parcels.wrap(postItem));
mCurrentFragment = new PostFragment();
mCurrentFragment.setArguments(args);
isFromReply = true;
return mCurrentFragment;
}
public PostFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mRootView = inflater.inflate(R.layout.fragment_post, container, false);
if (savedInstanceState == null) {
ButterKnife.bind(this, mRootView);
initUI();
}
return mRootView;
}
private void initUI() {
//UI Setup
mLayoutManager = new GridLayoutManager(getActivity(), 1);
mRecyclerView.setLayoutManager(mLayoutManager);
mDataFactory = new PostFeedDataFactory(getActivity());
mEmoticonDataFactory = new EmoticonFeedDataFactory(getActivity());
TextView textThreadTopic = (TextView) mRootView.findViewById(R.id.threadTopic);
TextView textNumPosts = (TextView) mRootView.findViewById(R.id.numPosts);
//FAB onClick Set-Up
mFabMenu.setOnClickListener(this);
mShareFab.setOnClickListener(this);
mReplyFab.setOnClickListener(this);
mFlipFab.setOnClickListener(this);
//FAB Animation Set up
fab_open = AnimationUtils.loadAnimation(getActivity().getApplicationContext(),
R.anim.fab_open);
fab_close = AnimationUtils.loadAnimation(getActivity().getApplicationContext(),
R.anim.fab_close);
rotate_forward = AnimationUtils.loadAnimation(getActivity().getApplicationContext(),
R.anim.rotate_forward);
rotate_backward = AnimationUtils.loadAnimation(getActivity().getApplicationContext(),
R.anim.rotate_backward);
//Toolbar
((AppCompatActivity) getActivity()).setSupportActionBar(mToolbar);
((AppCompatActivity) getActivity()).getSupportActionBar().setDisplayShowTitleEnabled(false);
mToolbar.setNavigationIcon(R.drawable.ic_back_white);
mToolbar.invalidate();
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getActivity().finish();
}
});
//Load Parcel
Intent intent = getActivity().getIntent();
mThreads = Parcels.unwrap(getArguments().getParcelable("ThreadItem"));
mPost = Parcels.unwrap(getArguments().getParcelable("PostItemFromCompose"));
if (mThreads != null) {
if (mThreads.getName() != null) {
mThreadText.setText(mThreads.getName());
}
if (mThreads.getTopic_name() != null) {
textThreadTopic.setText(mThreads.getTopic_name());
}
if (mThreads.getNum_posts() != null) {
int numPosts = Integer.parseInt(mThreads.getNum_posts());
if (numPosts > 1000) {
textNumPosts.setText("1K");
} else {
textNumPosts.setText(mThreads.getNum_posts());
}
}
}
postAppBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
boolean isShow = false;
int scrollRange = -1;
#Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
if (scrollRange == -1) {
scrollRange = appBarLayout.getTotalScrollRange();
}
if (scrollRange + verticalOffset == 0) {
postCollapseToolbarLayout.setTitle("Threads");
mainContainer.setVisibility(View.INVISIBLE);
isShow = true;
} else if (isShow) {
postCollapseToolbarLayout.setTitle("");
isShow = false;
mainContainer.setVisibility(View.VISIBLE);
}
}
});
flipAnimation =
AnimationUtils.loadAnimation(getActivity().getApplicationContext(), R.anim.flip);
loadData(true, 1);
}
private void loadData(final boolean firstLoad, int readDirection) {
if (isFromReply) {
if (mPost.getThread_id() != null) {
mDataFactory.getPostFeed(mPost.getThread_id(), readDirection, mCurrentPage,
new PostFeedDataFactory.PostFeedDataFactoryCallback() {
#Override
public void onPostDataReceived(PostResponse response) {
mData = response;
if (mData.getItems() != null) {
for (int i = 0; i < mData.getItems().size(); i++) {
Posts singlePost = response.getItems().get(i);
postList.add(singlePost);
}
if (firstLoad) {
mIsLoading = false;
mData.getItems().clear();
mData.getItems().addAll(postList);
mEmoticonDataFactory.getEmoticonFeed(
new EmoticonFeedDataFactory.EmoticonFeedDataFactoryCallback() {
#Override
public void onEmoticonDataReceived(EmoticonResponse response) {
mEmoticon = response;
populateUIWithData();
}
#Override
public void onEmoticonDataFailed(Exception exception) {
}
});
} else {
mIsLoading = false;
refreshPosts(postList);
}
if (mData.getItems().size() > 0) {
if (Integer.valueOf(mData.getTotalPosts()) >= response.getItems().size()) {
mCurrentPage++;
} else {
mIsLastPage = true;
}
}
}
}
#Override
public void onPostDataFailed(Exception exception) {
customToast("Error: " + exception.toString());
}
});
}
} else {
if (mThreads.getId() != null)
mDataFactory.getPostFeed(mThreads.getId(), readDirection, mCurrentPage,
new PostFeedDataFactory.PostFeedDataFactoryCallback() {
#Override
public void onPostDataReceived(PostResponse response) {
mData = response;
if (mData.getItems() != null) {
for (int i = 0; i < mData.getItems().size(); i++) {
Posts singlePost = response.getItems().get(i);
postList.add(singlePost);
}
if (firstLoad) {
mIsLoading = false;
mData.getItems().clear();
mData.getItems().addAll(postList);
mEmoticonDataFactory.getEmoticonFeed(
new EmoticonFeedDataFactory.EmoticonFeedDataFactoryCallback() {
#Override
public void onEmoticonDataReceived(EmoticonResponse response) {
mEmoticon = response;
populateUIWithData();
}
#Override
public void onEmoticonDataFailed(Exception exception) {
}
});
} else {
mIsLoading = false;
refreshPosts(postList);
}
if (mData.getItems().size() > 0) {
if (Integer.valueOf(mData.getTotalPosts()) >= response.getItems().size()) {
mCurrentPage++;
} else {
mIsLastPage = true;
}
}
}
}
#Override
public void onPostDataFailed(Exception exception) {
customToast("Error: " + exception.toString());
}
});
}
}
private void populateUIWithData() {
ImageButton moreOptionsButton = (ImageButton) mRootView.findViewById(R.id.moreOptions);
moreOptionsButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
PopupMenu popupMenu = new PopupMenu(v.getContext(), v);
popupMenu.inflate(R.menu.thread_options);
popupMenu.getMenu();
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.watch:
WatchedThreadsRequestData watchedThreadsRequestData = new WatchedThreadsRequestData(getActivity());
watchedThreadsRequestData.setWatchedThread(mThreads.getId(), new WatchedThreadsRequestData.WatchedThreadsFeedback() {
#Override
public void onWatchedRequestReceived(ThreadResponse response) {
customToast("Thread watched");
}
#Override
public void onWatchedRequestFailed(Exception exception) {
customToast("Thread wasn't watched: " + exception.toString());
}
});
return true;
case R.id.shareThread:
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.putExtra(Intent.EXTRA_TEXT, mThreads.getName() + " - " + Constants.LIVE_URL +
"talk/" + mThreads.getTopic_url() + '/' + mThreads.getThread_url());
sharingIntent.setType("text/plain");
getActivity().startActivity(Intent.createChooser(sharingIntent, "Share via"));
return true;
case R.id.hideThread:
customToast("Hide: coming soon");
return true;
default:
customToast("Somethings Wrong");
return true;
}
}
});
setForceShowIcon(popupMenu);
popupMenu.show();
}
});
if (mAdapter == null) {
mAdapter = new PostAdapter(getActivity(), mData, mEmoticon);
mRecyclerView.setAdapter(mAdapter);
} else {
mAdapter.setData(mData.getItems());
mAdapter.notifyDataSetChanged();
}
mRecyclerView.addOnScrollListener(paginationListener);
}
public static void setForceShowIcon(PopupMenu popupMenu) {
try {
Field[] fields = popupMenu.getClass().getDeclaredFields();
for (Field field : fields) {
if ("mPopup".equals(field.getName())) {
field.setAccessible(true);
Object menuPopupHelper = field.get(popupMenu);
Class<?> classPopupHelper = Class.forName(menuPopupHelper
.getClass().getName());
Method setForceIcons = classPopupHelper.getMethod(
"setForceShowIcon", boolean.class);
setForceIcons.invoke(menuPopupHelper, true);
break;
}
}
} catch (Throwable e) {
e.printStackTrace();
}
}
private RecyclerView.OnScrollListener paginationListener = new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
boolean hasEnded = newState == SCROLL_STATE_IDLE;
if (hasEnded) {
mFabMenu.show();
mFabMenu.setClickable(true);
} else {
if (mIsFabOpen)
closeMenu();
mFabMenu.hide();
mFabMenu.setClickable(false);
}
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int visibleItemCount = mLayoutManager.getChildCount();
int totalItemCount = mLayoutManager.getItemCount();
int firstVisibleItemPosition = mLayoutManager.findFirstVisibleItemPosition();
if (!mIsLoading && !mIsLastPage) {
if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount) {
loadMoreItems();
}
}
//Back to top
if (mLayoutManager.findLastVisibleItemPosition() == totalItemCount - 1) {
mBackToTop.setVisibility(View.VISIBLE);
mBackToTop.setClickable(true);
mBackToTop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mLayoutManager.scrollToPositionWithOffset(0,0);
}
});
} else {
mBackToTop.setVisibility(View.GONE);
mBackToTop.setClickable(false);
}
}
};
private void loadMoreItems() {
if (!isFlipped) {
mIsLoading = true;
loadData(false, 1);
} else {
mIsLoading = true;
loadData(false, -1);
}
}
private void refreshPosts(ArrayList<Posts> newObjects) {
postList.addAll(newObjects);
populateUIWithData();
}
#Override
public void onClick(View v) {
int id = v.getId();
switch (id) {
case R.id.fabMenu:
animateFAB();
break;
case R.id.shareFab:
share();
break;
case R.id.replyFab:
reply();
break;
case R.id.flipFab:
flip();
break;
}
}
public void animateFAB() {
if (mIsFabOpen) {
closeMenu();
} else {
mFabMenu.startAnimation(rotate_forward);
mReplyFab.startAnimation(fab_open);
mShareFab.startAnimation(fab_open);
mFlipFab.startAnimation(fab_open);
mReplyFab.setClickable(true);
mShareFab.setClickable(true);
mFlipFab.setClickable(true);
mFlipTextView.setVisibility(View.VISIBLE);
mShareTextView.setVisibility(View.VISIBLE);
mReplyTextView.setVisibility(View.VISIBLE);
mBackgroundView.setVisibility(View.VISIBLE);
mIsFabOpen = true;
}
}
private void closeMenu() {
mFabMenu.startAnimation(rotate_backward);
mReplyFab.startAnimation(fab_close);
mShareFab.startAnimation(fab_close);
mFlipFab.startAnimation(fab_close);
mReplyFab.setClickable(false);
mShareFab.setClickable(false);
mFlipFab.setClickable(false);
mFlipTextView.setVisibility(View.INVISIBLE);
mShareTextView.setVisibility(View.INVISIBLE);
mReplyTextView.setVisibility(View.INVISIBLE);
mBackgroundView.setVisibility(View.INVISIBLE);
mIsFabOpen = false;
}
private void reply() {
PreferenceConnector.writeString(getActivity().getApplicationContext(), "threadID", mThreads.getId());
PreferenceConnector.writeString(getActivity().getApplicationContext(), "threadTitle", mThreads.getName());
if (PreferenceConnector.readString(getActivity(), "authToken") == null ||
PreferenceConnector.readString(getActivity(), "authToken").equalsIgnoreCase("skip")) {
final AlertDialog.Builder loginDialog = new AlertDialog.Builder(getActivity());
loginDialog.setTitle("Please log in");
loginDialog.setMessage("You need to be logged in to reply");
loginDialog.setPositiveButton("Log in", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(getActivity().getApplicationContext(), LoginActivity.class);
startActivity(intent);
}
});
loginDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
loginDialog.show();
} else {
closeMenu();
Intent intent = new Intent(getActivity().getApplicationContext(), NewPostActivity.class);
intent.putExtra("Threads", Parcels.wrap(mThreads));
getActivity().finish();
startActivityForResult(intent, REQUEST_CODE);
}
}
private void share() {
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.putExtra(Intent.EXTRA_TEXT, mThreads.getName() + " - " + Constants.LIVE_URL +
"talk/" + mThreads.getTopic_url() + '/' + mThreads.getThread_url());
sharingIntent.setType("text/plain");
startActivity(Intent.createChooser(sharingIntent, "Share via"));
}
private void flip() {
if (!isFlipped) {
mAdapter.clearAll();
isFlipped = true;
mRecyclerView.startAnimation(flipAnimation);
loadData(false, -1);
closeMenu();
} else {
mAdapter.clearAll();
isFlipped = false;
mRecyclerView.startAnimation(flipAnimation);
loadData(true, 1);
closeMenu();
}
}
private void customToast(String toastMessage) {
LayoutInflater inflater = getActivity().getLayoutInflater();
View layout = inflater.inflate(R.layout.custom_toast,
(ViewGroup) getActivity().findViewById(R.id.toastContainer));
TextView customToastText = (TextView) layout.findViewById(R.id.customToastText);
customToastText.setText(toastMessage);
Toast toast = new Toast(getActivity().getApplicationContext());
toast.setGravity(Gravity.BOTTOM, 0, 25);
toast.setDuration(Toast.LENGTH_LONG);
toast.setView(layout);
toast.show();
}
#Override
public void onResume() {
super.onResume();
if (mData != null && mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
if (mIsFabOpen) {
closeMenu();
} else {
getActivity().finish();
}
return true;
}
return false;
}
});
}
public void updateView() {
mAdapter.notifyDataSetChanged();
}
}
Thanks in advance once again.
Your problem basically boils down to this:
private void refreshPosts(ArrayList<Posts> newObjects) {
postList.addAll(newObjects);
populateUIWithData();
}
The list can only get bigger, never smaller. If the server has lots and lots of posts, then OutOfMemory is pretty much inevitable.
One approach to solving this problem is to use an LRU (Least Recently Used) cache. There is a utility class you can use: android.util.LruCache.
An LRU Cache is essentially a Map. Items are stored with a key, like an ID. With an LRU cache, you put new items in, but once a pre-determined limit is reached, old items start getting pushed out to make room for new items.
This will save memory, but make a lot more management code for you.
Your adapter, instead of having a list of posts, will just have a list of the post IDs. This should be much easier on memory.
As the user scrolls and you collect more posts, you add the post ID to the list, and map the post into the LRU cache using the post ID.
When you bind to the list item view, you look up the post using the post's ID in the LRU cache.
If it's there, great. That's called a cache hit. Bind the post to the
list item view.
If not, then you have a cache miss. You have some work to do.
Start a server request to retrieve the post by ID. I see your current code just retrieves blocks of posts, so you'll need some new server code here.
When the request completes, put the post in the LRU cache and let the adapter know your item has changed using adapter.notifyItemChanged(). Unless the user has scrolled beyond it, the RecyclerView should try to bind with the list item view again. This time, you should get a cache hit.
This is the basic idea. I'd write some code, but I still have a lot of questions since I can't see your model classes, data factories, and adapter class.
Once you have it working, you have to tune the limit on the cache so that it's low enough not to overrun memory, but high enough that your hit/miss ratio isn't close to zero.
BTW, I noticed that you are making the mistake of creating a new adapter and handing it to the RecyclerView each time you get a block of posts. You should create your adapter once, keep a reference to it and update it. Have a method that adds a block of posts then calls notifyDataSetChanged().
Another idea for conserving memory is to use text compression. If the problem is more a result of a large average size of the post rather than a large number of posts, you might explore this idea in addition to the LRU cache.
The concept is that you could take posts over a certain size, write them into a buffer using a ZipOutputStream then save the buffer in memory. When it's time to display the post, you read the buffer with a ZipInputStream to uncompress the text. Here the issue is performance as the compression/decompression is pretty CPU-intensive. But if the problem is really long posts, this approach might be something to consider.
An even better approach: Only save the first part of the post as an "overview" display in the list. When the user clicks on the list item, retrieve the entire post from the server and display that in another page.
i have designed app where i have used mulitiselectgridview for image selection.my requirement is i want to restrict user to select max 8 images, means whenever a user try to chek on the 9th element it should display a warning message as popup i.e max 8 images can be selected and that 9th images should be autometically unchecked.
public class MultiImagePicActivity extends Activity {
GridView mGrid;
private String[] arrPath,modifiedArrayPath;
private int ids[];
private int count;
int selectCount;
Activity act=this;
List<String> imagepaths;
int maximageselection;
//int sel=0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//now get Intent Extras
imagepaths=new ArrayList<String>();
imagepaths.clear();
loadApps();
setContentView(R.layout.grid_1);
mGrid = (GridView) findViewById(R.id.myGrid);
mGrid.setAdapter(new ImageAdapterxtends());
mGrid.setChoiceMode(GridView.CHOICE_MODE_MULTIPLE_MODAL);
mGrid.setMultiChoiceModeListener(new MultiChoiceModeListener());
}
private void loadApps() {
final String[] columns = { MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID };
final String orderBy = MediaStore.Images.Media._ID;
Cursor imagecursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, null, null, orderBy);
int image_column_index = imagecursor.getColumnIndex(MediaStore.Images.Media._ID);
this.count = imagecursor.getCount();
this.arrPath = new String[this.count];
ids = new int[count];
for (int i = 0; i <this.count; i++) {
imagecursor.moveToPosition(i);
ids[i] = imagecursor.getInt(image_column_index);
int dataColumnIndex = imagecursor.getColumnIndex(MediaStore.Images.Media.DATA);
arrPath[i] = imagecursor.getString(dataColumnIndex);
}
imagecursor.close();
}
#Override
public void onBackPressed() {
setResult(Activity.RESULT_CANCELED);
super.onBackPressed();
}
public class ImageAdapterxtends extends BaseAdapter{
CheckableLayout l;
ImageView i;
#Override
public int getCount() {
// TODO Auto-generated method stub
return arrPath.length;
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return arrPath[position];
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
if (convertView == null) {
i = new ImageView(MultiImagePicActivity.this);
i.setScaleType(ImageView.ScaleType.FIT_CENTER);
i.setLayoutParams(new ViewGroup.LayoutParams(50, 50));
l = new CheckableLayout(MultiImagePicActivity.this);
l.setLayoutParams(new GridView.LayoutParams(
GridView.LayoutParams.WRAP_CONTENT,
GridView.LayoutParams.WRAP_CONTENT));
l.addView(i);
} else {
l = (CheckableLayout) convertView;
i = (ImageView) l.getChildAt(0);
}
// Bitmap bmp = Utility.getResizedBitmap(BitmapFactory.decodeFile(arrPath[position]), 50, 50);
// i.setImageBitmap(bmp);
try {
setBitmap(i, ids[position]);
} catch (Throwable e) {
}
return l;
}
}
private void setBitmap(final ImageView iv,final int id) {
new AsyncTask<Void, Void, Bitmap>() {
Bitmap myBitmap;
#Override
protected Bitmap doInBackground(Void... params) {
return MediaStore.Images.Thumbnails.getThumbnail(getApplicationContext().getContentResolver(), id, MediaStore.Images.Thumbnails.MICRO_KIND, null);
}
#Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
//iv.setImageBitmap(result);
setMyBitmap(result);
}
public final void setMyBitmap(Bitmap bitmap) {
if (this.myBitmap != null) {
this.myBitmap.recycle();
}
this.myBitmap = bitmap;
iv.getLayoutParams().height = 100;
iv.getLayoutParams().width = 100;
iv.setImageBitmap(myBitmap);
}
}.execute();
}
public class CheckableLayout extends FrameLayout implements Checkable {
private boolean mChecked;
public CheckableLayout(Context context) {
super(context);
}
public void setChecked(boolean checked) {
mChecked = checked;
setForeground(checked ? getResources().getDrawable(R.drawable.tr) : null);
}
public boolean isChecked() {
return mChecked;
}
public void toggle() {
//sel--;
selectCount--;
setChecked(!mChecked);
}
}
public class MultiChoiceModeListener implements
GridView.MultiChoiceModeListener {
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate the menu for the CAB
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
//return true;
mode.setTitle("Select Items");
mode.setSubtitle("One item selected");
return true;
}
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return true;
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
// Respond to clicks on the actions in the CAB
switch (item.getItemId()) {
case R.id.menu_ok:
Intent i = new Intent();
modifiedArrayPath=imagepaths.toArray(new String[imagepaths.size()]);
i.putExtra("selectedImagepath", modifiedArrayPath);
//i.putExtra("data", selectedPath);
setResult(Activity.RESULT_OK, i);
//Toast.makeText(getApplicationContext(),String.valueOf(a),Toast.LENGTH_LONG).show();
//TODO do your stuff here
//mode.finish(); // Action picked, so close the CAB
act.finish();
return true;
default:
return false;
}
}
public void onDestroyActionMode(ActionMode mode) {
Toast.makeText(getApplicationContext(), "text", 1);
}
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) {
selectCount = mGrid.getCheckedItemCount();
if(checked){
imagepaths.add(arrPath[position]);
if(selectCount>8){
imagepaths.remove(arrPath[position]);
new AlertDialog.Builder(MultiImagePicActivity.this)
.setTitle("Restriction")
.setMessage("Max 8 images are allowed!!!")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// continue with delete
//finish();
dialog.dismiss();
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
selectCount=maximageselection;
}
switch (selectCount) {
case 1:
mode.setSubtitle("One item selected");
break;
default:
mode.setSubtitle("" + selectCount + " items selected");
break;
}
}
else
imagepaths.remove(arrPath[position]);
}
}
}