一款基于Material Desgin設計的APP

Corinne9175 8年前發布 | 25K 次閱讀 Android開發 移動開發

來自: http://blog.csdn.net/lyhhj/article/details/50413625


源碼小編已經上傳到github上了,求star啊
https://github.com/Hankkin/TaoSchool

前言

好久沒寫博客了,小編最近在研究Material Desgin(以下簡稱MD),話說現在市場的上App好多都用上了MD,先簡單的介紹以下MD吧,它到底是個什么東東啊?
看看官方文檔吧(中文版的呦)
http://wiki.jikexueyuan.com/project/material-design/
官方解釋說叫:原質化設計
小編也不懂什么叫原質化設計,我的理解就是遵循著用戶體驗的效果實現著一些讓用戶用起來舒適滿意的動畫效果及設計。怎么樣這個夠形象了吧,不看效果炫不炫,只看用戶用著你的APP滿意不滿意。大體就是這樣,就這樣,小編追趕著時代的潮流也設計了一個屬于自己的APP。它叫淘School(也可以叫它“淘學”哦)。
下載地址:
二維碼:
這里寫圖片描述
網站:
http://hankkin.bmob.cn
PRE:
http://pre.im/x9nH
360開發者平臺:
http://zhushou.#/detail/index/soft_id/3181637?recrefer=SE_D_%E6%B7%98School
百度開發平臺
http://shouji.baidu.com/soft/item?docid=8561791&from=&f=search_app_淘School%40list_1_title%401%40header_all_input
看一下效果吧:
這里寫圖片描述

介紹

淘School是一款基于MD的一款校園二手商品交易平臺,當然小編只是簡單的開發了一些功能,并沒有完善,只是想做一款MD的APP,并沒有交易支付的功能,只是把我感覺比較好的MD的一些組件融到了項目中,下面小編來詳細介紹一下用到的技術:
因為小編服務器端不是很熟練,所以就用了Bmob,還不錯挺容易上手的,就依賴了它的兩個庫而已,網絡請求和模型都是封裝好的,我們直接調用就可以。
先看一下小編引用的一些庫吧:

compile 'com.android.support:appcompat-v7:23.1.0'
    compile files('libs/BmobSDK_V3.4.5_1111.jar')
    compile files('libs/okio-1.4.0.jar')
    compile 'com.android.support:support-v4:23.1.0'
    compile 'com.github.manuelpeinado.fadingactionbar:fadingactionbar-abc:3.1.2'
    compile 'com.android.support:design:23.1.0'
    compile 'com.pnikosis:materialish-progress:1.7'
    compile 'me.drakeet.materialdialog:library:1.2.8'
    compile 'com.jakewharton:butterknife:7.0.1'
    compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
    compile 'com.weiwangcn.betterspinner:library:1.1.0'
    compile 'com.nineoldandroids:library:2.4.0'

1.Android Support Desgin

CollapsingAvatarToolbar 頭像隨ListView滾動縮回到ActionBar特效
TextInputLayout帶動畫的輸入框

2.ActionBarDrawerToggle、DrawerLayout、ActionBar 結合

3.RippleEffect水波紋效果

4.PagerSlidingTabStrip+viewpager實現選項卡左右滑動

5.FloatActiconButton懸浮按鈕實現仿釘釘懸浮按鈕

6.PullToZoomScrollView實現下拉自動放大頭部View

7.materialdialog實現的對話框

8.MaterialSpinner實現的帶效果的spinner

9.butterknife注解框架

小編用到的技術基本上就這些,下面小編會詳細的介紹一下。

技術實現

1.主界面

先介紹一下主界面吧,主界面小編用的是ActionBarDrawerToggle+DrawerLayout+ActionBar實現的滑動抽屜效果。布局文件就不介紹了,這個用的也挺多的,網上資料也很多,介紹幾個方法吧

//設定左上角突變可點擊
        getSupportActionBar().setHomeButtonEnabled(true); 
        // 給左上角圖標的左邊加上一個返回的圖標 。對應ActionBar.DISPLAY_HOME_AS_UP
        getSupportActionBar().setDisplayHomeAsUpEnabled(true); 
        //設置標題 getSupportActionBar().setTitle(getResources().getString(R.string.action_title));
         // 使自定義的普通View能在title欄顯示,即actionBar.setCustomView能起作用,對應ActionBar.DISPLAY_SHOW_CUSTOM
        actionBar.setDisplayShowCustomEnabled(true) 
closeDrawers();//關閉抽屜

2.滑動選項卡

小編主界面的滑動選項卡用的是PagerSlidingTabStrip+viewpager管理fragment,詳細用法大家可以看一下小編的這邊博客:Android源碼解析-仿今日頭條PagerSlidingTabStrip滑動頁面導航效果不詳細介紹了。

3.主界面的懸浮按鈕

懸浮按鈕在github上有Demo,
https://github.com/futuresimple/android-floating-action-button
https://github.com/makovkastar/FloatingActionButton
小編用的是第一個,然后重寫了一下里面的滑動監聽實現了listview滑動顯示隱藏按鈕。看一下布局文件:

<com.hankkin.compustrading.view.floatbutton.FloatingActionsMenu
        android:id="@+id/multiple_actions"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        fab:fab_addButtonColorNormal="@color/origle"
        fab:fab_addButtonColorPressed="@color/origle_tab"
        fab:fab_addButtonPlusIconColor="@color/white"
        fab:fab_labelStyle="@style/menu_labels_style"
        android:layout_marginBottom="@dimen/smaller_space"
        android:layout_marginRight="@dimen/smaller_space"
        android:layout_marginEnd="@dimen/smaller_space">

    <com.hankkin.compustrading.view.floatbutton.FloatingActionButton
        android:id="@+id/fb_update"
        android:src="@drawable/update"
        fab:fab_labelStyle="@style/menu_labels_style"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        fab:fab_colorNormal="@color/theme_color"
        fab:fab_colorPressed="@color/theme_color_tab"/>

    <com.hankkin.compustrading.view.floatbutton.FloatingActionButton
        android:id="@+id/fb_new"
        fab:paddingEnd="@dimen/small_space"
        android:src="@drawable/edit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        fab:fab_colorNormal="@color/theme_color"
        fab:fab_colorPressed="@color/theme_color_tab"/>
    <com.hankkin.compustrading.view.floatbutton.FloatingActionButton
        android:id="@+id/fb_person"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/title_person"
        fab:fab_colorNormal="@color/theme_color"
        fab:fab_colorPressed="@color/theme_color_tab"/>

</com.hankkin.compustrading.view.floatbutton.FloatingActionsMenu></pre> <p>下面是重寫的ListView滑動監聽實現顯示隱藏懸浮按鈕</p>

public void attachToListView(@NonNull AbsListView listView,
                               ScrollDirectionListener scrollDirectionListener,
                               AbsListView.OnScrollListener onScrollListener) {
    AbsListViewScrollDetectorImpl scrollDetector = new AbsListViewScrollDetectorImpl();
    scrollDetector.setScrollDirectionListener(scrollDirectionListener);
    scrollDetector.setOnScrollListener(onScrollListener);
    scrollDetector.setListView(listView);
    scrollDetector.setScrollThreshold(mScrollThreshold);
    listView.setOnScrollListener(scrollDetector);
  }

private class AbsListViewScrollDetectorImpl extends AbsListViewScrollDetector { private ScrollDirectionListener mScrollDirectionListener; private AbsListView.OnScrollListener mOnScrollListener;

private void setScrollDirectionListener(ScrollDirectionListener scrollDirectionListener) {
  mScrollDirectionListener = scrollDirectionListener;
}

public void setOnScrollListener(AbsListView.OnScrollListener onScrollListener) {
  mOnScrollListener = onScrollListener;
}

@Override
public void onScrollDown() {
  show();
  if (mScrollDirectionListener != null) {
    mScrollDirectionListener.onScrollDown();
  }
}

@Override
public void onScrollUp() {
  hide();
  if (mScrollDirectionListener != null) {
    mScrollDirectionListener.onScrollUp();
  }
}

@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
                     int totalItemCount) {
  if (mOnScrollListener != null) {
    mOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
  }

  super.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
}

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
  if (mOnScrollListener != null) {
    mOnScrollListener.onScrollStateChanged(view, scrollState);
  }

  super.onScrollStateChanged(view, scrollState);
}

} public void show() { show(true); }

public void hide() { hide(true); } public void show(boolean animate) { toggle(true, animate, false); }

public void hide(boolean animate) { toggle(false, animate, false); } private void toggle(final boolean visible, final boolean animate, boolean force) { if (mVisible != visible || force) { mVisible = visible; int height = getHeight(); if (height == 0 && !force) { ViewTreeObserver vto = getViewTreeObserver(); if (vto.isAlive()) { vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { ViewTreeObserver currentVto = getViewTreeObserver(); if (currentVto.isAlive()) { currentVto.removeOnPreDrawListener(this); } toggle(visible, animate, true); return true; } }); return; } } int translationY = visible ? 0 : height + getMarginBottom(); if (animate) { ViewPropertyAnimator.animate(this).setInterpolator(mInterpolator) .setDuration(TRANSLATE_DURATION_MILLIS) .translationY(translationY); } else { ViewHelper.setTranslationY(this, translationY); }

  // On pre-Honeycomb a translated view is still clickable, so we need to disable clicks manually
  if (!hasHoneycombApi()) {
    setClickable(visible);
  }
}

} private int getMarginBottom() { int marginBottom = 0; final ViewGroup.LayoutParams layoutParams = getLayoutParams(); if (layoutParams instanceof ViewGroup.MarginLayoutParams) { marginBottom = ((ViewGroup.MarginLayoutParams) layoutParams).bottomMargin; } return marginBottom; } private boolean hasHoneycombApi() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; } }</pre>

然后再activity中這樣用:

fab.attachToListView(lvProduct, new ScrollDirectionListener() {
                @Override
                public void onScrollDown() {
                    Log.d("ListViewFragment", "onScrollDown()");
                }

            @Override
            public void onScrollUp() {
                Log.d("ListViewFragment", "onScrollUp()");
            }
        }, new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                Log.d("ListViewFragment", "onScrollStateChanged()");
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                Log.d("ListViewFragment", "onScroll()");
            }
        });</pre> <p>很簡單。</p>

4.商品詳細界面上下滑動頭像回到actionbar上

這個效果是小編一直都想實現的,因為技術、時間、能力有限,所以一直沒去搞,在網上搜了好多相關的帖子,博客,終于讓我找到一個類似的,做了一下改動實現了。
這個技術是CoordinatorLayout+Toolbar+CollapsingAvatarToolbar實現的。實際上support desgin可以實現文字的上下滑動但是沒有頭像的上下滑動改變大小。CollapsingAvatarToolbar這個組件實現了這一效果,當然并不是小編寫的,只是小編改的,但是能改出來小編也已經很高興了。給大家看一下布局:

<?xml version="1.0" encoding="utf-8"?>

<android.support.design.widget.CoordinatorLayout xmlns:android="

<android.support.design.widget.AppBarLayout  android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="200dp" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <android.support.design.widget.CollapsingToolbarLayout  android:id="@+id/collapsing_toolbar" android:layout_width="match_parent" android:layout_height="match_parent" app:contentScrim="@color/theme_color" app:layout_scrollFlags="scroll|exitUntilCollapsed">

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

        <com.hankkin.compustrading.view.CollapsingAvatarToolbar  android:id="@+id/stuff_container" android:layout_width="wrap_content" android:layout_height="?attr/actionBarSize" android:orientation="vertical">

            <com.hankkin.compustrading.view.RoundedImageView  android:id="@+id/usericon" android:layout_width="40dp" android:layout_height="40dp" android:layout_gravity="center_vertical" android:src="@drawable/defaut" />

            <TextView  android:id="@+id/username" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:fontFamily="sans-serif-medium" android:text="Hankkin" android:textColor="@android:color/white" android:textSize="18dp" />

            <!--<LinearLayout android:layout_width="wrap_content"-->
            <!--android:layout_height="wrap_content"-->
            <!--android:layout_gravity="center_vertical"-->
            <!--android:layout_marginLeft="16dp"-->
            <!--android:orientation="vertical">-->

            <!-- -->

            <!--<TextView android:id="@+id/subtitle"-->
            <!--android:layout_width="wrap_content"-->
            <!--android:layout_height="wrap_content"-->
            <!--android:text="Subtitle"-->
            <!--android:textColor="#80ffffff"-->
            <!--android:textSize="15dp" />-->
            <!--</LinearLayout>-->
        </com.hankkin.compustrading.view.CollapsingAvatarToolbar>

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

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

<android.support.v4.widget.NestedScrollView  android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/gray" app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <LinearLayout  android:padding="@dimen/small_space" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content">
        <LinearLayout  android:gravity="center_vertical" android:padding="@dimen/small_space" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content">
            <com.hankkin.compustrading.view.RoundedImageView  android:id="@+id/iv_user_head" android:src="@drawable/defaut" android:layout_width="35dp" android:layout_height="35dp" />
            <TextView  android:layout_marginLeft="@dimen/small_space" android:textSize="@dimen/normal_textSize" android:text="Hankkin" android:textColor="@color/black" android:layout_weight="1" android:id="@+id/tv_username" android:layout_width="wrap_content" android:layout_height="wrap_content" />
            <TextView  android:textColor="@color/deep_gray" android:textSize="@dimen/small_textSize" android:text="asdas" android:id="@+id/tv_time" android:layout_width="wrap_content" android:layout_height="wrap_content" />
        </LinearLayout>

        <TextView  android:layout_marginLeft="@dimen/small_space" android:textColor="@color/black" android:textSize="@dimen/normal_textSize" android:id="@+id/tv_pro_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="二手" />

        <TextView  android:layout_marginLeft="@dimen/small_space" android:textColor="@color/black" android:textSize="@dimen/normal_textSize" android:id="@+id/tv_pro_desc" android:layout_width="wrap_content" android:layout_height="wrap_content" />

        <ImageView  android:scaleType="fitXY" android:id="@+id/iv_product" android:layout_width="match_parent" android:layout_height="300dp" android:background="@color/deep_gray" />
        <LinearLayout  android:paddingBottom="@dimen/small_space" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content">

            <TextView  android:drawablePadding="@dimen/tiny_space" android:drawableLeft="@drawable/location" android:textSize="@dimen/small_textSize" android:layout_marginTop="@dimen/small_space" android:layout_marginLeft="@dimen/middle_space" android:text="天津理工大學" android:id="@+id/tv_school" android:layout_weight="1" android:layout_width="wrap_content" android:layout_height="wrap_content" />
            <TextView  android:textSize="@dimen/small_textSize" android:textColor="@color/theme_color" android:layout_marginRight="@dimen/middle_space" android:layout_marginTop="@dimen/small_space" android:text="¥" android:id="@+id/tv_price" android:layout_width="wrap_content" android:layout_height="wrap_content" />

        </LinearLayout>

        <LinearLayout  android:layout_marginTop="@dimen/middle_space" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="64dp">

            <LinearLayout  android:gravity="center" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="match_parent">
                <ImageView  android:src="@drawable/telephone" android:layout_width="wrap_content" android:layout_height="match_parent" />

            </LinearLayout>
            <LinearLayout  android:gravity="center" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="match_parent">
                <ImageView  android:src="@drawable/sms" android:layout_width="wrap_content" android:layout_height="match_parent" />

            </LinearLayout>
            <LinearLayout  android:gravity="center" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="match_parent">
                <ImageView  android:src="@drawable/collect" android:layout_width="wrap_content" android:layout_height="match_parent" />

            </LinearLayout>

        </LinearLayout>
    </LinearLayout>



</android.support.v4.widget.NestedScrollView>


</android.support.design.widget.CoordinatorLayout></pre>

效果就這樣:
這里寫圖片描述

5.個人資料界面

這個界面小編用的是PullToZoomScrollViewEx,github地址
https://github.com/matrixxun/PullToZoomInListView
用法也很簡單,我們在布局里面嵌套一個PullToZoomScrollViewEx,而布局的head,content,footer都可以自定義,然后引用進來就可以了。

PullToZoomScrollViewEx scrollView = (PullToZoomScrollViewEx) findViewById(R.id.my_pull_scoll);
        headView = LayoutInflater.from(this).inflate(R.layout.profile_head_view, null, false);
        zoomView = LayoutInflater.from(this).inflate(R.layout.profile_zoom_view, null, false);
        contentView = LayoutInflater.from(this).inflate(R.layout.profile_contect_view, null, false);
        scrollView.setHeaderView(headView);
        scrollView.setZoomView(zoomView);
        scrollView.setScrollContentView(contentView);

6.其他

其他的注解、dialog等小編在這里就不介紹了,很多資料,小編把網址給大家貼下來,有興趣的可以看一下:
推薦一個Android開發懶人庫 – ButterKnife
MaterialDialog
BetterSpinner

APP有很多不合理的地方,還請小伙伴們多多包涵哈,多多指正,源碼估計元旦回去之后等我完善之后會開源出來的,大家可以多多關注我的博客和github,要是有的小伙伴等不及可以留下郵箱,我會及時關注給你們發源碼的。

</div>

 本文由用戶 Corinne9175 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!