问题
I'm new to Android and therefore faced such problem.
How can I change layout from:
To:
XML fragment_main:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.snbgearassistant.MainActivity$PlaceholderFragment" >
<TextView
android:id="@+id/section_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
So I need these tabs having grid layout with different content.
回答1:
You must use a GridView inside the ViewPager. So, in your MainActivity
, you would have this layout.
Create the activity_main.xml layout
This is the main layout. Everything will live inside of it, including your fragments and tabs.
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.myapp.gridview.MainActivity" />
Create your MainActivity.java class
public class MainActivity extends ActionBarActivity implements ActionBar.TabListener
{
SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {@link ViewPager} that will host the section contents.
*/
ViewPager mViewPager;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Here we load the xml layout we created above
setContentView(R.layout.activity_main);
// Set up the action bar.
final ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
// When swiping between different sections, select the corresponding
// tab. We can also use ActionBar.Tab#select() to do this if we have
// a reference to the Tab.
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener()
{
@Override
public void onPageSelected(int position)
{
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++)
{
// Create a tab with text corresponding to the page title defined by
// the adapter. Also specify this Activity object, which implements
// the TabListener interface, as the callback (listener) for when
// this tab is selected.
actionBar.addTab(
actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
}
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
{
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
{
}
@Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction)
{
}
/**
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter
{
public SectionsPagerAdapter(FragmentManager fm)
{
super(fm);
}
@Override
public Fragment getItem(int position)
{
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
return new PlaceholderFragment();
}
@Override
public int getCount()
{
// Show 3 total pages.
return 3;
}
@Override
public CharSequence getPageTitle(int position)
{
Locale l = Locale.getDefault();
switch (position)
{
case 0:
return getString(R.string.title_section1).toUpperCase(l);
case 1:
return getString(R.string.title_section2).toUpperCase(l);
case 2:
return getString(R.string.title_section3).toUpperCase(l);
}
return null;
}
}
}
Don't forget to create your strings for these
R.string.title_section1, ...
strings on your code, or you will have an error.
Now we must create a layout for the fragment (the page that will be displayed inside the tab), and it must contain a GridView
.
Create a fragment_main.xml layout
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<GridView
android:id="@+id/gridview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:verticalSpacing="0dp"
android:horizontalSpacing="0dp"
android:stretchMode="columnWidth"
android:numColumns="2" />
</FrameLayout>
Now let's define the fragment class that will take care of inflating this layout and handling the views.
Create a fragment to inflate the GridView layout: PlaceHolderFragment.java
/**
* A placeholder fragment containing a the gridview
*/
public class PlaceholderFragment extends Fragment
{
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
// Here we inflate the layout we created above
GridView gridView = (GridView) rootView.findViewById(R.id.gridview);
gridView.setAdapter(new MyAdapter(MainActivity.this.getApplicationContext()));
return rootView;
}
}
Now we must create an adapter class to handle each item of the GridView
, this way you can manage the behavior of each one.
Create the Adapter to support the GridView items: MyAdapter.java
As you can see here, we are adding some items to the GridView by adding them to an ArrayList
of the type Item
defined in the end of the adapter class.
private class MyAdapter extends BaseAdapter
{
private List<Item> items = new ArrayList<Item>();
private LayoutInflater inflater;
public MyAdapter(Context context)
{
inflater = LayoutInflater.from(context);
items.add(new Item("Image 1", Color.GREEN));
items.add(new Item("Image 2", Color.RED));
items.add(new Item("Image 3", Color.BLUE));
items.add(new Item("Image 4", Color.GRAY));
items.add(new Item("Image 5", Color.YELLOW));
}
@Override
public int getCount() {
return items.size();
}
@Override
public Object getItem(int i)
{
return items.get(i);
}
@Override
public long getItemId(int i)
{
return items.get(i).colorId;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup)
{
View v = view;
ImageView picture;
TextView name;
if(v == null)
{
v = inflater.inflate(R.layout.gridview_item, viewGroup, false);
v.setTag(R.id.picture, v.findViewById(R.id.picture));
v.setTag(R.id.text, v.findViewById(R.id.text));
}
picture = (ImageView)v.getTag(R.id.picture);
name = (TextView)v.getTag(R.id.text);
Item item = (Item)getItem(i);
picture.setBackgroundColor(item.colorId);
name.setText(item.name);
return v;
}
private class Item
{
final String name;
final int colorId;
Item(String name, int drawableId)
{
this.name = name;
this.colorId = drawableId;
}
}
}
Now to make the GridView
items keep with the correct width, aligned side by side, we use a custom class to define the measured dimension.
Why this needs to be done? According to @kcoppock's answer:
Basically, in Android's
ImageView
class, there's no way to simply specify "hey, keep a square aspect ratio (width / height) for this view" unless you hard code width and height. You could do some manual adjustment ofLayoutParams
in the adapter's getView, but frankly, it's much simpler to letImageView
handle all the measurements, and just override the results to say "Whatever the width ends up being, make my height stay the same". You never have to think about it, it's always square, and it just works as expected. Basically this is the easiest way to keep the view square.
Create a class SquareImageView.java
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageView;
public class SquareImageView extends ImageView
{
public SquareImageView(Context context)
{
super(context);
}
public SquareImageView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public SquareImageView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth()); //Snap to width
}
}
Now we must define the XML layout for the GridView
items.
Create a XML layout gridview_item.xml
As you can see, here we add two items to the layout. One is a element of the type SquareImageView
(the class we created above) and the TextView
which is a label for each image.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.myapp.gridview.SquareImageView
android:id="@+id/picture"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
/>
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="15dp"
android:paddingBottom="15dp"
android:layout_gravity="bottom"
android:textColor="@android:color/white"
android:background="#55000000"
/>
</FrameLayout>
And here it is, I tested the code and this is the final result. Of course you would change those colors for your images, but this is the approach you should follow.
Note: To set images instead of colors to the GridView
item, in your getView()
method of the MyAdapter
class use setImageResource(int) instead of setBackgroundColor(int)
.
回答2:
Answer Given By rogcg is very good and nice. But the Images for each fragment is same. I like to add some codes in the mainactivity which has viewpager.I think we can use fragment instead of activity, Here is the code.The same code as the Main Activity given by rogcg. Add these codes too.
In Layout for mainfragment add ActionBarlayout,toolbar and slidingtablayout
In Mainfragment,add
private List<Fragment> mFragments = new Vector<Fragment>();
in oncreate(), create three fragments ,
mFragments.add(new HomeFragment());
mFragments.add(new Title1());
mFragments.add(new Title2());
mFragments.add(new Title3());
in onCreateView(),add
mSectionsPagerAdapter = new SectionsPagerAdapter(getChildFragmentManager());
mViewPager.setAdapter(mSectionsPagerAdapter);
tabLayout = (SlidingTabLayout) v.findViewById(R.id.tabanim_tabs);
tabLayout.setViewPager(mViewPager);
in SectionPageAdapter class,add
@Override
public Fragment getItem(int position) {
return mFragments.get(position+1);
}
@Override
public int getCount() {
return 3;
}
@Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position)
{
case 0:
return getString(R.string.English).toUpperCase(l);
case 1:
return getString(R.string.Tamil).toUpperCase(l);
case 2:
return getString(R.string.Hindi).toUpperCase(l);
}
return null;
}
Now add any view in Title1() fragment as you usage and add any things in it I think this message was useful. please vote for me. Thank you.
来源:https://stackoverflow.com/questions/23493527/grid-layout-within-tabs