【问题标题】:Grid layout within tabs选项卡内的网格布局
【发布时间】:2014-05-06 11:31:19
【问题描述】:

我是 Android 新手,因此遇到了这样的问题。

如何更改布局:

到:

XML 片段主:

<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>

所以我需要这些标签具有不同内容的网格布局。

【问题讨论】:

    标签: android android-fragments android-viewpager android-gridview android-tabs


    【解决方案1】:

    您必须在 ViewPager 中使用 GridView。因此,在您的 MainActivity 中,您将拥有此布局。

    创建 activity_main.xml 布局

    这是主要布局。一切都将存在于其中,包括您的片段和标签。

    <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" />
    

    创建您的 MainActivity.java 类

    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;
            }
        }
    }
    

    不要忘记在代码中为这些R.string.title_section1, ... 字符串创建字符串,否则会出错。

    现在我们必须为片段(将在选项卡内显示的页面)创建一个布局,并且它必须包含一个GridView

    创建一个 fragment_main.xml 布局

    <?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>
    

    现在让我们定义片段类,它将负责扩展此布局并处理视图。

    创建一个片段来膨胀 GridView 布局: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;
        }
    }
    

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

    创建支持 GridView 项的适配器:MyAdapter.java

    正如您在此处看到的,我们将一些项目添加到 GridView,方法是将它们添加到适配器类末尾定义的 Item 类型的 ArrayList

    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;
                }
            }
        }
    

    现在为了让GridView 项目保持正确的宽度,并排对齐,我们使用自定义类来定义测量尺寸。

    为什么需要这样做?根据@kcoppock's answer

    基本上,在 Android 的 ImageView 类中,除非您硬编码宽度和高度,否则无法简单地指定“嘿,保持此视图的正方形纵横比(宽度/高度)”。您可以在适配器的 getView 中对LayoutParams 进行一些手动调整,但坦率地说,让ImageView 处理所有测量结果要简单得多,只需覆盖结果即可说“无论宽度最终是多少,让我的高度保持不变相同”。您永远不必考虑它,它始终是方形的,并且可以按预期工作。基本上这是保持视图正方形的最简单方法。

    创建一个类 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
        }
    }
    

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

    创建一个 XML 布局 gridview_item.xml

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

    <?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>
    

    在这里,我测试了代码,这是最终结果。当然,您会更改图像的这些颜色,但这是您应该遵循的方法。

    注意:要为GridView 项设置图像而不是颜色,请在MyAdapter 类的getView() 方法中使用setImageResource(int) 而不是setBackgroundColor(int)

    【讨论】:

    • @AnZyuZya 你需要使用android.support.v4android.support.v7。另外,您需要将其导入android.support.v7.app.ActionBarActivity
    • ActionBarActivity 存在于android.support.v7.app,正如您在the docs 中看到的那样,它位于app compact 库中。这里是a link,可帮助您将支持 v7 添加到您的项目中。
    • 谢谢,那个指南太棒了。希望我能给你更多的赞成票 :D 但最后一个问题。你能写出你对每个班级所做的进口清单吗?因此,我遇到了一些错误。
    • @AnZyuZya on eclipse 如果你点击 CTRL+Shift+O 它会自动导入你需要的所有东西。
    • @AnZyuZya 这里是你的进口清单。 paste.kde.org/pnwea6rnk希望能解决你的问题。但是您应该使用 CTRL+Shift+O 来自动导入缺少的类。
    【解决方案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.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-28
      • 1970-01-01
      • 2023-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-08
      相关资源
      最近更新 更多