快速搭建App应用框架
主要控件:
ViewPage(主界面)
TextInputLayout(登录界面)
AppBarLayout+TabLayout(顶部导航)
DrawerLayout+NavigationView(侧滑菜单)
界面如下:
简约的登录风格采用TextInputLayout,button采用自定义的风格,对于主界面,采用了Viewpage+TabLayout侧滑就可以切换界面,侧滑菜单也挺方便使用,下面代码讲解如何实现
一.登录界面
我们准备两个按钮状态,一个是正常的,一个是按下时的颜色,让用户更明确的知道自己点击了按钮 ,对于EditText,选择TextInputLayout包裹,布局代码如下:<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".Activity.MainActivity"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.TextInputLayout
android:layout_margin="16dp"
android:id="@+id/tl_username"
android:layout_centerInParent="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:hintTextAppearance="@style/hintAppearance"
app:errorTextAppearance="@style/errorAppearance"
app:boxBackgroundColor="@color/colorPrimary"
>
<EditText
android:textSize="22sp"
android:id="@+id/et_username"
android:hint="username"
android:maxLength="25"
android:maxLines="1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_below="@id/tl_username"
android:id="@+id/tl_password"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_centerHorizontal="true"
android:layout_margin="16dp"
app:hintTextAppearance="@style/hintAppearance"
app:errorTextAppearance="@style/errorAppearance"
app:boxStrokeColor="@color/colorPrimary"
app:boxBackgroundColor="@color/colorPrimary">
<EditText
android:textSize="22sp"
android:inputType="textPassword"
android:id="@+id/et_password"
android:hint="password"
android:maxLength="25"
android:maxLines="1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.TextInputLayout>
<Button
android:onClick="loginClick"
android:id="@+id/btn_login"
android:layout_below="@id/tl_password"
android:text="Login Now"
android:textSize="18sp"
android:background="@drawable/my_button"
android:layout_margin="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
drawable/my_button.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/button_press"/>
<item android:state_pressed="false" android:drawable="@drawable/mybutton"/>
</selector>
drawable/button_press.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size android:width="300dp"
android:height="60dp"/>
<corners android:radius="30dp"/>
<gradient
android:angle="45"
android:startColor="@color/mytoolbar"
android:endColor="@color/mytoolbar"/>
<solid android:color="@color/grey"/>
</shape>
drawable/mybutton.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size android:width="300dp"
android:height="60dp"/>
<corners android:radius="30dp"/>
<gradient
android:angle="45"
android:startColor="@color/colorAccent"
android:endColor="@color/colorAccent"/>
<solid android:color="@color/mytoolbar"/>
</shape>
res/colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#008577</color>
<color name="colorPrimaryDark">#000000</color>
<color name="colorAccent">#000000</color>
<color name="mytoolbar">#FFC6BBBF</color>
<color name="red">#FFff0000</color>
<color name="grey">#FF979395</color>
</resources>
res/styles.xml
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- 需要设置为NoActionBar. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="errorAppearance" parent="TextAppearance.AppCompat">
<item name="android:textSize">18sp</item>
<item name="android:textColor">@color/red</item>
</style>
<style name="hintAppearance" parent="TextAppearance.AppCompat">
<item name="android:textSize">18sp</item>
<item name="android:textColor">@color/colorAccent</item>
</style>
</resources>
登录界面主要就是设置TextInputLayout的一些属性,比如错误时的字体颜色,水平线的颜色,浮动字体颜色,以及button的设置,下面是简单的登录代码
import android.content.Intent;
import android.support.design.widget.TextInputLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import com.example.yang.toolbar.R;
public class MainActivity extends AppCompatActivity {
private TextInputLayout tl_username,tl_password;
private EditText et_username,et_password;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InitView();
}
private void InitView() {
tl_username=findViewById(R.id.tl_username);
tl_password=findViewById(R.id.tl_password);
et_username=findViewById(R.id.et_username);
et_password=findViewById(R.id.et_password);
}
private boolean vaildate(String string){
return string.length()>=4;
}
public void loginClick(View view) {
String username=et_username.getText().toString();
String password=et_password.getText().toString();
if(!vaildate(username)){
tl_username.setErrorEnabled(true);
//设置错误提示
tl_username.setError("please input correct username");
}
else if(!vaildate(password)){
tl_password.setErrorEnabled(true);
//设置错误提示
tl_password.setError("please input correct password");
}else if(username.equals("Yang")&&password.equals("123456")){
Intent intent=new Intent();
intent.setClass(MainActivity.this, TabLayoutActivity.class);
startActivity(intent);
}
}
}
主界面
从上至下,分别是ToolBar,TabLayout,ViewPage,布局代码也很简单,应为还有侧滑菜单,所以整体布局,采用Drawerlayout,代码如下:<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
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/main_drawerlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".Activity.TabLayoutActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Light">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/grey">
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="@+id/tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIndicatorColor="@color/colorAccent"
android:background="@color/grey"
app:tabMode="scrollable"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/viewpager"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</LinearLayout>
<android.support.design.widget.NavigationView
android:id="@+id/main_navigationview"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/navigation_header"
app:menu="@menu/drawer_menu"/>
</android.support.v4.widget.DrawerLayout>
布局代码不是很复杂,采用AppBarLayout将ToolBar和TabLayout包裹起来,再和ViewPager放在整个LinearLayout,最后放入NavigationView.
界面代码如下
import android.support.design.widget.NavigationView;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
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.Gravity;
import android.view.MenuItem;
import android.widget.Toast;
import com.example.yang.toolbar.Adapter.FragmentAdapter;
import com.example.yang.toolbar.Fragment.ListFragment;
import com.example.yang.toolbar.R;
import java.util.ArrayList;
import java.util.List;
public class TabLayoutActivity extends AppCompatActivity {
private ViewPager viewPager;//设置主界面的侧滑菜单
private TabLayout tabLayout;//设置顶部的tab
private DrawerLayout drawerLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tab_layout);
Toolbar toolbar=findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final ActionBar ab=getSupportActionBar();
ab.setHomeAsUpIndicator(R.drawable.menu);
ab.setDisplayHomeAsUpEnabled(true);
drawerLayout=findViewById(R.id.main_drawerlayout);
NavigationView navigationView=findViewById(R.id.main_navigationview);
if(navigationView!=null){
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
menuItem.setChecked(true);
String title=menuItem.getTitle().toString();
Toast.makeText(getApplicationContext(),title ,Toast.LENGTH_SHORT).show();
drawerLayout.closeDrawers();
return true;
}
});
}
viewPager=findViewById(R.id.viewpager);
InitVierPager();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
//导航栏必须要设置,否则点击按钮NavigationView不会出现
switch (item.getItemId()){
case android.R.id.home:
drawerLayout.openDrawer(Gravity.START);
break;
}
return true;
}
private void InitVierPager() {
tabLayout=findViewById(R.id.tab);
List<String> titles=new ArrayList<>();
titles.add("精选");
titles.add("体育");
titles.add("巴萨");
titles.add("购物");
titles.add("明星");
titles.add("视频");
titles.add("健康");
titles.add("励志");
titles.add("图文");
titles.add("本地");
titles.add("动漫");
titles.add("搞笑");
for(int i=0;i<titles.size();i++){
tabLayout.addTab(tabLayout.newTab().setText(titles.get(i)));//添加tab
}
List<Fragment> fragments=new ArrayList<>();
for(int i=0;i<titles.size();i++){
fragments.add(new ListFragment());//添加fragment,这里主要是给viewpager使用,当我们侧滑界面时,fragments会自动切换
}
FragmentAdapter fragmentAdapter=new FragmentAdapter(getSupportFragmentManager(),fragments ,titles);
//adapter是设置给viewpage的
viewPager.setAdapter(fragmentAdapter);
tabLayout.setupWithViewPager(viewPager);
//将tablayout和Viewpager关联起来
//使用的主要步骤:第一步:布局文件中需要AppBarLayout,这个是设置顶部的,还可以添加一个toolbar和TabLayout
//TabLayout就是设置那些顶部的titles,主界面用viewpager,然后将ViewPager和TabLayout关联起来,这样每次
//我们切换titles时,viewpager也会切换,切换viewPager时titles也会切换
}
}
两个适配器,一个是ViewPager的,另一个是每个fragment的。
FragmentAdapter
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import java.util.List;
/**
* createtime:2019/9/17
* author:Yang
* describe:
*/
public class FragmentAdapter extends FragmentStatePagerAdapter {
private List<Fragment> fragments;
private List<String> titles;
public FragmentAdapter(FragmentManager fm,List<Fragment> fragments,List<String> titles) {
super(fm);
this.fragments=fragments;
this.titles=titles;
}
@Override
public Fragment getItem(int i) {
return fragments.get(i);
}
@Override
public int getCount() {
return fragments.size();
}
public CharSequence getPageTitle(int position){
return titles.get(position);
}
}
RecyclerViewAdapter
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import com.example.yang.toolbar.R;
/**
* createtime:2019/9/17
* author:Yang
* describe:
*/
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
private Context context;
public RecyclerViewAdapter(Context context){
this.context=context;
}
@Override
public RecyclerViewAdapter.ViewHolder onCreateViewHolder( ViewGroup viewGroup, int i) {
View view=LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item_card_main,viewGroup,false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder( ViewHolder viewHolder, int i) {
final View view=viewHolder.mview;
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context,"孤傲冷艳美杜莎" , Toast.LENGTH_SHORT).show();
}
});
}
@Override
public int getItemCount() {
return 10;
}
public static class ViewHolder extends RecyclerView.ViewHolder{
public final View mview;
public ViewHolder(View itemView) {
super(itemView);
this.mview=itemView;
}
}
}
RecyclerViewAdapter是决定每一个Fragment中的内容,他的布局代码如下
layout/list_item_card_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp">
<ImageView
android:src="@drawable/mei"
android:layout_width="150dp"
android:layout_height="60dp" />
<TextView
android:text="气质冷艳绝美,倾国倾城,高冷又不失骄傲,温柔又不失坚强,有着难以想象的执着,拥有君临天下的能力。"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
</LinearLayout>
ListFragment是对应每一个Tab产生的一个界面,他的布局只有一个RecyclerView
layout/list_fragment
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_marginTop="10dp"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="60dp">
</android.support.v7.widget.RecyclerView>
ListFragment代码
import com.example.yang.toolbar.Adapter.RecyclerViewAdapter;
import com.example.yang.toolbar.R;
/**
* createtime:2019/9/17
* author:Yang
* describe:
*/
public class ListFragment extends Fragment {
//该Fragment是用来填充ViewPager的,该界面只有一个RecyclerView,但是具体显示什么内容还是需要Adapter来进行设置
private RecyclerView recyclerView;
@Override
public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
recyclerView= (RecyclerView) inflater.inflate(R.layout.list_fragment,container,false );
return recyclerView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//设置recyclerview的适配器以及布局管理器,我认为这里需要根据不同的title加载不同的布局
recyclerView.setLayoutManager(new LinearLayoutManager(recyclerView.getContext()));
recyclerView.setAdapter(new RecyclerViewAdapter(getActivity()));
}
}
通过上面的工作,我们的主界面就完成了,下面设置侧滑菜单
侧滑菜单
侧滑菜单布局主要是 下面两个文件app:headerLayout="@layout/navigation_header"
app:menu="@menu/drawer_menu"
一个是顶部的header布局,另外一个是菜单
代码如下:
layout/navigation_header
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:background="@color/grey"
android:theme="@style/ThemeOverlay.AppCompat.Dark"
android:layout_width="match_parent"
android:layout_height="150dp">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center"
android:layout_marginLeft="50dp"
android:background="@drawable/xiao"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"
android:text="萧炎"
android:textSize="20sp"
android:textColor="#ffffff"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>
</LinearLayout>
menu/drawer_menu
<?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">
<group android:checkableBehavior="single">
<item android:id="@+id/nav_home"
android:icon="@drawable/first"
android:title="首页"/>
<item android:id="@+id/nav_message"
android:icon="@drawable/message"
android:title="信息"/>
<item android:id="@+id/nav_music"
android:icon="@drawable/music"
android:title="音乐"/>
<item android:id="@+id/nav_thing"
android:icon="@drawable/thing"
android:title="事项"/>
</group>
<item android:title="其他">
<menu>
<item android:title="设置"
android:icon="@drawable/set"/>
<item
android:title="关于"
android:icon="@drawable/about"/>
</menu>
</item>
</menu>
这样,每当我们点击导航按钮,菜单就会从侧面滑出来,主界面也可以进一步的自定义,根据不同的tab显示不同的Fragment而不是显示同一个fragment,我们就已经搭建好了app的框架