Now i can create PagerIndicator but i don't know how to put map it, which one page will show Driving Stat. and another one will show map+driving stat. In addition, Is it possible to make 2 view work together as you see in the picture below.(the time and distance still run)
I don't know about GMap control but here is how I use different layouts in my app.
First you could create a layout for your Map control
Secondly add it in your ViewPager
#Override
public Object instantiateItem(View pager, int position) {
LayoutInflater inflater = (LayoutInflater) SettingsActivity.this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = null;
switch (position) {
case 0: //first page
view = inflater.inflate(R.layout.yourMapLayout,
null);
TextView text = (TextView) view
.findViewById(R.id.text);
text.setText("I am an added text")
...
If I understood corect and you are using android.support.v4.view.ViewPager , which would be a good candidate to accomplish your task.
I use below code and it works :)
#Override
public Object instantiateItem( View pager, final int position )
{
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = null;
if(position == 0) {
view = inflater.inflate(R.layout.my_map, null);
((ViewPager) pager).addView(view,0);
}
return view;
}
Related
If we have N categories (between 1 and 100 according to a REST API) and each with X items (between 1 and 50, depending on the category), what is the best way to do a category RecyclerView?
To add do this I am adding card views for each item item of a category in the method "onBindViewHolder" like this:
#Override
public void onBindViewHolder(MoviesViewHolder holder, int i) {
holder.title.setText(items.get(i).getTitle());
// I add a CardView (item_category.xml) for each item in the list
for (ObjectShort object: items.get(i).getObjects()) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.item_category, holder.linearCategories, false);
ImageView img = (ImageView) view.findViewById(R.id.iv_wallpaper);
imageLoader.load(img, object.getImg().getPoster().getThumbnail());
holder.linearCategories.addView(view);
}
}
And when it is recycled I remove the ITEMS elements in "onViewRecycled" because if I do not do it when doing vertical scrolling and reloading a category, items are added again duplicating:
#Override
public void onViewRecycled(MoviesViewHolder holder) {
// delete all items
holder.linearCategories.removeAllViews();
}
Is there any better way to do it? This is not effective and the scroll is very slow
thanks to all
To answer your question, I'm going to go back to the old days of ListView. Let's imagine that I had a simple list where each row was just a title and an image. A really naive implementation of getView() to support that list might look like this:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.itemview, parent, false);
TextView title = view.findViewById(R.id.title);
title.setText("hello world");
ImageView image = view.findViewById(R.id.image);
image.setImageResource(R.drawable.my_image);
return view;
}
There's two major sources of performance trouble in this implementation:
We're inflating a new view every time
We're calling findViewById() every time
Number 1 was solved by making use of the convertView parameter, and number 2 was solved by something called the "view holder pattern". When the Google dev team created the RecyclerView API to replace ListView, they made "view holders" a first-class citizen, and now everyone works with RecyclerView.ViewHolders by default.
It's important to remember that the performance gains of avoiding repeated view inflation and repeated view lookup were so valuable that Google baked them into the new system.
Now let's look at your code...
public void onBindViewHolder(MoviesViewHolder holder, int i) {
...
for (ObjectShort object: items.get(i).getObjects()) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.item_category, holder.linearCategories, false);
ImageView img = (ImageView) view.findViewById(R.id.iv_wallpaper);
imageLoader.load(img, object.getImg().getPoster().getThumbnail());
holder.linearCategories.addView(view);
}
}
This for loop inside your bind method has all the same problems that my naive getView() implementation above had. Inflating a new view for each item in the category, and invoking findViewById() to get ahold of its ImageView is going to be expensive, especially when the user flings the list.
To fix your performance problems, just apply the same logic to your "inner" list of content as you have to your "outer" content: use a RecyclerView for items (inside each ViewHolder for categories).
Here is a really simple sample app that illustrates my solution: https://gist.github.com/zizibaloob/2eb64f63ba8d1468100a69997d525a54
I'm facing some trouble with the navigation drawer adapter.
It's supposed to display items as follows: Favorito, Categorias, and small sub categories underneath categorias.
I programmed the navigation drawer adapter to use a big_layout.xml file by default, but if its position is greater than a certain value, then it uses a small_layout.xml file.
It works fine for the first few items, but the problem is when I scroll down to see the rest of the items, they use the big_layout.xml, and then when I scroll back up, the original big items change their view and use the small layout!
below is the code, and this is a screen shot of the bad results: http://i.stack.imgur.com/QWwts.jpg
#Override
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
LayoutInflater laoutInflater = (LayoutInflater)
context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (getItemId(position)>3)
view = laoutInflater.inflate(R.layout.drawer_list_item_small, null);
if (getItemId(position)<=3)
view = laoutInflater.inflate(R.layout.drawer_list_item, null);
}
ImageView icon = (ImageView) view.findViewById(R.id.icon);
icon.setImageResource(drawerItems.get(position).getIcon());
TextView title = (TextView) view.findViewById(R.id.title);
title.setText(drawerItems.get(position).getTitle());
return view;}
Is there anything wrong I'm doing ? , Is there something missing that might be responsible of making the view stable?
How can i fix this ?
Your issue is with recycling. When you scroll down and back up, the views using the small layout are no longer needed, and so are eligible for recycling - now, the view is not null, so the layout will not be reinitialised based on its position, but merely updated with the new content.
You can fix this by using ViewTypes in your list adapter class, overriding the following methods.
#Override
public int getItemViewType(int position) {
return (position > 3) ? 0 : 1;
}
#Override
public int getViewTypeCount() {
return 2;
}
Then, in your getView() you will not be given a view (for recycling) if it is of the wrong view type.
#Override
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
int layout = getLayoutForViewType(position);
view = LayoutInflater.from(parent.getContext()).inflate(layout, null);
}
...
return view;
}
private int getLayoutForViewType(int position) {
if (getItemViewType(position) == 0) {
return R.layout.blahblahblah;
}
return R.layout.bloobloobloo;
}
I am trying to do something like the android market to show products from different categories. I have implemented that behavior with this library, and it's all running good.
What I want to do now is to have a list view in the page of the categories, and in each one of the others a grid view. Of course, each one of them will have different sources of data.
How can I achieve that ? Does it have anything to do with adapters?
I have find one Very good Example you can find that on this site
https://github.com/astuetz/ViewPagerExtensions
Else hope this code will be Helpful to you.
#Override
public Object instantiateItem(View collection, int position) {
View v = new View(PatientView.this.getApplicationContext());
final LayoutInflater inflater = (LayoutInflater) PatientView.this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
switch (position) {
case 0:
v = inflater.inflate(R.layout.patientp1,
(ViewGroup) null, false);
((Button) v.findViewById(R.id.pp1btnbck)).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
finish();
}
});
break;
case 1:
v = inflater.inflate(R.layout.patientp2, null, false
);
break;
default:
TextView tv = new TextView(PatientView.this.context);
tv.setText("Page " + position);
tv.setTextColor(Color.WHITE);
tv.setTextSize(30);
v = tv;
break;
}
((ViewPager) collection).addView(v, 0);
return v;
}
I think you want extend FragmentPagerAdapter, override getItem, and return the proper Fragment object (or ListFragment) depending on the index/position in the ViewPager.
In the layout xml for your Activity you should include a ViewPager (<android.support.v4.view.ViewPager>), and in your Activity onCreate use the setAdapter method of ViewPager to assign your FragmentPagerAdapter.
I have an Activity, which simply consists in listing Pair<String, String> objects. I have a custom TextWithSubTextAdapter, which extends ArrayAdapter:
public View getView(int position, View convertView, ViewGroup parent)
{
View view;
if (convertView == null)
{
LayoutInflater li = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = li.inflate(R.layout.text_sub, null);
TextView tv = (TextView)view.findViewById(R.id.mainText);
tv.setText(mCategories.get(position).first);
TextView desc = (TextView)view.findViewById(R.id.subText);
desc.setText(Html.fromHtml(mCategories.get(position).second));
}
else
{
view = (View) convertView;
}
return view;
}
mCategories is an ArrayList<Pair<String, String>>
I then call lv.setAdapter(new TextSubTextAdapter(this, Common.physConstants));
As long as I have a limited set of elements, It works great, because I don't need to scroll. However, when I add enough elements, after scrolling, the items swap their positions, like this:
I suspect that this behavior is due to me calling mCategories.get(position). Because the Views are never kept in the background and Android regenerates them every time, I never get the same item, as position will rarely have the same value.
Is there a way to get a constant id, which could allow me to get items with fixed positions ? I tried to use getItemID, but I do not understand how to implement it.
Note: Every string comes from a strings.xml file. They are never compared, and instanciated once, at startup.
When you scroll your list Android dynamically reuses the Views which scroll out of the screen. These convertViews don't have the content which should be at this position yet. You have to set that manually.
View view;
if (convertView == null)
{
LayoutInflater li = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = li.inflate(R.layout.text_sub, null);
}
else
{
view = convertView;
}
TextView tv = (TextView)view.findViewById(R.id.mainText);
tv.setText(mCategories.get(position).first);
TextView desc = (TextView)view.findViewById(R.id.subText);
desc.setText(Html.fromHtml(mCategories.get(position).second));
return view;
In my app the user spins a carousel. On the selected Item I need to display a separate xml view for each item. The carousel is visibile at all time at the bottom with the view visible in the top half. I think that there is a better way than to use fragments. Any ideas? The following code is not functional as of now but I think an inflator may be the way to go but to get it done is troubling me. After case0 there is case1-case5.
carousel.setOnItemSelectedListener(new OnItemSelectedListener(){
public void onItemSelected(CarouselAdapter<?> parent, View view,
int position, long id) {
switch(position){
case 0:
final View firstview;
LayoutInflater inflater = (LayoutInflater) getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
firstview = inflater.inflate(R.layout.selected_item, null);
break;
case 1:
In case anyone else runs into this problem I solved it:
LayoutInflater inflater = (LayoutInflater) CarouselActivity.this.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
LinearLayout inflateView = (LinearLayout) findViewById( R.id.InflateParent );
View nextView = null;
switch(position){
case 0:
System.out.println("Case 0");
inflateView.removeAllViews();
nextView = inflater.inflate( R.layout.nextview, null );
inflateView.addView(nextView);