选项​​卡中网格布局 [英] Grid layout within tabs

查看:196
本文介绍了选项​​卡中网格布局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是新来的Andr​​oid,因此面临着这样的问题。

如何变更布局从:

要:

XML fragment_main:

 <的RelativeLayout的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
的xmlns:工具=htt​​p://schemas.android.com/tool​​s
机器人:layout_width =match_parent
机器人:layout_height =match_parent
机器人:paddingBottom会=@扪/ activity_vertical_margin
机器人:paddingLeft =@扪/ activity_horizo​​ntal_margin
机器人:paddingRight =@扪/ activity_horizo​​ntal_margin
机器人:paddingTop =@扪/ activity_vertical_margin
工具:上下文=$ com.example.snbgearassistant.MainActivity PlaceholderFragment>
<的TextView
    机器人:ID =@ + ID / section_label
    机器人:layout_width =WRAP_CONTENT
    机器人:layout_height =WRAP_CONTENT/>< / RelativeLayout的>

所以,我需要具有不同内容的网格布局这些选项卡。


解决方案

您必须使用ViewPager里面的GridView。所以,在你的 MainActivity ,你有这样的布局。

创建activity_main.xml中布局

这是主要的布局。一切都将生活在它的内部,包括你的碎片和标签。

 < android.support.v4.view.ViewPager的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    的xmlns:工具=htt​​p://schemas.android.com/tool​​s
    机器人:ID =@ + ID /寻呼机
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent
    工具:上下文=com.myapp.gridview.MainActivity/>

创建MainActivity.java类

 公共类MainActivity扩展ActionBarActivity实现ActionBar.TabListener
{    SectionsPagerAdapter mSectionsPagerAdapter;    / **
     *本{@link ViewPager}将承载部分内容。
     * /
    ViewPager mViewPager;    @覆盖
    保护无效的onCreate(捆绑savedInstanceState)
    {
        super.onCreate(savedInstanceState);        //这里我们加载我们上面创建的XML布局
        的setContentView(R.layout.activity_main);        //设置操作栏。
        最后的动作条动作条= getSupportActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);        //创建将返回一个片段为三个的适配器
        //活性的主要部分。
        mSectionsPagerAdapter =新SectionsPagerAdapter(getSupportFragmentManager());        //设置的ViewPager与部分适配器。
        mViewPager =(ViewPager)findViewById(R.id.pager);
        mViewPager.setAdapter(mSectionsPagerAdapter);        //当不同部分之间滑动,选择对应的
        // 标签。我们也可以使用ActionBar.Tab#select()来做到这一点,如果我们有
        //为Tab的参考。
        mViewPager.setOnPageChangeListener(新ViewPager.SimpleOnPageChangeListener()
        {
            @覆盖
            公共无效使用onPageSelected(INT位置)
            {
                actionBar.setSelectedNavigationItem(位置);
            }
        });        //对于每一个应用中的部分,添加标签,操作栏。
        的for(int i = 0; I< mSectionsPagerAdapter.getCount();我++)
        {
            //创建对应于定义的页面标题文字标签
            //适配器。同时,指定此活动的对象,它实现
            //将TabListener接口,回调(监听程序)进行时
            //这个选项卡中选择。
            actionBar.addTab(
                    actionBar.newTab()
                            .setText(mSectionsPagerAdapter.getPageTitle(I))
                            .setTabListener(本));
        }
    }
    @覆盖
    公共无效onTabSelected(ActionBar.Tab选项卡,FragmentTransaction fragmentTransaction)
    {
        //当选择给定的标签上,切换到相应的页面
        //的ViewPager。
        mViewPager.setCurrentItem(tab.getPosition());
    }    @覆盖
    公共无效onTabUnselected(ActionBar.Tab选项卡,FragmentTransaction fragmentTransaction)
    {    }    @覆盖
    公共无效onTabReselected(ActionBar.Tab选项卡,FragmentTransaction fragmentTransaction)
    {    }    / **
     * A {@link FragmentPagerAdapter}返回对应片段
     *章节/标签/页面。
     * /
    公共类SectionsPagerAdapter扩展FragmentPagerAdapter
    {        公共SectionsPagerAdapter(FragmentManager FM)
        {
            超(FM);
        }        @覆盖
        公共片段的getItem(INT位置)
        {
            //的getItem被称为实例化片段为给定的页面。
            //返回一个PlaceholderFragment(定义如下静态内部类)。
            返回新PlaceholderFragment();
        }        @覆盖
        公众诠释getCount将()
        {
            //显示3总页​​数。
            返回3;
        }        @覆盖
        公共CharSequence的getPageTitle(INT位置)
        {
            区域设置L = Locale.getDefault();
            开关(位置)
            {
                情况下0:
                    返回的getString(R.string.title_section1).toUpperCase(升);
                情况1:
                    返回的getString(R.string.title_section2).toUpperCase(升);
                案例2:
                    返回的getString(R.string.title_section3).toUpperCase(升);
            }
            返回null;
        }
    }
}


  

不要忘了在你的code创建这些 R.string.title_section1,... 字符串的字符串,或者你将有一个错误。


现在,我们必须创建片段(将在标签内显示的页面)的布局,并且它必须包含一个 GridView控件

创建fragment_main.xml布局

 <?XML版本=1.0编码=UTF-8&GT?;
<的FrameLayout
    的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent>
    < GridView控件
        机器人:ID =@ + ID / GridView控件
        机器人:layout_width =match_parent
        机器人:layout_height =match_parent
        机器人:verticalSpacing =0dp
        机器人:horizo​​ntalSpacing =0dp
        机器人:stretchMode =columnWidth时
        机器人:为numColumns =2/>
< /&的FrameLayout GT;

现在让我们定义的片段类,将采取夸大这种布局和处理意见的照顾。

创建片段膨胀GridView的布局:PlaceHolderFragment.java

  / **
 *包含在GridView的占位符片段
 * /
公共类PlaceholderFragment扩展片段
{
    / **
     *片段参数重新presenting本节号
     *片段。
     * /
    私有静态最后弦乐ARG_SECTION_NUMBER =SECTION_NUMBER;    公共PlaceholderFragment(){
    }    @覆盖
    公共查看onCreateView(LayoutInflater充气器,容器的ViewGroup,捆绑savedInstanceState)
    {
        查看rootView = inflater.inflate(R.layout.fragment_main,集装箱,FALSE);        //这里我们夸大我们在上面创建的布局
        GridView控件的GridView =(GridView控件)rootView.findViewById(R.id.gridview);
        gridView.setAdapter(新MyAdapter(MainActivity.this.getApplicationContext()));        返回rootView;
    }
}

现在,我们必须创建一个适配器类来处理 GridView控件的每一个项目,这样你可以管理每个人的行为。

创建适配器以支持在GridView项目:MyAdapter.java

正如你所看到的,我们将它们添加到的ArrayList 类型的添加一些项目到GridView 项目在适配器类的末尾定义。

 私有类MyAdapter延伸BaseAdapter
{
        私人列表<项目>项目=新的ArrayList<项目>();
        私人LayoutInflater吹气;        公共MyAdapter(上下文的背景下)
        {
            充气= LayoutInflater.from(上下文);            items.add(新项目(图片1,Color.GREEN));
            items.add(新项目(图像2,Color.RED));
            items.add(新项目(图像3,Color.BLUE));
            items.add(新项目(图像4,Color.GRAY));
            items.add(新项目(图片5,Color.YELLOW));
        }        @覆盖
        公众诠释的getCount(){
            返回items.size();
        }        @覆盖
        公共对象的getItem(int i)以
        {
            返回items.get(ⅰ);
        }        @覆盖
        众长getItemId(int i)以
        {
            返回items.get(我).colorId;
        }        @覆盖
        公共查看getView(INT I,观景,ViewGroup中的ViewGroup)
        {
            视图V =视图。
            ImageView的图片;
            TextView的名称;            如果(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));
            }            照片=(ImageView的)v.getTag(R.id.picture);
            名称=(TextView中)v.getTag(R.id.text);            项目项目=(项目)的getItem(I)            picture.setBackgroundColor(item.colorId);
            name.setText(item.name);            返回伏;
        }        私有类项目
        {
            最终字符串名称;
            最终诠释colorId;            项目(字符串名称,诠释drawableId)
            {
                this.name =名称;
                this.colorId = drawableId;
            }
        }
    }

现在让 GridView控件项目保持与正确的宽度,对齐并排,我们使用一个自定义的类来定义的测量尺度。

为什么这需要做什么?据 @ kcoppock的回答


  

基本上,Android的的ImageView 类,有没有办法简单地指定哎,保持一个正方形纵横比(宽/高)对这一观点,除非你辛苦$ C $ç宽度和高度。你可以做的LayoutParams 的一些手工调整适配器的getView,但坦率地说,这是更简单,让的ImageView 处理所有测量,只是重写的结果,说:无论宽度最终被,让我的身高保持不变。你从来没有去想它,它总是广场,它只是按预期工作。基本上,这是保持视图广场的最简单方法。


创建一个类SquareImageView.java

 进口android.content.Context;
进口android.util.AttributeSet;
进口android.widget.ImageView;公共类SquareImageView扩展的ImageView
{
    公共SquareImageView(上下文的背景下)
    {
        超级(上下文);
    }    公共SquareImageView(上下文的背景下,ATTRS的AttributeSet)
    {
        超(背景下,ATTRS);
    }    公共SquareImageView(上下文的背景下,ATTRS的AttributeSet,INT defStyle)
    {
        超(背景下,ATTRS,defStyle);
    }    @覆盖
    保护无效onMeasure(INT widthMeasureSpec,诠释heightMeasureSpec)
    {
        super.onMeasure(widthMeasureSpec,heightMeasureSpec);
        setMeasuredDimension(getMeasuredWidth(),getMeasuredWidth()); //捕捉到宽
    }
}

现在我们必须定义为 GridView控件项目XML布局。

创建一个XML布局gridview_item.xml

正如你所看到的,在这里我们添加两个项目的布局。一个是类型的元素 SquareImageView (类我们上面创建)和的TextView 这是每一个标签图像。

 <?XML版本=1.0编码=UTF-8&GT?;<的FrameLayout的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent>
    < com.myapp.gridview.SquareImageView
        机器人:ID =@ + ID /图片
        机器人:layout_width =match_parent
        机器人:layout_height =match_parent
        机器人:scaleType =centerCrop
        />
    <的TextView
        机器人:ID =@ + ID /文
        机器人:layout_width =match_parent
        机器人:layout_height =WRAP_CONTENT
        机器人:paddingLeft =10dp
        机器人:paddingRight =10dp
        机器人:paddingTop =15dp
        机器人:paddingBottom会=15dp
        机器人:layout_gravity =底
        机器人:文字颜色=@机器人:彩色/白
        机器人:背景=#5500
        />
< /&的FrameLayout GT;

和这里是,我测试了code,这是最后的结果。当然,你会改变这些颜色为你的形象,但是这是你应该采取的办法。

注意::要设置的图像,而不是颜色的 GridView控件项目,在你的 getView() MyAdapter 类使用<方法href=\"http://developer.android.com/reference/android/widget/ImageView.html#setImageResource%28int%29\"相对=nofollow> setImageResource(INT) 而不是 setBackgroundColor(INT)

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.

解决方案

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 of LayoutParams in the adapter's getView, but frankly, it's much simpler to let ImageView 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).

这篇关于选项​​卡中网格布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆