美文网首页
Material Design

Material Design

作者: gogoingmonkey | 来源:发表于2017-04-27 20:59 被阅读36次

    开发很多都要求安卓跟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/

    相关文章

      网友评论

          本文标题:Material Design

          本文链接:https://www.haomeiwen.com/subject/flknzttx.html