├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── TestMaterialDesign.iml ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── zs │ │ └── it │ │ └── testmaterialdesign │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── zs │ │ └── it │ │ └── testmaterialdesign │ │ ├── ActiveSharedTransitionActivity.java │ │ ├── CollapsingToolbarLayoutActivity.java │ │ ├── CoordinaterLayoutActivity.java │ │ ├── DividerGridItemDecoration.java │ │ ├── DividerItemDecoration.java │ │ ├── MainActivity.java │ │ ├── MuchSharedTransitionActivity.java │ │ ├── MyActionProvider.java │ │ ├── MyActionProvider2.java │ │ ├── TabLayoutActivity.java │ │ ├── TestActivityCompactActivity.java │ │ └── TestAnimationActivity.java │ └── res │ ├── anim │ ├── path_morph.xml │ └── rotation.xml │ ├── drawable-v21 │ ├── animvectordrawable.xml │ ├── ripple_drawable.xml │ ├── state_list_anim_drawable.xml │ └── vectordrawable.xml │ ├── drawable │ ├── animvectordrawable.xml │ ├── list_divider.xml │ ├── ripple_drawable.xml │ ├── state_list_anim.xml │ ├── state_list_anim_drawable.xml │ └── vectordrawable.xml │ ├── layout-v21 │ └── activity_main.xml │ ├── layout │ ├── activity_active_shared_transition.xml │ ├── activity_collapsing_toolbar_layout.xml │ ├── activity_coordinater_layout.xml │ ├── activity_main.xml │ ├── activity_much_shared_transition.xml │ ├── activity_tab_layout.xml │ ├── activity_test_activity_compact.xml │ ├── activity_test_animation.xml │ ├── header_just_username.xml │ ├── layout_simple_item.xml │ └── myactionprovider.xml │ ├── menu │ ├── menu_active_shared_transition.xml │ ├── menu_collapsing_toolbar_layout.xml │ ├── menu_coordinater_layout_activity.xml │ ├── menu_drawer.xml │ ├── menu_main.xml │ ├── menu_much_shared_transition.xml │ ├── menu_tab_layout.xml │ ├── menu_test_activity_compact.xml │ ├── menu_test_animation.xml │ └── popup_menu.xml │ ├── mipmap-hdpi │ ├── ic_brightness_medium_white_36dp.png │ └── ic_launcher.png │ ├── mipmap-mdpi │ ├── ic_brightness_medium_white_36dp.png │ └── ic_launcher.png │ ├── mipmap-xhdpi │ ├── ic_bg.jpg │ ├── ic_brightness_medium_white_36dp.png │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ ├── ic_brightness_medium_white_36dp.png │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_brightness_medium_white_36dp.png │ ├── transition │ ├── change_image_transform.xml │ └── explode.xml │ ├── values-v21 │ └── styles.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── device-2016-01-04-162643.png ├── device-2016-01-04-162729.png ├── device-2016-01-04-162749.png ├── device-2016-01-04-162810.png ├── device-2016-01-04-162830.png ├── device-2016-01-04-162904.png ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | .DS_Store 6 | /build 7 | /captures 8 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | TestMaterialDesign -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TestMaterialDesign 2 | 该测试程序是用来测试和学习Android Material Design设计风格的; 3 | 主要了解了 4 | android support design包中的组件CollapsingToolBarLayout、CoordinatorLayout、AppBarLayout、CollapsingToolbarLayout、NavigationView、TextInputLayout、Snackbar、FloatingActionButton等; 5 | v7、v7包中的ToolBar、RecycleView、NestedScrollView、DrawerLayout等; 6 | Material design提供的动画如Activity间共享视图转场动画(ActivityOptions.makeSceneTransitionAnimation、Activity.finishAfterTransition())等; 7 | v4包中提供的兼容动画 ActivityOptionsCompat.makeScaleUpAnimation等; 8 | 5.x版本中提供的新的差之器PathInterperator,新的drawable标签,矢量图等; 9 | 10 | 截图: 11 | ![image1](https://github.com/ZhangSir/TestMaterialDesign/blob/master/device-2016-01-04-162643.png) 12 | ![image2](https://github.com/ZhangSir/TestMaterialDesign/blob/master/device-2016-01-04-162729.png) 13 | ![image3](https://github.com/ZhangSir/TestMaterialDesign/blob/master/device-2016-01-04-162749.png) 14 | ![image4](https://github.com/ZhangSir/TestMaterialDesign/blob/master/device-2016-01-04-162810.png) 15 | ![image5](https://github.com/ZhangSir/TestMaterialDesign/blob/master/device-2016-01-04-162830.png) 16 | ![image6](https://github.com/ZhangSir/TestMaterialDesign/blob/master/device-2016-01-04-162904.png) 17 | -------------------------------------------------------------------------------- /TestMaterialDesign.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.1" 6 | 7 | defaultConfig { 8 | applicationId "com.zs.it.testmaterialdesign" 9 | minSdkVersion 15 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | 14 | // dex突破65535的限制 15 | multiDexEnabled true 16 | } 17 | 18 | lintOptions { 19 | abortOnError false 20 | } 21 | 22 | signingConfigs { 23 | debug { 24 | // No debug config 25 | } 26 | 27 | release { 28 | // storeFile file("../yourapp.keystore") 29 | // storePassword "your password" 30 | // keyAlias "your alias" 31 | // keyPassword "your password" 32 | } 33 | } 34 | 35 | buildTypes { 36 | debug { 37 | // 显示Log 38 | buildConfigField "boolean", "LOG_DEBUG", "true" 39 | 40 | versionNameSuffix "-debug" 41 | minifyEnabled false 42 | zipAlignEnabled false 43 | shrinkResources false 44 | signingConfig signingConfigs.debug 45 | } 46 | release { 47 | // 不显示Log 48 | buildConfigField "boolean", "LOG_DEBUG", "false" 49 | 50 | minifyEnabled true 51 | zipAlignEnabled true 52 | // 移除无用的resource文件 53 | shrinkResources true 54 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 55 | signingConfig signingConfigs.release 56 | } 57 | } 58 | } 59 | 60 | dependencies { 61 | compile fileTree(dir: 'libs', include: ['*.jar']) 62 | compile 'com.android.support:appcompat-v7:23.0.0' 63 | compile 'com.android.support:design:23.1.1' 64 | } 65 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\Android\Android-Studio\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/zs/it/testmaterialdesign/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.zs.it.testmaterialdesign; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 24 | 27 | 28 | 31 | 32 | 35 | 36 | 39 | 40 | 43 | 44 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/zs/it/testmaterialdesign/ActiveSharedTransitionActivity.java: -------------------------------------------------------------------------------- 1 | package com.zs.it.testmaterialdesign; 2 | 3 | import android.os.Build; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.os.Bundle; 6 | import android.transition.Explode; 7 | import android.view.Menu; 8 | import android.view.MenuItem; 9 | import android.view.Window; 10 | import android.widget.ImageView; 11 | 12 | public class ActiveSharedTransitionActivity extends AppCompatActivity { 13 | 14 | private ImageView iv1, iv2; 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS); 19 | if(Build.VERSION.SDK_INT >= 21){ 20 | // getWindow().setAllowEnterTransitionOverlap(true); 21 | getWindow().setEnterTransition(new Explode()); 22 | getWindow().setExitTransition(new Explode()); 23 | } 24 | super.onCreate(savedInstanceState); 25 | setContentView(R.layout.activity_active_shared_transition); 26 | 27 | iv1 = (ImageView) this.findViewById(R.id.iv_t1); 28 | iv2 = (ImageView) this.findViewById(R.id.iv_t2); 29 | 30 | if(Build.VERSION.SDK_INT >= 21){ 31 | //动态设置共享视图 32 | iv1.setTransitionName(getString(R.string.transition_name5)); 33 | iv2.setTransitionName(getString(R.string.transition_name6)); 34 | } 35 | } 36 | 37 | @Override 38 | public boolean onCreateOptionsMenu(Menu menu) { 39 | // Inflate the menu; this adds items to the action bar if it is present. 40 | getMenuInflater().inflate(R.menu.menu_active_shared_transition, menu); 41 | return true; 42 | } 43 | 44 | @Override 45 | public boolean onOptionsItemSelected(MenuItem item) { 46 | // Handle action bar item clicks here. The action bar will 47 | // automatically handle clicks on the Home/Up button, so long 48 | // as you specify a parent activity in AndroidManifest.xml. 49 | int id = item.getItemId(); 50 | 51 | //noinspection SimplifiableIfStatement 52 | if (id == R.id.action_settings) { 53 | return true; 54 | } 55 | 56 | return super.onOptionsItemSelected(item); 57 | } 58 | 59 | @Override 60 | public void onBackPressed() { 61 | if(Build.VERSION.SDK_INT >= 21){ 62 | //如果需要逆转该过渡动画,使用Activity.finishAfterTransition()方法代替Activity.finish() 63 | this.finishAfterTransition(); 64 | }else{ 65 | super.onBackPressed(); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/zs/it/testmaterialdesign/CollapsingToolbarLayoutActivity.java: -------------------------------------------------------------------------------- 1 | package com.zs.it.testmaterialdesign; 2 | 3 | import android.support.v7.app.ActionBar; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.os.Bundle; 6 | import android.support.v7.widget.Toolbar; 7 | import android.view.Menu; 8 | import android.view.MenuItem; 9 | 10 | public class CollapsingToolbarLayoutActivity extends AppCompatActivity { 11 | 12 | @Override 13 | protected void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | setContentView(R.layout.activity_collapsing_toolbar_layout); 16 | 17 | Toolbar toolbar = (Toolbar) this.findViewById(R.id.toolbar); 18 | setSupportActionBar(toolbar); 19 | 20 | ActionBar ab = getSupportActionBar(); 21 | ab.setDisplayHomeAsUpEnabled(true); 22 | 23 | } 24 | 25 | @Override 26 | public boolean onCreateOptionsMenu(Menu menu) { 27 | // Inflate the menu; this adds items to the action bar if it is present. 28 | getMenuInflater().inflate(R.menu.menu_collapsing_toolbar_layout, menu); 29 | return true; 30 | } 31 | 32 | @Override 33 | public boolean onOptionsItemSelected(MenuItem item) { 34 | // Handle action bar item clicks here. The action bar will 35 | // automatically handle clicks on the Home/Up button, so long 36 | // as you specify a parent activity in AndroidManifest.xml. 37 | int id = item.getItemId(); 38 | //noinspection SimplifiableIfStatement 39 | if (id == R.id.action_settings) { 40 | return true; 41 | }else if(id == android.R.id.home){ 42 | this.finish(); 43 | return true; 44 | } 45 | 46 | return super.onOptionsItemSelected(item); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/zs/it/testmaterialdesign/CoordinaterLayoutActivity.java: -------------------------------------------------------------------------------- 1 | package com.zs.it.testmaterialdesign; 2 | 3 | import android.content.DialogInterface; 4 | import android.os.Build; 5 | import android.os.Bundle; 6 | import android.support.design.widget.Snackbar; 7 | import android.support.v4.app.ActivityCompat; 8 | import android.support.v7.app.ActionBar; 9 | import android.support.v7.app.AppCompatActivity; 10 | import android.support.v7.widget.DefaultItemAnimator; 11 | import android.support.v7.widget.GridLayoutManager; 12 | import android.support.v7.widget.LinearLayoutManager; 13 | import android.support.v7.widget.RecyclerView; 14 | import android.support.v7.widget.StaggeredGridLayoutManager; 15 | import android.support.v7.widget.Toolbar; 16 | import android.transition.Explode; 17 | import android.view.LayoutInflater; 18 | import android.view.Menu; 19 | import android.view.MenuItem; 20 | import android.view.MotionEvent; 21 | import android.view.View; 22 | import android.view.ViewGroup; 23 | import android.view.Window; 24 | import android.widget.ListView; 25 | import android.widget.TextView; 26 | import android.widget.Toast; 27 | 28 | import java.util.ArrayList; 29 | import java.util.List; 30 | 31 | public class CoordinaterLayoutActivity extends AppCompatActivity { 32 | 33 | private RecyclerView mRecyclerView; 34 | 35 | private List listStr; 36 | 37 | private MyAdapter mAdapter; 38 | 39 | @Override 40 | protected void onCreate(Bundle savedInstanceState) { 41 | getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS); 42 | if(Build.VERSION.SDK_INT >= 21){ 43 | // getWindow().setAllowEnterTransitionOverlap(true); 44 | getWindow().setEnterTransition(new Explode()); 45 | getWindow().setExitTransition(new Explode()); 46 | } 47 | 48 | super.onCreate(savedInstanceState); 49 | setContentView(R.layout.activity_coordinater_layout); 50 | 51 | this.initData(); 52 | 53 | Toolbar toolbar = (Toolbar) this.findViewById(R.id.toolbar); 54 | setSupportActionBar(toolbar); 55 | 56 | ActionBar ab = getSupportActionBar(); 57 | ab.setDisplayHomeAsUpEnabled(true); 58 | 59 | mRecyclerView = (RecyclerView) this.findViewById(R.id.recyclerview); 60 | /*设置布局管理器 61 | LinearLayoutManager 现行管理器,支持横向、纵向。 62 | GridLayoutManager 网格布局管理器 63 | StaggeredGridLayoutManager 瀑布就式布局管理器*/ 64 | // mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); 65 | //添加分割线 66 | // mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST)); 67 | 68 | // mRecyclerView.setLayoutManager(new GridLayoutManager(this, 4)); 69 | //添加分割线 70 | mRecyclerView.addItemDecoration(new DividerGridItemDecoration(this)); 71 | 72 | mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.VERTICAL)); 73 | 74 | /*添加增减数据时的动画效果*/ 75 | mRecyclerView.setItemAnimator(new DefaultItemAnimator()); 76 | mRecyclerView.setAdapter(mAdapter = new MyAdapter()); 77 | 78 | } 79 | 80 | private void initData(){ 81 | listStr = new ArrayList(); 82 | for (int i = 0; i < 50; i++){ 83 | listStr.add("" + i); 84 | } 85 | } 86 | 87 | /** 88 | * 新增一条数据 89 | */ 90 | private void addData(){ 91 | int position = listStr.size()/2; 92 | listStr.add(position, "ADD"); 93 | mAdapter.notifyItemInserted(position);//更新显示列表 94 | } 95 | 96 | /** 97 | * 删除一条数据 98 | */ 99 | private void deleteData(){ 100 | int position = listStr.size()/2; 101 | listStr.remove(position); 102 | mAdapter.notifyItemRemoved(position);//更新显示列表 103 | } 104 | 105 | @Override 106 | public boolean onCreateOptionsMenu(Menu menu) { 107 | // Inflate the menu; this adds items to the action bar if it is present. 108 | getMenuInflater().inflate(R.menu.menu_coordinater_layout_activity, menu); 109 | return true; 110 | } 111 | 112 | @Override 113 | public boolean onOptionsItemSelected(MenuItem item) { 114 | // Handle action bar item clicks here. The action bar will 115 | // automatically handle clicks on the Home/Up button, so long 116 | // as you specify a parent activity in AndroidManifest.xml. 117 | int id = item.getItemId(); 118 | 119 | //noinspection SimplifiableIfStatement 120 | if (id == R.id.action_settings) { 121 | return true; 122 | }else if(id == android.R.id.home){ 123 | this.finish(); 124 | return true; 125 | }else if(id == R.id.action_add){ 126 | this.addData(); 127 | return true; 128 | }else if(id == R.id.action_delete){ 129 | this.deleteData(); 130 | return true; 131 | } 132 | 133 | return super.onOptionsItemSelected(item); 134 | } 135 | 136 | class MyAdapter extends RecyclerView.Adapter { 137 | 138 | 139 | /** 140 | * Called when RecyclerView needs a new {@link ViewHolder} of the given type to represent 141 | * an item. 142 | *

143 | * This new ViewHolder should be constructed with a new View that can represent the items 144 | * of the given type. You can either create a new View manually or inflate it from an XML 145 | * layout file. 146 | *

147 | * The new ViewHolder will be used to display items of the adapter using 148 | * {@link #onBindViewHolder(ViewHolder, int, List)}. Since it will be re-used to display 149 | * different items in the data set, it is a good idea to cache references to sub views of 150 | * the View to avoid unnecessary {@link View#findViewById(int)} calls. 151 | * 152 | * @param parent The ViewGroup into which the new View will be added after it is bound to 153 | * an adapter position. 154 | * @param viewType The view type of the new View. 155 | * @return A new ViewHolder that holds a View of the given view type. 156 | * @see #getItemViewType(int) 157 | * @see #onBindViewHolder(ViewHolder, int) 158 | */ 159 | @Override 160 | public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 161 | MyViewHolder holder = new MyViewHolder( 162 | LayoutInflater.from(CoordinaterLayoutActivity.this) 163 | .inflate(R.layout.layout_simple_item, parent, false)); 164 | return holder; 165 | } 166 | 167 | /** 168 | * Called by RecyclerView to display the data at the specified position. This method should 169 | * update the contents of the {@link ViewHolder#itemView} to reflect the item at the given 170 | * position. 171 | *

172 | * Note that unlike {@link ListView}, RecyclerView will not call this method 173 | * again if the position of the item changes in the data set unless the item itself is 174 | * invalidated or the new position cannot be determined. For this reason, you should only 175 | * use the position parameter while acquiring the related data item inside 176 | * this method and should not keep a copy of it. If you need the position of an item later 177 | * on (e.g. in a click listener), use {@link ViewHolder#getAdapterPosition()} which will 178 | * have the updated adapter position. 179 | *

180 | * Override {@link #onBindViewHolder(ViewHolder, int, List)} instead if Adapter can 181 | * handle effcient partial bind. 182 | * 183 | * @param holder The ViewHolder which should be updated to represent the contents of the 184 | * item at the given position in the data set. 185 | * @param position The position of the item within the adapter's data set. 186 | */ 187 | @Override 188 | public void onBindViewHolder(MyViewHolder holder, int position) { 189 | holder.tvNum.setText(listStr.get(position)); 190 | 191 | int height = 100; 192 | if(position%5 == 1){ 193 | height = 200; 194 | }else if(position%5 == 2){ 195 | height = 100; 196 | }else if(position%5 == 3){ 197 | height = 250; 198 | }else if(position%5 == 4){ 199 | height = 150; 200 | }else if(position%5 == 0){ 201 | height = 180; 202 | } 203 | holder.tvNum.setHeight(height); 204 | } 205 | 206 | /** 207 | * Returns the total number of items in the data set hold by the adapter. 208 | * 209 | * @return The total number of items in this adapter. 210 | */ 211 | @Override 212 | public int getItemCount() { 213 | return listStr.size(); 214 | } 215 | 216 | 217 | 218 | class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener{ 219 | TextView tvNum; 220 | 221 | public MyViewHolder(View itemView) { 222 | super(itemView); 223 | tvNum = (TextView) itemView.findViewById(R.id.tv_simple_item); 224 | itemView.setOnClickListener(this); 225 | itemView.setOnLongClickListener(this); 226 | 227 | } 228 | 229 | /** 230 | * Called when a view has been clicked and held. 231 | * 232 | * @param v The view that was clicked and held. 233 | * @return true if the callback consumed the long click, false otherwise. 234 | */ 235 | @Override 236 | public boolean onLongClick(View v) { 237 | Snackbar sb = Snackbar.make(v, "长按" + mRecyclerView.getChildLayoutPosition(v), Snackbar.LENGTH_LONG); 238 | sb.setAction("action", new View.OnClickListener() { 239 | @Override 240 | public void onClick(View v) { 241 | Toast.makeText(CoordinaterLayoutActivity.this, "action", Toast.LENGTH_SHORT).show(); 242 | } 243 | }); 244 | sb.show(); 245 | return false; 246 | } 247 | 248 | /** 249 | * Called when a view has been clicked. 250 | * 251 | * @param v The view that was clicked. 252 | */ 253 | @Override 254 | public void onClick(View v) { 255 | Toast.makeText(CoordinaterLayoutActivity.this, "点击" + mRecyclerView.getChildLayoutPosition(v), Toast.LENGTH_SHORT).show(); 256 | } 257 | } 258 | } 259 | 260 | @Override 261 | public void onBackPressed() { 262 | // if(Build.VERSION.SDK_INT >= 21){ 263 | // //如果需要逆转该过渡动画,使用Activity.finishAfterTransition()方法代替Activity.finish() 264 | // this.finishAfterTransition(); 265 | // }else{ 266 | // super.onBackPressed(); 267 | // } 268 | //使用兼容包关闭 269 | ActivityCompat.finishAfterTransition(this); 270 | } 271 | } 272 | -------------------------------------------------------------------------------- /app/src/main/java/com/zs/it/testmaterialdesign/DividerGridItemDecoration.java: -------------------------------------------------------------------------------- 1 | package com.zs.it.testmaterialdesign; 2 | 3 | 4 | import android.content.Context; 5 | import android.content.res.TypedArray; 6 | import android.graphics.Canvas; 7 | import android.graphics.Rect; 8 | import android.graphics.drawable.Drawable; 9 | import android.support.v7.widget.GridLayoutManager; 10 | import android.support.v7.widget.RecyclerView; 11 | import android.support.v7.widget.RecyclerView.LayoutManager; 12 | import android.support.v7.widget.RecyclerView.State; 13 | import android.support.v7.widget.StaggeredGridLayoutManager; 14 | import android.view.View; 15 | 16 | /** 17 | * 引用http://blog.csdn.net/lmj623565791/article/details/45059587 18 | * Created by zhangshuo on 2015/12/15. 19 | */ 20 | public class DividerGridItemDecoration extends RecyclerView.ItemDecoration 21 | { 22 | 23 | private static final int[] ATTRS = new int[] { android.R.attr.listDivider }; 24 | private Drawable mDivider; 25 | 26 | public DividerGridItemDecoration(Context context) 27 | { 28 | final TypedArray a = context.obtainStyledAttributes(ATTRS); 29 | mDivider = a.getDrawable(0); 30 | a.recycle(); 31 | } 32 | 33 | @Override 34 | public void onDraw(Canvas c, RecyclerView parent, State state) 35 | { 36 | 37 | drawHorizontal(c, parent); 38 | drawVertical(c, parent); 39 | 40 | } 41 | 42 | private int getSpanCount(RecyclerView parent) 43 | { 44 | // 列数 45 | int spanCount = -1; 46 | LayoutManager layoutManager = parent.getLayoutManager(); 47 | if (layoutManager instanceof GridLayoutManager) 48 | { 49 | 50 | spanCount = ((GridLayoutManager) layoutManager).getSpanCount(); 51 | } else if (layoutManager instanceof StaggeredGridLayoutManager) 52 | { 53 | spanCount = ((StaggeredGridLayoutManager) layoutManager) 54 | .getSpanCount(); 55 | } 56 | return spanCount; 57 | } 58 | 59 | public void drawHorizontal(Canvas c, RecyclerView parent) 60 | { 61 | int childCount = parent.getChildCount(); 62 | for (int i = 0; i < childCount; i++) 63 | { 64 | final View child = parent.getChildAt(i); 65 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child 66 | .getLayoutParams(); 67 | final int left = child.getLeft() - params.leftMargin; 68 | final int right = child.getRight() + params.rightMargin 69 | + mDivider.getIntrinsicWidth(); 70 | final int top = child.getBottom() + params.bottomMargin; 71 | final int bottom = top + mDivider.getIntrinsicHeight(); 72 | mDivider.setBounds(left, top, right, bottom); 73 | mDivider.draw(c); 74 | } 75 | } 76 | 77 | public void drawVertical(Canvas c, RecyclerView parent) 78 | { 79 | final int childCount = parent.getChildCount(); 80 | for (int i = 0; i < childCount; i++) 81 | { 82 | final View child = parent.getChildAt(i); 83 | 84 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child 85 | .getLayoutParams(); 86 | final int top = child.getTop() - params.topMargin; 87 | final int bottom = child.getBottom() + params.bottomMargin; 88 | final int left = child.getRight() + params.rightMargin; 89 | final int right = left + mDivider.getIntrinsicWidth(); 90 | 91 | mDivider.setBounds(left, top, right, bottom); 92 | mDivider.draw(c); 93 | } 94 | } 95 | 96 | private boolean isLastColum(RecyclerView parent, int pos, int spanCount, 97 | int childCount) 98 | { 99 | LayoutManager layoutManager = parent.getLayoutManager(); 100 | if (layoutManager instanceof GridLayoutManager) 101 | { 102 | if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边 103 | { 104 | return true; 105 | } 106 | } else if (layoutManager instanceof StaggeredGridLayoutManager) 107 | { 108 | int orientation = ((StaggeredGridLayoutManager) layoutManager) 109 | .getOrientation(); 110 | if (orientation == StaggeredGridLayoutManager.VERTICAL) 111 | { 112 | if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边 113 | { 114 | return true; 115 | } 116 | } else 117 | { 118 | childCount = childCount - childCount % spanCount; 119 | if (pos >= childCount)// 如果是最后一列,则不需要绘制右边 120 | return true; 121 | } 122 | } 123 | return false; 124 | } 125 | 126 | private boolean isLastRaw(RecyclerView parent, int pos, int spanCount, 127 | int childCount) 128 | { 129 | LayoutManager layoutManager = parent.getLayoutManager(); 130 | if (layoutManager instanceof GridLayoutManager) 131 | { 132 | childCount = childCount - childCount % spanCount; 133 | if (pos >= childCount)// 如果是最后一行,则不需要绘制底部 134 | return true; 135 | } else if (layoutManager instanceof StaggeredGridLayoutManager) 136 | { 137 | int orientation = ((StaggeredGridLayoutManager) layoutManager) 138 | .getOrientation(); 139 | // StaggeredGridLayoutManager 且纵向滚动 140 | if (orientation == StaggeredGridLayoutManager.VERTICAL) 141 | { 142 | childCount = childCount - childCount % spanCount; 143 | // 如果是最后一行,则不需要绘制底部 144 | if (pos >= childCount) 145 | return true; 146 | } else 147 | // StaggeredGridLayoutManager 且横向滚动 148 | { 149 | // 如果是最后一行,则不需要绘制底部 150 | if ((pos + 1) % spanCount == 0) 151 | { 152 | return true; 153 | } 154 | } 155 | } 156 | return false; 157 | } 158 | 159 | @Override 160 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) 161 | { 162 | int spanCount = getSpanCount(parent); 163 | int childCount = parent.getAdapter().getItemCount(); 164 | if (isLastRaw(parent, parent.getChildLayoutPosition(view), spanCount, childCount))// 如果是最后一行,则不需要绘制底部 165 | { 166 | outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); 167 | } else if (isLastColum(parent, parent.getChildLayoutPosition(view), spanCount, childCount))// 如果是最后一列,则不需要绘制右边 168 | { 169 | outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); 170 | } else 171 | { 172 | outRect.set(0, 0, mDivider.getIntrinsicWidth(), 173 | mDivider.getIntrinsicHeight()); 174 | } 175 | } 176 | } -------------------------------------------------------------------------------- /app/src/main/java/com/zs/it/testmaterialdesign/DividerItemDecoration.java: -------------------------------------------------------------------------------- 1 | package com.zs.it.testmaterialdesign; 2 | /* 3 | * Copyright (C) 2014 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * limitations under the License. 7 | */ 8 | 9 | import android.content.Context; 10 | import android.content.res.TypedArray; 11 | import android.graphics.Canvas; 12 | import android.graphics.Rect; 13 | import android.graphics.drawable.Drawable; 14 | import android.support.v7.widget.LinearLayoutManager; 15 | import android.support.v7.widget.RecyclerView; 16 | import android.support.v7.widget.RecyclerView.State; 17 | import android.util.Log; 18 | import android.view.View; 19 | 20 | 21 | /** 22 | * This class is from the v7 samples of the Android SDK. It's not by me! 23 | *

24 | * See the license above for details. 25 | */ 26 | public class DividerItemDecoration extends RecyclerView.ItemDecoration { 27 | 28 | private static final int[] ATTRS = new int[]{ 29 | android.R.attr.listDivider 30 | }; 31 | 32 | public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; 33 | 34 | public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; 35 | 36 | private Drawable mDivider; 37 | 38 | private int mOrientation; 39 | 40 | public DividerItemDecoration(Context context, int orientation) { 41 | final TypedArray a = context.obtainStyledAttributes(ATTRS); 42 | mDivider = a.getDrawable(0); 43 | a.recycle(); 44 | setOrientation(orientation); 45 | } 46 | 47 | public void setOrientation(int orientation) { 48 | if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) { 49 | throw new IllegalArgumentException("invalid orientation"); 50 | } 51 | mOrientation = orientation; 52 | } 53 | 54 | /*onDraw方法先于drawChildren 55 | onDrawOver在drawChildren之后,一般我们选择复写其中一个即可。 56 | getItemOffsets 可以通过outRect.set()为每个Item设置一定的偏移量,主要用于绘制Decorator。*/ 57 | 58 | @Override 59 | public void onDraw(Canvas c, RecyclerView parent, State state) { 60 | Log.v("DividerItemdecoration", "onDraw()"); 61 | 62 | if (mOrientation == VERTICAL_LIST) { 63 | drawVertical(c, parent); 64 | } else { 65 | drawHorizontal(c, parent); 66 | } 67 | 68 | } 69 | 70 | 71 | public void drawVertical(Canvas c, RecyclerView parent) { 72 | final int left = parent.getPaddingLeft(); 73 | final int right = parent.getWidth() - parent.getPaddingRight(); 74 | 75 | final int childCount = parent.getChildCount(); 76 | for (int i = 0; i < childCount; i++) { 77 | final View child = parent.getChildAt(i); 78 | android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(parent.getContext()); 79 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child 80 | .getLayoutParams(); 81 | final int top = child.getBottom() + params.bottomMargin;//当前item的bottom位置 + bottomMargin作为当前divider的top位置 82 | final int bottom = top + mDivider.getIntrinsicHeight();//divider的Top位置 + dividerHeight最为divider的bottom位置 83 | //设置divider绘制的位置 84 | mDivider.setBounds(left, top, right, bottom); 85 | mDivider.draw(c); 86 | } 87 | } 88 | 89 | public void drawHorizontal(Canvas c, RecyclerView parent) { 90 | final int top = parent.getPaddingTop(); 91 | final int bottom = parent.getHeight() - parent.getPaddingBottom(); 92 | 93 | final int childCount = parent.getChildCount(); 94 | for (int i = 0; i < childCount; i++) { 95 | final View child = parent.getChildAt(i); 96 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child 97 | .getLayoutParams(); 98 | final int left = child.getRight() + params.rightMargin; 99 | final int right = left + mDivider.getIntrinsicHeight(); 100 | mDivider.setBounds(left, top, right, bottom); 101 | mDivider.draw(c); 102 | } 103 | } 104 | 105 | @Override 106 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) { 107 | if (mOrientation == VERTICAL_LIST) { 108 | //设置偏移量,在每个item下增加mDivider.getIntrinsicHeight()的高度区域,作为绘制divider的区域 109 | outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); 110 | } else { 111 | outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /app/src/main/java/com/zs/it/testmaterialdesign/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.zs.it.testmaterialdesign; 2 | 3 | import android.app.ActivityOptions; 4 | import android.content.Intent; 5 | import android.graphics.drawable.RippleDrawable; 6 | import android.os.Build; 7 | import android.support.design.widget.CoordinatorLayout; 8 | import android.support.design.widget.FloatingActionButton; 9 | import android.support.design.widget.NavigationView; 10 | import android.support.design.widget.Snackbar; 11 | import android.support.design.widget.TextInputLayout; 12 | import android.support.v7.app.ActionBarDrawerToggle; 13 | import android.support.v7.widget.SearchView; 14 | import android.support.v7.widget.ShareActionProvider; 15 | import android.support.v4.view.MenuItemCompat; 16 | import android.support.v4.widget.DrawerLayout; 17 | import android.support.v7.app.ActionBar; 18 | import android.support.v7.app.AppCompatActivity; 19 | import android.os.Bundle; 20 | import android.support.v7.widget.Toolbar; 21 | import android.text.TextUtils; 22 | import android.transition.Explode; 23 | import android.util.TypedValue; 24 | import android.view.Menu; 25 | import android.view.MenuItem; 26 | import android.view.View; 27 | import android.view.ViewConfiguration; 28 | import android.view.Window; 29 | import android.widget.ArrayAdapter; 30 | import android.widget.Button; 31 | import android.widget.EditText; 32 | import android.widget.ImageView; 33 | import android.widget.LinearLayout; 34 | import android.widget.SpinnerAdapter; 35 | import android.widget.Toast; 36 | 37 | import java.lang.reflect.Field; 38 | import java.lang.reflect.Method; 39 | 40 | public class MainActivity extends AppCompatActivity { 41 | 42 | private DrawerLayout drawerLayout; 43 | private NavigationView navigationView; 44 | 45 | private TextInputLayout tilAccount, tilPassword; 46 | private EditText etAccount, etPassword; 47 | 48 | private Button btn1, btn5; 49 | 50 | private FloatingActionButton fabtn, fabtn2, fab, fab2; 51 | 52 | private CoordinatorLayout coordinatorLayout; 53 | 54 | @Override 55 | protected void onCreate(Bundle savedInstanceState) { 56 | 57 | getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS); 58 | if(Build.VERSION.SDK_INT >= 21){ 59 | // getWindow().setAllowEnterTransitionOverlap(true); 60 | getWindow().setEnterTransition(new Explode()); 61 | getWindow().setExitTransition(new Explode()); 62 | } 63 | super.onCreate(savedInstanceState); 64 | setContentView(R.layout.activity_main); 65 | 66 | drawerLayout = (DrawerLayout)this.findViewById(R.id.drawerlayout); 67 | navigationView = (NavigationView) this.findViewById(R.id.navigationview); 68 | 69 | Toolbar toolbar = (Toolbar) this.findViewById(R.id.toolbar); 70 | setSupportActionBar(toolbar); 71 | 72 | final ActionBar ab = getSupportActionBar(); 73 | // ab.setHomeAsUpIndicator(R.mipmap.ic_brightness_medium_white_36dp); 74 | ab.setDisplayHomeAsUpEnabled(true); 75 | 76 | //设置actionBar返回按钮跟随DrawerLayout的侧滑状态改变 77 | ActionBarDrawerToggle abdt = new ActionBarDrawerToggle(this, drawerLayout,toolbar, R.string.open, R.string.close); 78 | abdt.syncState(); 79 | drawerLayout.setDrawerListener(abdt); 80 | 81 | setupDrawerContent(navigationView); 82 | 83 | fabtn = (FloatingActionButton) this.findViewById(R.id.fabtn); 84 | 85 | fabtn2 = (FloatingActionButton) this.findViewById(R.id.fabtn2); 86 | 87 | fab = (FloatingActionButton) this.findViewById(R.id.fab); 88 | 89 | fab2 = (FloatingActionButton)this.findViewById(R.id.fab2); 90 | 91 | coordinatorLayout = (CoordinatorLayout) this.findViewById(R.id.coordinatorlayout); 92 | 93 | tilAccount = (TextInputLayout) this.findViewById(R.id.tilayout_account); 94 | etAccount = tilAccount.getEditText(); 95 | tilPassword = (TextInputLayout) this.findViewById(R.id.tilayout_password); 96 | etPassword = tilPassword.getEditText(); 97 | 98 | btn1 = (Button) this.findViewById(R.id.btn1); 99 | 100 | // RippleDrawable.createRipple(btn1, getColor(android.R.color.holo_red_dark)); 101 | 102 | 103 | btn5 = (Button) this.findViewById(R.id.btn5); 104 | btn5.setOnClickListener(new View.OnClickListener() { 105 | @Override 106 | public void onClick(View v) { 107 | 108 | Intent it = new Intent(); 109 | it.setClass(MainActivity.this, TestAnimationActivity.class); 110 | if(Build.VERSION.SDK_INT >= 21){ 111 | startActivity(it, 112 | ActivityOptions.makeSceneTransitionAnimation(MainActivity.this).toBundle()); 113 | }else{ 114 | startActivity(it); 115 | } 116 | } 117 | }); 118 | 119 | navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { 120 | @Override 121 | public boolean onNavigationItemSelected(MenuItem item) { 122 | item.setChecked(true); 123 | drawerLayout.closeDrawers(); 124 | return false; 125 | } 126 | }); 127 | 128 | 129 | fabtn.setOnClickListener(new View.OnClickListener() { 130 | @Override 131 | public void onClick(View v) { 132 | if (TextUtils.isEmpty(tilAccount.getError())) { 133 | tilAccount.setError("账户格式不正确"); 134 | tilPassword.setError("密码有误"); 135 | } else { 136 | tilAccount.setError(null); 137 | tilPassword.setError(null); 138 | } 139 | 140 | Snackbar snackbar = Snackbar.make(v, "哈哈哈", Snackbar.LENGTH_INDEFINITE); 141 | snackbar.setAction("test", new View.OnClickListener() { 142 | @Override 143 | public void onClick(View v) { 144 | Toast.makeText(MainActivity.this, "嘎嘎嘎", Toast.LENGTH_SHORT).show(); 145 | } 146 | }); 147 | snackbar.show(); 148 | } 149 | }); 150 | 151 | fabtn2.setOnClickListener(new View.OnClickListener() { 152 | @Override 153 | public void onClick(View v) { 154 | Snackbar snackbar = Snackbar.make(v, "test snackbar", Snackbar.LENGTH_LONG); 155 | snackbar.setAction("test", new View.OnClickListener() { 156 | @Override 157 | public void onClick(View v) { 158 | Toast.makeText(MainActivity.this, "snackbar action", Toast.LENGTH_SHORT).show(); 159 | } 160 | }); 161 | snackbar.getView().setBackgroundResource(android.R.color.holo_orange_light); 162 | snackbar.setActionTextColor(getResources().getColor(android.R.color.holo_purple)); 163 | snackbar.show(); 164 | 165 | Intent it = new Intent(); 166 | it.setClass(MainActivity.this, TabLayoutActivity.class); 167 | startActivity(it); 168 | } 169 | }); 170 | 171 | fab.setOnClickListener(new View.OnClickListener() { 172 | @Override 173 | public void onClick(View v) { 174 | Intent it = new Intent(); 175 | it.setClass(MainActivity.this, CoordinaterLayoutActivity.class); 176 | startActivity(it); 177 | } 178 | }); 179 | 180 | fab2.setOnClickListener(new View.OnClickListener() { 181 | @Override 182 | public void onClick(View v) { 183 | Intent it = new Intent(); 184 | it.setClass(MainActivity.this, CollapsingToolbarLayoutActivity.class); 185 | startActivity(it); 186 | } 187 | }); 188 | 189 | SpinnerAdapter mSpinnerAdapter = ArrayAdapter.createFromResource(this, 190 | R.array.action_list, 191 | android.R.layout.simple_spinner_dropdown_item); 192 | /** 193 | * 在这里配合Fragment,实现不同的页面导航 194 | */ 195 | ActionBar.OnNavigationListener mOnNavigationListener = new ActionBar.OnNavigationListener() { 196 | 197 | @Override 198 | public boolean onNavigationItemSelected(int position, long itemId) { 199 | Toast.makeText(MainActivity.this, position + "", Toast.LENGTH_SHORT).show(); 200 | // Fragment newFragment = null; 201 | // switch (position) { 202 | // case 0: 203 | // newFragment = new Fragment1(); 204 | // break; 205 | // case 1: 206 | // newFragment = new Fragment2(); 207 | // break; 208 | // case 2: 209 | // newFragment = new Fragment3(); 210 | // break; 211 | // default: 212 | // break; 213 | // } 214 | // getSupportFragmentManager().beginTransaction() 215 | // .replace(R.id.container, newFragment, strings[position]) 216 | // .commit(); 217 | return true; 218 | } 219 | }; 220 | 221 | ab.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);//导航模式必须设为NAVIGATION_MODE_LIST 222 | ab.setListNavigationCallbacks(mSpinnerAdapter, 223 | mOnNavigationListener); 224 | 225 | 226 | setOverflowShowingAlways(); 227 | } 228 | 229 | /** 230 | * Google认为隐藏在overflow中的Action按钮都应该只显示文字; 231 | * overflow中的Action按钮应不应该显示图标,是由MenuBuilder这个类的setOptionalIconsVisible方法来决定的, 232 | * 如果我们在overflow被展开的时候给这个方法传入true,那么里面的每一个Action按钮对应的图标就都会显示出来了。 233 | * 调用的方法当然仍然是用反射了 234 | * @param featureId 235 | * @param menu 236 | * @return 237 | */ 238 | @Override 239 | public boolean onMenuOpened(int featureId, Menu menu) { 240 | if (featureId == Window.FEATURE_ACTION_BAR && menu != null) { 241 | if (menu.getClass().getSimpleName().equals("MenuBuilder")) { 242 | try { 243 | Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE); 244 | m.setAccessible(true); 245 | m.invoke(menu, true); 246 | } catch (Exception e) { 247 | } 248 | } 249 | } 250 | return super.onMenuOpened(featureId, menu); 251 | } 252 | 253 | private void setupDrawerContent(NavigationView navigationView) 254 | { 255 | navigationView.setNavigationItemSelectedListener( 256 | 257 | new NavigationView.OnNavigationItemSelectedListener() 258 | { 259 | 260 | @Override 261 | public boolean onNavigationItemSelected(MenuItem menuItem) 262 | { 263 | menuItem.setChecked(true); 264 | drawerLayout.closeDrawers(); 265 | return true; 266 | } 267 | }); 268 | } 269 | 270 | @Override 271 | public boolean onCreateOptionsMenu(Menu menu) { 272 | // Inflate the menu; this adds items to the action bar if it is present. 273 | getMenuInflater().inflate(R.menu.menu_main, menu); 274 | //搜索视窗,因为showAsAction="ifRoom",所以图三中出现了搜索按钮 275 | MenuItem searchItem = menu.findItem(R.id.menu_search); 276 | searchItem.expandActionView();//搜索框默认展开 277 | final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem); 278 | // searchView.setIconified(false); 279 | // searchView.setIconifiedByDefault(false); 280 | searchView.setSubmitButtonEnabled(true);//显示提交搜索按钮 281 | 282 | setSearchView(searchView); 283 | 284 | searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { 285 | @Override 286 | public boolean onQueryTextSubmit(String query) { 287 | Toast.makeText(MainActivity.this, query, Toast.LENGTH_SHORT).show(); 288 | return true; 289 | } 290 | 291 | @Override 292 | public boolean onQueryTextChange(String newText) { 293 | Toast.makeText(MainActivity.this, newText, Toast.LENGTH_SHORT).show(); 294 | return true; 295 | } 296 | }); 297 | 298 | MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() { 299 | 300 | /** 301 | * Called when a menu item with 302 | * is expanded. 303 | * 304 | * @param item Item that was expanded 305 | * @return true if the item should expand, false if expansion should be suppressed. 306 | */ 307 | @Override 308 | public boolean onMenuItemActionExpand(MenuItem item) { 309 | Toast.makeText(MainActivity.this, "展开", Toast.LENGTH_SHORT).show(); 310 | return true; 311 | } 312 | 313 | /** 314 | * Called when a menu item with 315 | * is collapsed. 316 | * 317 | * @param item Item that was collapsed 318 | * @return true if the item should collapse, false if collapsing should be suppressed. 319 | */ 320 | @Override 321 | public boolean onMenuItemActionCollapse(MenuItem item) { 322 | Toast.makeText(MainActivity.this, "收起", Toast.LENGTH_SHORT).show(); 323 | return true; 324 | } 325 | }); 326 | 327 | //分享视窗,因为showAsAction="never",所以只能在溢出菜单中才看见到 328 | ShareActionProvider mShareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(menu.findItem(R.id.menu_share)); 329 | Intent shareIntent = new Intent(Intent.ACTION_SEND); 330 | shareIntent.setType("image/*"); 331 | mShareActionProvider.setShareIntent(shareIntent); 332 | 333 | //设置视窗,MyActionProvider就是我们自定义的ActionProvider 334 | MyActionProvider myActionProvider = (MyActionProvider) MenuItemCompat.getActionProvider(menu.findItem(R.id.menu_setting)); 335 | 336 | return true; 337 | } 338 | 339 | @Override 340 | public boolean onOptionsItemSelected(MenuItem item) { 341 | // Handle action bar item clicks here. The action bar will 342 | // automatically handle clicks on the Home/Up button, so long 343 | // as you specify a parent activity in AndroidManifest.xml. 344 | int id = item.getItemId(); 345 | 346 | switch (id) { 347 | case R.id.menu_search: 348 | Toast.makeText(this, "搜索", Toast.LENGTH_SHORT).show(); 349 | return true; 350 | case R.id.menu_share: 351 | Toast.makeText(this, "分享", Toast.LENGTH_SHORT).show(); 352 | return true; 353 | case R.id.menu_setting: 354 | Toast.makeText(this, "设置", Toast.LENGTH_SHORT).show(); 355 | return true; 356 | case R.id.menu_theme: 357 | Toast.makeText(this, "主题", Toast.LENGTH_SHORT).show(); 358 | return true; 359 | case R.id.menu_system: 360 | Toast.makeText(this, "系统设置", Toast.LENGTH_SHORT).show(); 361 | return true; 362 | case R.id.menu_account://第二种实现自定义ActionProvider的方式,见MyActionProvider2 363 | Toast.makeText(this, "账户", Toast.LENGTH_SHORT).show(); 364 | return true; 365 | case R.id.menu_more://第一种实现自定义ActionProvider的方式,见MyActionProvider 366 | Toast.makeText(this, "更多", Toast.LENGTH_SHORT).show(); 367 | return true; 368 | 369 | case R.id.menu_help: 370 | Toast.makeText(this, "帮助", Toast.LENGTH_SHORT).show(); 371 | return true; 372 | default: 373 | return super.onOptionsItemSelected(item); 374 | } 375 | 376 | } 377 | 378 | 379 | /** 380 | * 设置SearchView,这里通过id映射获取searchView中的各个组件,并为其设置样式 381 | * @param mSearchView 382 | */ 383 | private void setSearchView(SearchView mSearchView) { 384 | final float density = getResources().getDisplayMetrics().density; 385 | mSearchView.setIconified(false); 386 | mSearchView.setIconifiedByDefault(false); 387 | final int closeImgId = getResources().getIdentifier("search_close_btn", "id", getPackageName()); 388 | ImageView closeImg = (ImageView) mSearchView.findViewById(closeImgId); 389 | if (closeImg != null) { 390 | LinearLayout.LayoutParams paramsImg = (LinearLayout.LayoutParams) closeImg.getLayoutParams(); 391 | paramsImg.topMargin = (int) (-2 * density); 392 | closeImg.setImageResource(android.R.drawable.ic_delete); 393 | closeImg.setLayoutParams(paramsImg); 394 | } 395 | final int editViewId = getResources().getIdentifier("search_src_text", "id", getPackageName()); 396 | SearchView.SearchAutoComplete mEdit = (SearchView.SearchAutoComplete) mSearchView.findViewById(editViewId); 397 | if (mEdit != null) { 398 | mEdit.setHintTextColor(getResources().getColor(android.R.color.holo_blue_light)); 399 | mEdit.setTextColor(getResources().getColor(android.R.color.holo_red_dark)); 400 | mEdit.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); 401 | mEdit.setHint("请输入关键字"); 402 | } 403 | LinearLayout rootView = (LinearLayout) mSearchView.findViewById(R.id.search_bar); 404 | rootView.setBackgroundResource(android.R.color.holo_orange_dark); 405 | rootView.setClickable(true); 406 | LinearLayout editLayout = (LinearLayout) mSearchView.findViewById(R.id.search_plate); 407 | LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) editLayout.getLayoutParams(); 408 | LinearLayout tipLayout = (LinearLayout) mSearchView.findViewById(R.id.search_edit_frame); 409 | LinearLayout.LayoutParams tipParams = (LinearLayout.LayoutParams) tipLayout.getLayoutParams(); 410 | tipParams.leftMargin = 0; 411 | tipParams.rightMargin = 0; 412 | tipLayout.setLayoutParams(tipParams); 413 | 414 | ImageView icTip = (ImageView) mSearchView.findViewById(R.id.search_mag_icon); 415 | icTip.setImageResource(android.R.drawable.ic_menu_search); 416 | // icTip.setVisibility(View.GONE); 417 | 418 | ImageView icGo = (ImageView) mSearchView.findViewById(R.id.search_go_btn); 419 | icGo.setImageResource(android.R.drawable.ic_media_play); 420 | // icGo.setVisibility(View.VISIBLE); 421 | 422 | params.topMargin = (int) (4 * density); 423 | editLayout.setLayoutParams(params); 424 | 425 | // mSearchView.setSubmitButtonEnabled(false); 426 | 427 | } 428 | 429 | 430 | /** 431 | * 如果手机没有物理Menu键的话,overflow按钮就可以显示,如果有物理Menu键的话,overflow按钮就不会显示出来; 432 | * 在ViewConfiguration这个类中有一个叫做sHasPermanentMenuKey的静态变量,系统就是根据这个变量的值来判断手机有没有物理Menu键的。 433 | * 当然这是一个内部变量,我们无法直接访问它,但是可以通过反射的方式修改它的值,让它永远为false就可以了 434 | */ 435 | private void setOverflowShowingAlways() { 436 | try { 437 | ViewConfiguration config = ViewConfiguration.get(this); 438 | Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey"); 439 | menuKeyField.setAccessible(true); 440 | menuKeyField.setBoolean(config, false); 441 | } catch (Exception e) { 442 | e.printStackTrace(); 443 | } 444 | } 445 | 446 | 447 | 448 | 449 | } 450 | -------------------------------------------------------------------------------- /app/src/main/java/com/zs/it/testmaterialdesign/MuchSharedTransitionActivity.java: -------------------------------------------------------------------------------- 1 | package com.zs.it.testmaterialdesign; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.view.Menu; 6 | import android.view.MenuItem; 7 | 8 | public class MuchSharedTransitionActivity extends AppCompatActivity { 9 | 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.activity_much_shared_transition); 14 | } 15 | 16 | @Override 17 | public boolean onCreateOptionsMenu(Menu menu) { 18 | // Inflate the menu; this adds items to the action bar if it is present. 19 | getMenuInflater().inflate(R.menu.menu_much_shared_transition, menu); 20 | return true; 21 | } 22 | 23 | @Override 24 | public boolean onOptionsItemSelected(MenuItem item) { 25 | // Handle action bar item clicks here. The action bar will 26 | // automatically handle clicks on the Home/Up button, so long 27 | // as you specify a parent activity in AndroidManifest.xml. 28 | int id = item.getItemId(); 29 | 30 | //noinspection SimplifiableIfStatement 31 | if (id == R.id.action_settings) { 32 | return true; 33 | } 34 | 35 | return super.onOptionsItemSelected(item); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/zs/it/testmaterialdesign/MyActionProvider.java: -------------------------------------------------------------------------------- 1 | package com.zs.it.testmaterialdesign; 2 | 3 | import android.content.Context; 4 | import android.support.v4.view.ActionProvider; 5 | import android.support.v7.widget.PopupMenu; 6 | import android.view.LayoutInflater; 7 | import android.view.MenuInflater; 8 | import android.view.MenuItem; 9 | import android.view.SubMenu; 10 | import android.view.View; 11 | import android.widget.ImageView; 12 | import android.widget.Toast; 13 | 14 | /** 15 | * 自定义一个视窗操作器,实现构造函数和onCreateActionView即可;通过此种方式创建的自定义ActionView, 16 | * 只有显示在ActionBar上(即不在OverFlow中)时才能响应自定义ImageView的点击事件; 17 | * (在OverFlow中响应的是menu本身的事件,而非menu中的我们自定义的ImageView的事件) 18 | * 且显示的PopupMenu的点击事件无法在Activity的onOptionsItemSelected()中监听到; 19 | * Created by zhangshuo on 2015/12/7. 20 | */ 21 | public class MyActionProvider extends ActionProvider { 22 | 23 | 24 | private Context context; 25 | private LayoutInflater inflater; 26 | private View view; 27 | private ImageView button; 28 | 29 | PopupMenu mPopupMenu; 30 | 31 | public MyActionProvider(Context context) { 32 | super(context); 33 | // TODO Auto-generated constructor stub 34 | this.context = context; 35 | inflater = LayoutInflater.from(context); 36 | view = inflater.inflate(R.layout.myactionprovider, null); 37 | } 38 | 39 | 40 | @Override 41 | public View onCreateActionView() { 42 | // TODO Auto-generated method stub 43 | button = (ImageView) view.findViewById(R.id.iv); 44 | button.setOnClickListener(new View.OnClickListener() { 45 | 46 | @Override 47 | public void onClick(View v) { 48 | // TODO Auto-generated method stub 49 | showPopup(v); 50 | Toast.makeText(context, "显示PopupMenu", Toast.LENGTH_SHORT).show(); 51 | } 52 | }); 53 | return view; 54 | } 55 | 56 | /** 57 | * show the popup menu. 58 | * 59 | * @param v 60 | */ 61 | private void showPopup(View v) { 62 | mPopupMenu = new PopupMenu(context, v); 63 | mPopupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { 64 | 65 | @Override 66 | public boolean onMenuItemClick(MenuItem item) { 67 | switch (item.getItemId()){ 68 | case R.id.popup_menu1: 69 | Toast.makeText(context, "popup_menu1", Toast.LENGTH_SHORT).show(); 70 | break; 71 | case R.id.popup_menu2: 72 | Toast.makeText(context, "popup_menu2", Toast.LENGTH_SHORT).show(); 73 | break; 74 | } 75 | return false; 76 | } 77 | 78 | }); 79 | MenuInflater inflater = mPopupMenu.getMenuInflater(); 80 | inflater.inflate(R.menu.popup_menu, mPopupMenu.getMenu()); 81 | mPopupMenu.show(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/zs/it/testmaterialdesign/MyActionProvider2.java: -------------------------------------------------------------------------------- 1 | package com.zs.it.testmaterialdesign; 2 | 3 | import android.content.Context; 4 | import android.support.v4.view.ActionProvider; 5 | import android.view.LayoutInflater; 6 | import android.view.MenuItem; 7 | import android.view.SubMenu; 8 | import android.view.View; 9 | import android.widget.ImageView; 10 | import android.widget.Toast; 11 | 12 | /** 13 | * 自定义一个视窗操作器,通过重写hasSubMenu返回true和重写onPrepareSubMenu添加子菜单项实现 14 | * Created by zhangshuo on 2015/12/7. 15 | */ 16 | public class MyActionProvider2 extends ActionProvider { 17 | 18 | 19 | private Context context; 20 | 21 | public MyActionProvider2(Context context) { 22 | super(context); 23 | // TODO Auto-generated constructor stub 24 | this.context = context; 25 | } 26 | 27 | 28 | @Override 29 | public View onCreateActionView() { 30 | // TODO Auto-generated method stub 31 | 32 | return null; 33 | } 34 | 35 | @Override 36 | public void onPrepareSubMenu(SubMenu subMenu) { 37 | subMenu.clear(); 38 | subMenu.add("sub menu 1").setIcon(R.mipmap.ic_brightness_medium_white_36dp) 39 | .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { 40 | @Override 41 | public boolean onMenuItemClick(MenuItem item) { 42 | Toast.makeText(context, "sub menu 1", Toast.LENGTH_SHORT).show(); 43 | return false; 44 | } 45 | }); 46 | subMenu.add("sub menu 2").setIcon(R.mipmap.ic_brightness_medium_white_36dp) 47 | .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { 48 | @Override 49 | public boolean onMenuItemClick(MenuItem item) { 50 | Toast.makeText(context, "sub menu 2", Toast.LENGTH_SHORT).show(); 51 | return false; 52 | } 53 | }); 54 | } 55 | 56 | @Override 57 | public boolean hasSubMenu() { 58 | return true; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/zs/it/testmaterialdesign/TabLayoutActivity.java: -------------------------------------------------------------------------------- 1 | package com.zs.it.testmaterialdesign; 2 | 3 | import android.support.design.widget.TabLayout; 4 | import android.support.v4.view.PagerAdapter; 5 | import android.support.v4.view.ViewPager; 6 | import android.support.v7.app.ActionBar; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.os.Bundle; 9 | import android.support.v7.widget.Toolbar; 10 | import android.view.Menu; 11 | import android.view.MenuItem; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | import android.widget.TextView; 15 | 16 | public class TabLayoutActivity extends AppCompatActivity { 17 | 18 | private TabLayout tablayout; 19 | private ViewPager viewPager; 20 | 21 | private String[] mTitle = new String[20]; 22 | private String[] mData = new String[20]; 23 | 24 | private MyAdapter mAdapter = null; 25 | 26 | @Override 27 | protected void onCreate(Bundle savedInstanceState) { 28 | super.onCreate(savedInstanceState); 29 | setContentView(R.layout.activity_tab_layout); 30 | tablayout = (TabLayout) this.findViewById(R.id.tablayout); 31 | viewPager = (ViewPager) this.findViewById(R.id.viewpager); 32 | 33 | Toolbar toolbar = (Toolbar) this.findViewById(R.id.toolbar); 34 | setSupportActionBar(toolbar); 35 | 36 | final ActionBar ab = getSupportActionBar(); 37 | // ab.setHomeAsUpIndicator(R.mipmap.ic_brightness_medium_white_36dp); 38 | ab.setDisplayHomeAsUpEnabled(true); 39 | 40 | for (int i = 0; i < mTitle.length; i++){ 41 | mTitle[i] = "title" + i; 42 | mData[i] = "data" + i; 43 | } 44 | 45 | tablayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { 46 | @Override 47 | public void onTabSelected(TabLayout.Tab tab) { 48 | viewPager.setCurrentItem(tab.getPosition()); 49 | } 50 | 51 | @Override 52 | public void onTabUnselected(TabLayout.Tab tab) { 53 | 54 | } 55 | 56 | @Override 57 | public void onTabReselected(TabLayout.Tab tab) { 58 | 59 | } 60 | }); 61 | 62 | mAdapter = new MyAdapter(); 63 | 64 | tablayout.setTabsFromPagerAdapter(mAdapter); 65 | 66 | TabLayout.TabLayoutOnPageChangeListener listener = new TabLayout.TabLayoutOnPageChangeListener(tablayout); 67 | 68 | viewPager.addOnPageChangeListener(listener); 69 | 70 | viewPager.setAdapter(mAdapter); 71 | 72 | //这个方法是addOnPageChangeListener和setOnTabSelectedListener的封装 73 | // tablayout.setupWithViewPager(viewPager); 74 | 75 | } 76 | 77 | 78 | class MyAdapter extends PagerAdapter { 79 | 80 | @Override 81 | public CharSequence getPageTitle(int position) { 82 | return mTitle[position]; 83 | } 84 | 85 | 86 | @Override 87 | public int getCount() { 88 | return mData.length; 89 | } 90 | 91 | @Override 92 | public boolean isViewFromObject(View arg0, Object arg1) { 93 | return arg0 == arg1; 94 | } 95 | 96 | @Override 97 | public void destroyItem(ViewGroup container, int position, Object object) { 98 | container.removeView((View) object); 99 | } 100 | 101 | @Override 102 | public Object instantiateItem(ViewGroup container, final int position) { 103 | TextView tv = new TextView(TabLayoutActivity.this); 104 | tv.setTextSize(30.f); 105 | tv.setText(mData[position]); 106 | ((ViewPager) container).addView(tv); 107 | return tv; 108 | } 109 | } 110 | 111 | @Override 112 | public boolean onCreateOptionsMenu(Menu menu) { 113 | // Inflate the menu; this adds items to the action bar if it is present. 114 | getMenuInflater().inflate(R.menu.menu_tab_layout, menu); 115 | return true; 116 | } 117 | 118 | @Override 119 | public boolean onOptionsItemSelected(MenuItem item) { 120 | // Handle action bar item clicks here. The action bar will 121 | // automatically handle clicks on the Home/Up button, so long 122 | // as you specify a parent activity in AndroidManifest.xml. 123 | int id = item.getItemId(); 124 | 125 | switch (id){ 126 | case android.R.id.home: 127 | this.finish(); 128 | return true; 129 | case R.id.action_settings: 130 | 131 | break; 132 | } 133 | 134 | return super.onOptionsItemSelected(item); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /app/src/main/java/com/zs/it/testmaterialdesign/TestActivityCompactActivity.java: -------------------------------------------------------------------------------- 1 | package com.zs.it.testmaterialdesign; 2 | 3 | import android.animation.Animator; 4 | import android.animation.AnimatorInflater; 5 | import android.animation.ObjectAnimator; 6 | import android.animation.StateListAnimator; 7 | import android.animation.ValueAnimator; 8 | import android.graphics.Path; 9 | import android.graphics.RectF; 10 | import android.graphics.drawable.Animatable; 11 | import android.graphics.drawable.AnimatedStateListDrawable; 12 | import android.graphics.drawable.Drawable; 13 | import android.graphics.drawable.StateListDrawable; 14 | import android.media.Image; 15 | import android.os.Build; 16 | import android.support.v4.app.ActivityCompat; 17 | import android.support.v7.app.AppCompatActivity; 18 | import android.os.Bundle; 19 | import android.view.Menu; 20 | import android.view.MenuItem; 21 | import android.view.View; 22 | import android.view.animation.PathInterpolator; 23 | import android.widget.Button; 24 | import android.widget.ImageView; 25 | import android.widget.Toast; 26 | 27 | public class TestActivityCompactActivity extends AppCompatActivity { 28 | 29 | private ImageView iv, ivAnim; 30 | 31 | private Button btnStart, btnPause, btnResume, btnStop, btnStateListAnimActive, btnStateListAnimDrawable, btnAnimatedVectorDrawable; 32 | 33 | private ObjectAnimator oa = null; 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | setContentView(R.layout.activity_test_activity_compact); 39 | 40 | iv = (ImageView) this.findViewById(R.id.iv); 41 | ivAnim = (ImageView) this.findViewById(R.id.iv_anim); 42 | btnStart = (Button) this.findViewById(R.id.btn_start); 43 | btnPause = (Button) this.findViewById(R.id.btn_pause); 44 | btnResume = (Button) this.findViewById(R.id.btn_resume); 45 | btnStop = (Button) this.findViewById(R.id.btn_stop); 46 | 47 | btnStateListAnimActive = (Button) this.findViewById(R.id.btn_state_list_anim_active); 48 | // btnStateListAnimDrawable = (Button) this.findViewById(R.id.btn_state_list_anim_drawable); 49 | 50 | // AnimatedStateListDrawable a = AnimatedStateListDrawable.createFro 51 | 52 | if(Build.VERSION.SDK_INT >= 21){ 53 | // 给视图分配动画使用android:stateListAnimator属性。 54 | // 在代码中使用,使用AnimatorInflater.loadStateListAnimator()方法,并且使用View.setStateListAnimator()方法。 55 | // 当你的主题是继承的Material主题,按钮默认有一个Z动画。如果需要避免这个动画,设置android:stateListAnimator属性为@null即可。 56 | StateListAnimator slAnim = AnimatorInflater.loadStateListAnimator(this, R.drawable.state_list_anim); 57 | btnStateListAnimActive.setStateListAnimator(slAnim); 58 | } 59 | 60 | btnAnimatedVectorDrawable = (Button) this.findViewById(R.id.btn_animated_vector_drawable); 61 | 62 | btnAnimatedVectorDrawable.setOnClickListener(new View.OnClickListener() { 63 | @Override 64 | public void onClick(View v) { 65 | Drawable drawable = btnAnimatedVectorDrawable.getBackground(); 66 | if(drawable instanceof Animatable){ 67 | //启动矢量图动画 68 | ((Animatable) drawable).start(); 69 | } 70 | } 71 | }); 72 | 73 | if(Build.VERSION.SDK_INT >= 21){ 74 | //起始颜色为红色 75 | int startColor = 0xffff0000; 76 | //终止颜色为绿色 77 | int endColor = 0xff00ff00; 78 | ObjectAnimator oa1 = ObjectAnimator.ofArgb(getWindow().getDecorView(), "backgroundColor", startColor, endColor); 79 | oa1.setDuration(5000); 80 | oa1.setRepeatCount(ValueAnimator.INFINITE); 81 | oa1.setRepeatMode(ValueAnimator.REVERSE); 82 | oa1.setInterpolator(new PathInterpolator(0.4f, 0, 1, 1)); 83 | oa1.start(); 84 | } 85 | 86 | 87 | btnStart.setOnClickListener(new View.OnClickListener() { 88 | @Override 89 | public void onClick(View v) { 90 | if(Build.VERSION.SDK_INT >= 21){ 91 | //PathInterpolator的代码使用方法 92 | Path path = new Path(); 93 | // path.addCircle(360, 360, 200, Path.Direction.CW);//无动画 94 | // Path path = new Path(); 95 | path.moveTo(100, 100); 96 | // path.lineTo(600, 100); 97 | // path.lineTo(100, 600); 98 | // path.lineTo(600, 600); 99 | // path.arcTo(new RectF(100, 100, 600, 900), 90, 180);//无动画 100 | path.cubicTo(100, 100, 500, 500, 200, 800); 101 | path.close(); 102 | 103 | oa = ObjectAnimator.ofFloat(ivAnim, ivAnim.X, ivAnim.Y, path); 104 | oa.setDuration(5000); 105 | oa.setRepeatCount(ValueAnimator.INFINITE); 106 | oa.setRepeatMode(ValueAnimator.REVERSE); 107 | oa.addListener(new Animator.AnimatorListener() { 108 | @Override 109 | public void onAnimationStart(Animator animation) { 110 | Toast.makeText(TestActivityCompactActivity.this, "开始", Toast.LENGTH_SHORT).show(); 111 | } 112 | 113 | @Override 114 | public void onAnimationEnd(Animator animation) { 115 | Toast.makeText(TestActivityCompactActivity.this, "结束", Toast.LENGTH_SHORT).show(); 116 | } 117 | 118 | @Override 119 | public void onAnimationCancel(Animator animation) { 120 | Toast.makeText(TestActivityCompactActivity.this, "取消", Toast.LENGTH_SHORT).show(); 121 | } 122 | 123 | @Override 124 | public void onAnimationRepeat(Animator animation) { 125 | Toast.makeText(TestActivityCompactActivity.this, "重复", Toast.LENGTH_SHORT).show(); 126 | } 127 | }); 128 | oa.addPauseListener(new Animator.AnimatorPauseListener() { 129 | @Override 130 | public void onAnimationPause(Animator animation) { 131 | Toast.makeText(TestActivityCompactActivity.this, "暂停", Toast.LENGTH_SHORT).show(); 132 | } 133 | 134 | @Override 135 | public void onAnimationResume(Animator animation) { 136 | Toast.makeText(TestActivityCompactActivity.this, "恢复", Toast.LENGTH_SHORT).show(); 137 | } 138 | }); 139 | oa.start(); 140 | } 141 | 142 | } 143 | }); 144 | 145 | btnPause.setOnClickListener(new View.OnClickListener() { 146 | @Override 147 | public void onClick(View v) { 148 | if(null != oa){ 149 | if(Build.VERSION.SDK_INT >= 19){ 150 | oa.pause(); 151 | } 152 | } 153 | } 154 | }); 155 | 156 | btnResume.setOnClickListener(new View.OnClickListener() { 157 | @Override 158 | public void onClick(View v) { 159 | if(null != oa){ 160 | if(Build.VERSION.SDK_INT >= 19){ 161 | oa.resume(); 162 | } 163 | } 164 | } 165 | }); 166 | 167 | btnStop.setOnClickListener(new View.OnClickListener() { 168 | @Override 169 | public void onClick(View v) { 170 | if(null != oa){ 171 | oa.cancel(); 172 | } 173 | } 174 | }); 175 | } 176 | 177 | @Override 178 | public boolean onCreateOptionsMenu(Menu menu) { 179 | // Inflate the menu; this adds items to the action bar if it is present. 180 | getMenuInflater().inflate(R.menu.menu_test_activity_compact, menu); 181 | return true; 182 | } 183 | 184 | @Override 185 | public boolean onOptionsItemSelected(MenuItem item) { 186 | // Handle action bar item clicks here. The action bar will 187 | // automatically handle clicks on the Home/Up button, so long 188 | // as you specify a parent activity in AndroidManifest.xml. 189 | int id = item.getItemId(); 190 | 191 | //noinspection SimplifiableIfStatement 192 | if (id == R.id.action_settings) { 193 | return true; 194 | } 195 | 196 | return super.onOptionsItemSelected(item); 197 | } 198 | 199 | @Override 200 | public void onBackPressed() { 201 | //使用兼容包关闭 202 | // super.onBackPressed(); 203 | ActivityCompat.finishAfterTransition(this); 204 | // overridePendingTransition(0, R.transition.change_image_transform); 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /app/src/main/java/com/zs/it/testmaterialdesign/TestAnimationActivity.java: -------------------------------------------------------------------------------- 1 | package com.zs.it.testmaterialdesign; 2 | 3 | import android.animation.Animator; 4 | import android.animation.AnimatorListenerAdapter; 5 | import android.annotation.SuppressLint; 6 | import android.annotation.TargetApi; 7 | import android.app.ActivityOptions; 8 | import android.content.Intent; 9 | import android.os.Build; 10 | import android.support.v4.app.ActivityCompat; 11 | import android.support.v4.app.ActivityOptionsCompat; 12 | import android.support.v7.app.AppCompatActivity; 13 | import android.os.Bundle; 14 | import android.transition.Explode; 15 | import android.util.Pair; 16 | import android.view.Menu; 17 | import android.view.MenuItem; 18 | import android.view.View; 19 | import android.view.ViewAnimationUtils; 20 | import android.view.Window; 21 | import android.widget.Button; 22 | import android.widget.ImageView; 23 | import android.widget.TextView; 24 | import android.widget.Toast; 25 | 26 | import junit.framework.Test; 27 | 28 | public class TestAnimationActivity extends AppCompatActivity { 29 | 30 | private ImageView ivPic, ivTransition1, ivTransition2, ivTransition4, ivTransition5, ivTransition6, ivCompact; 31 | private TextView tvTransition3; 32 | private Button btnControl, btnOne, btnMuch, btnActive; 33 | 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) { 36 | 37 | getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS); 38 | if(Build.VERSION.SDK_INT >= 21){ 39 | // getWindow().setAllowEnterTransitionOverlap(true); 40 | getWindow().setEnterTransition(new Explode()); 41 | getWindow().setExitTransition(new Explode()); 42 | } 43 | 44 | 45 | super.onCreate(savedInstanceState); 46 | setContentView(R.layout.activity_test_animation); 47 | 48 | ivPic = (ImageView) this.findViewById(R.id.iv_anim); 49 | ivTransition1 = (ImageView) this.findViewById(R.id.iv_transition1); 50 | ivTransition2 = (ImageView) this.findViewById(R.id.iv_transition2); 51 | tvTransition3 = (TextView) this.findViewById(R.id.tv_transition3); 52 | ivTransition4 = (ImageView) this.findViewById(R.id.iv_transition4); 53 | ivTransition5 = (ImageView) this.findViewById(R.id.iv_transition5); 54 | ivTransition6 = (ImageView) this.findViewById(R.id.iv_transition6); 55 | 56 | ivCompact = (ImageView) this.findViewById(R.id.iv_compact); 57 | 58 | btnControl = (Button) this.findViewById(R.id.btn_control); 59 | btnOne = (Button) this.findViewById(R.id.btn_one); 60 | btnMuch = (Button) this.findViewById(R.id.btn_much); 61 | btnActive = (Button) this.findViewById(R.id.btn_active); 62 | 63 | btnControl.setOnClickListener(new View.OnClickListener() { 64 | @Override 65 | public void onClick(View v) { 66 | if(Build.VERSION.SDK_INT >= 21){ 67 | if(ivPic.getVisibility() == View.VISIBLE){ 68 | //当前可视,执行隐藏 69 | 70 | // get the center for the clipping circle 71 | int cx = (ivPic.getLeft() + ivPic.getRight()) / 2; 72 | int cy = (ivPic.getTop() + ivPic.getBottom()) / 2; 73 | 74 | // get the initial radius for the clipping circle 75 | int initialRadius = ivPic.getWidth(); 76 | 77 | // create the animation (the final radius is zero) 78 | Animator anim = 79 | ViewAnimationUtils.createCircularReveal(ivPic, cx, cy, initialRadius, 0); 80 | 81 | // make the view invisible when the animation is done 82 | anim.addListener(new AnimatorListenerAdapter() { 83 | @Override 84 | public void onAnimationEnd(Animator animation) { 85 | super.onAnimationEnd(animation); 86 | ivPic.setVisibility(View.INVISIBLE); 87 | } 88 | }); 89 | 90 | // start the animation 91 | anim.start(); 92 | 93 | btnControl.setText("显示"); 94 | }else{ 95 | //当前不可视,执行显示 96 | 97 | // get the center for the clipping circle 98 | int cx = (ivPic.getLeft() + ivPic.getRight()) / 2; 99 | int cy = (ivPic.getTop() + ivPic.getBottom()) / 2; 100 | 101 | // get the final radius for the clipping circle 102 | int finalRadius = Math.max(ivPic.getWidth(), ivPic.getHeight()); 103 | 104 | // create the animator for this view (the start radius is zero) 105 | Animator anim = 106 | ViewAnimationUtils.createCircularReveal(ivPic, cx, cy, 0, finalRadius); 107 | 108 | // make the view visible and start the animation 109 | ivPic.setVisibility(View.VISIBLE); 110 | anim.start(); 111 | btnControl.setText("隐藏"); 112 | } 113 | } 114 | 115 | } 116 | }); 117 | 118 | 119 | btnOne.setOnClickListener(new View.OnClickListener() { 120 | @Override 121 | public void onClick(View v) { 122 | Intent it = new Intent(); 123 | it.setClass(TestAnimationActivity.this, CoordinaterLayoutActivity.class); 124 | // if(Build.VERSION.SDK_INT >= 21){ 125 | // // shareView: 需要共享的视图 126 | // // shareName: 设置的android:transitionName=shareName 127 | //// 如果不想使用transition可以设置options bundle为null。 128 | //// 如果需要逆转该过渡动画,使用Activity.finishAfterTransition()方法代替Activity.finish() 129 | // ActivityOptions option = ActivityOptions.makeSceneTransitionAnimation(TestAnimationActivity.this, ivTransition1, getString(R.string.transition_name1)); 130 | // startActivity(it, option.toBundle()); 131 | // }else{ 132 | // startActivity(it); 133 | // } 134 | 135 | 136 | //兼容包的这种启动方式,只对5.x有效果,低版本的只是不报错,但没有动画效果 137 | ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation( 138 | TestAnimationActivity.this, ivTransition1, getString(R.string.transition_name1)); 139 | ActivityCompat.startActivity(TestAnimationActivity.this, new Intent(TestAnimationActivity.this, CoordinaterLayoutActivity.class), 140 | options.toBundle()); 141 | 142 | Toast.makeText(TestAnimationActivity.this, "一个共享视图", Toast.LENGTH_SHORT).show(); 143 | } 144 | }); 145 | 146 | btnMuch.setOnClickListener(new View.OnClickListener() { 147 | @Override 148 | public void onClick(View v) { 149 | //多个共享视图 150 | Intent it = new Intent(); 151 | it.setClass(TestAnimationActivity.this, MuchSharedTransitionActivity.class); 152 | if(Build.VERSION.SDK_INT >= 21){ 153 | // shareView: 需要共享的视图 154 | // shareName: 设置的android:transitionName=shareName 155 | // 如果不想使用transition可以设置options bundle为null。 156 | // 如果需要逆转该过渡动画,使用Activity.finishAfterTransition()方法代替Activity.finish() 157 | ActivityOptions option = ActivityOptions.makeSceneTransitionAnimation(TestAnimationActivity.this, 158 | Pair.create((View)ivTransition2, getString(R.string.transition_name2)), Pair.create((View)tvTransition3, getString(R.string.transition_name3)), Pair.create((View)ivTransition4, getString(R.string.transition_name4))); 159 | startActivity(it, option.toBundle()); 160 | }else{ 161 | startActivity(it); 162 | } 163 | Toast.makeText(TestAnimationActivity.this, "多个共享视图", Toast.LENGTH_SHORT).show(); 164 | } 165 | }); 166 | 167 | btnActive.setOnClickListener(new View.OnClickListener() { 168 | @Override 169 | public void onClick(View v) { 170 | //动态添加共享视图 171 | 172 | Intent it = new Intent(); 173 | it.setClass(TestAnimationActivity.this, ActiveSharedTransitionActivity.class); 174 | if(Build.VERSION.SDK_INT >= 21){ 175 | ivTransition5.setTransitionName(getString(R.string.transition_name5)); 176 | ivTransition6.setTransitionName(getString(R.string.transition_name6)); 177 | // shareView: 需要共享的视图 178 | // shareName: 设置的android:transitionName=shareName 179 | // 如果不想使用transition可以设置options bundle为null。 180 | // 如果需要逆转该过渡动画,使用Activity.finishAfterTransition()方法代替Activity.finish() 181 | ActivityOptions option = ActivityOptions.makeSceneTransitionAnimation(TestAnimationActivity.this, 182 | Pair.create((View)ivTransition5, getString(R.string.transition_name5)), Pair.create((View)ivTransition6, getString(R.string.transition_name6))); 183 | startActivity(it, option.toBundle()); 184 | }else{ 185 | startActivity(it); 186 | } 187 | Toast.makeText(TestAnimationActivity.this, "动态添加共享视图", Toast.LENGTH_SHORT).show(); 188 | } 189 | }); 190 | 191 | 192 | ivCompact.setOnClickListener(new View.OnClickListener() { 193 | @Override 194 | public void onClick(View v) { 195 | 196 | // ActivityOptionsCompat是一个静态类,提供了为数不多的几个方法,下面我们来罗列一下:    197 | // ActivityOptionsCompat.makeCustomAnimation(Context context, int enterResId, int exitResId)    198 | // makeCustomAnimation在实现效果上和overridePendingTransition也是相同的  199 | // ActivityOptionsCompat.makeScaleUpAnimation(View source,int startX, int startY, int startWidth, int startHeight)   200 | // ActivityOptionsCompat.makeThumbnailScaleUpAnimation(View source,Bitmap thumbnail, int startX, int startY)    201 | // ActivityOptionsCompat.makeSceneTransitionAnimation(Activity activity, View sharedElement, String sharedElementName)   202 | // ActivityOptionsCompat.makeSceneTransitionAnimation(Activity activity,Pair… sharedElements)   203 | 204 | //让新的Activity从一个小的范围扩大到全屏 205 | ActivityOptionsCompat options = 206 | ActivityOptionsCompat.makeScaleUpAnimation(v, //The View that the new activity is animating from 207 | (int)v.getWidth()/2, (int)v.getHeight()/2, //拉伸开始的坐标 208 | 0, 0);//拉伸开始的区域大小,这里用(0,0)表示从无到全屏 209 | Intent intent = new Intent(TestAnimationActivity.this, TestActivityCompactActivity.class); 210 | ActivityCompat.startActivity(TestAnimationActivity.this, intent, options.toBundle()); 211 | 212 | Toast.makeText(TestAnimationActivity.this, "支持5.X以下的兼容包动画", Toast.LENGTH_SHORT).show(); 213 | } 214 | }); 215 | } 216 | 217 | @Override 218 | public boolean onCreateOptionsMenu(Menu menu) { 219 | // Inflate the menu; this adds items to the action bar if it is present. 220 | getMenuInflater().inflate(R.menu.menu_test_animation, menu); 221 | return true; 222 | } 223 | 224 | @Override 225 | public boolean onOptionsItemSelected(MenuItem item) { 226 | // Handle action bar item clicks here. The action bar will 227 | // automatically handle clicks on the Home/Up button, so long 228 | // as you specify a parent activity in AndroidManifest.xml. 229 | int id = item.getItemId(); 230 | 231 | //noinspection SimplifiableIfStatement 232 | if (id == R.id.action_settings) { 233 | return true; 234 | } 235 | 236 | return super.onOptionsItemSelected(item); 237 | } 238 | } 239 | -------------------------------------------------------------------------------- /app/src/main/res/anim/path_morph.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/anim/rotation.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/animvectordrawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 11 | 14 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ripple_drawable.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/state_list_anim_drawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 8 | 10 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/vectordrawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 14 | 19 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/animvectordrawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 11 | 14 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/list_divider.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ripple_drawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 12 | 13 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/state_list_anim.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | 25 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/state_list_anim_drawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 8 | 10 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vectordrawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 22 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout-v21/activity_main.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | 14 | 21 | 22 | 29 | 30 | 31 | 40 | 41 | 45 | 46 | 47 | 48 | 56 | 57 | 61 | 62 | 63 | 64 |