[Module] 02 - Menu, SideBar and Navigation
本篇介绍各种常见的UI控件技巧,重点放在一些难度较高的设计。
- 主界面
- 功能引导(类似于viewpager) 【UI框架设计1】
- 侧边栏(SlideingMenu, DrawerLayout)【UI框架设计2】
- Material Design 定制theme到AndroidManifest的application theme中
- 底部加载更多 【Bottom Navigation Bar with Activities】
- 自定义alertdialog等对话框(可以写在BaseActivity中)
- 通用的popupwindow
- 快速返回顶部按钮
- Toolbar代替actionbar
- 各种新式的Material design兼容控件
- 带有删除的EditText
- 定制下拉加载的控件
- listview/recyclerview的基础adapter
1 ORM框架(无需再用contentprovider或者sqlitedatebasehelper之类的古董工具了) 2 规划各种业务Bean文件(配合ORM框架) 3 Http请求框架(volley,推荐使用okHttp,RxJava+Rxandroid+retrofit等) 4 JSON解析和构建框架(Gson,fastJson,不要用jackson因为比较大,除非需要用嵌套的需求) 5 设计一个好的请求基类(BaseRequest、BaseResponse) 6 JWT 7 BaseActivity和BaseFragment(把公用的代码写在里面,比如检测网络、弹出alertdialog等等) 8 定制一个Application类代替默认的(很多第三方框架需要把一些代码写到定制的Application类里面) 9 消息推送(比如友盟) 10 用户反馈(比如友盟) 11 数据统计(比如友盟) 12 更新(比如友盟) 13 数据备份和恢复 14 点赞、评论、收藏模块 15 About界面(版权申明+常用软件设置+版本更新+国际化等) 16 在线crash log上报(比如腾讯的bugly) 17 快速开发框架(这里推荐使用butterknife和eventbus) 18 内存泄漏检测工具(leakcanary) 19 图片加载库(Glide) 20 加密解密(RSA,MD5,DES) 21 带有删除的EditText 22 定制下拉加载的控件 23 listview/recyclerview的基础adapter 24 定制搜索框 25 工具类(比如sharepreference,File,ScreenDesity,Sql,字符串处理,dpsp互转等等) 26 底部加载更多 27 自定义alertdialog等对话框(可以写在BaseActivity中) 28 通用的popupwindow 29 快速返回顶部按钮 30 Toolbar代替actionbar 31 各种新式的Material design兼容控件 32 界面滑动冲突的问题(横竖冲突、同向冲突) 33 离线登录功能 34 bitmap缓存策略 35 最后项目要发布了,那么久需要混淆和打包了,前者关于混淆网上有很多相关的文章,这里需要注意的是很多你所使用的第三方库都需要在混淆的时候给剔除,因为他们是基于反射机制的。这点需要你在使用每个第三方库的时候多看他们的说明书多加小心。其次,混淆后一定要打个包重新回归测试一下,以免出现因混淆而导致的问题。
紧接着要考虑的是:逻辑处理与界面分离:
Fragment
from: 教学视频
from: CodingWithMitch
了解 adapter 的使用:
public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private SectionsStatePagerAdapter mSectionsStatePagerAdapter; // useless here. private ViewPager mViewPager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.d(TAG, "onCreate: Started."); mSectionsStatePagerAdapter = new SectionsStatePagerAdapter(getSupportFragmentManager()); // useless here. mViewPager = (ViewPager) findViewById(R.id.containter); //setup the pager setupViewPager(mViewPager); // ----> } private void setupViewPager(ViewPager viewPager){ SectionsStatePagerAdapter adapter = new SectionsStatePagerAdapter(getSupportFragmentManager()); adapter.addFragment(new Fragment1(), "Fragment1"); adapter.addFragment(new Fragment2(), "Fragment2"); adapter.addFragment(new Fragment3(), "Fragment3"); viewPager.setAdapter(adapter); } public void setViewPager(int fragmentNumber){ mViewPager.setCurrentItem(fragmentNumber); } }
adapter 的写法:
public class SectionsStatePagerAdapter extends FragmentStatePagerAdapter { private final List<Fragment> mFragmentList = new ArrayList<>(); private final List<String> mFragmentTitleList = new ArrayList<>(); public SectionsStatePagerAdapter(FragmentManager fm) { super(fm); }
public void addFragment(Fragment fragment, String title){ mFragmentList.add(fragment); mFragmentTitleList.add(title); } @Override public Fragment getItem(int position) { return mFragmentList.get(position); } @Override public int getCount() { return mFragmentList.size(); } }
fragment 的写法:
public class Fragment1 extends Fragment { private static final String TAG = "Fragment1"; private Button btnNavFrag1; private Button btnNavFrag2; private Button btnNavFrag3; private Button btnNavSecondActivity; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable final Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment1_layout, container, false); btnNavFrag1 = (Button) view.findViewById(R.id.btnNavFrag1); btnNavFrag2 = (Button) view.findViewById(R.id.btnNavFrag2); btnNavFrag3 = (Button) view.findViewById(R.id.btnNavFrag3); btnNavSecondActivity = (Button) view.findViewById(R.id.btnNavSecondActivity); Log.d(TAG, "onCreateView: started."); btnNavFrag1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(getActivity(), "Going to Fragment 1", Toast.LENGTH_SHORT).show(); ((MainActivity)getActivity()).setViewPager(0); } }); btnNavFrag2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(getActivity(), "Going to Fragment 2", Toast.LENGTH_SHORT).show(); ((MainActivity)getActivity()).setViewPager(1); } }); btnNavFrag3.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(getActivity(), "Going to Fragment 3", Toast.LENGTH_SHORT).show(); ((MainActivity)getActivity()).setViewPager(2); } }); btnNavSecondActivity.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(getActivity(), "Going to Fragment 1", Toast.LENGTH_SHORT).show(); Intent intent = new Intent(getActivity(), SecondActivity.class); startActivity(intent); } }); return view; } }
对话框
最近学习弹框时发现有三种类型的可供使用, PopupWindow、dialog,DialogFragment。
虽然在功能上 PopupWindow 更符合需要,dialog也能做到,但是使用 DialogFragment 代码更简洁、更方便封装功能模块。
public class MyCustomDialog extends DialogFragment {
// 定义 ////////////////////////////////////////////////// public interface OnInputListener{ void sendInput(String input); } public OnInputListener mOnInputListener; /////////////////////////////////////////////////////////
... ... @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
... ... mActionOk.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.d(TAG, "onClick: capturing input"); String input = mInput.getText().toString(); // if(!input.equals("")){ // // //Easiest way: just set the value // ((MainActivity)getActivity()).mInputDisplay.setText(input); // // }
// 使用 // "Best Practice" but it takes longer mOnInputListener.sendInput(input); getDialog().dismiss(); } }); return view; } @Override public void onAttach(Context context) { super.onAttach(context); try{
// 初始化 // mOnInputListener = (OnInputListener) getActivity(); }catch (ClassCastException e){ Log.e(TAG, "onAttach: ClassCastException: " + e.getMessage() ); } } }
实现了松耦合。
public class MainActivity extends AppCompatActivity implements MyCustomDialog.OnInputListener { ... ...
// 继承实现 // @Override public void sendInput(String input) { Log.d(TAG, "sendInput: got the input: " + input); // mInputDisplay.setText(input); mInput = input; setInputToTextView(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... ... mOpenDialog.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.d(TAG, "onClick: opening dialog."); MyCustomDialog dialog = new MyCustomDialog(); dialog.show(getFragmentManager(), "MyCustomDialog"); } }); } private void setInputToTextView(){ mInputDisplay.setText(mInput); } }
下拉加载控件,以及快速回到顶部
/* implement */
对话条加泡泡
- list
- bubble
/* implement */
原型设计
Mockplus: A Simple Yet Powerful Prototype Design Tool

浙公网安备 33010602011771号