Dynamic ListView issue on Android - android

Currently I am working on an Android app and use parse as backend where I have created a ListView of nearby places dynamically. But I face the following design issue: When the user clicks on a place, a view must appear under the clicked item.
And I have faced a problem with grouping the place, as you can see in figure 1, there are many branches for HSBC bank. In which case they are under HSBC.
I have tried expandable ListView before, but it does not give much customization for child view , just simple one.
my BaseAdapter:
import java.util.ArrayList;
import java.util.List;
import com.parse.ParseGeoPoint;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewManager;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public class ListViewAdapter extends BaseAdapter {
// Declare Variables
Context context;
LayoutInflater inflater;
//ImageLoader imageLoader;
private List<AnywallPost> AnywallPostlist = null;
private ArrayList<AnywallPost> arraylist;
public ListViewAdapter(Context context,
List<AnywallPost> AnywallPostlist) {
this.context = context;
this.AnywallPostlist = AnywallPostlist;
inflater = LayoutInflater.from(context);
this.arraylist = new ArrayList<AnywallPost>();
this.arraylist.addAll(AnywallPostlist);
}
public class ViewHolder {
TextView distance;
TextView name;
}
#Override
public int getCount() {
return AnywallPostlist.size();
}
#Override
public Object getItem(int position) {
return AnywallPostlist.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public View getView(final int position, View view, ViewGroup parent) {
final ViewHolder holder;
final View row=view;
if (view == null) {
holder = new ViewHolder();
view = inflater.inflate(R.layout.user_custom, null);
// Locate the TextViews in listview_item.xml
holder.distance = (TextView) view.findViewById(R.id.disView);
holder.name = (TextView) view.findViewById(R.id.nameView);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
// Set the results into TextViews
holder.name.setText(AnywallPostlist.get(position).getText());
holder.distance.setText(AnywallPostlist.get(position).getDis());
//Listen for ListView Item Click
view.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Toast.makeText(context,AnywallPostlist.get(position).getText(), Toast.LENGTH_LONG).show();
}
});
return view;
}
}
.
import com.parse.ParseClassName;
import com.parse.ParseGeoPoint;
import com.parse.ParseObject;
import com.parse.ParseQuery;
import com.parse.ParseUser;
/**
* Data model for a post.
*/
#ParseClassName("places")
public class AnywallPost extends ParseObject {
public String getText() {
return getString("text");
}
public void setText(String value) {
put("text", value);
}
public String getBank() {
return getString("bank");
}
public void setBank(String value) {
put("bank", value);
}
public ParseUser getUser() {
return getParseUser("user");
}
public void setUser(ParseUser value) {
put("user", value);
}
public String getType()
{
return getString("type");
}
public void setType(String value)
{
put("type",value);
}
public ParseGeoPoint getLocation() {
return getParseGeoPoint("location");
}
public void setLocation(ParseGeoPoint value) {
put("location", value);
}
public String getDis()
{
return getString("dis");
}
public void setdis(String value)
{
put("dis",value);
}
public static ParseQuery<AnywallPost> getQuery() {
return ParseQuery.getQuery(AnywallPost.class);
}
}
.
switch (getItemViewType(position)) {
case 0:
Bank bank = (Bank) getItem(position);
holder.name.setText(bank.name);
String str = String.valueOf(bank.numBranches);
holder.cn.setText(str);
imageLoader.DisplayImage(bank.image,
holder.logo);
Toast.makeText(getActivity(), "img"+bank.image,Toast.LENGTH_LONG).show();
// ... set the image here
// ... set the number of branches here
break;
case 1:
branch = (AnywallPost) getItem(position);
holder.name.setText(branch.getText());
holder.distance.setText(branch.getDis());
holder.b.setText(branch.getbranch());
imageLoader.DisplayImage(branch.getimg(),
holder.logo);
break;
case 2:
branch = (AnywallPost) getItem(position);
holder.name.setText(branch.getText());
holder.distance.setText(branch.getDis());
holder.b.setText(branch.getbranch());
imageLoader.DisplayImage(branch.getimg(),
holder.logo);
// ... set values for all the expanded view widgets too
break;
}
I have used this code to get image from parse and I add it to AnywallPost
ParseFile image = (ParseFile) country.get("image");
AnywallPost map = new AnywallPost();
map.setimg(image.getUrl());
then, I used this code to load the image and it worked fine
imageLoader.DisplayImage(AnywallPostlist.get(position).getimg(),
holder.logo);

Here is my idea:
You will have two layouts, a brief one with the name & distance, and an expanded one with the name & distance plus all the details.
The brief layout will have a view type of 0, and the expanded layout will have a view type of 1.
When you click on the item, you set a flag in the list model to indicate that the view has switched from brief view to long view. So you should see the view switch. If you click on an expanded view, it will revert to brief view.
I don't have a way to test this, but here is how I think the code will look:
public class ListViewAdapter extends BaseAdapter {
// Declare Variables
Context context;
LayoutInflater inflater;
//ImageLoader imageLoader;
private List<AnywallPost> AnywallPostlist = null;
private ArrayList<AnywallPost> arraylist;
/** this array holds a flag for each item to show if it is in brief view more or expanded view mode*/
private boolean[] expandedView;
public ListViewAdapter(Context context,
List<AnywallPost> AnywallPostlist) {
this.context = context;
this.AnywallPostlist = AnywallPostlist;
inflater = LayoutInflater.from(context);
this.arraylist = new ArrayList<AnywallPost>();
this.arraylist.addAll(AnywallPostlist);
this.expandedView = new boolean[AnywallPostlist.size()];
}
public class ViewHolder {
TextView distance;
TextView name;
// ... add all your expanded view fields here too
}
#Override
public int getCount() {
return AnywallPostlist.size();
}
#Override
public int getViewTypeCount() {
return 2; // brief & expanded
}
#Override
public int getItemViewType(int position) {
return expandedView[position] ? 1 : 0;
}
#Override
public Object getItem(int position) {
return AnywallPostlist.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public View getView(final int position, View view, ViewGroup parent) {
final ViewHolder holder;
final View row=view;
if (view == null) {
holder = new ViewHolder();
int layout = expandedView[position] ? R.layout.user_custom_expanded : R.layout.user_custom;
view = inflater.inflate(layout, parent, false);
// Locate the TextViews in listview_item.xml
holder.distance = (TextView) view.findViewById(R.id.disView);
holder.name = (TextView) view.findViewById(R.id.nameView);
if (expandedView[position]) {
// ... locate all the expanded view widgets too
}
view.setTag(holder);
} else {
// because the view type is determined by expandedView[position], the correct layout will be recycled here
holder = (ViewHolder) view.getTag();
}
// Set the results into TextViews
holder.name.setText(AnywallPostlist.get(position).getText());
holder.distance.setText(AnywallPostlist.get(position).getDis());
if (expandedView[position]) {
// ... set all the values for your expanded view too
}
//Listen for ListView Item Click
view.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
if (expandedView[position]) {
// this is expanded view so toggle it back to brief view
expandedView[position] = false;
} else {
// clear any expanded views elsewhere
expandedView = new boolean[AnywallPostlist.size()];
// toggle brief view to expanded
expandedView[position] = true;
}
// forces the ListView to refresh and convert the brief view into an expanded view and vice versa.
ListViewAdapter.this.notifyDataSetChanged();
// Toast.makeText(context,AnywallPostlist.get(position).getText(), Toast.LENGTH_LONG).show();
}
});
if (expandedView[position]) {
// ... add all your event listeners for the expanded view widgets
}
return view;
}
}
You can also add a toggle button with expand/collapse indicator to the view to control the expand/collapse so you don't click anywhere on the view to change it.
You can do this with an ExpandableListView if you want, you just need to change to an ExpandableListAdapter and do your layouts a little differently.

Here is some code to make a heterogeneous list:
Take a really good look at the constructor to see how I divided up the branches by bank them strung them all together into one big list.
The list is just an Object array, so you figure out what the item is like this:
If it's a Bank, then well, it's a bank.
If it's an AnywallPost and expandedView[position] == false then it's a branch, brief view
If it's an AnywallPost and expandedView[position] == true then it's a branch, expanded view
public class Bank {
private String name;
private String image; // maybe this needs to be URL?
private int numBranches;
}
public class ListViewAdapter extends BaseAdapter {
// Declare Variables
Context context;
LayoutInflater inflater;
ImageLoader imageLoader;
private Object[] masterList;
/** this array holds a flag for each item to show if it is in brief view more or expanded view mode*/
private boolean[] expandedView;
public ListViewAdapter(Context context,
List<AnywallPost> AnywallPostlist) {
this.context = context;
inflater = LayoutInflater.from(context);
/*
* Phase I -- get list of banks and organize the branches by bank
*/
int count = 0;
List<String bankNames = new ArrayList<String>();
List<Bank> banks = new ArrayList<Bank>();
Map<String, Bank> bankMap = new HashMap<String, Bank>();
Map<String, List<AnywallPost>> mappedBranches = new HashMap<String, List<AnywallPost>>();
Bank bank = null;
List<AnywallPost> branches = null;
for (AnywallPost branch : AnywallPostlist) {
// have we started a branch list for this bank?
if (! bankNames.contains(branch.getBank())) { // no we haven't
// remember the bank name
bankNames.add(branch.getBank());
// init a new Bank
bank = new Bank();
bank.name = branch.getBank();
bank.image = branch.getImg(); // if this is URL make image in Bank a URL
banks.add(bank);
bankMap.put(bank.name, bank);
count++;
// create a list for this bank's branches and index it by bank
branches = new ArrayList<AnywallPost>();
mappedBranches.put(branch.getBank(), branches);
} else { // yes we have
// get the bank for this name
// this fixes the problem with the branch counts
bank = bankMap.get(branch.getBank());
// get the branch list we already created for this bank
branches = mappedBranches.get(branch.getBank());
}
// remember the branch for this bank
branches.add(branch);
count++;
// increment the number of branches for this bank
bank.numBranches++;
}
/*
* Phase II -- sort the banks and branches
*/
// ... here you can order the banks by name, branches by distance, etc.
/*
* Phase III -- create the mixed list
*/
int index = 0;
masterList = new Object[count];
for (Bank bank : banks) {
// append a bank to the list
masterList[index] = bank;
index++;
for (AnywallPost branch : mappedBranches.get(bank.name)) {
// append a branch to the list
masterList[index] = branch;
index++;
}
}
this.expandedView = new boolean[count];
}
public class ViewHolder {
TextView distance;
TextView name;
ImageView logo;
// ... add all your expanded view fields here too
}
#Override
public int getCount() {
return masterList.length;
}
#Override
public int getViewTypeCount() {
return 4; // bank brief, bank expanded, branch brief & branch expanded
}
#Override
public Object getItem(int position) {
return masterList[position];
}
#Override
public int getItemViewType(int position) {
if (getItem(position) instanceof Bank) {
return expandedView[position] ? 1 : 0;
}
return expandedView[position] ? 3 : 2;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View view, ViewGroup parent) {
final ViewHolder holder;
final View row=view;
if (view == null) {
holder = new ViewHolder();
int layout = 0;
switch (getItemViewType(position)) {
case 0:
layout = R.layout.bank_brief;
break;
case 1:
layout = R.layout.bank_expanded;
break;
case 2:
layout = R.layout.branch_brief;
break;
case 3:
layout = R.layout.branch_expanded;
break;
}
view = inflater.inflate(layout, parent, false);
switch (getItemViewType(position)) {
case 0:
holder.name = (TextView) view.findViewById(R.id.nameView);
break;
case 1:
holder.name = (TextView) view.findViewById(R.id.nameView);
// ... locate all the bank expanded view widgets too
break;
case 2:
holder.name = (TextView) view.findViewById(R.id.nameView);
holder.distance = (TextView) view.findViewById(R.id.disView);
break;
case 3:
holder.name = (TextView) view.findViewById(R.id.nameView);
holder.distance = (TextView) view.findViewById(R.id.disView);
// ... locate all the expanded view widgets too
break;
}
view.setTag(holder);
} else {
// because the view type is determined by expandedView[position], the correct layout will be recycled here
holder = (ViewHolder) view.getTag();
}
AnywallPost branch = null;
switch (getItemViewType(position)) {
case 0:
Bank bank = (Bank) getItem(position);
holder.name.setText(bank.name);
imageLoader.DisplayImage(bank.image, holder.logo);
// ... set the number of branches here
break;
case 1:
holder.name.setText(bank.name);
imageLoader.DisplayImage(bank.image, holder.logo);
// ... set the number of branches here
break;
case 1:
branch = (AnywallPost) getItem(position);
holder.name.setText(branch.getText());
holder.distance.setText(branch.getDis());
break;
case 2:
branch = (AnywallPost) getItem(position);
holder.name.setText(branch.getText());
holder.distance.setText(branch.getDis());
// ... set values for all the expanded view widgets too
break;
}
//Listen for ListView Item Click
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
if (expandedView[position]) {
// this is expanded view so toggle it back to brief view
expandedView[position] = false;
} else {
// clear any expanded views elsewhere
expandedView = new boolean[expandedView.length];
// toggle brief view to expanded
expandedView[position] = true;
}
if (getItem(position) instanceof AnywallPost) { // only for branches
// AnywallPost branch = (AnywallPost) getItem(position);
// Toast.makeText(context, branch.getText(), Toast.LENGTH_LONG).show();
}
// forces the ListView to refresh and convert the brief view into an expanded view and vice versa.
notifyDataSetChanged();
}
});
if (expandedView[position]) {
// ... add all your event listeners for the expanded view widgets
}
return view;
}
}

Related

Updating ListView after selecting Item from Dialog Window

I've got the following Problem.
I have a ListView which displays me Articles with different Categories.
When I select a Category from my Dialog Window and press the PositiveButton "OK", I want to update my ListView, that it now lists only the Articles from the Category, selected in the Dialog Window.
I created an interface in the DialogFragment, which is a callback to get value from the Dialog.
This is the Class:
public class SelectFilterDialog extends DialogFragment implements DialogInterface.OnClickListener{
private static int mSelectedIndex;
private static String mSelectedCategory;
private String[] categories = {"All", "Announcements","Commerce","Development", "Distributions", "Front","Kernel","Legal", "Letters", "Press", "Security"};
static OnDialogSelectListener mDialogSelectorCallback;
//callback method to get values from a Dialog
public interface OnDialogSelectListener{
public void onSelectedOption();
}
public static SelectFilterDialog newInstance(int selected) {
final SelectFilterDialog dialog = new SelectFilterDialog();
mSelectedIndex = selected;
return dialog;
}
public Dialog onCreateDialog(Bundle savedInstanceState) {
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Select Filter");
builder.setPositiveButton("OK", this);
builder.setNegativeButton("Cancel", this);
builder.setSingleChoiceItems(categories, mSelectedIndex, this);
return builder.create();
}
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which){
case Dialog.BUTTON_POSITIVE:{
dialog.dismiss();
mDialogSelectorCallback.onSelectedOption();
}break;
case Dialog.BUTTON_NEGATIVE:{
dialog.cancel();
}break;
default:
mSelectedIndex = which;
setSelectedCategory(categories[which]);
break;
}
}
public void setDialogSelectListener(OnDialogSelectListener listener){
this.mDialogSelectorCallback = listener;
}
public void setSelectedCategory(String category){
this.mSelectedCategory = category;
}
public static String getSelectedCategory(){
return mSelectedCategory;
}
public static int getSelectedIndex(){
return mSelectedIndex;
}
}
In my SearchFragment Class , i show the List and implement the Interface from the SelectFilterDialog Fragment.
In the Method, i update the selectedCategory, after pressing the OK button, and then update the adapter with notifyDataSetChanged()
SearchFragment:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_bar_filter: {
showDialog();
}
}
return super.onOptionsItemSelected(item);
}
void showDialog() {
SelectFilterDialog dialog = SelectFilterDialog.newInstance(preSelectedValue);
dialog.setDialogSelectListener(this);
dialog.show(getActivity().getFragmentManager(), "dialog");
}
#Override
public void onSelectedOption() {
selectedCategory = dialog.getSelectedCategory();
preSelectedValue = dialog.getSelectedIndex();
Log.i(TAG, "selectedCategory : " +selectedCategory);
article_list_adapter.updateCategory(selectedCategory);
}
In my Adapter, i receive the Category in my updateCategory and fill the currentArticle List with the Articles with the correct Category.
This works fine.
After that i call NotifyDataSetChanged to update the view.
public void updateCategory(String category) {
this.currentArticles.clear();
this.selectedCategory = category;
for (Article article : entireArticles) {
if (category.equals(article.getCategory())) {
currentArticles.add(article);
}
}
notifyDataSetChanged();
}
notifyDataSetChanged();
}
But in the getView it throws an IndexOutOfBounce exception.
After selecting a Category from the dialog, e.g "Kernel", it adds only my 3 Kernel Categories to the currentArticle List, which is fine.
But int the getView statement:
Article currentArticle = currentArticles.get(_position);
It points on index 3 , though there are only 3 elements in the list.
java.lang.IndexOutOfBoundsException: Invalid index 3, size is 3
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at klinar.kronlachner.binder.app.Article_List_Adapter.getView(Article_List_Adapter.java:99)
Can you help me ? :)
public Article_List_Adapter(Context _c, int textViewResourceId, List<Article> articles) {
super(_c, textViewResourceId, articles);
this.entireArticles = new ArrayList<Article>();
this.currentArticles = new ArrayList<Article>();
entireArticles.addAll(articles);
currentArticles.addAll(articles);
this.storedArticles = new ArrayList<Article>(articles);
}
public View getView(int _position, View _convertView, ViewGroup _parent) {
View view = _convertView;
ViewHolder viewHolder;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.article_list_row, null);
viewHolder = new ViewHolder();
viewHolder.article_icon = (ImageView) view.findViewById(R.id.article_category_icon);
viewHolder.articleTitle = (TextView) view.findViewById(R.id.article_title);
viewHolder.articleCategory = (TextView) view.findViewById(R.id.article_category);
viewHolder.articleDate = (TextView) view.findViewById(R.id.article_date);
viewHolder.articleAuthor = (TextView) view.findViewById(R.id.article_author);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) _convertView.getTag();
}
//Find the article to work with
Article currentArticle = currentArticles.get(_position);
//fill the Article_View
switch (currentArticle.getCategory()) {
case "Kernel": {
viewHolder.article_icon.setImageResource(R.drawable.ic_list_letter_k);
}
break;
case "Security": {
viewHolder.article_icon.setImageResource(R.drawable.ic_list_letter_s);
}
break;
default: {
viewHolder.article_icon.setImageResource(R.drawable.ic_list_letter_s);
}
}
viewHolder.articleTitle.setText(currentArticle.getTitle());
viewHolder.articleCategory.setText(currentArticle.getCategory());
viewHolder.articleDate.setText(currentArticle.getDate());
viewHolder.articleAuthor.setText(currentArticle.getAuthor());
return view;
Do this in your adapter class
create two List one for AllCategoryArticle and another for currentCategoryArticle.
class ArticleAdapter{
ArrayList<Model> currentArticle;
ArrayList<Model> entireArticle;
String selectedCategory="all"; //setting default category as "all"
public ArticleAdapter(ArrayList<Model> categoryList){
this.entireList=categoryList;
this.currentList=this.entireList;
}
//create updateCategory in adapter
/*call this method(updateCategory()) in you frgament/activity to update the adapter
according to you category that is selected in dialog
*/
public void updateCategory(String category){
this.currentArticle.clear();
this.selectedCategory=category;
for(Model item: entireArticle){
if(category.equals(item.getCategory()))
{
currentArticle.add(item);
}
}
notifyDataSetChanged();
}
........
........
#Override
public View getView(int _position, View _convertView, ViewGroup _parent) {
View view = _convertView;
ViewHolder viewHolder;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.article_list_row, null);
viewHolder = new ViewHolder();
viewHolder.article_icon = (ImageView) view.findViewById(R.id.article_category_icon);
viewHolder.articleTitle = (TextView) view.findViewById(R.id.article_title);
viewHolder.articleCategory = (TextView) view.findViewById(R.id.article_category);
viewHolder.articleDate = (TextView) view.findViewById(R.id.article_date);
viewHolder.articleAuthor = (TextView) view.findViewById(R.id.article_author);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) _convertView.getTag();
}
//Find the article to work with
Article currentArticle = articles.get(_position);
//just remove if condition because already you have filtered article by category in currentArticle
//fill the Article_View
switch (currentArticle.getCategory()) {
case "Kernel":
viewHolder.article_icon.setImageResource(R.drawable.ic_list_letter_k);
break;
case "Security":
viewHolder.article_icon.setImageResource(R.drawable.ic_list_letter_s);
break;
default:
viewHolder.article_icon.setImageResource(R.drawable.ic_list_letter_s);
}
viewHolder.articleTitle.setText(currentArticle.getTitle());
viewHolder.articleCategory.setText(currentArticle.getCategory());
viewHolder.articleDate.setText(currentArticle.getDate());
viewHolder.articleAuthor.setText(currentArticle.getAuthor());
return view;
}
}
Do this in your Activity/Fragment which has tha ArticleAdapter
modification in onSelectedOption() method in your activity/Fragment
#Override
public void onSelectedOption() {
selectedCategory = dialog.getSelectedCategory();
preSelectedValue = dialog.getSelectedIndex();
Log.i(TAG, "selectedCategory : " +selectedCategory);
article_list_adapter.updateSelectedCategory(selectedCategory);
Log.i(TAG, "adapter Category : " +article_list_adapter.getSelectedCategory());
/*
call updateCategory() instead of notifyDataSetChanged()
updateCategory() will update your adapter
*/
//article_list_adapter.notifyDataSetChanged();
article_list_adapter.updateCategory(selectedCategory);
}
Problem in your code is
your trying to update the adapter using notifyDataSetChanged without updating your list.
notifyDataSetChanged() will work when there is an update in adapter model not in any variable in your adapter . see this how notifyDataSetChanged works in listView
EDIT:changes in adapter class
class Adapter{
ArrayList entireArticle;
ArrayList currentArticle;
public Adapter(Context context,ArrayList list){
this.entireArticle=new ArrayList();
this.currentArticle=new ArrayList();
entireArticle.addAll(list);
currentArticle.addAll(list);
}
public void updateCategory(String category){
this.currentArticle.clear();
this.selectedCategory=category;
if(category.equals("All")){ // add all article from entrieArticle if category=="all"
this.currentArticle.addAll(entireArticle);
}else{ //otherwise filter the article
for(Model item: entireArticle){
if(category.equals(item.getCategory()))
{
currentArticle.add(item);
}
}
}
notifyDataSetChanged();
}
...............
.................
}
do this changes in your adapter class and it will work i've checked this.
I hope this will help you.

Android Recycler layouts not inflating properly why

I use an android recyclerview to inflate three layouts as shown in my code but the footer is not being inflated properly hence hides some data of the listview layout. Where is the problem with my code since I want the listview layout to be displayed as the last layout in the recyclerview adapter.
package com.news254.inception.newsapp;
import android.content.Intent;
import android.content.res.Configuration;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
public class Newspaper extends AppCompatActivity {
Toolbar mtoolbar;
String TITLES[] = {"Newspaper","Gossip","Entertainment","Sports","International","About","Exit"};
int ICONS[] = {R.drawable.newspaper,R.drawable.gossip,R.drawable.entertainment,R.drawable.sports,R.drawable.international,R.drawable.about,R.drawable.exit};
//Similarly we Create a String Resource for the name and email in the header
view
//And we also create a int resource for profile picture in the header view
Boolean isDrawerOpen =true;
private Toolbar toolbar; // Declaring the
Toolbar Object
RecyclerView mRecyclerView; // Declaring
RecyclerView
RecyclerView.Adapter mAdapter; // Declaring Adapter
For Recycler View
RecyclerView.LayoutManager mLayoutManager; // Declaring Layout
Manager as a linear layout manager
DrawerLayout Drawer; // Declaring
DrawerLayout
ActionBarDrawerToggle mDrawerToggle;
ImageView
Nation,Standard,Capital,Nairobian,BusinessDaily,EastAfrican,Star,Mwakilishi,Citizen;
String nation = "http://www.nation.co.ke";
String standard = "http://www.standardmedia.co.ke";
String star = "http://www.the-star.co.ke";
String nairobian = "http://www.sde.co.ke/m/thenairobian";
String eastafrican = "http://www.theeastafrican.co.ke";
String businessdaily = "http://www.businessdailyafrica.com";
String mwakilishi = "http://www.mwakilishi.com";
String capital = "http://www.capitalfm.co.ke";
String citizen = "http://www.theweeklycitizen.co.ke";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_news);
mtoolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mtoolbar);
mRecyclerView = (RecyclerView) findViewById(R.id.RecyclerView); // Assigning the RecyclerView Object to the xml View
mRecyclerView.setHasFixedSize(true); // Letting the system know that the list objects are of fixed size
mAdapter = new MyAdapter(TITLES,ICONS); // Creating the Adapter of MyAdapter class(which we are going to see in a bit)
// And passing the titles,icons,header view name, header view email,
// and header view profile picture
mRecyclerView.setAdapter(mAdapter); // Setting the adapter to RecyclerView
mLayoutManager = new LinearLayoutManager(this); // Creating a layout Manager
mRecyclerView.setLayoutManager(mLayoutManager); // Setting the layout Manager
Nation = (ImageView) findViewById(R.id.nation);
Nation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent p = new Intent(Newspaper.this,Browser.class);
p.putExtra("site",nation);
startActivity(p);
}
});
Standard = (ImageView) findViewById(R.id.standard);
Standard.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent p = new Intent(Newspaper.this,Browser.class);
p.putExtra("site",standard);
startActivity(p);
}
});
Star = (ImageView) findViewById(R.id.star);
Star.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent p = new Intent(Newspaper.this,Entertainment.class);
p.putExtra("site",star);
startActivity(p);
}
});
Capital = (ImageView) findViewById(R.id.capital);
Capital.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent p = new Intent(Newspaper.this,Browser.class);
p.putExtra("site",capital);
startActivity(p);
}
});
Nairobian = (ImageView) findViewById(R.id.nairobian);
Nairobian.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent p = new Intent(Newspaper.this,Browser.class);
p.putExtra("site",nairobian);
startActivity(p);
}
});
Citizen = (ImageView) findViewById(R.id.citizen);
Citizen.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent p = new Intent(Newspaper.this,Browser.class);
p.putExtra("site",citizen);
startActivity(p);
}
});
EastAfrican = (ImageView) findViewById(R.id.eastafrican);
EastAfrican.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent p = new Intent(Newspaper.this,Browser.class);
p.putExtra("site",eastafrican);
startActivity(p);
}
});
BusinessDaily = (ImageView) findViewById(R.id.businessdaily);
BusinessDaily.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent p = new Intent(Newspaper.this,Browser.class);
p.putExtra("site",businessdaily);
startActivity(p);
}
});
Mwakilishi = (ImageView) findViewById(R.id.mwakilishi);
Mwakilishi.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent p = new Intent(Newspaper.this,Browser.class);
p.putExtra("site",mwakilishi);
startActivity(p);
}
});
Drawer = (DrawerLayout) findViewById(R.id.DrawerLayout); // Drawer object Assigned to the view
mDrawerToggle = new ActionBarDrawerToggle(this,Drawer,toolbar,R.string.drawer_open,R.string.drawer_close){
#Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
// code here will execute once the drawer is opened( As I dont want anything happened whe drawer is
// open I am not going to put anything here)
}
#Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
// Code here will execute once drawer is closed
}
/* #Override
public void onDrawerSlide(View drawerView, float slideOffset) {
if(slideOffset >.55 && !isDrawerOpen)
{
onDrawerOpened(drawerView);
isDrawerOpen=true;
}
else if (slideOffset <.45 && isDrawerOpen)
{
onDrawerClosed(drawerView);
isDrawerOpen = false;
}
// super.onDrawerSlide(drawerView, slideOffset);
}*/
}; // Drawer Toggle Object Made
Drawer.setDrawerListener(mDrawerToggle);
// / Drawer Listener set to the Drawer toggle
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mDrawerToggle.setDrawerIndicatorEnabled(true);
}
#Override
public void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_news, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if(mDrawerToggle.onOptionsItemSelected(item))
{
return true;
}
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
} }
package com.news254.inception.newsapp;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
/**
* Created by hp1 on 28-12-2014.
*/
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private static final int TYPE_FOOTER = 2; // Declaring Variable to
Understand which View is being worked on
// IF the view under inflation and population is header or Item
private static final int TYPE_ITEM = 1;
private static final int TYPE_HEADER= 0;
private String mNavTitles[]; // String Array to store the passed titles
Value from MainActivity.java
private int mIcons[]; // Int Array to store the passed icons
resource value from MainActivity.java
private int mfooter[];
private String mtitleFoot[];
int Holderid;
// Creating a ViewHolder which extends the RecyclerView View Holder
// ViewHolder are used to to store the inflated views in order to
recycle them
public static class ViewHolder extends RecyclerView.ViewHolder {
int Holderid;
TextView textView;
ImageView imageView;
ImageView about;
TextView name;
public ViewHolder(View itemView,int ViewType) { // Creating ViewHolder Constructor with View and viewType As a parameter
super(itemView);
// Here we set the appropriate view in accordance with the the view type as passed when the holder object is created
if(ViewType == TYPE_ITEM) {
textView = (TextView) itemView.findViewById(R.id.rowText); // Creating TextView object with the id of textView from item_row.xml
imageView = (ImageView) itemView.findViewById(R.id.rowIcon);// Creating ImageView object with the id of ImageView from item_row.xml
Holderid = 1; // setting holder id as 1 as the object being populated are of type item row
}
else if(ViewType == TYPE_FOOTER){
about = (ImageView) itemView.findViewById(R.id.image); // Creating Text View object from header.xml for name
name = (TextView) itemView.findViewById(R.id.text); // Creating Text View object from header.xml for email
// Creating Image view object from header.xml for profile pic
Holderid =2; // Setting holder id = 0 as the object being populated are of type header view
}
else if(ViewType == TYPE_HEADER)
{
Holderid =0;
}
}
}
MyAdapter(String Titles[],int Icons[]){ // MyAdapter Constructor
with titles and icons parameter
// titles, icons, name, email, profile pic are passed from the
main activity as we
mNavTitles = Titles; //have seen earlier
mIcons = Icons;
//here we assign those passed values to the values
we declared here
//in adapter
}
//Below first we ovverride the method onCreateViewHolder which is called when
the ViewHolder is
//Created, In this method we inflate the item_row.xml layout if the
viewType is Type_ITEM or else we inflate header.xml
// if the viewType is TYPE_HEADER
// and pass it to the view holder
#Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int
viewType) {
if (viewType == TYPE_ITEM) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.listview,parent,false); //Inflating the layout
ViewHolder vhItem = new ViewHolder(v,viewType); //Creating ViewHolder and passing the object of type view
return vhItem; // Returning the created object
//inflate your layout and pass it to view holder
}
else if (viewType == TYPE_HEADER) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.header, parent, false); //Inflating the layout
ViewHolder vhHeader = new ViewHolder(v, viewType); //Creating ViewHolder and passing the object of type view
return vhHeader; //returning the object created
}
else if (viewType == TYPE_FOOTER) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.footer, parent, false); //Inflating the layout
ViewHolder vhHeader = new ViewHolder(v, viewType); //Creating ViewHolder and passing the object of type view
return vhHeader; //returning the object created
}
return null;
}
//Next we override a method which is called when the item in a row is
needed to be displayed, here the int position
// Tells us item at which position is being constructed to be displayed
and the holder id of the holder object tell us
// which view type is being created 1 for item row
#Override
public void onBindViewHolder(MyAdapter.ViewHolder holder, int
position) {
if(holder.Holderid ==1) { // as the list view is going to be called after the header view so we decrement the
// position by 1 and pass it to the holder while setting the text and image
holder.textView.setText(mNavTitles[position-2]); // Setting the Text with the array of our Titles
holder.imageView.setImageResource(mIcons[position-2]);// Settimg the image with array of our icons
}
else if (holder.Holderid ==2){
holder.about.setImageResource(mIcons[position]); // Similarly we set the resources for header view
holder.name.setText(mNavTitles[position]);
}
else if (holder.Holderid ==0){
}
}
// This method returns the number of items present in the list
#Override
public int getItemCount() {
return mNavTitles.length+2;
// the number of items in the list will be +1 the titles including the header view.
}
// Witht the following method we check what type of view is being passed
#Override
public int getItemViewType(int position) {
if (position == 0) {
return TYPE_HEADER;
}
else if (position ==2) {
return TYPE_FOOTER ;
}
else {
return TYPE_ITEM;
}
}
private boolean isPositionHeader(int position) {
return position == 0;
}
}
Change this
#Override
public int getItemViewType(int position) {
if (position == 0) {
return TYPE_HEADER;
}
else if (position ==2) {
return TYPE_FOOTER ;
}
else {
return TYPE_ITEM;
}
}
To
#Override
public int getItemViewType(int position) {
if(position==0){
return TYPE_HEADER;
}
else if((mNavTitles.length+ 1) == position){
return TYPE_FOOTER;
}else{
return TYPE_ITEM;
}
}

Updating TextView inside Header ListView

I'm trying to update my TextView when my onItenClick event fires, I have several TextViews, they are created as many I want inside my row template, but here goes the problem, when I try to set this TextView value it's acctually getting setted, but another textview, is also setted, with the same value I have on idea of the why to this behavior, but have no idea how to fix it.
My idea:
I my getRowView method (when I scroll the list), I'm seeing an
unusual behavior, once after I set some value to one of my itens, it
keep changing the text view that got this value. So I think here is
the core of the problem.
PS: I'm using the component HeaderListView, if you get another suggestion of framework to do the same thing, I would really appreciate.
PS2: Here goes my code:
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import br.com.soutsapp.souts.R;
import br.com.soutsapp.souts.model.Menu;
import br.com.soutsapp.souts.model.Product;
import br.com.soutsapp.souts.model.modelview.OrderItem;
import br.com.soutsapp.souts.userInterface.activity.SectionAdapter;
import br.com.soutsapp.souts.userInterface.adapter.HeaderListView;
public class MenuFragment extends Fragment {
private Context mContext;
private List<OrderItem> itens;
private Menu menu;
public MenuFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_menu, container, false);
mContext = getContext();
itens = new ArrayList<>();
menu = new Menu();
final String[] sec1 = {"aaaaaaaa","aaaaaaaa","aaaaaaaa","aaaaaaaa","aaaaaaaa","aaaaaaaa","aaaaaaaa"};
final String[] sec2 = {"bbbbbbbb","bbbbbbbb","bbbbbbbb","bbbbbbbb","bbbbbbbb","bbbbbbbb","bbbbbbbb"};
final String[] sec3 = {"cccccccc","cccccccc","cccccccc","cccccccc","cccccccc","cccccccc","cccccccc"};
final String[] sec4 = {"dddddddd","dddddddd","dddddddd","dddddddd","dddddddd","dddddddd","dddddddd"};
HeaderListView lv = (HeaderListView) v.findViewById(R.id.lv_menu_items);
lv.setAdapter(new SectionAdapter() {
#Override
public int numberOfSections() {
return menu.getMenuSessions().size();
}
#Override
public int numberOfRows(int section) {
return menu.getMenuSessions().get(section).size();
}
#Override
public Object getRowItem(int section, int row) {
return menu.getMenuSessions().get(section).get(row);
}
#Override
public boolean hasSectionHeaderView(int section) {
return true;
}
#Override
public View getRowView(int section, int row, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = getActivity().getLayoutInflater().inflate(getResources().getLayout(R.layout.menu_item_row), null);
}
//Product product = (Product)getRowItem(section, row);
//convertView.setId(product.getId());
TextView tvMenuItemName = (TextView) convertView.findViewById(R.id.tv_menu_item_name);
TextView tvMenuItemPrice = (TextView) convertView.findViewById(R.id.tv_price);
String itemName = ((Product)getRowItem(section,row)).getName();
tvMenuItemName.setText(itemName);
String itemPrice = String.valueOf(((Product) getRowItem(section, row)).getPrice());
tvMenuItemPrice.setText(itemPrice);
final int mySection = section;
final int myRow = row;
final TextView tvQuantity = (TextView) convertView.findViewById(R.id.tv_quantity);
tvQuantity.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Product product = (Product) getRowItem(mySection, myRow);
if (tvQuantity.getText().equals("1") && !tvQuantity.getText().equals("")){
tvQuantity.setText("");
OrderItem itenToRemove = null;
for(OrderItem item: itens){
if(item.getProductId() == product.getId()){
itenToRemove = item;
break;
}
}
itens.remove(itenToRemove);
}
else{
for(OrderItem item: itens){
if(item.getProductId() == product.getId()){
int quantity = item.getQuantity();
item.setQuantity(--quantity);
tvQuantity.setText(String.valueOf(item.getQuantity()));
break;
}
}
}
}
});
return convertView;
}
#Override
public int getSectionHeaderViewTypeCount() {
return 1;
}
#Override
public int getSectionHeaderItemViewType(int section) {
return section % 1;
}
#Override
public View getSectionHeaderView(int section, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = (TextView) getActivity().getLayoutInflater().inflate(getResources().getLayout(android.R.layout.simple_list_item_1), null);
}
if (getSectionHeaderItemViewType(section) == 0) {
((TextView) convertView).setText("Header for section " + section);
} else {
((TextView) convertView.findViewById(android.R.id.text1)).setText("Header for section " + section);
}
switch (section) {
case 0:
convertView.setBackgroundColor(getResources().getColor(R.color.Blue_Jay));
break;
case 1:
convertView.setBackgroundColor(getResources().getColor(R.color.Yellow));
break;
case 2:
convertView.setBackgroundColor(getResources().getColor(R.color.Red_Wine));
break;
}
return convertView;
}
#Override
public void onRowItemClick(AdapterView<?> parent, View view, int section, int row, long id) {
super.onRowItemClick(parent, view, section, row, id);
//Product p = (Product)view.getTag();
TextView tvQuantity = (TextView) view.findViewById(R.id.tv_quantity);
Product p = menu.getMenuSessions().get(section).get(row);
//Product p = (Product) getRowItem(section, row);
boolean exist = false;
for(OrderItem item : itens){
if(item.getProductId() == p.getId()){
int actualQuantity = item.getQuantity();
item.setQuantity(++actualQuantity);
tvQuantity.setText(String.valueOf(item.getQuantity()));
exist = true;
}
}
if(!exist){
itens.add(new OrderItem(p.getId(), 1));
tvQuantity.setText("1");
}
}
});
return v;
}
}
Here goes on screenshot, I had touch the "Smirnoff dose" item, and both "Smirnoff dose" and "Água" have their textviews values changed.

How to return "no search result" found in Android

My Search is done using a listView, so when the user key in the the first letter in the firstname, it will return the result, how can I make it display "no result found" in Android?
Please advise, do I need to create a a TextView?
public class ListViewAdapter extends BaseAdapter {
// Declare Variables
Context mContext;
LayoutInflater inflater;
private List<User> namelist = null;
private ArrayList<User> arraylist;
public ListViewAdapter(Context context,
List<User> worldpopulationlist) {
mContext = context;
this.namelist = worldpopulationlist;
inflater = LayoutInflater.from(mContext);
this.arraylist = new ArrayList<User>();
this.arraylist.addAll(namelist);
}
public class ViewHolder {
TextView firstname;
TextView lastname;
TextView position;
TextView company;
ImageView pix;
TextView searchresult;
}
#Override
public int getCount() {
return namelist.size();
}
#Override
public User getItem(int position) {
return namelist.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public View getView(final int position, View view, ViewGroup parent) {
final ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
view = inflater.inflate(R.layout.listview_item, null);
// Locate the TextViews in listview_item.xml
holder.firstname = (TextView) view.findViewById(R.id.firstname);
holder.lastname = (TextView) view.findViewById(R.id.lastname);
holder.position= (TextView) view.findViewById(R.id.position);
holder.company = (TextView) view.findViewById(R.id.company);
// Locate the ImageView in listview_item.xml
holder.pix = (ImageView) view.findViewById(R.id.pix);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
// Set the results into TextViews
holder.firstname.setText(namelist.get(position).getFirstName());
holder.lastname.setText(namelist.get(position).getLastName());
holder.position.setText(namelist.get(position).getDesignation());
holder.company.setText(namelist.get(position).getCompanyName());
// Set the results into ImageView
holder.pix.setImageResource(namelist.get(position).getProfileImage());
// Listen for ListView Item Click
view.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// Send single item click data to SingleItemView Class
Intent intent = new Intent(mContext, SingleItemView.class);
// Pass all data country
intent.putExtra("firstname",
(namelist.get(position).getFirstName()));
intent.putExtra("lastname",
(namelist.get(position).getLastName()));
// Pass all data rank
intent.putExtra("position",
(namelist.get(position).getDesignation()));
// Pass all data population
intent.putExtra("company",
(namelist.get(position).getCompanyName()));
// Pass all data flag
intent.putExtra("pix",
(namelist.get(position).getProfileImage()));
// Start SingleItemView Class
mContext.startActivity(intent);
}
});
return view;
}
// Filter Class
public void filter(String charText) {
charText = charText.toLowerCase(Locale.getDefault());
namelist.clear();
if (charText.length() == 0) {
namelist.addAll(arraylist);
} else {
for (User wp : arraylist) {
if (wp.getFirstName().toLowerCase(Locale.getDefault()).contains(charText)||wp.getLastName().toLowerCase(Locale.getDefault()).contains(charText) ) {
namelist.add(wp);
}
else
{
//what should I enter here?
}
}
}
notifyDataSetChanged();
}
}
In my App, for this case, I have an item in list which has a special type 'EMPTY_RESULT'.
Basically, after getting out result which is EMPTY, generate an item with specific type 'EMPTY_RESUT'in Adapter (means getCount() == 1 ), and notify dataset change.
Then, when getView be called, return the empty item and certainly you could design some UI for it to present empty result, such as an icon and text 'nothing found'.
Instead of creating a TextView, you can create a Toast, which is essentially a popup. You can create it like this:
Toast.makeText(mContext, "No Results Found", Toast.LENGTH_SHORT).show();
You can change the last parameter to Toast.LENGTH_LONG if you want the popup to last longer.

Android Settings UI

I am looking to build something similar to the settings UI of system android. I want something like a few checkboxpreferences, switchpreferences, edittextpreferences on the launch of application and then when user selects one preference open a fragment but i am just not able to figure that out.
I have referred Settings guide but it insists on using preference header. While displaying headers there is an unlikely overhead i am facing of displaying texts which in turn will load fragments.
For example,
My preference header is something like :
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- These settings headers are only used on tablets. -->
<header
android:fragment="${packageName}.${activityClass}$GeneralPreferenceFragment"
android:title="#string/pref_header_general" />
<header
android:fragment="${packageName}.${activityClass}$NotificationPreferenceFragment"
android:title="#string/pref_header_notifications" />
<header
android:fragment="${packageName}.${activityClass}$DataSyncPreferenceFragment"
android:title="#string/pref_header_data_sync" />
</preference-headers>
and just to load the actual data, i am having to use it. The actual data will have checkboxes and edittexts.
It would be great if someone gave some insights on this. It would be of great help if i could launch the actual fragment data on loading of screen. Better if i could have control of what fragment to call and call other fragments when a fragment item is selected.
To create custom preference headers, with switches and such, you need to extend PreferenceActivity with Headers as the Android docs describe and then override PreferenceActivity.setListAdapter to create your own list adapter, which creates the custom views. I made a pastebin with the code from the actual android settings activity to help you out. http://pastebin.com/RhSndGCQ
#Override
public void onBuildHeaders(List<Header> headers) {
loadHeadersFromResource(R.xml.settings_headers, headers);
updateHeaderList(headers);
}
#Override
public void setListAdapter(ListAdapter adapter) {
if (adapter == null) {
super.setListAdapter(null);
} else {
super.setListAdapter(new HeaderAdapter(this, getHeaders(), mAuthenticatorHelper));
}
}
private static class HeaderAdapter extends ArrayAdapter<Header> {
static final int HEADER_TYPE_CATEGORY = 0;
static final int HEADER_TYPE_NORMAL = 1;
static final int HEADER_TYPE_SWITCH = 2;
private static final int HEADER_TYPE_COUNT = HEADER_TYPE_SWITCH + 1;
private final WifiEnabler mWifiEnabler;
private final BluetoothEnabler mBluetoothEnabler;
private final ProfileEnabler mProfileEnabler;
private AuthenticatorHelper mAuthHelper;
private static class HeaderViewHolder {
ImageView icon;
TextView title;
TextView summary;
Switch switch_;
}
private LayoutInflater mInflater;
static int getHeaderType(Header header) {
if (header.fragment == null && header.intent == null) {
return HEADER_TYPE_CATEGORY;
} else if (header.id == R.id.wifi_settings
|| header.id == R.id.bluetooth_settings
|| header.id == R.id.profiles_settings) {
return HEADER_TYPE_SWITCH;
} else {
return HEADER_TYPE_NORMAL;
}
}
#Override
public int getItemViewType(int position) {
Header header = getItem(position);
return getHeaderType(header);
}
#Override
public boolean areAllItemsEnabled() {
return false; // because of categories
}
#Override
public boolean isEnabled(int position) {
return getItemViewType(position) != HEADER_TYPE_CATEGORY;
}
#Override
public int getViewTypeCount() {
return HEADER_TYPE_COUNT;
}
#Override
public boolean hasStableIds() {
return true;
}
public HeaderAdapter(Context context, List<Header> objects,
AuthenticatorHelper authenticatorHelper) {
super(context, 0, objects);
mAuthHelper = authenticatorHelper;
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Temp Switches provided as placeholder until the adapter replaces these with actual
// Switches inflated from their layouts. Must be done before adapter is set in super
mWifiEnabler = new WifiEnabler(context, new Switch(context));
mBluetoothEnabler = new BluetoothEnabler(context, new Switch(context));
mProfileEnabler = new ProfileEnabler(context, null, new Switch(context));
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
HeaderViewHolder holder;
Header header = getItem(position);
int headerType = getHeaderType(header);
View view = null;
if (convertView == null || headerType == HEADER_TYPE_SWITCH) {
holder = new HeaderViewHolder();
switch (headerType) {
case HEADER_TYPE_CATEGORY:
view = new TextView(getContext(), null,
android.R.attr.listSeparatorTextViewStyle);
holder.title = (TextView) view;
break;
case HEADER_TYPE_SWITCH:
view = mInflater.inflate(R.layout.preference_header_switch_item, parent,
false);
holder.icon = (ImageView) view.findViewById(R.id.icon);
holder.title = (TextView)
view.findViewById(com.android.internal.R.id.title);
holder.summary = (TextView)
view.findViewById(com.android.internal.R.id.summary);
holder.switch_ = (Switch) view.findViewById(R.id.switchWidget);
break;
case HEADER_TYPE_NORMAL:
view = mInflater.inflate(
R.layout.preference_header_item, parent,
false);
holder.icon = (ImageView) view.findViewById(R.id.icon);
holder.title = (TextView)
view.findViewById(com.android.internal.R.id.title);
holder.summary = (TextView)
view.findViewById(com.android.internal.R.id.summary);
break;
}
view.setTag(holder);
} else {
view = convertView;
holder = (HeaderViewHolder) view.getTag();
}
// All view fields must be updated every time, because the view may be recycled
switch (headerType) {
case HEADER_TYPE_CATEGORY:
holder.title.setText(header.getTitle(getContext().getResources()));
break;
case HEADER_TYPE_SWITCH:
// Would need a different treatment if the main menu had more switches
if (header.id == R.id.wifi_settings) {
mWifiEnabler.setSwitch(holder.switch_);
} else if (header.id == R.id.bluetooth_settings) {
mBluetoothEnabler.setSwitch(holder.switch_);
} else if (header.id == R.id.profiles_settings) {
mProfileEnabler.setSwitch(holder.switch_);
}
// No break, fall through on purpose to update common fields
//$FALL-THROUGH$
case HEADER_TYPE_NORMAL:
if (header.extras != null
&& header.extras.containsKey(ManageAccountsSettings.KEY_ACCOUNT_TYPE)) {
String accType = header.extras.getString(
ManageAccountsSettings.KEY_ACCOUNT_TYPE);
ViewGroup.LayoutParams lp = holder.icon.getLayoutParams();
lp.width = getContext().getResources().getDimensionPixelSize(
R.dimen.header_icon_width);
lp.height = lp.width;
holder.icon.setLayoutParams(lp);
Drawable icon = mAuthHelper.getDrawableForType(getContext(), accType);
holder.icon.setImageDrawable(icon);
} else {
holder.icon.setImageResource(header.iconRes);
}
holder.title.setText(header.getTitle(getContext().getResources()));
CharSequence summary = header.getSummary(getContext().getResources());
if (!TextUtils.isEmpty(summary)) {
holder.summary.setVisibility(View.VISIBLE);
holder.summary.setText(summary);
} else {
holder.summary.setVisibility(View.GONE);
}
break;
}
return view;
}
public void resume() {
mWifiEnabler.resume();
mBluetoothEnabler.resume();
mProfileEnabler.resume();
}
public void pause() {
mWifiEnabler.pause();
mBluetoothEnabler.pause();
mProfileEnabler.pause();
}
}

Categories

Resources