android——卡片式布局

Posted xxbbtt

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android——卡片式布局相关的知识,希望对你有一定的参考价值。

一、CardView

<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5dp"
    app:cardCornerRadius="4dp">

        <TextView
            android:id="@+id/overwatch_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_margin="5dp"
            android:textSize="16sp"/>

</android.support.v7.widget.CardView>

  这是一个CardView的简单布局,app:cardCornerRadius这个属性指定了卡片圆角的弧度,另外还可以通过app:elevation指定卡片的高度,改变卡片的阴影效果。

  要使用CardView需要添加相应的库,在app/build.gradle中:

    compile \'com.android.support:recyclerview-v7:26.+\'
    compile \'com.android.support:cardview-v7:26.+\'
    compile \'com.github.bumptech.glide:glide:4.0.0\'

  第一行是RecyclerView需要的库,第二行就是CardView,第三行是一个Glide的库,Glide是一个超级强大的图片加载库,一行代码就能实现图片加载功能。

  首先在主活动的布局中加入RecyclerView:

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_height="match_parent"
            android:layout_width="match_parent" />

  然后为RecyclerView的子项指定一个自定义的布局,在layout目录下新建overwatch_item.xml:

<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5dp"
    app:cardCornerRadius="4dp">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <ImageView
            android:id="@+id/overwatch_image"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:scaleType="centerCrop"/>

        <TextView
            android:id="@+id/overwatch_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_margin="5dp"
            android:textSize="16sp"/>
    </LinearLayout>
</android.support.v7.widget.CardView>

  然后新建一个OverWatch类:

public class OverWatch {

    private String name;

    private int imageID;

    public OverWatch(String name, int imageID) {
        this.imageID = imageID;
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public int getImageID() {
        return imageID;
    }
}

  这个类就是每个卡片的内容了。name代表名字,imageID代表图片资源ID。

  然后就需要为RecyclerView准备一个适配器:

 1 public class OverWatchAdapter extends RecyclerView.Adapter<OverWatchAdapter.ViewHolder> {
 2 
 3     private Context mContext;
 4 
 5     private List<OverWatch> mOverWatch;
 6 
 7     static class ViewHolder extends RecyclerView.ViewHolder{
 8 
 9         CardView cardView;
10         ImageView overwatchImage;
11         TextView overwatchName;
12         
13         public ViewHolder(View view){
14             super(view);
15             cardView = (CardView) view;
16             overwatchImage = (ImageView) view.findViewById(R.id.overwatch_image);
17             overwatchName = (TextView) view.findViewById(R.id.overwatch_name);
18         }
19     }
20 
21     public OverWatchAdapter(List<OverWatch> OverWatchList){
22         mOverWatch = OverWatchList;
23     }
24 
25     public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
26         if(mContext == null){
27             mContext = parent.getContext();
28         }
29         View view = LayoutInflater.from(mContext).inflate(R.layout.overwatch_item,parent,false);
30         return  new ViewHolder(view);
31     }
32     public void onBindViewHolder(ViewHolder viewHolder, int position) {
33         OverWatch overWatch = mOverWatch.get(position);
34         viewHolder.overwatchName.setText(overWatch.getName());
35         Glide.with(mContext).load(overWatch.getImageID()).into(viewHolder.overwatchImage);
36     }
37 
38     public int getItemCount() {
39         return mOverWatch.size();
40     }
41 }

  第35行就是Glide加载图片的方法,首先是调用Glide.with()方法传入一个Context参数,然后调用load()方法去加载图片,参数可以是URI,也可以使一个本地路径,或者是一个资源ID,然后再调用into()方法将图片设置到某一个ImageView中去。

  然后就是主活动的java代码:

 1 public class MainActivity extends AppCompatActivity {
 2 
 3     private DrawerLayout mDrawerLayout;
 4 
 5     private OverWatch[] overWatches = {new OverWatch("猎空",R.drawable.img_1),new OverWatch("猎空",R.drawable.img_2),
 6             new OverWatch("猎空",R.drawable.img_3),new OverWatch("猎空",R.drawable.img_5),
 7             new OverWatch("猎空",R.drawable.img_6),new OverWatch("猎空",R.drawable.img_7),
 8             new OverWatch("猎空",R.drawable.img_8),new OverWatch("猎空",R.drawable.img_9),
 9             new OverWatch("猎空",R.drawable.img_10),new OverWatch("猎空",R.drawable.img_11)};
10 
11     private List<OverWatch> overWatchList = new ArrayList<>();
12 
13     private OverWatchAdapter overWatchAdapter;
14     @Override
15     protected void onCreate(Bundle savedInstanceState) {
16         super.onCreate(savedInstanceState);
17         setContentView(R.layout.activity_main);
18  ...
19 
20         //图片加载
21         initOverWatch();
22         RecyclerView reccyclerView = (RecyclerView) findViewById(R.id.recycler_view);
23         GridLayoutManager layoutManager = new GridLayoutManager(MainActivity.this,2);
24         reccyclerView.setLayoutManager(layoutManager);
25         overWatchAdapter = new OverWatchAdapter(overWatchList);
26         reccyclerView.setAdapter(overWatchAdapter);
27     }
28 
29 ...
30     }
31 
32 ...
33 
34     //存放图片
35     private  void initOverWatch(){
36         overWatchList.clear();
37         for (int i = 0; i < 50; i++){
38             Random random = new Random();
39             int index = random.nextInt(overWatches.length);
40             overWatchList.add(overWatches[index]);
41         }
42     }
43 }

  运行程序:

 

二、AppBarLayout

  刚刚的RecyclerView把Toolbar挡住了.从布局xml中看:

    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_height="match_parent"
            android:layout_width="match_parent" />

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/fab"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:src="@drawable/ic_done"
            app:elevation="8dp" />

    </android.support.design.widget.CoordinatorLayout>

  Toolbar、RecyclerView、FloatingActionButton都是放置在CoordinatorLayout中的,因为CoordinatorLayout就是一个加强版的FrameLayout,从上到下的布局会逐渐覆盖,所以我们可以把Toolbar的布局代码下移试试:  

  但是这样Toolbar又把RecyclerView的一部分覆盖住了,所以再试试在CoordinatorLayout中嵌套一个LinearLayout:

    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

            <android.support.v7.widget.RecyclerView
                android:id="@+id/recycler_view"
                android:layout_height="match_parent"
                android:layout_width="match_parent" />
        </LinearLayout>

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/fab"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:src="@drawable/ic_done"
            app:elevation="8dp" />
    </android.support.design.widget.CoordinatorLayout>

  然后就完成了:

   然后其实这里想讲的是AppBarLayout,其实AppBarLayout就是垂直方向上的LinearLayout不过是在其内部做了很多滚动事件的封装,所以可以用AppBarLayout避免这个遮挡

  先把Toolbar嵌套到AppBarLayout中,然后给RecyclerView指定一个布局行为:

    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
            
        </android.support.design.widget.AppBarLayout>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_height="match_parent"
            android:layout_width="match_parent" 
            app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/fab"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:src="@drawable/ic_done"
            app:elevation="8dp" />
    </android.support.design.widget.CoordinatorLayout>

  效果和使用LinearLayout一样。但是AppBarLayout做了一些滚动事件的封装。比如这样改:

<android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:layout_scrollFlags="scroll|enterAlways|snap"/>

    </android.support.design.widget.AppBarLayout>

app:layout_scrollFlags这个属性的值指定为scroll就是,当RecyclerView向上滚动的时候,Toolbar会随着滚动而隐藏,enterAlways是指向下滚动的时候,snap指根据滚动的距离,自动选择隐藏还是显示。

 

三、下拉刷新

 使用的是SwipeRefreshLayout然某个控件实现下拉刷新:

        <android.support.v4.widget.SwipeRefreshLayout
            android:id="@+id/swip_refresh"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">
            
            <android.support.v7.widget.RecyclerView
                android:id="@+id/recycler_view"
                android:layout_height="match_parent"
                android:layout_width="match_parent" />
            
        </android.support.v4.widget.SwipeRefreshLayout>

  将想要实现下拉刷新的某控件嵌套在SwipeRefreshLayout就行了,这里要注意把app:layout_behavior="@string/appbar_scrolling_view_behavior"这个属性移到SwipeRefreshLayout。

  然后是JAVA代码:

public class MainActivity extends AppCompatActivity {

...

    private SwipeRefreshLayout swipeRefresh;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
...

        //下拉刷新
        swipeRefresh = (SwipeRefreshLayout) findViewById(R.id.swip_refresh);
        swipeRefresh.setColorSchemeResources(R.color.colorPrimary);
        swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                refreshOverWatch();
            }
        });
    }

 ...

    //刷新图片
    private  void refreshOverWatch(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    Thread.sleep(1000);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        initOverWatch();
                        overWatchAdapter.notifyDataSetChanged();
                        swipeRefresh.setRefreshing(false);
                    }
                });
            }
        }).start();
    }
}

具体步骤就是:

1、获取SwipeRefreshLayout的实例。

2、设置监听器。

3、编写刷新的使用的方法

在这里要注意的有,setColorSchemeResources()这个方法设置的是刷新时进度条的颜色,Thread.sleep(1000)先让线程沉睡一秒,让,然后改变数据,接着调用overWatchAdapter.notifyDataSetChanged()方法通知数据发生了变化,swipeRefresh.setRefreshing(false)用于表示刷新事件结束,并隐藏进度条。

以上是关于android——卡片式布局的主要内容,如果未能解决你的问题,请参考以下文章

回收站视图未在 android studio 中显示一张卡片视图

android——卡片式布局

android片段表格布局

Android片段布局完成膨胀

android精美卡片式布局Cardview_RecyclerView

Recycler视图在android studio中未显示一张卡片视图