Material Design

2017-04-27  本文已影响36人  gogoingmonkey

开发很多都要求安卓跟IOS的效果一样,感觉非常不合理 在统一操作系统中统一UI 在14 年谷歌退出material Design;为了解决安卓平台风格不同意的问题,在安卓5.0系统开始,使用这种风格设计, 在 15年推出了design Support这个库;

ToolBar

    不适用默认的Actionbar,需要在在资源文件中 values/styles.xml中更改父类parent="Theme.AppCompat.Light.DarkActionBar"  为parent="Theme.AppCompat.Light.NoActionBar"或者

parent ="Theme.AppCompat.NoActionBar"> 二者的区别就是 后者为深色主题,衬托颜色是淡色,前者就相反。
首先在布局文件中声明了一个app 命名空间:xmlns:app="http://schemas.android.com/apk/res-auto",Toolbar代码如下:
<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" />
上面的theme属性,因为我们的主题选择了淡色的主题,这个时候字体会深色的就是黑色的,所以把这个属性设置为之前的,假如页面中有菜单栏,这个时候弹出的颜色会是深色的,所以加上popuptheme属性。代码两句就搞定:

Toolbar  tb = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(tb);
这个时候,如果你在清单文件中的Activity属性中写了 <activity android:name=".MainActivity"  android:label="XXXX">属性,如果没有写这个属性,默认使用应用名。
    我们的 Toolbar不仅要显示标题还要显示返回按钮等。在res目录新建一个menu文件夹,在里面新建一个toolbar.xml文件,文件内容:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/backup"
        android:icon="@drawable/ic_backup"
        android:title="Backup"
        app:showAsAction="always"/>
    <item
        android:id="@+id/delete"
        android:icon="@drawable/ic_delete"
        android:title="Delete"
        app:showAsAction="ifRoom"/>
    <item
        android:id="@+id/settings"
        android:icon="@drawable/ic_settings"
        android:title="Settings"
        app:showAsAction="never"/>
</menu>

并且在代码中增加如下代码:

 public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.toolbar, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                mDrawerLayout.openDrawer(GravityCompat.START);
                break;
            case R.id.backup:
                Toast.makeText(this, "You clicked Backup", Toast.LENGTH_SHORT).show();
                break;
            case R.id.delete:
                Toast.makeText(this, "You clicked Delete", Toast.LENGTH_SHORT).show();
                break;
            case R.id.settings:
                Toast.makeText(this, "You clicked Settings", Toast.LENGTH_SHORT).show();
                break;
            default:
        }
        return true;
    }

滑动菜单

     首先是在布局文件中写Drawlayout 这个里面包含2个子项,第一个是主页面显示的,第二个是抽屉边显示的内容;
      抽屉的布局需要加一个属性,layout_gravity="left" 指定抽屉在哪边,代码不提示。Material Design库推荐我们设置一个按钮,提示用户有抽屉栏,增加如下代码:
dl = (DrawerLayout) findViewById(R.id.drawlayout);
        ActionBar supportActionBar = getSupportActionBar();
        if(supportActionBar != null ){
            supportActionBar.setDisplayHomeAsUpEnabled(true);
            supportActionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
        }

....
 switch (item.getItemId()) {
            case android.R.id.home:
                dl.openDrawer(GravityCompat.START);
                break;
}

使用NavigationView

使用这个控件来实现左边的菜单选线:

1.添加依赖:
compile 'com.android.support:design:24.2.1'
compile 'de.hdodenhof:circleimageview:2.1.0'
第一个是依赖库,第二个是圆图片处理;
2.增加一个menu文件如下:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_call"
            android:icon="@drawable/nav_call"
            android:title="Call" />
        <item
            android:id="@+id/nav_friends"
            android:icon="@drawable/nav_friends"
            android:title="Friends" />
        <item
            android:id="@+id/nav_location"
            android:icon="@drawable/nav_location"
            android:title="Location" />
        <item
            android:id="@+id/nav_mail"
            android:icon="@drawable/nav_mail"
            android:title="Mail" />
        <item
            android:id="@+id/nav_task"
            android:icon="@drawable/nav_task"
            android:title="Tasks" />
    </group>
</menu>

为了美观,我们还写一个抽屉的头像的布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="180dp"
    android:background="?attr/colorPrimary"
    android:padding="10dp">

    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/icon_image"
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:layout_centerInParent="true"
        android:src="@drawable/nav_icon" />

    <TextView
        android:id="@+id/username"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="tonygreendev@gmail.com"
        android:textColor="#FFF"
        android:textSize="14sp" />

    <TextView
        android:id="@+id/mail"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/username"
        android:text="Tony Green"
        android:textColor="#FFF"
        android:textSize="14sp" />

</RelativeLayout>

下面就是用navigationView这个控件在布局中如下使用:

<android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/nav_header"
        app:menu="@menu/nav_menu" />

下面就添加代码:

     nv.setCheckedItem(R.id.nav_call);
        nv.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                dl.closeDrawers();
                return true;
            }
        });

默认选择一个,然后点击后就关闭抽屉。

悬浮按钮和可交互提示

FloatingActionButton
实现悬浮按钮! 默认颜色colorAccent ,找到对应ID,设置点击事件就可以了;

<android.support.design.widget.FloatingActionButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/floatbutton"
    android:layout_gravity="bottom|end"
    android:layout_margin="15dp"
    android:src="@drawable/ic_done"
    android:elevation="18dp"   //设置悬浮高度的
    /> 

Snackbar :
不是Toast的 替代品。与之有不同的应用场景,比如用户删除东西没有交互就删了会很心疼的;

FloatingActionButton   fab= (FloatingActionButton) findViewById(R.id.floatbutton);
 fab.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View v) {
         Log.e("", "onClick: "+"sssssssssss" );
         Snackbar.make(v,"我是弹唱内容",Snackbar.LENGTH_INDEFINITE).setAction("undo", new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 Toast.makeText(MainActivity.this,"是是是",Toast.LENGTH_LONG).show();
             }
         }).show();
     }
 }).show();
    这个时候,你会发现弹出的东西吧这个悬浮按钮遮住了。。。

CoordinatorLayout

    这个可以说是一个加强的贞布局,可以监听 说有子空间的各种事件,比如刚才的遮住了,当他要弹出来的时候,就把floatingctionBar 往上移动

这个SnackBar并不是他的子空间, 但是还是能接受呢。因为刚才我们传入的第一个参数就是view 就是Snacker 的,所以会有这个效果 如果你试试传入Drawlauoyt
就会被遮挡!

卡片式布局

  CardView V 7的 其实也是一个FrameLayout 提供了圆角和阴影效果,看上去有立体效果,用法和普通的差不多,多了两个属性app:cardCornerRadius= "4dp"  app:elevition ="5dp" ,添加下面的依赖:
compile 'com.android.support:recyclerview-v7:24.2.1'
    compile 'com.android.support:cardview-v7:24.2.1'
    compile 'com.github.bumptech.glide:glide:3.7.0'
    使用recyclerview来展示列表,定义子项的布局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<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/fruit_image"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:scaleType="centerCrop" />

        <TextView
            android:id="@+id/fruit_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>

recycleView的代码如下。但是按照这样,你会发现Toolbar 被挡住了。

RecyclerView 的 写法:
class FirutAdapter extends RecyclerView.Adapter<FirutAdapter.ViewHolder> {
    private List<Fruit> mfirutlsit;
    private Context mcontext;

    @Override
    public FirutAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //第三步,从写这个方法
        if (mcontext == null) {
            mcontext = parent.getContext();
        }
        View view = LayoutInflater.from(mcontext).inflate(R.layout.rec_item, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(FirutAdapter.ViewHolder holder, int position) {
//  第四步,在这个方法中处理对应的每一个内容
        Fruit fruit = mfirutlsit.get(position);
//        holder.imageView.setImageResource(fruit.getImageId());
        holder.textView.setText(fruit.getFruitName());
        Glide.with(mcontext).load(fruit.getImageId()).into(holder.imageView);
    }

    @Override
    public int getItemCount() {
        return mfirutlsit.size();
    }

    //第一步,把Viewholder这个内部类 改为静态的,然后写他的成员变量。 这个几个都是子项目中的, 然后在这个的构造中,找ID
    static class ViewHolder extends RecyclerView.ViewHolder {
        CardView cardVie;
        ImageView imageView;
        TextView textView;

        public ViewHolder(View itemView) {
            super(itemView);
            cardVie = (CardView) itemView;
            imageView = (ImageView) itemView.findViewById(R.id.image);
            textView = (TextView) itemView.findViewById(R.id.fruitname);
        }
    }

    //第二步,重写整个FriutAdapter的构造,定义一个成员变量,用来接收外部传来的整个数据集合
    public FirutAdapter(List<Fruit> fruitList) {
        this.mfirutlsit = fruitList;
    }
}



MainActivity中:
  initFruits();
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        GridLayoutManager layoutManager = new GridLayoutManager(this, 2);
        recyclerView.setLayoutManager(layoutManager);
        adapter = new FruitAdapter(fruitList);
        recyclerView.setAdapter(adapter);


initFruits(){
 fruitList.clear();
        for (int i = 0; i < 50; i++) {
            Random random = new Random();
            int index = random.nextInt(fruits.length);
            fruitList.add(fruits[index]);
        }
}

AppbarLayout

  这个相当于是个线性布局,对滑动事件做了封装,,在使用时候。吧toolbar 放在这个里面,然后在recyclerView 中添加一句话

app:layout_behavior="@string/appbar_scrolling_view_behavior"
然后在ToolBar上增加一个属性:
app:layout_scrollFlags="scroll|snap|enterAlways"
scrool表示向下滚时候跟随,,隐藏 向上滚得时候显示, 然后就是显示一般的时候去计算

下拉刷新

  <android.support.v4.widget.SwipeRefreshLayout
            android:id="@+id/swipe_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_width="match_parent"
                android:layout_height="match_parent" />
        </android.support.v4.widget.SwipeRefreshLayout>

代码中:

 swipeRefresh = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);
        swipeRefresh.setColorSchemeResources(R.color.colorPrimary);
        swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                refreshFruits();
            }
        });
    }

    private void refreshFruits() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        initFruits();
                        adapter.notifyDataSetChanged();
                        swipeRefresh.setRefreshing(false);
                    }
                });
            }
        }).start();
    }

比起之前的ActionBar ToolBar 是可以随着 RecyclerView移动 但是materail Design 并没说标题就要这样,可以自己定制一个;

可折叠的

CollapsingToolbarLayout 可折叠的
这个不能独立存在,只能依赖AppBarLayout 的子布局

水果详情页面的 布局文件:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_fruit_detail"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    tools:context="com.example.aa.mytestdemo.FruitDetail">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbarlayout"
        android:layout_width="match_parent"
        android:layout_height="250dp">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsinglayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:theme="ThemeOverlay.Appcompat.Dark.ActioBar"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="exitUntilCollapsed|scroll">

            <ImageView
                android:id="@+id/imageDetail"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                app:layout_collapseMode="parallax" />

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin">

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

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

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/scrollview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
    <
    </android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>

现在在刚才的RecyclerView 的OncreateViewHolder方法中加入如下代码做点击事件:

        final ViewHolder viewHolder = new ViewHolder(view);
        viewHolder.cardVie.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int adapterPosition = viewHolder.getAdapterPosition();

                Firut firut = mfirutlsit.get(adapterPosition);

                Intent intent = new Intent(mcontext,FirutActivity.class);
                intent.putExtra("fruit_name",firut.getName());
                intent.putExtra("fruit_image_id",firut.getId());
                mcontext.startActivity(intent);
            }
        });

在新建一个Activity 代码中:

package com.yuhan.myapplication;

import android.content.Intent;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;

public class FirutActivity extends AppCompatActivity {

    public static final String FRUIT_NAME = "fruit_name";

    public static final String FRUIT_IMAGE_ID = "fruit_image_id";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_firut);
        Intent intent = getIntent();
        String fruitName = intent.getStringExtra(FRUIT_NAME);
        int fruitImageId = intent.getIntExtra(FRUIT_IMAGE_ID, 0);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        CollapsingToolbarLayout collapsingToolbar = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
        ImageView fruitImageView = (ImageView) findViewById(R.id.fruit_image_view);
        TextView fruitContentText = (TextView) findViewById(R.id.fruit_content_text);
        setSupportActionBar(toolbar);
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
        }
        collapsingToolbar.setTitle(fruitName);
        Glide.with(this).load(fruitImageId).into(fruitImageView);
        String fruitContent = generateFruitContent(fruitName);
        fruitContentText.setText(fruitContent);
    }
    private String generateFruitContent(String fruitName) {
        StringBuilder fruitContent = new StringBuilder();
        for (int i = 0; i < 500; i++) {
            fruitContent.append(fruitName);
        }
        return fruitContent.toString();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                finish();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

沉浸状态栏

在安卓5.0 钱都不能对系统状态栏 设置。。在除了在Imageview中增加这个属性还需要在他上面的所有增加,

 android:fitsSystemWindows="true"
```        
          但是还是没有效果,现在就需要在 程序的主题中把状态栏的颜色设置为透明的
Android:statusBarColor  指定为@Android:color/transparent         但是这个属性是API 21  也就是安卓5.0才有的
在资源文件中新建一个values-v21文件夹,然后新建一个stely文件
```
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="FriutActivityTheme" parent="AppTheme">
        <item name="android:statusBarColor">@android:color/transparent</item>
    </style>
</resources>
然后在values文件中增加  
<style name="FriutActivityTheme" parent="AppTheme">
</style>
```
然后在清单文件中<activity android:name=".FruitDetail"
    android:theme="@style/FriutActivityTheme"></activity>

详细资料参考:https://material.io/guidelines/
上一篇下一篇

猜你喜欢

热点阅读