版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_25074703/article/details/82957570
淘宝、京东商城等电商平台的首页在下滑刷新的过程中会出现左右不对齐的效果,这种情况的产生主要是由商品类型决定的。不同类型的商品决定了其独特的展示方式,一般情况下会通过自营、满减、满折等标签+价格+描述呈现。鉴于商品的多样性和展示的复杂性,会形成不同的商品高低不一的视觉效果,下滑时错落有致地展示给人以瀑布般的美感,这就是我们要讲的瀑布流的概念。
本项目基于AndroidStudio3.0.1、Java1.8平台开发,如下图
本项目使用相对稳定的2.2.3版本,如下代码:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
maven {
url 'https://maven.google.com/'
name 'Google'
}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
// classpath 'com.novoda:bintray-release:0.4.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
maven {
url 'https://maven.google.com/'
name 'Google'
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
gradle-wrapper.properties配置如下:
#Wed Mar 08 09:36:55 CST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
注意:local.properties采用默认值即可
apply plugin: 'com.android.application' // this is a app
android {
compileSdkVersion 26
buildToolsVersion "26.0.3"
defaultConfig {
applicationId "com.edwin.idea" //package name but they are not identical
minSdkVersion 16 // 最小支持Android4.1版本
targetSdkVersion 26 // 目标版本是Android7.1.1
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
//为flavor设置一个版本,命名是随意的
flavorDimensions "versionCode"
}
buildTypes {
debug {
minifyEnabled false // debug版本不混淆
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:25.0.1' // 兼容包,注意与编译工具版本一致
compile 'com.android.support:recyclerview-v7:25.0.1' //recyclerview 兼容包
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
}
本着“拎包入住”这一博客思想,本文没有采用流水账似的开发方式,而是将笔者在企业项目中的方案直接展示,以使童鞋们在Android项目开发过程中少走弯路。
首先,在上文提到的applicationId “com.edwin.idea” 对应的包下创建抽象的空Activity命名为MainActivity.java,该Activity作为一个基础Activity被edwinidea应用中所有的Activity继承。在…/src/main/java/com.edwin.idea上右击,选择New—>Java class,在弹出的对话框的Name中输入布局文件名MainActivity,Superclass选项输入AppCompatActivity单击OK按钮,创建MainActivity.java文件其实现非常简单,如下:
package com.edwin.idea;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public abstract class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setBackgroundDrawable(null); // 派生类都有自己的背景图,这里为了减少层级
}
}
当然派生Activity只是一个控制器,具体的实现还是要由我们的碎片大神Fragment来完成,有时一个Activity需要多个Fragment,所以一个抽象的Fragment是必不可少的。AbstractFragment.java代码如下:
package com.edwin.idea;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* Created by Edwin,CHEN on 2018/9/18.
*/
public abstract class AbstractFragment extends android.support.v4.app.Fragment {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
/**
* 初始化数据
*/
protected void initData() {
}
}
注意,这里的Fragment来自v4包,只支持Android3.0及以上版本。
写到这里,我已经跃跃欲试想跑一把hello world看看了,你呢?但时机未到,接下来需要在上文提到的applicationId “com.edwin.idea” 对应的包下创建package,命名为staggered。通常,如果我们需要实现应用中某个功能的时候,可以将相关的代码放在同一个文件夹package下,因为这是功能实现的第一线。如果功能过大,可以按照fragment、baseview、model、adapter等的方式分组。这样结构化明显,便于维护。如下图:
其中,StaggeredActivity继承自MainActivity,在…/src/main/res/layout上右击,选择New—>Layout resource file,在弹出的对话框的File name中输入布局文件名activity_staggered,Root element选项输入FrameLayout单击OK按钮,创建activity_staggered.xml布局文件,实现如下:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent">
FrameLayout>
FrameLayout本身就是一个容器布局,用来装载Fragment碎片来显示。这样,StaggeredActivity就成了一个名副其实的董事长controller,将所有的UI工作交给Fragment这个CEO来完成。轻松+愉快!
在…/src/main/java/com.edwin.idea/staggered上右击,选择New—>Java class,在弹出的对话框的Name中输入布局文件名StaggeredActivity,Superclass选项输入MainActivity单击OK按钮,创建StaggeredActivity.java文件如下:
package com.edwin.idea.staggered;
import android.os.Bundle;
import com.edwin.idea.MainActivity;
import com.edwin.idea.R;
/**
* Created by Edwin,CHEN on 2018/9/18.
*/
public class StaggeredActivity extends MainActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_staggered);
}
}
加载完布局文件后,当然少不了在AndroidManifest.xml文件中注册StaggeredActivity,注册表如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.edwin.idea">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".staggered.StaggeredActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
intent-filter>
activity>
application>
manifest>
android:theme="@style/AppTheme"使用了自定义主题AppTheme在res/values/styles.xml中,如下:
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
- "colorPrimary"
>@color/colorPrimary
- "colorPrimaryDark">@color/colorPrimaryDark
- "colorAccent">@color/colorAccent
style>
resources>
其中自定义颜色在res/values/colors.xml中,如下:
<resources>
<color name="colorPrimary">#3F51B5color>
<color name="colorPrimaryDark">#303F9Fcolor>
<color name="colorAccent">#FF4081color>
resources>
这里的Activity被赋予了和,并不是偶然的。他们结合使用,说明StaggeredActivity是EdwinIdea的LaunchActivity,换句话说点击桌面icon,首先看到的Activity就是它。另外,凡是需要隐式启动的Activity都必须添加属性,注意不是LAUNCHER了。由于应用只有一个Activity,这里不做过多讨论。
Ctrl + R走一波吧,如果所料不差,你应该可以看到一个空白页了????
StaggeredFragment继承自AbstractFragment,它责任重大,被StaggeredActivity委托来完成瀑布流的所有显示工作。其代码如下:
布局文件fragment_staggered.xml
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recycler_view"
android:padding="3dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
android.support.v7.widget.RecyclerView>
很简单,只有一个RecyclerView
package com.edwin.idea.staggered;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.edwin.idea.AbstractFragment;
import com.edwin.idea.R;
/**
* Created by Edwin,CHEN on 2018/9/18.
*/
public class StaggeredFragment extends AbstractFragment {
ViewGroup viewGroupRoot;
public static Fragment newInstance(){
return new StaggeredFragment();
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
viewGroupRoot = (ViewGroup) inflater.inflate(R.layout.fragment_staggered, null);
return viewGroupRoot;
}
@Override
protected void initData() {
}
}
创建了StaggeredFragment如何实现委托呢,这里只需要在StaggerActivity的onCreate()中添加如下代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_staggered);
// 委托给Fragment处理
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().replace(R.id.container_fragment, StaggeredFragment.newInstance()).commitNow();
}
}
StaggeredFragment.newInstance()采用单例模式,可以有效利用内存资源。commitNow()方法还有3个兄弟,都能完成commit处理,但是commitNow可以保证Fragment立即更新,尤其在使用viewPager做切换时,使用commit会导致更新不及时两个fragment叠加的问题,在低性能手机上容易出现。
好了,Ctrl + R一下吧,还是白屏吧????
代码的基本框架算是搭好了,可以更改一下recyclerView的背景,测试一下委托成功没?!
有诗云: