@@ -34,7 +34,7 @@ apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" | |||
android { | |||
compileSdkVersion 28 | |||
compileSdkVersion 29 | |||
lintOptions { | |||
disable 'InvalidPackage' | |||
@@ -44,7 +44,7 @@ android { | |||
defaultConfig { | |||
applicationId "cn.zhios.zhiying" | |||
minSdkVersion 21 | |||
targetSdkVersion 28 | |||
targetSdkVersion 29 | |||
versionCode 1 | |||
versionName "1.0" | |||
aaptOptions.cruncherEnabled = false | |||
@@ -157,9 +157,33 @@ flutter { | |||
} | |||
dependencies { | |||
implementation 'androidx.appcompat:appcompat:1.2.0' | |||
implementation 'androidx.constraintlayout:constraintlayout:2.0.2' | |||
testImplementation 'junit:junit:4.12' | |||
androidTestImplementation 'androidx.test:runner:1.1.1' | |||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' | |||
//登陆 | |||
implementation 'com.ali.auth.sdk:alibabauth_core:2.0.0.11@aar' | |||
implementation 'com.ali.auth.sdk:alibabauth_ui:2.0.0.11@aar' | |||
implementation 'com.ali.auth.sdk:alibabauth_ext:2.0.0.11@aar' | |||
//安全组件 | |||
implementation 'com.taobao.android:securityguardaar3:5.4.171@aar' | |||
implementation 'com.taobao.android:securitybodyaar3:5.4.99@aar' | |||
implementation 'com.taobao.android:avmpaar3:5.4.36@aar' | |||
implementation 'com.taobao.android:sgmiddletieraar3:5.4.9@aar' | |||
//Mtop | |||
implementation 'com.taobao.android:mtopsdk_allinone_open:3.1.2.5@jar' | |||
//applink | |||
implementation 'com.alibaba.sdk.android:alibc_link_partner:4.1.15@aar' | |||
//ut | |||
implementation 'com.taobao.android:utdid4all:1.5.2' | |||
implementation 'com.alibaba.mtl:app-monitor-sdk:2.6.4.5_for_bc' | |||
// 电商基础组件 | |||
implementation 'com.alibaba.sdk.android:AlibcTradeCommon:4.0.0.16@aar' | |||
implementation 'com.alibaba.sdk.android:AlibcTradeBiz:4.0.0.16@aar' | |||
implementation 'com.alibaba.sdk.android:nb_trade:4.0.0.16@aar' | |||
implementation 'com.alibaba:fastjson:1.2.41@jar' | |||
} | |||
@@ -1,40 +1,51 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | |||
xmlns:tools="http://schemas.android.com/tools" | |||
package="cn.zhios.zhiying_base_widget_example"> | |||
<!-- io.flutter.app.FlutterApplication is an android.app.Application that | |||
calls FlutterMain.startInitialization(this); in its onCreate method. | |||
In most cases you can leave this as-is, but you if you want to provide | |||
additional functionality it is fine to subclass or reimplement | |||
FlutterApplication and put your custom class here. --> | |||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> | |||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> | |||
<uses-permission android:name="android.permission.INTERNET" /> | |||
<application | |||
android:name="io.flutter.app.FlutterApplication" | |||
android:label="@string/app_name" | |||
android:icon="@mipmap/ic_launcher" | |||
android:label="@string/app_name" | |||
android:usesCleartextTraffic="true" | |||
tools:replace="android:name"> | |||
<activity android:name=".WebActivity"></activity> | |||
<activity | |||
android:name=".TestActivity" | |||
android:theme="@style/Theme.AppCompat.NoActionBar"> | |||
<!-- <intent-filter>--> | |||
<!-- <action android:name="android.intent.action.MAIN" />--> | |||
<!-- <category android:name="android.intent.category.LAUNCHER" />--> | |||
<!-- </intent-filter>--> | |||
</activity> | |||
<activity | |||
android:name=".MainActivity" | |||
android:launchMode="singleTop" | |||
android:theme="@style/LaunchTheme" | |||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" | |||
android:hardwareAccelerated="true" | |||
android:launchMode="singleTop" | |||
android:theme="@style/LaunchTheme" | |||
android:usesCleartextTraffic="true" | |||
android:windowSoftInputMode="adjustResize"> | |||
<intent-filter> | |||
<action android:name="android.intent.action.MAIN" /> | |||
<category android:name="android.intent.category.LAUNCHER" /> | |||
</intent-filter> | |||
<intent-filter> | |||
<action android:name="android.intent.action.MAIN" /> | |||
<category android:name="android.intent.category.LAUNCHER" /> | |||
</intent-filter> | |||
</activity> | |||
<!-- Don't delete the meta-data below. | |||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> | |||
<!-- | |||
Don't delete the meta-data below. | |||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java | |||
--> | |||
<meta-data | |||
android:name="flutterEmbedding" | |||
android:value="2" /> | |||
</application> | |||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> | |||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> | |||
<uses-permission android:name="android.permission.INTERNET"/> | |||
</manifest> | |||
</manifest> |
@@ -38,7 +38,8 @@ public class MainActivity extends FlutterActivity implements ZhiyingFlutterCommN | |||
@Override | |||
public Map getSetting() { | |||
Map map = new HashMap(); | |||
map.put("domain", "http://inapi.izhyin.cn"); //"http://120.76.175.204:8989"); | |||
//map.put("domain", "http://inapi.izhyin.cn"); //"http://120.76.175.204:8989"); | |||
map.put("domain", "http://192.168.0.113:5000"); | |||
map.put("master_id", "123456"); | |||
map.put("secret_key", "123456"); | |||
// map.put("token", "123465"); | |||
@@ -0,0 +1,108 @@ | |||
package cn.zhios.zhiying_base_widget_example; | |||
import androidx.appcompat.app.AppCompatActivity; | |||
import android.app.Activity; | |||
import android.content.Intent; | |||
import android.os.Bundle; | |||
import android.util.Log; | |||
import android.view.View; | |||
import android.webkit.WebChromeClient; | |||
import android.webkit.WebView; | |||
import android.webkit.WebViewClient; | |||
import android.widget.TextView; | |||
import android.widget.Toast; | |||
import com.alibaba.baichuan.android.trade.AlibcTrade; | |||
import com.alibaba.baichuan.android.trade.AlibcTradeSDK; | |||
import com.alibaba.baichuan.android.trade.callback.AlibcTradeCallback; | |||
import com.alibaba.baichuan.android.trade.callback.AlibcTradeInitCallback; | |||
import com.alibaba.baichuan.android.trade.model.AlibcShowParams; | |||
import com.alibaba.baichuan.trade.biz.context.AlibcTradeResult; | |||
import com.alibaba.baichuan.trade.biz.core.taoke.AlibcTaokeParams; | |||
import com.alibaba.baichuan.trade.biz.login.AlibcLogin; | |||
import com.alibaba.baichuan.trade.biz.login.AlibcLoginCallback; | |||
import com.alibaba.baichuan.trade.common.utils.AlibcLogger; | |||
import java.util.HashMap; | |||
public class TestActivity extends Activity { | |||
@Override | |||
protected void onCreate(Bundle savedInstanceState) { | |||
super.onCreate(savedInstanceState); | |||
setContentView(R.layout.activity_test); | |||
TextView aliBcTV = findViewById(R.id.tv_aliBc); | |||
AlibcTradeSDK.asyncInit(this.getApplication(), new AlibcTradeInitCallback() { | |||
@Override | |||
public void onSuccess() { | |||
Toast.makeText(TestActivity.this, "阿里百川注册成功", Toast.LENGTH_LONG).show(); | |||
} | |||
@Override | |||
public void onFailure(int i, String s) { | |||
Toast.makeText(TestActivity.this, "阿里百川注册失败" + s, Toast.LENGTH_LONG).show(); | |||
} | |||
}); | |||
aliBcTV.setOnClickListener(new View.OnClickListener() { | |||
@Override | |||
public void onClick(View v) { | |||
AlibcLogin.getInstance().showLogin(new AlibcLoginCallback() { | |||
@Override | |||
public void onSuccess(int i, String s, String s1) { | |||
Toast.makeText(TestActivity.this, "授权成功" + s, Toast.LENGTH_LONG).show(); | |||
} | |||
@Override | |||
public void onFailure(int i, String s) { | |||
Toast.makeText(TestActivity.this, "登陆失败" + s, Toast.LENGTH_LONG).show(); | |||
} | |||
}); | |||
} | |||
}); | |||
findViewById(R.id.tv_open_detail).setOnClickListener(new View.OnClickListener() { | |||
AlibcShowParams showParams = new AlibcShowParams(); | |||
@Override | |||
public void onClick(View v) { | |||
// // 以显示传入url的方式打开页面(第二个参数是套件名称) | |||
// AlibcTrade.openByUrl(TestActivity.this, "", "http://www.izhim.com/comm/tb_callback.php?_ctrl=domain&domain_state=MTI2&domain_return_url=aHR0cDovLzE5Mi4xNjguMC4xMTM6NTAwMC9hcGkvdjEvdGFvYmFvL2F1dGgvY2FsbGJhY2s%2FdGltZT0xNjAyNDk4MjA3", new WebView(TestActivity.this), | |||
// new WebViewClient(), new WebChromeClient(), showParams, | |||
// new AlibcTaokeParams("","",""), new HashMap<String,String>(), new AlibcTradeCallback() { | |||
// @Override | |||
// public void onTradeSuccess(AlibcTradeResult tradeResult) { | |||
// AlibcLogger.i("", "request success"); | |||
// } | |||
// @Override | |||
// public void onFailure(int code, String msg) { | |||
// AlibcLogger.e("", "code=" + code + ", msg=" + msg); | |||
// if (code == -1) { | |||
// Toast.makeText(TestActivity.this, msg, Toast.LENGTH_SHORT).show(); | |||
// } | |||
// } | |||
// }); | |||
if (!AlibcLogin.getInstance().isLogin()) { | |||
AlibcLogin.getInstance().showLogin(new AlibcLoginCallback() { | |||
@Override | |||
public void onSuccess(int i, String s, String s1) { | |||
startActivity(new Intent(TestActivity.this,WebActivity.class)); | |||
} | |||
@Override | |||
public void onFailure(int i, String s) { | |||
Log.d("阿里百川授权失败",s); | |||
} | |||
}); | |||
} else { | |||
startActivity(new Intent(TestActivity.this,WebActivity.class)); | |||
} | |||
} | |||
}); | |||
} | |||
} |
@@ -0,0 +1,521 @@ | |||
package cn.zhios.zhiying_base_widget_example; | |||
import android.annotation.SuppressLint; | |||
import android.app.Activity; | |||
import android.content.ComponentName; | |||
import android.content.Intent; | |||
import android.graphics.Bitmap; | |||
import android.net.Uri; | |||
import android.net.http.SslError; | |||
import android.os.Bundle; | |||
import android.util.Log; | |||
import android.util.Patterns; | |||
import android.view.View; | |||
import android.webkit.GeolocationPermissions; | |||
import android.webkit.JavascriptInterface; | |||
import android.webkit.SslErrorHandler; | |||
import android.webkit.ValueCallback; | |||
import android.webkit.WebChromeClient; | |||
import android.webkit.WebResourceError; | |||
import android.webkit.WebResourceRequest; | |||
import android.webkit.WebSettings; | |||
import android.webkit.WebView; | |||
import android.webkit.WebViewClient; | |||
import android.widget.Toast; | |||
import com.alibaba.baichuan.android.trade.AlibcTrade; | |||
import com.alibaba.baichuan.android.trade.callback.AlibcTradeCallback; | |||
import com.alibaba.baichuan.android.trade.model.AlibcShowParams; | |||
import com.alibaba.baichuan.trade.biz.context.AlibcTradeResult; | |||
import com.alibaba.baichuan.trade.biz.core.taoke.AlibcTaokeParams; | |||
import com.alibaba.baichuan.trade.biz.login.AlibcLogin; | |||
import com.alibaba.baichuan.trade.biz.login.AlibcLoginCallback; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
public class WebActivity extends Activity { | |||
WebView mainWeb; | |||
@Override | |||
protected void onCreate(Bundle savedInstanceState) { | |||
super.onCreate(savedInstanceState); | |||
setContentView(R.layout.activity_web_bc); | |||
mainWeb = findViewById(R.id.webview_main); | |||
mainWeb.getSettings().setJavaScriptEnabled(true); | |||
mainWeb.getSettings().setDomStorageEnabled(true); | |||
mainWeb.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT); | |||
mainWeb.getSettings().setLoadWithOverviewMode(true); | |||
mainWeb.getSettings().setAllowFileAccess(true); | |||
mainWeb.getSettings().setDatabaseEnabled(true); | |||
MyWebClient myWebClient = new MyWebClient(); | |||
MyWebChromeClient myWebChromeClient = new MyWebChromeClient(); | |||
mainWeb.setWebViewClient(myWebClient); | |||
mainWeb.setWebChromeClient(myWebChromeClient); | |||
Map<String, String> exParams = new HashMap<>();//yhhpass参数 | |||
// AlibcTaokeParams alibcTaokeParams = new AlibcTaokeParams("", "", ""); | |||
// alibcTaokeParams.pid = SPUtils.getPrefString(mActivity, Pkey.pid, ""); | |||
// alibcTaokeParams.adzoneid = SPUtils.getPrefString(mActivity, Pkey.APP_adzoneId, ""); | |||
// alibcTaokeParams.extraParams = new HashMap<>(); | |||
// alibcTaokeParams.extraParams.put("taokeAppkey", SPUtils.getPrefString(mActivity, Pkey.APP_alliance_appkey, "")); | |||
AlibcShowParams showParams = new AlibcShowParams(); | |||
showParams.setBackUrl("alisdk://"); | |||
AlibcTrade.openByUrl(WebActivity.this, "", "http://www.izhim.com/comm/tb_callback.php?_ctrl=domain&domain_state=MTI2&domain_return_url=aHR0cDovLzE5Mi4xNjguMC4xMTM6NTAwMC9hcGkvdjEvdGFvYmFvL2F1dGgvY2FsbGJhY2s%2FdGltZT0xNjAyNDk4MjA3", | |||
mainWeb, new MyBaichuanWebClient(), new MyWebChromeClient(), showParams, | |||
new AlibcTaokeParams("", "", ""), exParams, new AlibcTradeCallback() { | |||
@Override | |||
public void onTradeSuccess(AlibcTradeResult alibcTradeResult) { | |||
} | |||
@Override | |||
public void onFailure(int i, String s) { | |||
} | |||
}); | |||
} | |||
//用于百川授权的简化的WebClient | |||
@SuppressLint("AddJavascriptInterface") | |||
private class MyBaichuanWebClient extends WebViewClient { | |||
@SuppressLint("AddJavascriptInterface") | |||
@Override | |||
public boolean shouldOverrideUrlLoading(WebView view, final String url) { | |||
Log.d("百川拦截", url); | |||
//绑定会员关系时获取网页内容关闭网页 | |||
if (url.contains("comm/tbredirect.php") && !url.contains("oauth.m.taobao.com") && url.contains("track_id")) { | |||
Log.d("百川系时获取网页内容关闭网页", url); | |||
mainWeb.addJavascriptInterface(new InJavaScriptLocalObj(), "java_obj"); | |||
} | |||
if (url.contains("oauth.taobao.com/authorize") || url.contains("oauth.m.taobao.com/authorize")) { | |||
//渠道授权改动测试 | |||
Log.d("百川渠道授权改动测试", url); | |||
Map<String, String> exParams = new HashMap<>();//yhhpass参数 | |||
AlibcShowParams showParams = new AlibcShowParams(); | |||
showParams.setBackUrl("alisdk://"); | |||
AlibcTrade.openByUrl(WebActivity.this, "", url, | |||
mainWeb, new MyBaichuanWebClient(), new MyWebChromeClient(), showParams, | |||
new AlibcTaokeParams("", "", ""), exParams, new AlibcTradeCallback() { | |||
@Override | |||
public void onTradeSuccess(AlibcTradeResult alibcTradeResult) { | |||
Log.d("cg", alibcTradeResult.toString()); | |||
} | |||
@Override | |||
public void onFailure(int i, String s) { | |||
Log.d("sb", s); | |||
} | |||
}); | |||
} | |||
return super.shouldOverrideUrlLoading(view, url); | |||
} | |||
@Override | |||
public void onPageStarted(WebView view, String url, Bitmap favicon) { | |||
// WebLoad.setVisibility(View.GONE); | |||
mainWeb.setVisibility(View.GONE); | |||
//开始加载设置为透明 | |||
super.onPageStarted(view, url, favicon); | |||
} | |||
@Override | |||
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { | |||
super.onReceivedError(view, request, error); | |||
} | |||
@Override | |||
public void onPageFinished(WebView view, String url) { | |||
// WebLoad.setVisibility(View.GONE); | |||
mainWeb.setVisibility(View.VISIBLE); | |||
// 获取页面内容 | |||
view.loadUrl("javascript:window.java_obj.showSource(" | |||
+ "document.documentElement.innerText);"); | |||
// 获取解析<meta name="share-description" content="获取到的值"> | |||
view.loadUrl("javascript:window.java_obj.showDescription(" | |||
+ "document.querySelector('meta[name=\"share-description\"]').getAttribute('content')" | |||
+ ");"); | |||
// quanyikaText(); | |||
super.onPageFinished(view, url); | |||
} | |||
//处理 [Android]用WebView访问证书有问题的SSL网页 | |||
//http://blog.sina.com.cn/s/blog_4cd978f90102vrxk.html | |||
@Override | |||
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { | |||
handler.proceed(); | |||
} | |||
} | |||
/** | |||
* 绑定渠道 | |||
*/ | |||
private final class InJavaScriptLocalObj { | |||
@JavascriptInterface | |||
public void showSource(final String html) { | |||
//获取网页内容,用于判断是否成功绑定关系id | |||
try { | |||
if (html.contains("成功")) {//成功 | |||
Toast.makeText(WebActivity.this, "授权成功", Toast.LENGTH_SHORT).show(); | |||
finish(); | |||
} else {//失败 | |||
mainWeb.setAlpha(0); | |||
} | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
} | |||
} | |||
@JavascriptInterface | |||
public void showDescription(String str) { | |||
} | |||
} | |||
public class MyWebChromeClient extends WebChromeClient { | |||
private CustomViewCallback mCustomViewCallback; | |||
// 横屏时,显示视频的view | |||
private View mCustomView; | |||
// 点击全屏按钮时,调用的方法 | |||
@Override | |||
public void onShowCustomView(View view, CustomViewCallback callback) { | |||
super.onShowCustomView(view, callback); | |||
//isFullPlayVedio = true; | |||
//如果view 已经存在,则隐藏 | |||
if (mCustomView != null) { | |||
callback.onCustomViewHidden(); | |||
return; | |||
} | |||
mCustomView = view; | |||
mCustomView.setVisibility(View.VISIBLE); | |||
mCustomViewCallback = callback; | |||
} | |||
// 取消全屏调用的方法 | |||
@Override | |||
public void onHideCustomView() { | |||
super.onHideCustomView(); | |||
if (mCustomView == null) { | |||
return; | |||
} | |||
mCustomView.setVisibility(View.GONE); | |||
mCustomView = null; | |||
try { | |||
mCustomViewCallback.onCustomViewHidden(); | |||
} catch (Exception e) { | |||
} | |||
// setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//竖屏 | |||
} | |||
@Override | |||
public void onProgressChanged(WebView view, int newProgress) { | |||
} | |||
@Override | |||
public void onReceivedTitle(WebView view, String title) { | |||
super.onReceivedTitle(view, title); | |||
// Logger.wtf("我的url" + view.getUrl()); | |||
String url = view.getUrl(); | |||
if (Patterns.WEB_URL.matcher(title).matches()) { | |||
//网址不显示为标题 | |||
} else { | |||
//不是网址 | |||
if (!url.contains("api.ejiayou.com/pages/platform/soulList/index.html")) { | |||
} | |||
} | |||
} | |||
@Override | |||
public void onGeolocationPermissionsShowPrompt(final String origin, final GeolocationPermissions.Callback callback) { | |||
super.onGeolocationPermissionsShowPrompt(origin, callback); | |||
} | |||
// For Android 3.0+ | |||
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) { | |||
} | |||
// For Android < 3.0 | |||
public void openFileChooser(ValueCallback<Uri> uploadMsg) { | |||
openFileChooser(uploadMsg, ""); | |||
} | |||
// For Android > 4.1.1 | |||
public void openFileChooser(ValueCallback<Uri> uploadMsg, | |||
String acceptType, String capture) { | |||
openFileChooser(uploadMsg, acceptType); | |||
} | |||
// For Android > 5.0 | |||
@Override | |||
public boolean onShowFileChooser(WebView webView, | |||
ValueCallback<Uri[]> filePathCallback, | |||
FileChooserParams fileChooserParams) { | |||
return true; | |||
} | |||
} | |||
@SuppressLint("AddJavascriptInterface") | |||
private class MyWebClient extends WebViewClient { | |||
@SuppressLint("AddJavascriptInterface") | |||
@Override | |||
public boolean shouldOverrideUrlLoading(WebView view, final String url) { | |||
if (url.startsWith("tel:")) { | |||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); | |||
return true; | |||
} | |||
if (url.startsWith("bdnetdisk:")) { | |||
return true; | |||
} | |||
if (url.contains("tmast://")) { | |||
try { | |||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); | |||
startActivity(intent); | |||
} catch (Exception e) { | |||
} | |||
return true; | |||
} | |||
if (url.startsWith("http://ditu.amap.com") || | |||
url.startsWith("https://ditu.amap.com")) { | |||
return true; | |||
} | |||
if (url.contains("oauth.taobao.com/authorize") || url.contains("oauth.m.taobao.com/authorize")) { | |||
// mainWeb.addJavascriptInterface(new InJavaScriptLocadeUpgralObj(), "java_obj"); | |||
Map<String, String> exParams = new HashMap<>();//yhhpass参数 | |||
// AlibcTaokeParams alibcTaokeParams = new AlibcTaokeParams("", "", ""); | |||
// alibcTaokeParams.pid = SPUtils.getPrefString(mActivity, Pkey.pid, ""); | |||
// alibcTaokeParams.adzoneid = SPUtils.getPrefString(mActivity, Pkey.APP_adzoneId, ""); | |||
// alibcTaokeParams.extraParams = new HashMap<>(); | |||
// alibcTaokeParams.extraParams.put("taokeAppkey", SPUtils.getPrefString(mActivity, Pkey.APP_alliance_appkey, "")); | |||
AlibcShowParams showParams = new AlibcShowParams(); | |||
showParams.setBackUrl("alisdk://"); | |||
AlibcTrade.openByUrl(WebActivity.this, "", url, mainWeb, new MyBaichuanWebClient(), new MyWebChromeClient(), showParams, | |||
new AlibcTaokeParams("", "", ""), exParams, new AlibcTradeCallback() { | |||
@Override | |||
public void onTradeSuccess(AlibcTradeResult alibcTradeResult) { | |||
} | |||
@Override | |||
public void onFailure(int i, String s) { | |||
} | |||
}); | |||
} | |||
if (url.contains("tbopen://") || url.contains("tmall://") || url.contains("taobaotravel://")) { | |||
return true; | |||
} | |||
if (url.contains("dianping://")) { | |||
return true; | |||
} | |||
if (url.contains("aliim:")) { | |||
return true; | |||
} | |||
if (url.contains("?mod=appapi&act=miandan_course&ctrl=close")) { | |||
finish(); | |||
return true; | |||
} | |||
if (url.contains("vipma.net/quickapp.html?")) { | |||
return true; | |||
} | |||
// 如下方案可在非微信内部WebView的H5页面中调出微信支付 | |||
if (url.startsWith("weixin://wap/pay?")) { | |||
try { | |||
Intent intent = new Intent(); | |||
intent.setAction(Intent.ACTION_VIEW); | |||
intent.setData(Uri.parse(url)); | |||
startActivity(intent); | |||
return true; | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
} | |||
return true; | |||
} | |||
if (url.startsWith("weixin://")) { | |||
try { | |||
Intent intent = new Intent(); | |||
intent.setAction(Intent.ACTION_VIEW); | |||
intent.setData(Uri.parse(url)); | |||
startActivity(intent); | |||
return true; | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
} | |||
return true; | |||
} | |||
if (url.endsWith("native://wechat")) { | |||
Intent intent = new Intent(); | |||
ComponentName cmp = new ComponentName("com.tencent.mm", "com.tencent.mm.ui.LauncherUI"); | |||
intent.setAction(Intent.ACTION_MAIN); | |||
intent.addCategory(Intent.CATEGORY_LAUNCHER); | |||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | |||
intent.setComponent(cmp); | |||
startActivity(intent); | |||
return true; | |||
} | |||
if (url.contains("navite://save#")) { | |||
} | |||
//不拦截的话绑定淘宝关系id的时候会因为下面login.m.taobao.com的拦截而唤醒手淘授权之后导致不能切换帐号 | |||
// if (url.contains("client_id") && url.contains("login.m.taobao.com/logout.htm?")) { | |||
// view.loadUrl(url); | |||
// return true; | |||
// } | |||
if (url.contains("client_id")) { | |||
view.loadUrl(url); | |||
return true; | |||
} | |||
// if (url.contains("login.m.taobao.com")) { | |||
// if (!AlibcLogin.getInstance().isLogin()) { | |||
// AlibcLogin.getInstance().showLogin(new AlibcLoginCallback() { | |||
//// @Override | |||
//// public void onSuccess(int i) { | |||
//// } | |||
// | |||
// @Override | |||
// public void onSuccess(int i, String s, String s1) { | |||
// | |||
// } | |||
// | |||
// @Override | |||
// public void onFailure(int i, String s) { | |||
// } | |||
// }); | |||
// } | |||
// return true; | |||
// } | |||
if (url.contains("maliprod.alipay.com") && !url.contains("confirmGoods.do")) { | |||
AlibcLogin.getInstance().showLogin(new AlibcLoginCallback() { | |||
@Override | |||
public void onSuccess(int i, String s, String s1) { | |||
} | |||
@Override | |||
public void onFailure(int i, String s) { | |||
} | |||
}); | |||
} | |||
if (url.contains("intent://go/ju/webview?")) { | |||
return true; | |||
} | |||
// if (url.contains("s.click.taobao.com")) { | |||
// Logger.wtf(SPUtils.getPrefString(WebActivity.this, Pkey.IS_OPEN_TAOBAO, "")); | |||
// if (SPUtils.getPrefString(WebActivity.this, Pkey.IS_OPEN_TAOBAO, "").equals("shoutao")) { | |||
// if (!Token.isLogin()) { | |||
// if (isFirst2Login) { | |||
// ActivityJump.toLogin(WebActivity.this); | |||
// } | |||
// isFirst2Login = false; | |||
// finish(); | |||
// } else { | |||
// if (isInstallTaoBao(WebActivity.this)) { | |||
// jump2TaoBao(url); | |||
// finish(); | |||
// } else { | |||
// view.loadUrl(url); | |||
// } | |||
// } | |||
// return true; | |||
// } | |||
// } | |||
// if (url.contains("kingcard.dgunicom.com") && url.contains("newMsg") && url.contains("fill.html")) { | |||
// getItf(url); | |||
// } | |||
// else { | |||
// Logger.wtf("123"); | |||
// mainWeb.loadUrl(url); | |||
// } | |||
return super.shouldOverrideUrlLoading(view, url); | |||
} | |||
@Override | |||
public void onPageStarted(WebView view, String url, Bitmap favicon) { | |||
// WebLoad.setVisibility(View.GONE); | |||
//开始加载设置为透明 | |||
super.onPageStarted(view, url, favicon); | |||
} | |||
@Override | |||
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { | |||
super.onReceivedError(view, request, error); | |||
} | |||
@Override | |||
public void onPageFinished(WebView view, String url) { | |||
// WebLoad.setVisibility(View.GONE); | |||
// // 获取页面内容 | |||
view.loadUrl("javascript:window.java_obj.showSource(" | |||
+ "document.documentElement.innerText);"); | |||
// 获取解析<meta name="share-description" content="获取到的值"> | |||
view.loadUrl("javascript:window.java_obj.showDescription(" | |||
+ "document.querySelector('meta[name=\"share-description\"]').getAttribute('content')" | |||
+ ");"); | |||
// quanyikaText(); | |||
super.onPageFinished(view, url); | |||
} | |||
//处理 [Android]用WebView访问证书有问题的SSL网页 | |||
//http://blog.sina.com.cn/s/blog_4cd978f90102vrxk.html | |||
@Override | |||
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { | |||
handler.proceed(); | |||
} | |||
} | |||
} | |||
@@ -1,12 +1,11 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<!-- Modify this file to customize your launch splash screen --> | |||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> | |||
<item android:drawable="@android:color/white" /> | |||
<!-- <item android:drawable="@android:color/white" />--> | |||
<!-- You can insert your own image assets here --> | |||
<!-- <item> | |||
<item> | |||
<bitmap | |||
android:gravity="center" | |||
android:src="@mipmap/launch_image" /> | |||
</item> --> | |||
android:src="@drawable/bg_launcher" /> | |||
</item> | |||
</layer-list> |
@@ -0,0 +1,26 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent"> | |||
<TextView | |||
android:id="@+id/tv_aliBc" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:clickable="true" | |||
android:text="登陆" | |||
android:padding="12dp" | |||
android:textColor="#FFFFFF" | |||
android:focusable="true"> | |||
</TextView> | |||
<TextView | |||
android:id="@+id/tv_open_detail" | |||
android:layout_width="wrap_content" | |||
android:layout_height="wrap_content" | |||
android:focusable="true" | |||
android:clickable="true" | |||
android:text="打开淘宝详情" | |||
/> | |||
</LinearLayout> |
@@ -0,0 +1,14 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<LinearLayout 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:layout_width="match_parent" | |||
android:layout_height="match_parent" | |||
tools:context="cn.zhios.zhiying_base_widget_example.WebActivity"> | |||
<WebView | |||
android:id="@+id/webview_main" | |||
android:layout_width="match_parent" | |||
android:layout_height="match_parent"/> | |||
</LinearLayout> |
@@ -15,6 +15,10 @@ allprojects { | |||
repositories { | |||
google() | |||
jcenter() | |||
maven { | |||
url "http://repo.baichuan-android.taobao.com/content/groups/BaichuanRepositories/" | |||
} | |||
} | |||
} | |||
@@ -13,6 +13,7 @@ import 'package:provider/provider.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
import 'package:flutter_alibc/flutter_alibc.dart'; | |||
import 'package:flutter_alibc/alibc_model.dart'; | |||
import 'package:flutter_alibc/alibc_const_key.dart'; | |||
class IntellectSearchGoodsDialog extends StatefulWidget { | |||
final IntellectDialogDataModel model; | |||
@@ -31,7 +32,6 @@ class _IntellectSearchGoodsDialogState | |||
@override | |||
void initState() { | |||
requestStyle(); | |||
super.initState(); | |||
} | |||
@@ -243,7 +243,10 @@ class _IntellectSearchGoodsDialogState | |||
), | |||
), | |||
Text( | |||
widget?.model?.price ?? "", | |||
(num.tryParse(widget?.model?.price ?? "0") - | |||
num.tryParse( | |||
widget?.model?.couponPrice ?? "0")).toString() ?? | |||
"", | |||
style: TextStyle( | |||
fontSize: 32.sp, | |||
color: HexColor.fromHex( | |||
@@ -281,12 +284,10 @@ class _IntellectSearchGoodsDialogState | |||
child: Text( | |||
(_styleModel?.moduleList?.saveBtn?.content ?? "") + | |||
" ¥" + | |||
((double.tryParse( | |||
widget?.model?.couponPrice ?? "0.0") ?? | |||
((num.tryParse(widget?.model?.couponPrice ?? "0") ?? | |||
0) + | |||
double.tryParse( | |||
num.tryParse( | |||
widget?.model?.commission ?? '0')) | |||
.toString() | |||
.toString(), | |||
style: TextStyle( | |||
color: HexColor.fromHex( | |||
@@ -353,17 +354,26 @@ class _IntellectSearchGoodsDialogState | |||
RouterUtil.goLogin(context); | |||
return; | |||
} else { | |||
print("平台"+widget?.model?.provider??""); | |||
print("平台" + widget?.model?.provider ?? ""); | |||
print("链接" + widget?.model?.couponUrl ?? ""); | |||
if (widget?.model?.provider == 'taobao') { | |||
TradeResult result = | |||
await FlutterAlibc.openByUrl(url: widget?.model?.couponUrl??""); | |||
TradeResult result = await FlutterAlibc.openByUrl( | |||
url: widget?.model?.couponUrl ?? "", | |||
openType: AlibcOpenType.AlibcOpenTypeNative, | |||
backUrl: "alisdk://"); | |||
Logger.debug('${result.errorCode} ${result.errorMessage} '); | |||
print("链接"+widget?.model?.couponUrl??""); | |||
print("错误码"+result.errorCode); | |||
print("原因"+result.errorMessage); | |||
print("链接" + widget?.model?.couponUrl ?? ""); | |||
print("错误码" + result.errorCode); | |||
print("原因" + result.errorMessage); | |||
} else { | |||
RouterUtil.openWebview(widget?.model?.couponUrl, context); | |||
await FlutterAlibc.openByUrl( | |||
url: widget?.model?.couponUrl, | |||
openType: AlibcOpenType.AlibcOpenTypeNative); | |||
} | |||
///关闭弹窗 | |||
if (Navigator.canPop(context)) { | |||
Navigator.pop(context); | |||
} | |||
} | |||
} | |||
@@ -10,6 +10,7 @@ class IntellectDialogDataModel { | |||
String couponUrl; | |||
String couponPrice; | |||
IntellectDialogDataModel( | |||
{this.itemId, | |||
this.title, | |||
@@ -0,0 +1,71 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class TipDialog extends StatelessWidget { | |||
String title; | |||
TipDialog({this.title = "温馨提示", this.content}); | |||
String content; | |||
@override | |||
Widget build(BuildContext context) { | |||
return Scaffold( | |||
backgroundColor: Colors.transparent, | |||
body: Column( | |||
mainAxisAlignment: MainAxisAlignment.center, | |||
crossAxisAlignment: CrossAxisAlignment.center, | |||
children: <Widget>[ | |||
Container( | |||
width: double.infinity, | |||
decoration: BoxDecoration( | |||
color: Colors.white, borderRadius: BorderRadius.circular(20)), | |||
margin: EdgeInsets.only(left: 91.w, right: 91.w), | |||
child: Column( | |||
children: <Widget>[ | |||
Padding( | |||
padding: const EdgeInsets.only(top: 16), | |||
child: Text( | |||
title, | |||
style: TextStyle(fontSize: 30.sp,fontWeight: FontWeight.w400), | |||
), | |||
), | |||
Container( | |||
margin: EdgeInsets.all(16), | |||
constraints: BoxConstraints(minHeight: 100), | |||
child: Text( | |||
content, | |||
style: TextStyle(fontSize: 26.sp), | |||
), | |||
), | |||
Row( | |||
children: <Widget>[ | |||
Expanded( | |||
child: Padding( | |||
padding: const EdgeInsets.only( | |||
left: 16, right: 16, bottom: 16), | |||
child: FlatButton( | |||
padding: EdgeInsets.only(top: 10, bottom: 10), | |||
color: HexColor.fromHex("#FFFF4242"), | |||
shape: RoundedRectangleBorder( | |||
borderRadius: BorderRadius.circular(50)), | |||
onPressed: () { | |||
Navigator.pop(context); | |||
}, | |||
child: Text( | |||
"知道了", | |||
style: TextStyle( | |||
color: HexColor.fromHex("#FFFFFF"), | |||
fontSize: 26.sp), | |||
)), | |||
)) | |||
], | |||
) | |||
], | |||
), | |||
) | |||
], | |||
), | |||
); | |||
} | |||
} |
@@ -1,6 +1,22 @@ | |||
import 'dart:convert'; | |||
import 'package:flutter/material.dart'; | |||
import 'package:pull_to_refresh/pull_to_refresh.dart'; | |||
import 'package:zhiying_base_widget/pages/hot_ranking_page/hot_ranking_page_sk.dart'; | |||
import 'package:zhiying_base_widget/pages/main_page/notifier/main_page_bg_notifier.dart'; | |||
import 'package:zhiying_base_widget/pages/main_page/notifier/main_page_notifier.dart'; | |||
import 'package:zhiying_base_widget/utils/contants.dart'; | |||
import 'package:zhiying_comm/util/base_bloc.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
import 'package:provider/provider.dart'; | |||
import 'hot_ranking_page_bloc.dart'; | |||
class HotRankingPage extends StatefulWidget { | |||
final Map<String, dynamic> data; | |||
const HotRankingPage(this.data, {Key key}) : super(key: key); | |||
@override | |||
_HotRankingPageState createState() => _HotRankingPageState(); | |||
} | |||
@@ -10,7 +26,6 @@ class _HotRankingPageState extends State<HotRankingPage> { | |||
Widget build(BuildContext context) { | |||
print('hot_ranking_page build'); | |||
// | |||
// List<Widget> contentWidgets = tabs.map((item) { | |||
// BaseTabModel model = BaseTabModel.fromJson(item); | |||
@@ -19,6 +34,134 @@ class _HotRankingPageState extends State<HotRankingPage> { | |||
// if (_currentIndex >= contentWidgets.length) { | |||
// _currentIndex = 0; | |||
// } | |||
return Scaffold(); | |||
return Scaffold( | |||
backgroundColor: Color(0xfff9f9f9), | |||
body: MultiProvider( | |||
providers: [ | |||
ChangeNotifierProvider.value(value: MainPageBgNotifier()), | |||
], | |||
child: BlocProvider<HotRankingPageBloc>( | |||
bloc: HotRankingPageBloc(), | |||
child: _HotRankingPageContainer(data: widget.data), | |||
), | |||
), | |||
); | |||
} | |||
} | |||
class _HotRankingPageContainer extends StatefulWidget { | |||
final Map<String, dynamic> data; | |||
const _HotRankingPageContainer({Key key, this.data}) : super(key: key); | |||
@override | |||
__HotRankingPageContainerState createState() => | |||
__HotRankingPageContainerState(); | |||
} | |||
class __HotRankingPageContainerState extends State<_HotRankingPageContainer> { | |||
HotRankingPageBloc _bloc; | |||
RefreshController _refreshController; | |||
String backgroundImage; | |||
@override | |||
void initState() { | |||
_refreshController = RefreshController(); | |||
_bloc = BlocProvider.of<HotRankingPageBloc>(context); | |||
if (widget.data.containsKey(Constants.SkipIdentifierName)) { | |||
_bloc.loadData(widget.data[Constants.SkipIdentifierName]); | |||
} | |||
super.initState(); | |||
} | |||
@override | |||
Widget build(BuildContext context) { | |||
return StreamBuilder( | |||
stream: _bloc.outData, | |||
builder: (context, asyncSnapshot) { | |||
var model = asyncSnapshot.data; | |||
if (model == null) { | |||
return HotRankingPageSkeleton(); | |||
} | |||
for (var item in model) { | |||
WidgetModel widgetModel = | |||
WidgetModel.fromJson(Map<String, dynamic>.from(item)); | |||
if (item.containsKey("mod_name") && | |||
item['mod_name'] == "hot_rank_bg_img") { | |||
_bloc.backgroundImage = json.decode(item['data'])['bg_img']; | |||
break; | |||
} | |||
} | |||
return Stack( | |||
children: <Widget>[ | |||
Container( | |||
height: 293.h, | |||
decoration: BoxDecoration( | |||
image: DecorationImage( | |||
image: CachedNetworkImageProvider( | |||
_bloc.backgroundImage ?? ""), | |||
fit: BoxFit.fill)), | |||
), | |||
Column( | |||
children: _createContent(context, model), | |||
) | |||
], | |||
); | |||
}, | |||
); | |||
} | |||
//刷新 | |||
void _onLoading() async {} | |||
///构建子模块 | |||
_createContent(BuildContext context, List<Map<String, dynamic>> model) { | |||
List<Widget> list = List(); | |||
if (model == null) { | |||
///骨架图 | |||
} else { | |||
for (var item in model) { | |||
WidgetModel widgetModel = | |||
WidgetModel.fromJson(Map<String, dynamic>.from(item)); | |||
if (item.containsKey("mod_name") && | |||
item['mod_name'] == "hot_rank_tab_view") { | |||
list.add(Expanded( | |||
child: WidgetFactory.create(widgetModel.modName, | |||
isSliver: false, model: item)[0])); | |||
continue; | |||
} | |||
list.addAll(WidgetFactory.create(widgetModel.modName, | |||
isSliver: false, model: item)); | |||
} | |||
} | |||
return list; | |||
} | |||
} | |||
class _SilverAppBarDelegate extends SliverPersistentHeaderDelegate { | |||
_SilverAppBarDelegate(BuildContext context, this.child) { | |||
this.context = context; | |||
} | |||
BuildContext context; | |||
final Widget child; | |||
@override | |||
double get minExtent => MediaQuery.of(context).padding.top + 44; | |||
@override | |||
double get maxExtent => MediaQuery.of(context).padding.top + 44; | |||
@override | |||
Widget build( | |||
BuildContext context, double shrinkOffset, bool overlapsContent) { | |||
return child; | |||
} | |||
@override | |||
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) { | |||
return false; | |||
} | |||
} |
@@ -3,42 +3,49 @@ import 'dart:async'; | |||
import 'package:zhiying_comm/util/base_bloc.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class HotRankingPage extends BlocBase { | |||
class HotRankingPageBloc extends BlocBase { | |||
List<Map<String, dynamic>> _pageData = List(); | |||
StreamController<List<Map<String, dynamic>>> _dataController = | |||
StreamController<List<Map<String, dynamic>>>(); | |||
StreamController<List<Map<String, dynamic>>>(); | |||
Stream<List<Map<String, dynamic>>> get outData => _dataController.stream; | |||
StreamController<Map<String, dynamic>> _eventController = | |||
StreamController.broadcast(); | |||
Stream<Map<String, dynamic>> get event => _eventController.stream; | |||
String backgroundImage; | |||
@override | |||
void dispose() { | |||
_dataController.close(); | |||
_eventController.close(); | |||
_dataController = null; | |||
_eventController.close(); | |||
} | |||
void loadData(int id) { | |||
NetUtil.request('/api/v1/mod', | |||
method: NetMethod.POST, | |||
params: Map<String, dynamic>.from({ | |||
'ids': [id] | |||
}), onCache: (data) { | |||
_loadData(id, data); | |||
}, onSuccess: (data) { | |||
_loadData(id, data); | |||
}); | |||
loadData(String skipIdentifier) { | |||
NetUtil.request('/api/v1/mod/${skipIdentifier}', method: NetMethod.GET, | |||
onCache: (data) { | |||
_loadData(data); | |||
}, onSuccess: (data) { | |||
print(data); | |||
_loadData(data); | |||
}); | |||
} | |||
void _loadData(int id, dynamic data) { | |||
String key = id.toString(); | |||
Map<String, dynamic> json = Map<String, dynamic>.from(data); | |||
if (json.containsKey(key)) { | |||
List<dynamic> list = json[key]; | |||
_pageData = list.map((item) { | |||
return Map<String, dynamic>.from(item); | |||
}).toList(); | |||
} | |||
void _loadData(dynamic data) { | |||
print(data["mod_lis"]); | |||
_pageData = List.from(data["mod_list"]).map((v) { | |||
return Map<String, dynamic>.from(v); | |||
}).toList(); | |||
_dataController.add(_pageData); | |||
} | |||
void sendEvent(Map<String,dynamic> event){ | |||
_eventController.add(event); | |||
} | |||
} |
@@ -0,0 +1,91 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:shimmer/shimmer.dart'; | |||
class HotRankingPageSkeleton extends StatelessWidget { | |||
@override | |||
Widget build(BuildContext context) { | |||
return Shimmer.fromColors( | |||
baseColor: Colors.grey[300], | |||
highlightColor: Colors.grey[100], | |||
child: Column( | |||
mainAxisSize: MainAxisSize.min, | |||
children: <Widget>[ | |||
Container( | |||
color: Colors.white, | |||
width: double.infinity, | |||
height: 96, | |||
), | |||
Container( | |||
width: double.infinity, | |||
margin: EdgeInsets.all(16), | |||
height: 48, | |||
child: Row( | |||
children: _buildTopRow(), | |||
)), | |||
Expanded( | |||
child: Container( | |||
child: Column( | |||
children: _buildBottomListItem(), | |||
), | |||
)) | |||
], | |||
), | |||
); | |||
} | |||
_buildBottomListItem() { | |||
List<Widget> listWidget = List(); | |||
for (var index = 0; index < 3; index++) { | |||
listWidget.add(Container( | |||
margin: EdgeInsets.only(left: 16, top: 10, bottom: 10), | |||
child: Row( | |||
children: <Widget>[ | |||
Container( | |||
width: 127, | |||
height: 127, | |||
color: Colors.white, | |||
), | |||
Container( | |||
height: 127, | |||
margin: EdgeInsets.only(left: 10), | |||
child: Column( | |||
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||
crossAxisAlignment: CrossAxisAlignment.start, | |||
children: <Widget>[ | |||
Container( | |||
height: 40, | |||
width: 200, | |||
color: Colors.white, | |||
), | |||
Container( | |||
height: 30, | |||
width: 100, | |||
color: Colors.grey, | |||
), | |||
Container( | |||
height: 30, | |||
width: 200, | |||
color: Colors.grey, | |||
) | |||
], | |||
), | |||
) | |||
], | |||
), | |||
)); | |||
} | |||
return listWidget; | |||
} | |||
_buildTopRow() { | |||
List<Widget> listWidget = List(); | |||
for (var index = 0; index < 5; index++) { | |||
listWidget.add(Container( | |||
width: 50, | |||
color: Colors.white, | |||
margin: EdgeInsets.all(10), | |||
)); | |||
} | |||
return listWidget; | |||
} | |||
} |
@@ -6,13 +6,17 @@ import 'package:zhiying_base_widget/pages/main_page/notifier/main_page_bg_notifi | |||
import 'package:zhiying_base_widget/pages/main_page/notifier/main_page_notifier.dart'; | |||
import 'package:zhiying_base_widget/utils/contants.dart'; | |||
import 'package:zhiying_base_widget/widgets/others/mine_header_bg_widget.dart'; | |||
import 'package:zhiying_base_widget/widgets/wallet/wallet_appbar/wallet_appbar_sk.dart'; | |||
import 'package:zhiying_base_widget/widgets/wallet/wallet_data/wallet_data_sk.dart'; | |||
import 'package:zhiying_base_widget/widgets/wallet/wallet_detail/wallet_detail_sk.dart'; | |||
import 'package:zhiying_base_widget/widgets/wallet/wallet_income/wallet_income_sk.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
import 'package:zhiying_comm/util/base_bloc.dart'; | |||
import 'package:zhiying_comm/util/custom_sliver_persistent_header_delegate.dart'; | |||
import 'wallet_page_bloc.dart'; | |||
import 'wallet_page_bloc.dart'; | |||
///钱包页面 | |||
class WalletPage extends StatefulWidget { | |||
final Map<String, dynamic> data; | |||
@@ -77,8 +81,8 @@ class _WalletPageContainerState extends State<_WalletPageContainer> { | |||
ScreenUtil.init(context, width: 750, height: 1334); | |||
return SmartRefresher( | |||
controller: _refreshController, | |||
enablePullDown: false, | |||
enablePullUp: false, | |||
enablePullDown: true, | |||
enablePullUp:true, | |||
header: WaterDropHeader(), | |||
onLoading: _onLoading, | |||
child: Container( | |||
@@ -86,15 +90,17 @@ class _WalletPageContainerState extends State<_WalletPageContainer> { | |||
child: Stack( | |||
fit: StackFit.passthrough, | |||
children: <Widget>[ | |||
MineHeaderBgWidget( | |||
controller: _controller, | |||
), | |||
StreamBuilder( | |||
stream: _pageBloc.outData, | |||
builder: (context, asyncSnapshot) { | |||
var model = asyncSnapshot.data; | |||
return CustomScrollView( | |||
slivers: _createContent(context, model), | |||
return Stack( | |||
children: <Widget>[ | |||
Container(height: 362.h, color: _pageBloc.backgroundColor), | |||
CustomScrollView( | |||
slivers: _createContent(context, model), | |||
) | |||
], | |||
); | |||
}, | |||
) | |||
@@ -108,37 +114,33 @@ class _WalletPageContainerState extends State<_WalletPageContainer> { | |||
BuildContext context, List<Map<String, dynamic>> model) { | |||
List<Widget> list = List(); | |||
if (model == null) { | |||
list.addAll(WidgetFactory.create( | |||
'normal_nav', | |||
isSliver: true, | |||
model: Map(), | |||
///骨架图 | |||
list.add(SliverToBoxAdapter( | |||
child: WalletAppbarSkeleton(), | |||
)); | |||
list.addAll(WidgetFactory.create( | |||
'wallet_data', | |||
isSliver: true, | |||
model: Map(), | |||
list.add(SliverToBoxAdapter( | |||
child: WalletDataSkeleton(), | |||
)); | |||
list.addAll(WidgetFactory.create( | |||
'wallet_detail', | |||
isSliver: true, | |||
model: Map(), | |||
list.add(SliverToBoxAdapter( | |||
child: WalletIncomeSkeleton(), | |||
)); | |||
list.addAll(WidgetFactory.create( | |||
'wallet_income', | |||
isSliver: true, | |||
model: Map(), | |||
list.add(SliverToBoxAdapter( | |||
child: WalletDetailSkeleton(), | |||
)); | |||
} else { | |||
for (var item in model) { | |||
WidgetModel widgetModel = | |||
WidgetModel.fromJson(Map<String, dynamic>.from(item)); | |||
if (item.containsKey("mod_name")&&item['mod_name']=="my_wallet_appbar") { | |||
if (item.containsKey("mod_name") && | |||
item['mod_name'] == "my_wallet_appbar") { | |||
list.add(SliverPersistentHeader( | |||
delegate: _SilverAppBarDelegate(context, | |||
WidgetFactory.create(widgetModel.modName, | |||
isSliver: false, model: item)[0]),pinned: true,)); | |||
continue; | |||
delegate: _SilverAppBarDelegate( | |||
context, | |||
WidgetFactory.create(widgetModel.modName, | |||
isSliver: false, model: item)[0]), | |||
pinned: true, | |||
)); | |||
continue; | |||
} | |||
list.addAll(WidgetFactory.create(widgetModel.modName, | |||
isSliver: true, model: item)); | |||
@@ -149,23 +151,23 @@ class _WalletPageContainerState extends State<_WalletPageContainer> { | |||
} | |||
class _SilverAppBarDelegate extends SliverPersistentHeaderDelegate { | |||
_SilverAppBarDelegate(BuildContext context,this.child){ | |||
this.context=context; | |||
_SilverAppBarDelegate(BuildContext context, this.child) { | |||
this.context = context; | |||
} | |||
BuildContext context; | |||
final Widget child; | |||
@override | |||
double get minExtent => MediaQuery.of(context).padding.top+44; | |||
double get minExtent => MediaQuery.of(context).padding.top + 44; | |||
@override | |||
double get maxExtent => MediaQuery.of(context).padding.top+44; | |||
double get maxExtent => MediaQuery.of(context).padding.top + 44; | |||
@override | |||
Widget build( | |||
BuildContext context, double shrinkOffset, bool overlapsContent) { | |||
return child; | |||
} | |||
@override | |||
@@ -1,16 +1,22 @@ | |||
import 'dart:async'; | |||
import 'dart:convert'; | |||
import 'package:flutter/cupertino.dart'; | |||
import 'package:flutter/material.dart'; | |||
import 'package:zhiying_base_widget/utils/contants.dart'; | |||
import 'package:zhiying_base_widget/widgets/wallet/wallet_appbar/model/WalletAppbarModel.dart'; | |||
import 'package:zhiying_base_widget/widgets/wallet/wallet_data/model/wallet_header_model.dart'; | |||
import 'package:zhiying_comm/util/base_bloc.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class WalletPageBloc extends BlocBase { | |||
List<Map<String, dynamic>> _tabs = List(); | |||
StreamController<List<Map<String, dynamic>>> _tabController = | |||
StreamController<List<Map<String, dynamic>>>(); | |||
Stream<List<Map<String, dynamic>>> get outData => _tabController.stream; | |||
Color backgroundColor = Colors.transparent; | |||
@override | |||
void dispose() { | |||
_tabController.close(); | |||
@@ -34,6 +40,14 @@ class WalletPageBloc extends BlocBase { | |||
var list = List.from(data["mod_list"]).map((v) { | |||
return Map<String, dynamic>.from(v); | |||
}).toList(); | |||
for (var item in list) { | |||
if (item['mod_name'] == "my_wallet_appbar") { | |||
WalletAppbarModel walletAppbarModel = | |||
WalletAppbarModel.fromJson(json.decode(item["data"])); | |||
backgroundColor = HexColor.fromHex(walletAppbarModel.appBarBgColor); | |||
break; | |||
} | |||
} | |||
_tabController.add(list); | |||
} | |||
} |
@@ -3,6 +3,7 @@ import 'package:sharesdk_plugin/sharesdk_register.dart'; | |||
import 'package:zhiying_base_widget/pages/favorite_page/favorite_page.dart'; | |||
import 'package:zhiying_base_widget/pages/goods_details_page/goods_details_page.dart'; | |||
import 'package:zhiying_base_widget/pages/home_page/home_page.dart'; | |||
import 'package:zhiying_base_widget/pages/hot_ranking_page/hot_ranking_page.dart'; | |||
import 'package:zhiying_base_widget/pages/invited_friends/invited_friends.dart'; | |||
import 'package:zhiying_base_widget/pages/launch_page/launch_page.dart'; | |||
import 'package:zhiying_base_widget/pages/main_page/main_page.dart'; | |||
@@ -29,6 +30,9 @@ import 'package:zhiying_base_widget/widgets/home/home_goods/home_goods_creater.d | |||
import 'package:zhiying_base_widget/widgets/home/home_notice/home_notice_widget.dart'; | |||
import 'package:zhiying_base_widget/widgets/home/home_slide_banner/home_slide_banner_creater.dart'; | |||
import 'package:zhiying_base_widget/widgets/home/home_sreach/home_sreach_creater.dart'; | |||
import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_appbar/hot_ranking_appbar.dart'; | |||
import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_list/hot_ranking_list.dart'; | |||
import 'package:zhiying_base_widget/widgets/hot_ranking/hot_tab_bar/hot_tab_bar.dart'; | |||
import 'package:zhiying_base_widget/widgets/mine/mine_data/mine_data.dart'; | |||
import 'package:zhiying_base_widget/widgets/mine/mine_header/mine_header.dart'; | |||
import 'package:zhiying_base_widget/widgets/mine/mine_nav/mine_nav_bg.dart'; | |||
@@ -99,6 +103,8 @@ class BaseWidgetRegister { | |||
PageFactory.regist('homePage', (model) => HomePage()); | |||
PageFactory.regist('pub.flutter.index', (model) => MainPage(model)); | |||
PageFactory.regist('pub.flutter.profile', (model) => MainPage(model)); | |||
PageFactory.regist( | |||
'pub.flutter.hot_rank', (model) => HotRankingPage(model)); | |||
PageFactory.regist( | |||
'pub.flutter.my_wallet', (model) => WalletPage(data: model)); | |||
PageFactory.regist('goods_details', (model) => GoodsDetailsPage(model)); | |||
@@ -304,5 +310,11 @@ class BaseWidgetRegister { | |||
'wallet_income', DefaultWidgetCreater((model) => WalletIncome())); | |||
//======================= 账单明细 | |||
//======================== 热榜 | |||
WidgetFactory.regist('hot_rank_appbar', DefaultWidgetCreater((model)=>HotRankingAppBar(model))); | |||
WidgetFactory.regist('hot_rank_tabs', DefaultWidgetCreater((model)=>HotRankTableBar(model))); | |||
WidgetFactory.regist('hot_rank_tab_view', DefaultWidgetCreater((model)=>HotRankingList(model))); | |||
} | |||
} |
@@ -99,7 +99,7 @@ class _GooddsDetailsFooterContainerState | |||
return; | |||
} | |||
if (shopType == 'taobao') { | |||
TradeResult result = await FlutterAlibc.openByUrl(url: url); | |||
TradeResult result = await FlutterAlibc.openByUrl(url: url,backUrl: "alisdk://"); | |||
Logger.debug('${result.errorCode} ${result.errorMessage} '); | |||
} else { | |||
RouterUtil.openWebview(url, context); | |||
@@ -0,0 +1,49 @@ | |||
import 'dart:convert'; | |||
import 'package:flutter/material.dart'; | |||
import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_appbar/model/hot_ranking_appbaar_model.dart'; | |||
import 'package:zhiying_comm/util/extension/color.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class HotRankingAppBar extends StatelessWidget { | |||
final Map<String, dynamic> data; | |||
const HotRankingAppBar(this.data, {Key key}) : super(key: key); | |||
@override | |||
Widget build(BuildContext context) { | |||
var model = HotRankingAppbarModel.fromJson(json.decode(data['data'])); | |||
return Container( | |||
height: MediaQuery.of(context).padding.top + 56, | |||
child: AppBar( | |||
elevation: 0, | |||
leading: Navigator.canPop(context) | |||
? IconButton( | |||
icon: Icon(Icons.arrow_back_ios), | |||
onPressed: () { | |||
Navigator.of(context).pop(); | |||
}) | |||
: Container(), | |||
backgroundColor: HexColor.fromHex(model.appBarBgColor==""?"#00000000":model.appBarBgColor), | |||
centerTitle: true, | |||
title: Container( | |||
child: Stack( | |||
alignment: Alignment.center, | |||
children: <Widget>[ | |||
Text( | |||
model.appBarName??"", | |||
style: | |||
TextStyle(color: HexColor.fromHex(model.appBarNameColor??"")), | |||
), | |||
CachedNetworkImage( | |||
height: 40.w, | |||
width: 144.w, | |||
imageUrl: model.appBarNameImg??"", | |||
fit: BoxFit.fill, | |||
) | |||
], | |||
), | |||
)), | |||
); | |||
} | |||
} |
@@ -0,0 +1,32 @@ | |||
class HotRankingAppbarModel { | |||
String appBarName; | |||
String appBarNameColor; | |||
String appBarBgImg; | |||
String appBarBgColor; | |||
String appBarNameImg; | |||
HotRankingAppbarModel( | |||
{this.appBarName, | |||
this.appBarNameColor, | |||
this.appBarBgImg, | |||
this.appBarBgColor, | |||
this.appBarNameImg}); | |||
HotRankingAppbarModel.fromJson(Map<String, dynamic> json) { | |||
appBarName = json['app_bar_name']; | |||
appBarNameColor = json['app_bar_name_color']; | |||
appBarBgImg = json['app_bar_bg_img']; | |||
appBarBgColor = json['app_bar_bg_color']; | |||
appBarNameImg = json['app_bar_name_img']; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['app_bar_name'] = this.appBarName; | |||
data['app_bar_name_color'] = this.appBarNameColor; | |||
data['app_bar_bg_img'] = this.appBarBgImg; | |||
data['app_bar_bg_color'] = this.appBarBgColor; | |||
data['app_bar_name_img'] = this.appBarNameImg; | |||
return data; | |||
} | |||
} |
@@ -1,44 +0,0 @@ | |||
import 'dart:async'; | |||
import 'package:zhiying_comm/util/base_bloc.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class HotRankingBloc extends BlocBase { | |||
List<Map<String, dynamic>> _pageData = List(); | |||
StreamController<List<Map<String, dynamic>>> _dataController = | |||
StreamController<List<Map<String, dynamic>>>(); | |||
Stream<List<Map<String, dynamic>>> get outData => _dataController.stream; | |||
@override | |||
void dispose() { | |||
_dataController.close(); | |||
_dataController = null; | |||
} | |||
void loadData(int id) { | |||
NetUtil.request('/api/v1/mod', | |||
method: NetMethod.POST, | |||
params: Map<String, dynamic>.from({ | |||
'ids': [id] | |||
}), onCache: (data) { | |||
_loadData(id, data); | |||
}, onSuccess: (data) { | |||
_loadData(id, data); | |||
}); | |||
} | |||
void _loadData(int id, dynamic data) { | |||
String key = id.toString(); | |||
Map<String, dynamic> json = Map<String, dynamic>.from(data); | |||
if (json.containsKey(key)) { | |||
List<dynamic> list = json[key]; | |||
_pageData = list.map((item) { | |||
return Map<String, dynamic>.from(item); | |||
}).toList(); | |||
} | |||
_dataController.add(_pageData); | |||
} | |||
} |
@@ -1,91 +0,0 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_bloc.dart'; | |||
import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_goods/hot_ranking_goods.dart'; | |||
import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_sk.dart'; | |||
class HotRankingContainer extends StatefulWidget { | |||
final Map<String, dynamic> data; | |||
const HotRankingContainer({Key key, this.data}) : super(key: key); | |||
@override | |||
_HotRankingState createState() => _HotRankingState(); | |||
} | |||
class _HotRankingState extends State<HotRankingContainer> | |||
with TickerProviderStateMixin { | |||
HotRankingBloc _bloc; | |||
TabController _tabController; | |||
@override | |||
void initState() { | |||
_bloc = HotRankingBloc(); | |||
super.initState(); | |||
} | |||
_buildTabs() { | |||
List<Widget> listWidget = List(); | |||
for (int index = 0; index < 4; index++) { | |||
listWidget.add(Tab( | |||
text: "hahah", | |||
)); | |||
} | |||
return listWidget; | |||
} | |||
@override | |||
void dispose() { | |||
_tabController.dispose(); | |||
super.dispose(); | |||
} | |||
///构建 | |||
void createTabController() { | |||
_tabController = TabController(length: 4, vsync: this); | |||
} | |||
///构建TabView | |||
_buildTabView() { | |||
List<Widget> listWidget = List(); | |||
for (var index = 0; index < 4; index++) { | |||
listWidget.add(ListView.builder( | |||
padding: EdgeInsets.all(0), | |||
itemCount: 10, | |||
itemBuilder: (context, index) { | |||
return Container( | |||
child: HotRankingGoods(), | |||
); | |||
})); | |||
} | |||
return listWidget; | |||
} | |||
@override | |||
Widget build(BuildContext context) { | |||
return StreamBuilder( | |||
stream: _bloc.outData, | |||
builder: (context, snapshot) { | |||
if (snapshot.data != null) { | |||
return HotRankingSkeleton(); | |||
} else { | |||
createTabController(); | |||
return Container( | |||
child: Column( | |||
children: <Widget>[ | |||
TabBar( | |||
controller: _tabController, | |||
isScrollable: true, | |||
tabs: _buildTabs(), | |||
), | |||
Expanded( | |||
child: TabBarView( | |||
controller: _tabController, | |||
children: _buildTabView())) | |||
], | |||
), | |||
); | |||
} | |||
}); | |||
} | |||
} |
@@ -1,218 +1,290 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:flutter_screenutil/flutter_screenutil.dart'; | |||
import 'package:zhiying_base_widget/widgets/home/home_quick_entry/cached_network_image_util.dart'; | |||
import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_list/model/hot_ranking_list_data_model.dart'; | |||
import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_list/model/hot_ranking_list_model.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
import 'package:cached_network_image/cached_network_image.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class HotRankingGoods extends StatelessWidget { | |||
Good good; | |||
HotRankingListModel styleModel; | |||
int index; | |||
HotRankingGoods({Key key, this.good, this.styleModel, this.index}) | |||
: super(key: key); | |||
@override | |||
Widget build(BuildContext context) { | |||
return Stack( | |||
children: <Widget>[ | |||
Container( | |||
padding: EdgeInsets.all(15.w), | |||
margin: | |||
EdgeInsets.only(top: 8.w, bottom: 8.w, left: 25.w, right: 25.w), | |||
decoration: BoxDecoration( | |||
color: Colors.white, borderRadius: BorderRadius.circular(15.w)), | |||
child: Row( | |||
crossAxisAlignment: CrossAxisAlignment.start, | |||
children: <Widget>[ | |||
Container( | |||
width: 254.w, | |||
height: 254.w, | |||
color: Colors.amber, | |||
), | |||
Expanded( | |||
child: Container( | |||
margin: EdgeInsets.only(left: 20.w), | |||
child: Column( | |||
mainAxisSize: MainAxisSize.max, | |||
children: <Widget>[ | |||
Container( | |||
height: 70.h, | |||
child: Row( | |||
children: <Widget>[ | |||
Expanded( | |||
child: RichText( | |||
overflow: TextOverflow.ellipsis, | |||
maxLines: 2, | |||
text: TextSpan(children: <InlineSpan>[ | |||
WidgetSpan( | |||
child: Container( | |||
decoration: BoxDecoration( | |||
color: Colors.red, | |||
borderRadius: | |||
BorderRadius.circular(4)), | |||
child: Padding( | |||
padding: EdgeInsets.only( | |||
left: 4.w, right: 4.w), | |||
child: Text( | |||
"京东", | |||
var indexImage; | |||
if (styleModel.hotRankIconList != null && | |||
styleModel.hotRankIconList.length > 0 && | |||
styleModel.hotRankIconList.length - 1 >= index) { | |||
indexImage = styleModel.hotRankIconList[index]; | |||
} | |||
Providers providers = getProvider(good.provider); | |||
return GestureDetector( | |||
onTap: () { | |||
RouterUtil.route(SkipModel(skipIdentifier: "goods_details"), | |||
{"provider": good.provider, "good_id": good.goodId}, context); | |||
}, | |||
child: Stack( | |||
children: <Widget>[ | |||
Container( | |||
padding: EdgeInsets.all(15.w), | |||
margin: | |||
EdgeInsets.only(top: 8.w, bottom: 8.w, left: 25.w, right: 25.w), | |||
decoration: BoxDecoration( | |||
color: Colors.white, borderRadius: BorderRadius.circular(15.w)), | |||
child: Row( | |||
crossAxisAlignment: CrossAxisAlignment.start, | |||
children: <Widget>[ | |||
Container( | |||
width: 254.w, | |||
height: 254.w, | |||
decoration: BoxDecoration( | |||
borderRadius: BorderRadius.circular(6), | |||
image: DecorationImage( | |||
image: CachedNetworkImageProvider(good.goodImage))), | |||
), | |||
Expanded( | |||
child: Container( | |||
margin: EdgeInsets.only(left: 20.w), | |||
child: Column( | |||
mainAxisSize: MainAxisSize.max, | |||
children: <Widget>[ | |||
Container( | |||
height: 70.h, | |||
child: Row( | |||
children: <Widget>[ | |||
Expanded( | |||
child: RichText( | |||
overflow: TextOverflow.ellipsis, | |||
maxLines: 2, | |||
text: TextSpan(children: <InlineSpan>[ | |||
WidgetSpan( | |||
child: Container( | |||
decoration: BoxDecoration( | |||
color: HexColor.fromHex( | |||
providers.providerBgColor), | |||
borderRadius: | |||
BorderRadius.circular(4)), | |||
child: Padding( | |||
padding: EdgeInsets.only( | |||
left: 4.w, right: 4.w), | |||
child: Text( | |||
good.providerName ?? "", | |||
style: TextStyle( | |||
color: HexColor.fromHex( | |||
providers.providerNameColor, | |||
), | |||
fontSize: 18.sp), | |||
), | |||
), | |||
)), | |||
WidgetSpan( | |||
child: SizedBox( | |||
width: 4.h, | |||
)), | |||
TextSpan( | |||
text: good.goodTitle, | |||
style: TextStyle( | |||
color: HexColor.fromHex( | |||
"#FFFFFF", | |||
), | |||
fontSize: 18.sp), | |||
), | |||
), | |||
)), | |||
WidgetSpan( | |||
child: SizedBox( | |||
width: 4.h, | |||
)), | |||
TextSpan( | |||
text: | |||
"Segway Ninebot mini Pro九号平衡车智能代步...", | |||
style: TextStyle( | |||
color: Colors.black, | |||
fontSize: 30.sp)) | |||
]))) | |||
styleModel.titleColor ?? ""), | |||
fontSize: 30.sp)) | |||
]))) | |||
], | |||
), | |||
), | |||
Row( | |||
children: <Widget>[ | |||
good.coupon == "" | |||
? Container() | |||
: Container( | |||
margin: EdgeInsets.only( | |||
top: 4, bottom: 4, right: 15.w), | |||
decoration: BoxDecoration( | |||
color: HexColor.fromHex(styleModel | |||
.couponCommission.left.couponBgColor), | |||
image: DecorationImage( | |||
image: CachedNetworkImageProvider( | |||
styleModel.couponCommission.left | |||
.couponBgImg))), | |||
child: Padding( | |||
padding: const EdgeInsets.only( | |||
left: 8, right: 8, top: 2, bottom: 2), | |||
child: Text( | |||
(good.coupon ?? "") + | |||
(styleModel.couponCommission.left | |||
.couonText ?? | |||
""), | |||
style: TextStyle( | |||
color: HexColor.fromHex(styleModel | |||
.couponCommission | |||
.left | |||
.couponFontColor), | |||
fontSize: 22.sp), | |||
), | |||
), | |||
), | |||
good.commission == "" | |||
? Container() | |||
: Container( | |||
margin: EdgeInsets.only(top: 4, bottom: 4), | |||
decoration: BoxDecoration( | |||
color: HexColor.fromHex(styleModel | |||
.couponCommission | |||
.right | |||
.commissionBgColor ?? | |||
""), | |||
image: DecorationImage( | |||
image: CachedNetworkImageProvider( | |||
styleModel.couponCommission.right | |||
.commissionBgImg ?? | |||
""))), | |||
child: Padding( | |||
padding: const EdgeInsets.only( | |||
left: 8, right: 8, top: 2, bottom: 2), | |||
child: Text( | |||
(styleModel.couponCommission.right | |||
.commissionText ?? | |||
"") + | |||
(good.commission ?? ""), | |||
style: TextStyle( | |||
color: HexColor.fromHex(styleModel | |||
.couponCommission | |||
.right | |||
.commissionFontColor), | |||
fontSize: 22.sp), | |||
), | |||
), | |||
), | |||
], | |||
), | |||
), | |||
Row( | |||
children: <Widget>[ | |||
Container( | |||
margin: EdgeInsets.only(top: 4, bottom: 4), | |||
decoration: BoxDecoration(color: Colors.red), | |||
child: Padding( | |||
padding: const EdgeInsets.only( | |||
left: 8, right: 8, top: 2, bottom: 2), | |||
child: Text( | |||
"50元券", | |||
style: TextStyle( | |||
color: Colors.white, fontSize: 22.sp), | |||
Padding( | |||
padding: const EdgeInsets.only(top: 4, bottom: 4), | |||
child: Row( | |||
crossAxisAlignment: CrossAxisAlignment.end, | |||
children: <Widget>[ | |||
Padding( | |||
padding: EdgeInsets.only(bottom: 6.sp), | |||
child: Text( | |||
"¥", | |||
style: TextStyle( | |||
color: HexColor.fromHex( | |||
styleModel.currentPriceColor ?? ""), | |||
fontSize: 20.sp), | |||
), | |||
), | |||
), | |||
), | |||
SizedBox( | |||
width: 10.sp, | |||
), | |||
Container( | |||
margin: EdgeInsets.only(top: 4, bottom: 4), | |||
decoration: BoxDecoration(color: Colors.red), | |||
child: Padding( | |||
padding: const EdgeInsets.only( | |||
left: 8, right: 8, top: 2, bottom: 2), | |||
child: Text( | |||
"50元券", | |||
Text( | |||
good.currentPrice ?? "", | |||
style: TextStyle( | |||
color: Colors.white, fontSize: 22.sp), | |||
color: HexColor.fromHex( | |||
styleModel.currentPriceColor ?? ""), | |||
fontSize: 40.sp), | |||
), | |||
), | |||
) | |||
], | |||
), | |||
Padding( | |||
padding: const EdgeInsets.only(top: 4, bottom: 4), | |||
child: Row( | |||
crossAxisAlignment: CrossAxisAlignment.end, | |||
children: <Widget>[ | |||
Padding( | |||
padding: EdgeInsets.only(bottom: 6.sp), | |||
child: Text( | |||
"¥", | |||
style: | |||
TextStyle(color: Colors.red, fontSize: 20.sp), | |||
SizedBox( | |||
width: 6, | |||
), | |||
), | |||
Text( | |||
"1409", | |||
style: | |||
TextStyle(color: Colors.red, fontSize: 40.sp), | |||
), | |||
SizedBox( | |||
width: 6, | |||
), | |||
Padding( | |||
padding: EdgeInsets.only(bottom: 4.sp), | |||
child: Text( | |||
"¥1409", | |||
style: TextStyle( | |||
color: Colors.red, | |||
fontSize: 22.sp, | |||
decoration: TextDecoration.lineThrough), | |||
Padding( | |||
padding: EdgeInsets.only(bottom: 4.sp), | |||
child: Text( | |||
"¥" + good.marketPrice ?? "", | |||
style: TextStyle( | |||
color: HexColor.fromHex( | |||
styleModel.marketPriceColor ?? ""), | |||
fontSize: 22.sp, | |||
decoration: TextDecoration.lineThrough), | |||
), | |||
), | |||
), | |||
], | |||
], | |||
), | |||
), | |||
), | |||
Row( | |||
children: <Widget>[ | |||
Expanded( | |||
child: Stack( | |||
alignment: Alignment.centerLeft, | |||
children: <Widget>[ | |||
Row( | |||
children: <Widget>[ | |||
Expanded( | |||
child: Container( | |||
height: 40.w, | |||
padding: EdgeInsets.only( | |||
left: 64.w, | |||
), | |||
margin: EdgeInsets.only(right: 20), | |||
color: Colors.red, | |||
child: Text( | |||
"热销1231.1万件", | |||
style: TextStyle( | |||
color: Colors.white, fontSize: 22.sp), | |||
), | |||
)) | |||
], | |||
), | |||
Container( | |||
color: Colors.amber, | |||
width: 48.w, | |||
height: 48.w, | |||
child: CachedNetworkImage( | |||
imageUrl: "", | |||
Row( | |||
children: <Widget>[ | |||
Expanded( | |||
child: Stack( | |||
alignment: Alignment.centerLeft, | |||
children: <Widget>[ | |||
Row( | |||
children: <Widget>[ | |||
Expanded( | |||
child: Container( | |||
height: 40.w, | |||
padding: EdgeInsets.only( | |||
left: 64.w, | |||
), | |||
margin: | |||
EdgeInsets.only(right: 20, left: 20.w), | |||
color: HexColor.fromHex( | |||
styleModel.hotRank.bgColor ?? ""), | |||
child: Text( | |||
"热销" + good.inorderCount + "件", | |||
style: TextStyle( | |||
color: Colors.white, fontSize: 22.sp), | |||
), | |||
)) | |||
], | |||
), | |||
Container( | |||
width: 48.w, | |||
height: 48.w, | |||
placeholder: (context, _) => | |||
Container(color: Colors.yellow), | |||
fit: BoxFit.fill, | |||
), | |||
), | |||
Align( | |||
alignment: Alignment.centerRight, | |||
child: Container( | |||
decoration: BoxDecoration( | |||
color: Colors.amber, | |||
borderRadius: BorderRadius.circular(20)), | |||
margin: EdgeInsets.only(right: 0), | |||
child: Padding( | |||
padding: EdgeInsets.only( | |||
left: 16, right: 16, top: 4, bottom: 4), | |||
child: Text( | |||
"马上抢", | |||
style: TextStyle( | |||
color: Colors.white, fontSize: 26.sp), | |||
), | |||
child: CachedNetworkImage( | |||
imageUrl: styleModel.hotRank.hotSaleImg ?? "", | |||
width: 48.w, | |||
height: 48.w, | |||
placeholder: (context, _) => | |||
Container(color: Colors.yellow), | |||
fit: BoxFit.fill, | |||
), | |||
), | |||
) | |||
], | |||
)) | |||
], | |||
) | |||
], | |||
), | |||
)) | |||
], | |||
), | |||
), | |||
Align( | |||
alignment: Alignment.topLeft, | |||
child: Container( | |||
margin: EdgeInsets.only(left: 40.w, top: 8.h), | |||
color: Colors.red, | |||
height: 60.w, | |||
width: 60.w, | |||
Align( | |||
alignment: Alignment.centerRight, | |||
child: Container( | |||
height: 48.h, | |||
width: 127.w, | |||
decoration: BoxDecoration( | |||
image: DecorationImage( | |||
image: CachedNetworkImageProvider( | |||
styleModel.hotRank.buyNowImg ?? | |||
""), | |||
fit: BoxFit.fitWidth), | |||
borderRadius: | |||
BorderRadius.circular(20)), | |||
margin: EdgeInsets.only(right: 0), | |||
)) | |||
], | |||
)) | |||
], | |||
) | |||
], | |||
), | |||
)) | |||
], | |||
), | |||
), | |||
) | |||
], | |||
Align( | |||
alignment: Alignment.topLeft, | |||
child: Container( | |||
decoration: BoxDecoration( | |||
image: DecorationImage( | |||
image: CachedNetworkImageProvider(indexImage ?? ""))), | |||
margin: EdgeInsets.only(left: 40.w, top: 8.h), | |||
height: 60.w, | |||
width: 60.w, | |||
), | |||
) | |||
], | |||
), | |||
); | |||
} | |||
Providers getProvider(String provider) { | |||
for (var item in styleModel.providers) { | |||
if (item.type == provider) { | |||
return item; | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,87 @@ | |||
import 'dart:async'; | |||
import 'dart:convert'; | |||
import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_list/model/hot_ranking_list_data_model.dart'; | |||
import 'package:zhiying_comm/util/base_bloc.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class HotRankingListBloc extends BlocBase { | |||
HotRankingListDataModel _pageData; | |||
StreamController<HotRankingListDataModel> _dataController = | |||
StreamController<HotRankingListDataModel>(); | |||
Stream<HotRankingListDataModel> get outData => _dataController.stream; | |||
String currentTypeId; | |||
int currentPage = 1; | |||
bool isLoading = false; | |||
@override | |||
void dispose() { | |||
_dataController.close(); | |||
_dataController = null; | |||
} | |||
void loadData(String typeId, int page,Function complete) { | |||
if (isLoading) { | |||
complete(); | |||
return; | |||
} | |||
isLoading = true; | |||
currentTypeId = typeId; | |||
NetUtil.request( | |||
'/api/v1/rec/taobao?type_id=' + typeId + '&page=' + page.toString(), | |||
method: NetMethod.GET, onSuccess: (data) { | |||
complete(); | |||
isLoading = false; | |||
_loadData(data); | |||
}, onError: (e) { | |||
complete(); | |||
isLoading = false; | |||
}); | |||
} | |||
void loadMoreData(String typeId,Function complete) { | |||
if (isLoading) { | |||
complete(); | |||
return; | |||
} | |||
currentPage++; | |||
isLoading = true; | |||
NetUtil.request( | |||
'/api/v1/rec/taobao?type_id=' + | |||
typeId + | |||
'&page=' + | |||
currentPage.toString(), | |||
method: NetMethod.GET, onSuccess: (data) { | |||
complete(); | |||
isLoading = false; | |||
_loadMoreData(data); | |||
}, onError: (e) { | |||
complete(); | |||
isLoading = false; | |||
}); | |||
} | |||
void _loadData(dynamic data) { | |||
if (_pageData != null && _pageData.good != null) { | |||
_pageData.good.clear(); | |||
_pageData.good.addAll(HotRankingListDataModel.fromJson(data).good); | |||
} else { | |||
_pageData = HotRankingListDataModel.fromJson(data); | |||
} | |||
_dataController.add(_pageData); | |||
} | |||
void _loadMoreData(dynamic data) { | |||
if (_pageData != null && _pageData.good != null) { | |||
_pageData.good.addAll(HotRankingListDataModel.fromJson(data).good); | |||
_dataController.add(_pageData); | |||
} | |||
} | |||
} | |||
// http://192.168.0.113:5000/api/v1/rec/taobao?page=1 | |||
// http://192.168.0.113:5000/api/v1/rec/taobao?page=1 |
@@ -0,0 +1,145 @@ | |||
import 'dart:convert'; | |||
import 'package:flutter/material.dart'; | |||
import 'package:pull_to_refresh/pull_to_refresh.dart'; | |||
import 'package:zhiying_base_widget/pages/hot_ranking_page/hot_ranking_page_bloc.dart'; | |||
import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_goods/hot_ranking_goods.dart'; | |||
import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_list/model/hot_ranking_list_data_model.dart'; | |||
import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_list/model/hot_ranking_list_model.dart'; | |||
import 'package:zhiying_comm/util/base_bloc.dart'; | |||
import 'hot_ranking_bloc.dart'; | |||
import 'hot_ranking_list_sk.dart'; | |||
class HotRankingList extends StatefulWidget { | |||
final Map<String, dynamic> data; | |||
const HotRankingList(this.data, {Key key}) : super(key: key); | |||
@override | |||
_HotRankingState createState() => _HotRankingState(); | |||
} | |||
class _HotRankingState extends State<HotRankingList> | |||
with TickerProviderStateMixin { | |||
HotRankingListBloc _bloc; | |||
TabController _tabController; | |||
RefreshController _refreshController; | |||
List<Good> goods; | |||
HotRankingPageBloc _pageBloc; | |||
ScrollController _scrollcontroller; | |||
@override | |||
void initState() { | |||
_bloc = HotRankingListBloc(); | |||
_refreshController = RefreshController(); | |||
_pageBloc = BlocProvider.of<HotRankingPageBloc>(context); | |||
_scrollcontroller=ScrollController(); | |||
if (_pageBloc != null) { | |||
_pageBloc.event.listen((event) { | |||
if (event.containsKey('type') && event['type'] == "loadData") { | |||
_bloc.currentPage=1; | |||
_bloc.loadData(event['type_id'], _bloc.currentPage, () {}); | |||
} | |||
}); | |||
} | |||
super.initState(); | |||
} | |||
_buildTabs() { | |||
List<Widget> listWidget = List(); | |||
for (int index = 0; index < 4; index++) { | |||
listWidget.add(Tab( | |||
text: "hahah", | |||
)); | |||
} | |||
return listWidget; | |||
} | |||
@override | |||
void dispose() { | |||
_tabController.dispose(); | |||
super.dispose(); | |||
} | |||
///构建 | |||
void createTabController() { | |||
_tabController = TabController(length: 4, vsync: this); | |||
} | |||
///构建TabView | |||
_buildTabView() { | |||
List<Widget> listWidget = List(); | |||
for (var index = 0; index < 4; index++) { | |||
listWidget.add(ListView.builder( | |||
padding: EdgeInsets.all(0), | |||
itemCount: 10, | |||
itemBuilder: (context, index) { | |||
return Container( | |||
child: HotRankingGoods(), | |||
); | |||
})); | |||
} | |||
return listWidget; | |||
} | |||
@override | |||
Widget build(BuildContext context) { | |||
return StreamBuilder<HotRankingListDataModel>( | |||
stream: _bloc.outData, | |||
builder: (context, snapshot) { | |||
if (snapshot.data == null) { | |||
return HotRankingSkeleton(); | |||
} else { | |||
goods = snapshot.data.good; | |||
if(_bloc.currentPage==1){ | |||
Future.delayed(Duration(milliseconds: 100),(){ | |||
_scrollcontroller.animateTo(0, duration: Duration(milliseconds: 100), curve: Curves.ease); | |||
}); | |||
} | |||
return SmartRefresher( | |||
controller: _refreshController, | |||
enablePullDown: true, | |||
enablePullUp: true, | |||
onLoading: _onLoading, | |||
onRefresh: _onRefresh, | |||
child: CustomScrollView( | |||
controller: _scrollcontroller, | |||
slivers: <Widget>[ | |||
SliverList( | |||
delegate: SliverChildBuilderDelegate(_buildListItem, | |||
childCount: goods.length)) | |||
], | |||
), | |||
); | |||
} | |||
}); | |||
} | |||
Future _onLoading() async { | |||
_bloc.loadMoreData(_bloc.currentTypeId, () { | |||
_refreshController.loadComplete(); | |||
}); | |||
return null; | |||
} | |||
Future _onRefresh() async { | |||
_bloc.currentPage = 1; | |||
_bloc.loadData(_bloc.currentTypeId, _bloc.currentPage, () { | |||
_refreshController.refreshCompleted(); | |||
}); | |||
} | |||
Widget _buildListItem(BuildContext context, int index) { | |||
return HotRankingGoods( | |||
styleModel: | |||
HotRankingListModel.fromJson(json.decode(widget.data['data'])), | |||
good: goods[index], | |||
index: index, | |||
); | |||
} | |||
} |
@@ -8,6 +8,7 @@ class HotRankingSkeleton extends StatelessWidget { | |||
baseColor: Colors.grey[300], | |||
highlightColor: Colors.grey[100], | |||
child: Column( | |||
mainAxisSize: MainAxisSize.min, | |||
children: <Widget>[ | |||
Container( | |||
width: double.infinity, |
@@ -0,0 +1,82 @@ | |||
class HotRankingListDataModel { | |||
String provider; | |||
List<Good> good; | |||
HotRankingListDataModel({this.provider, this.good}); | |||
HotRankingListDataModel.fromJson(Map<String, dynamic> json) { | |||
provider = json['provider']; | |||
if (json['good'] != null) { | |||
good = new List<Good>(); | |||
json['good'].forEach((v) { | |||
good.add(new Good.fromJson(v)); | |||
}); | |||
} | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['provider'] = this.provider; | |||
if (this.good != null) { | |||
data['good'] = this.good.map((v) => v.toJson()).toList(); | |||
} | |||
return data; | |||
} | |||
} | |||
class Good { | |||
String provider; | |||
String providerName; | |||
String goodId; | |||
String goodImage; | |||
String goodTitle; | |||
String shopName; | |||
String coupon; | |||
String commission; | |||
String marketPrice; | |||
String currentPrice; | |||
String inorderCount; | |||
Good( | |||
{this.provider, | |||
this.providerName, | |||
this.goodId, | |||
this.goodImage, | |||
this.goodTitle, | |||
this.shopName, | |||
this.coupon, | |||
this.commission, | |||
this.marketPrice, | |||
this.currentPrice, | |||
this.inorderCount}); | |||
Good.fromJson(Map<String, dynamic> json) { | |||
provider = json['provider']; | |||
providerName = json['provider_name']; | |||
goodId = json['good_id']; | |||
goodImage = json['good_image']; | |||
goodTitle = json['good_title']; | |||
shopName = json['shop_name']; | |||
coupon = json['coupon']; | |||
commission = json['commission']; | |||
marketPrice = json['market_price']; | |||
currentPrice = json['current_price']; | |||
inorderCount = json['inorder_count']; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['provider'] = this.provider; | |||
data['provider_name'] = this.providerName; | |||
data['good_id'] = this.goodId; | |||
data['good_image'] = this.goodImage; | |||
data['good_title'] = this.goodTitle; | |||
data['shop_name'] = this.shopName; | |||
data['coupon'] = this.coupon; | |||
data['commission'] = this.commission; | |||
data['market_price'] = this.marketPrice; | |||
data['current_price'] = this.currentPrice; | |||
data['inorder_count'] = this.inorderCount; | |||
return data; | |||
} | |||
} |
@@ -0,0 +1,211 @@ | |||
class HotRankingListModel { | |||
List<String> hotRankIconList; | |||
String topMargin; | |||
String leftRighMargin; | |||
List<Providers> providers; | |||
String titleColor; | |||
String currentPriceColor; | |||
String marketPriceColor; | |||
String shopNameColor; | |||
String saleCountColor; | |||
String shopIcon; | |||
CouponCommission couponCommission; | |||
HotRank hotRank; | |||
HotRankingListModel( | |||
{this.hotRankIconList, | |||
this.topMargin, | |||
this.leftRighMargin, | |||
this.providers, | |||
this.titleColor, | |||
this.currentPriceColor, | |||
this.marketPriceColor, | |||
this.shopNameColor, | |||
this.saleCountColor, | |||
this.shopIcon, | |||
this.couponCommission, | |||
this.hotRank}); | |||
HotRankingListModel.fromJson(Map<String, dynamic> json) { | |||
hotRankIconList = json['hot_rank_icon_list'].cast<String>(); | |||
topMargin = json['top_margin']; | |||
leftRighMargin = json['left_righ_margin']; | |||
if (json['providers'] != null) { | |||
providers = new List<Providers>(); | |||
json['providers'].forEach((v) { | |||
providers.add(new Providers.fromJson(v)); | |||
}); | |||
} | |||
titleColor = json['title_color']; | |||
currentPriceColor = json['current_price_color']; | |||
marketPriceColor = json['market_price_color']; | |||
shopNameColor = json['shop_name_color']; | |||
saleCountColor = json['sale_count_color']; | |||
shopIcon = json['shop_icon']; | |||
couponCommission = json['coupon_commission'] != null | |||
? new CouponCommission.fromJson(json['coupon_commission']) | |||
: null; | |||
hotRank = json['hot_rank'] != null | |||
? new HotRank.fromJson(json['hot_rank']) | |||
: null; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['hot_rank_icon_list'] = this.hotRankIconList; | |||
data['top_margin'] = this.topMargin; | |||
data['left_righ_margin'] = this.leftRighMargin; | |||
if (this.providers != null) { | |||
data['providers'] = this.providers.map((v) => v.toJson()).toList(); | |||
} | |||
data['title_color'] = this.titleColor; | |||
data['current_price_color'] = this.currentPriceColor; | |||
data['market_price_color'] = this.marketPriceColor; | |||
data['shop_name_color'] = this.shopNameColor; | |||
data['sale_count_color'] = this.saleCountColor; | |||
data['shop_icon'] = this.shopIcon; | |||
if (this.couponCommission != null) { | |||
data['coupon_commission'] = this.couponCommission.toJson(); | |||
} | |||
if (this.hotRank != null) { | |||
data['hot_rank'] = this.hotRank.toJson(); | |||
} | |||
return data; | |||
} | |||
} | |||
class Providers { | |||
String type; | |||
String providerNameColor; | |||
String providerBgColor; | |||
Providers({this.type, this.providerNameColor, this.providerBgColor}); | |||
Providers.fromJson(Map<String, dynamic> json) { | |||
type = json['type']; | |||
providerNameColor = json['provider_name_color']; | |||
providerBgColor = json['provider_bg_color']; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['type'] = this.type; | |||
data['provider_name_color'] = this.providerNameColor; | |||
data['provider_bg_color'] = this.providerBgColor; | |||
return data; | |||
} | |||
} | |||
class CouponCommission { | |||
Left left; | |||
Right right; | |||
CouponCommission({this.left, this.right}); | |||
CouponCommission.fromJson(Map<String, dynamic> json) { | |||
left = json['left'] != null ? new Left.fromJson(json['left']) : null; | |||
right = json['right'] != null ? new Right.fromJson(json['right']) : null; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
if (this.left != null) { | |||
data['left'] = this.left.toJson(); | |||
} | |||
if (this.right != null) { | |||
data['right'] = this.right.toJson(); | |||
} | |||
return data; | |||
} | |||
} | |||
class Left { | |||
String couonText; | |||
String couponFontColor; | |||
String couponBgColor; | |||
String couponBgImg; | |||
Left( | |||
{this.couonText, | |||
this.couponFontColor, | |||
this.couponBgColor, | |||
this.couponBgImg}); | |||
Left.fromJson(Map<String, dynamic> json) { | |||
couonText = json['couon_text']; | |||
couponFontColor = json['coupon_font_color']; | |||
couponBgColor = json['coupon_bg_color']; | |||
couponBgImg = json['coupon_bg_img']; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['couon_text'] = this.couonText; | |||
data['coupon_font_color'] = this.couponFontColor; | |||
data['coupon_bg_color'] = this.couponBgColor; | |||
data['coupon_bg_img'] = this.couponBgImg; | |||
return data; | |||
} | |||
} | |||
class Right { | |||
String commissionText; | |||
String commissionFontColor; | |||
String commissionBgColor; | |||
String commissionBgImg; | |||
Right( | |||
{this.commissionText, | |||
this.commissionFontColor, | |||
this.commissionBgColor, | |||
this.commissionBgImg}); | |||
Right.fromJson(Map<String, dynamic> json) { | |||
commissionText = json['commission_text']; | |||
commissionFontColor = json['commission_font_color']; | |||
commissionBgColor = json['commission_bg_color']; | |||
commissionBgImg = json['commission_bg_img']; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['commission_text'] = this.commissionText; | |||
data['commission_font_color'] = this.commissionFontColor; | |||
data['commission_bg_color'] = this.commissionBgColor; | |||
data['commission_bg_img'] = this.commissionBgImg; | |||
return data; | |||
} | |||
} | |||
class HotRank { | |||
String isOpen; | |||
String bgColor; | |||
String fontColor; | |||
String hotSaleImg; | |||
String buyNowImg; | |||
HotRank( | |||
{this.isOpen, | |||
this.bgColor, | |||
this.fontColor, | |||
this.hotSaleImg, | |||
this.buyNowImg}); | |||
HotRank.fromJson(Map<String, dynamic> json) { | |||
isOpen = json['is_open']; | |||
bgColor = json['bg_color']; | |||
fontColor = json['font_color']; | |||
hotSaleImg = json['hot_sale_img']; | |||
buyNowImg = json['buy_now_img']; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['is_open'] = this.isOpen; | |||
data['bg_color'] = this.bgColor; | |||
data['font_color'] = this.fontColor; | |||
data['hot_sale_img'] = this.hotSaleImg; | |||
data['buy_now_img'] = this.buyNowImg; | |||
return data; | |||
} | |||
} |
@@ -0,0 +1,99 @@ | |||
import 'dart:async'; | |||
import 'dart:convert'; | |||
import 'package:flutter/material.dart'; | |||
import 'package:zhiying_base_widget/pages/hot_ranking_page/hot_ranking_page_bloc.dart'; | |||
import 'package:zhiying_comm/util/base_bloc.dart'; | |||
import 'package:zhiying_comm/util/extension/color.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
import 'model/hot_tabbar_model.dart'; | |||
class HotRankTableBar extends StatefulWidget { | |||
final Map<String, dynamic> data; | |||
const HotRankTableBar(this.data, {Key key}) : super(key: key); | |||
@override | |||
_HotRankTableBarState createState() => _HotRankTableBarState(); | |||
} | |||
class _HotRankTableBarState extends State<HotRankTableBar> | |||
with TickerProviderStateMixin { | |||
TabController _tabController; | |||
HotRankingTabBarModel _barModel; | |||
HotRankingPageBloc _pageBloc; | |||
@override | |||
void initState() { | |||
_barModel = | |||
HotRankingTabBarModel.fromJson(json.decode(widget.data['data'])); | |||
_tabController = | |||
TabController(length: _barModel.tabList.length, vsync: this); | |||
_pageBloc = BlocProvider.of<HotRankingPageBloc>(context); | |||
///待页面初始化后发送加载事件 | |||
Timer(Duration(milliseconds: 100), () { | |||
if (_barModel != null && | |||
_barModel.tabList != null && | |||
_barModel.tabList.length > 0) { | |||
var params = { | |||
"type": "loadData", | |||
"type_id": _barModel.tabList[0].typeId | |||
}; | |||
_pageBloc.sendEvent(params); | |||
} | |||
}); | |||
super.initState(); | |||
} | |||
@override | |||
Widget build(BuildContext context) { | |||
return Container( | |||
margin: EdgeInsets.only(bottom: 10), | |||
child: TabBar( | |||
indicatorPadding: EdgeInsets.only(bottom: 0), | |||
indicatorSize: TabBarIndicatorSize.label, | |||
controller: _tabController, | |||
indicatorColor: HexColor.fromHex( | |||
_barModel.tabList[_tabController.index].nameSelectColor), | |||
unselectedLabelColor: HexColor.fromHex( | |||
_barModel.tabList[_tabController.index].nameNoSelectColor), | |||
labelColor: HexColor.fromHex( | |||
_barModel.tabList[_tabController.index].nameSelectColor), | |||
isScrollable: true, | |||
tabs: _buildTabs(), | |||
onTap: (index) { | |||
var params = { | |||
"type": "loadData", | |||
"type_id": _barModel.tabList[_tabController.index].typeId | |||
}; | |||
_pageBloc.sendEvent(params); | |||
}, | |||
), | |||
); | |||
} | |||
_buildTabs() { | |||
List<Widget> listWidget = List(); | |||
for (int index = 0; index < _barModel.tabList.length; index++) { | |||
var item = _barModel.tabList[index]; | |||
listWidget.add(Container( | |||
child: Padding( | |||
padding: const EdgeInsets.only( | |||
bottom: 2, | |||
top: 0, | |||
), | |||
child: Text( | |||
item.name, | |||
style: TextStyle(fontSize: 26.sp), | |||
), | |||
), | |||
)); | |||
} | |||
return listWidget; | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
class HotRankingTabBarModel { | |||
String indicatorColor; | |||
List<TabList> tabList; | |||
HotRankingTabBarModel({this.indicatorColor, this.tabList}); | |||
HotRankingTabBarModel.fromJson(Map<String, dynamic> json) { | |||
indicatorColor = json['indicator_color']; | |||
if (json['tab_list'] != null) { | |||
tabList = new List<TabList>(); | |||
json['tab_list'].forEach((v) { | |||
tabList.add(new TabList.fromJson(v)); | |||
}); | |||
} | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['indicator_color'] = this.indicatorColor; | |||
if (this.tabList != null) { | |||
data['tab_list'] = this.tabList.map((v) => v.toJson()).toList(); | |||
} | |||
return data; | |||
} | |||
} | |||
class TabList { | |||
String name; | |||
String nameSelectColor; | |||
String nameNoSelectColor; | |||
String typeId; | |||
TabList( | |||
{this.name, this.nameSelectColor, this.nameNoSelectColor, this.typeId}); | |||
TabList.fromJson(Map<String, dynamic> json) { | |||
name = json['name']; | |||
nameSelectColor = json['name_select_color']; | |||
nameNoSelectColor = json['name_no_select_color']; | |||
typeId = json['type_id']; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['name'] = this.name; | |||
data['name_select_color'] = this.nameSelectColor; | |||
data['name_no_select_color'] = this.nameNoSelectColor; | |||
data['type_id'] = this.typeId; | |||
return data; | |||
} | |||
} |
@@ -1,8 +1,8 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_container.dart'; | |||
import 'package:zhiying_base_widget/widgets/hot_ranking/hot_ranking_sk.dart'; | |||
import 'package:flutter_screenutil/flutter_screenutil.dart'; | |||
import 'hot_ranking_list/hot_ranking_list.dart'; | |||
class HotTest extends StatefulWidget { | |||
@override | |||
_HotTestState createState() => _HotTestState(); | |||
@@ -14,7 +14,7 @@ class _HotTestState extends State<HotTest> { | |||
// 屏幕适配初始化 | |||
ScreenUtil.init(context, width: 750, height: 1334); | |||
return Scaffold( | |||
body: HotRankingContainer(), | |||
body: HotRankingList(null), | |||
); | |||
} | |||
} |
@@ -15,6 +15,7 @@ class WalletAppbar extends StatelessWidget { | |||
return Container( | |||
height: MediaQuery.of(context).padding.top + 56, | |||
child: AppBar( | |||
elevation: 0, | |||
leading: Navigator.canPop(context) | |||
? IconButton( | |||
icon: Icon(Icons.arrow_back_ios), | |||
@@ -22,11 +23,11 @@ class WalletAppbar extends StatelessWidget { | |||
Navigator.of(context).pop(); | |||
}) | |||
: Container(), | |||
backgroundColor: HexColor.fromHex(model.appBarBgColor), | |||
backgroundColor: HexColor.fromHex(model.appBarBgColor??""), | |||
centerTitle: true, | |||
title: Text( | |||
model.appBarName, | |||
style: TextStyle(color: HexColor.fromHex(model.appBarNameColor)), | |||
model.appBarName??"", | |||
style: TextStyle(color: HexColor.fromHex(model.appBarNameColor??"")), | |||
), | |||
), | |||
); | |||
@@ -0,0 +1,20 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
import 'package:shimmer/shimmer.dart'; | |||
class WalletAppbarSkeleton extends StatelessWidget { | |||
@override | |||
Widget build(BuildContext context) { | |||
return Container( | |||
child: Shimmer.fromColors( | |||
baseColor: Colors.grey[300], | |||
highlightColor: Colors.grey[100], | |||
child: Container( | |||
child: AppBar( | |||
backgroundColor: Colors.white, | |||
), | |||
), | |||
), | |||
); | |||
} | |||
} |
@@ -3,6 +3,7 @@ class WalletHeaderModel { | |||
String headerAvatar; | |||
String headerCashOutText; | |||
String headerCashOutTextColor; | |||
String headerCashOutKey; | |||
String headerCashOutBtnImg; | |||
List<HeaderBottomList> headerBottomList; | |||
@@ -11,6 +12,7 @@ class WalletHeaderModel { | |||
this.headerAvatar, | |||
this.headerCashOutText, | |||
this.headerCashOutTextColor, | |||
this.headerCashOutKey, | |||
this.headerCashOutBtnImg, | |||
this.headerBottomList}); | |||
@@ -19,6 +21,7 @@ class WalletHeaderModel { | |||
headerAvatar = json['header_avatar']; | |||
headerCashOutText = json['header_cash_out_text']; | |||
headerCashOutTextColor = json['header_cash_out_text_color']; | |||
headerCashOutKey = json['header_cash_out_key']; | |||
headerCashOutBtnImg = json['header_cash_out_btn_img']; | |||
if (json['header_bottom_list'] != null) { | |||
headerBottomList = new List<HeaderBottomList>(); | |||
@@ -34,6 +37,7 @@ class WalletHeaderModel { | |||
data['header_avatar'] = this.headerAvatar; | |||
data['header_cash_out_text'] = this.headerCashOutText; | |||
data['header_cash_out_text_color'] = this.headerCashOutTextColor; | |||
data['header_cash_out_key'] = this.headerCashOutKey; | |||
data['header_cash_out_btn_img'] = this.headerCashOutBtnImg; | |||
if (this.headerBottomList != null) { | |||
data['header_bottom_list'] = | |||
@@ -44,50 +48,26 @@ class WalletHeaderModel { | |||
} | |||
class HeaderBottomList { | |||
String totalText; | |||
String totalTextColor; | |||
String totalValueColor; | |||
String cashOutText; | |||
String cashOutTextColor; | |||
String cashOutValueColor; | |||
String unfinalText; | |||
String unfinalTextColor; | |||
String unfinalValueColor; | |||
String text; | |||
String textColor; | |||
String valueColor; | |||
String valueKey; | |||
HeaderBottomList( | |||
{this.totalText, | |||
this.totalTextColor, | |||
this.totalValueColor, | |||
this.cashOutText, | |||
this.cashOutTextColor, | |||
this.cashOutValueColor, | |||
this.unfinalText, | |||
this.unfinalTextColor, | |||
this.unfinalValueColor}); | |||
HeaderBottomList({this.text, this.textColor, this.valueColor, this.valueKey}); | |||
HeaderBottomList.fromJson(Map<String, dynamic> json) { | |||
totalText = json['total_text']; | |||
totalTextColor = json['total_text_color']; | |||
totalValueColor = json['total_value_color']; | |||
cashOutText = json['cash_out_text']; | |||
cashOutTextColor = json['cash_out_text_color']; | |||
cashOutValueColor = json['cash_out_value_color']; | |||
unfinalText = json['unfinal_text']; | |||
unfinalTextColor = json['unfinal_text_color']; | |||
unfinalValueColor = json['unfinal_value_color']; | |||
text = json['text']; | |||
textColor = json['text_color']; | |||
valueColor = json['value_color']; | |||
valueKey = json['value_key']; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['total_text'] = this.totalText; | |||
data['total_text_color'] = this.totalTextColor; | |||
data['total_value_color'] = this.totalValueColor; | |||
data['cash_out_text'] = this.cashOutText; | |||
data['cash_out_text_color'] = this.cashOutTextColor; | |||
data['cash_out_value_color'] = this.cashOutValueColor; | |||
data['unfinal_text'] = this.unfinalText; | |||
data['unfinal_text_color'] = this.unfinalTextColor; | |||
data['unfinal_value_color'] = this.unfinalValueColor; | |||
data['text'] = this.text; | |||
data['text_color'] = this.textColor; | |||
data['value_color'] = this.valueColor; | |||
data['value_key'] = this.valueKey; | |||
return data; | |||
} | |||
} |
@@ -2,118 +2,159 @@ import 'dart:convert'; | |||
import 'package:flutter/cupertino.dart'; | |||
import 'package:flutter/material.dart'; | |||
import 'package:zhiying_base_widget/widgets/wallet/wallet_data/model/wallet_header_model.dart'; | |||
import 'package:zhiying_base_widget/widgets/wallet/wallet_data/wallet_data_bloc.dart'; | |||
import 'package:zhiying_base_widget/widgets/wallet/wallet_data/wallet_data_sk.dart'; | |||
import 'package:cached_network_image/cached_network_image.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class WalletData extends StatelessWidget { | |||
class WalletData extends StatefulWidget { | |||
final Map<String, dynamic> data; | |||
const WalletData(this.data, {Key key}) : super(key: key); | |||
@override | |||
Widget build(BuildContext context) { | |||
_WalletDataState createState() => _WalletDataState(); | |||
} | |||
class _WalletDataState extends State<WalletData> { | |||
Map<String, dynamic> data; | |||
WalletDataBloc _bloc; | |||
Map<String, dynamic> dataModel; | |||
@override | |||
void initState() { | |||
data = widget.data; | |||
_bloc = WalletDataBloc(); | |||
_bloc.loadHeaderData(); | |||
super.initState(); | |||
} | |||
@override | |||
Widget build(BuildContext context) { | |||
print(data); | |||
Map<String, dynamic> temp = json.decode(data['data']); | |||
var model = WalletHeaderModel.fromJson(temp); | |||
return Container( | |||
width: double.infinity, | |||
child: data == null | |||
? WalletDataSkeleton() | |||
: Container( | |||
margin: EdgeInsets.only(left: 12.5, right: 12.5,top: 10), | |||
padding: EdgeInsets.only(left: 36.w, right: 26.w), | |||
decoration: BoxDecoration( | |||
image: DecorationImage( | |||
image: CachedNetworkImageProvider(model.headerImg),fit: BoxFit.fill)), | |||
height: 290.h, | |||
child: Column( | |||
mainAxisAlignment: MainAxisAlignment.spaceEvenly, | |||
children: <Widget>[ | |||
Row( | |||
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||
children: <Widget>[ | |||
Row( | |||
children: <Widget>[ | |||
CachedNetworkImage( | |||
imageUrl: model.headerAvatar, | |||
height: 66.h, | |||
width: 52.w, | |||
), | |||
Padding( | |||
padding: const EdgeInsets.all(8.0), | |||
child: Column( | |||
crossAxisAlignment: CrossAxisAlignment.start, | |||
WalletHeaderModel model; | |||
return StreamBuilder( | |||
stream: _bloc.outData, | |||
builder: (context, asn) { | |||
dataModel = asn.data; | |||
if (data.containsKey('data')) { | |||
Map<String, dynamic> temp = json.decode(data['data']); | |||
model = WalletHeaderModel.fromJson(temp); | |||
} else { | |||
return WalletDataSkeleton(); | |||
} | |||
return Container( | |||
width: double.infinity, | |||
child: dataModel == null | |||
? WalletDataSkeleton() | |||
: Container( | |||
margin: EdgeInsets.only(left: 12.5, right: 12.5, top: 10), | |||
padding: EdgeInsets.only(left: 36.w, right: 26.w), | |||
decoration: BoxDecoration( | |||
image: DecorationImage( | |||
image: CachedNetworkImageProvider( | |||
model?.headerImg ?? ""), | |||
fit: BoxFit.fill)), | |||
height: 290.h, | |||
child: Column( | |||
mainAxisAlignment: MainAxisAlignment.spaceEvenly, | |||
children: <Widget>[ | |||
Row( | |||
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||
children: <Widget>[ | |||
Row( | |||
children: <Widget>[ | |||
Text( | |||
model.headerCashOutText, | |||
style: TextStyle( | |||
fontSize: 25.sp, | |||
color: HexColor.fromHex( | |||
model.headerCashOutTextColor)), | |||
), | |||
Text( | |||
"没数据", | |||
style: TextStyle( | |||
fontSize: 25.sp, | |||
color: HexColor.fromHex( | |||
model.headerCashOutTextColor)), | |||
CachedNetworkImage( | |||
imageUrl: model?.headerAvatar ?? "", | |||
height: 66.h, | |||
width: 52.h, | |||
fit: BoxFit.fill, | |||
), | |||
Padding( | |||
padding: const EdgeInsets.all(8.0), | |||
child: Column( | |||
crossAxisAlignment: | |||
CrossAxisAlignment.start, | |||
children: <Widget>[ | |||
Text( | |||
model?.headerCashOutText ?? "", | |||
style: TextStyle( | |||
fontSize: 25.sp, | |||
color: HexColor.fromHex( | |||
model?.headerCashOutTextColor ?? | |||
"")), | |||
), | |||
Text( | |||
dataModel.containsKey( | |||
model.headerCashOutKey) | |||
? dataModel[model.headerCashOutKey] | |||
: "", | |||
style: TextStyle( | |||
fontSize: 40.sp, | |||
color: HexColor.fromHex( | |||
model.headerCashOutTextColor)), | |||
), | |||
], | |||
), | |||
) | |||
], | |||
), | |||
) | |||
], | |||
), | |||
GestureDetector( | |||
child: Container( | |||
decoration: BoxDecoration( | |||
color: Colors.red, | |||
borderRadius: BorderRadius.circular(10), | |||
image: DecorationImage( | |||
image: CachedNetworkImageProvider(""), | |||
fit: BoxFit.fill)), | |||
child: Padding( | |||
padding: EdgeInsets.only( | |||
left: 29.w, | |||
right: 29.w, | |||
top: 20.w, | |||
bottom: 20.w), | |||
child: Text( | |||
"提现", | |||
style: TextStyle(color: Colors.white), | |||
), | |||
), | |||
GestureDetector( | |||
child: Container( | |||
decoration: BoxDecoration( | |||
color: Colors.red, | |||
borderRadius: BorderRadius.circular(10), | |||
image: DecorationImage( | |||
image: CachedNetworkImageProvider(""), | |||
fit: BoxFit.fill)), | |||
child: Padding( | |||
padding: EdgeInsets.only( | |||
left: 29.w, | |||
right: 29.w, | |||
top: 20.w, | |||
bottom: 20.w), | |||
child: Text( | |||
"提现", | |||
style: TextStyle(color: Colors.white), | |||
), | |||
), | |||
), | |||
) | |||
], | |||
), | |||
Divider( | |||
height: 1, | |||
), | |||
) | |||
], | |||
), | |||
Divider( | |||
height: 1, | |||
), | |||
Row( | |||
mainAxisAlignment: MainAxisAlignment.spaceAround, | |||
children: _buildTopListItem(model?.headerBottomList)) | |||
], | |||
), | |||
), | |||
Row( | |||
mainAxisAlignment: MainAxisAlignment.spaceAround, | |||
children: _buildTopListItem(model)) | |||
], | |||
), | |||
)); | |||
}, | |||
); | |||
} | |||
///构建顶部Item | |||
_buildTopListItem(List<HeaderBottomList> list) { | |||
_buildTopListItem(WalletHeaderModel model) { | |||
List<Widget> listWidget = List(); | |||
for (var item in list) { | |||
for (var item in model.headerBottomList) { | |||
listWidget.add(Column( | |||
mainAxisSize: MainAxisSize.min, | |||
children: <Widget>[ | |||
Text( | |||
"9999", | |||
style: TextStyle(color: Colors.red, fontSize: 30.sp), | |||
dataModel.containsKey(item.valueKey) | |||
? dataModel[item.valueKey] | |||
: "", | |||
style: TextStyle( | |||
color: HexColor.fromHex(item.valueColor), fontSize: 30.sp), | |||
), | |||
Text( | |||
"累计到账(元)", | |||
style: TextStyle(color: Colors.grey, fontSize: 22.sp), | |||
item.text, | |||
style: TextStyle( | |||
color: HexColor.fromHex(item.textColor), fontSize: 22.sp), | |||
), | |||
], | |||
)); | |||
@@ -0,0 +1,29 @@ | |||
import 'dart:async'; | |||
import 'dart:convert'; | |||
import 'package:zhiying_comm/util/base_bloc.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
class WalletDataBloc extends BlocBase { | |||
StreamController<Map<String, dynamic>> _dataController = | |||
StreamController<Map<String, dynamic>>(); | |||
Stream<Map<String, dynamic>> get outData => _dataController.stream; | |||
@override | |||
void dispose() { | |||
_dataController.close(); | |||
_dataController = null; | |||
} | |||
/// | |||
/// 加载头部数据 | |||
/// | |||
loadHeaderData() async { | |||
await NetUtil.request("/api/v1/user/wallet/header",onSuccess: (data){ | |||
_dataController.add(data); | |||
}); | |||
} | |||
} |
@@ -1,7 +1,8 @@ | |||
import 'package:flutter/material.dart'; | |||
import 'package:zhiying_base_widget/widgets/wallet/wallet_data/wallet_data.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
import 'wallet_data.dart'; | |||
class WalletDataCreater extends WidgetCreater { | |||
@override | |||
List<Widget> createWidgets(Map<String, dynamic> model) { | |||
@@ -0,0 +1,45 @@ | |||
class WalletDetailDataModel { | |||
String type; | |||
String finish; | |||
String selfbuyEstimatedIncome; | |||
String selfbuyPayOrder; | |||
String directPromoteEstimatedIncome; | |||
String directPromotePayOrder; | |||
String indirectPromoteEstimatedIncome; | |||
String indirectPromotePayOrder; | |||
WalletDetailDataModel( | |||
{this.type, | |||
this.finish, | |||
this.selfbuyEstimatedIncome, | |||
this.selfbuyPayOrder, | |||
this.directPromoteEstimatedIncome, | |||
this.directPromotePayOrder, | |||
this.indirectPromoteEstimatedIncome, | |||
this.indirectPromotePayOrder}); | |||
WalletDetailDataModel.fromJson(Map<String, dynamic> json) { | |||
type = json['type']; | |||
finish = json['finish']; | |||
selfbuyEstimatedIncome = json['selfbuy_estimated_income']; | |||
selfbuyPayOrder = json['selfbuy_pay_order']; | |||
directPromoteEstimatedIncome = json['direct_promote_estimated_income']; | |||
directPromotePayOrder = json['direct_promote_pay_order']; | |||
indirectPromoteEstimatedIncome = json['indirect_promote_estimated_income']; | |||
indirectPromotePayOrder = json['indirect_promote_pay_order']; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['type'] = this.type; | |||
data['finish'] = this.finish; | |||
data['selfbuy_estimated_income'] = this.selfbuyEstimatedIncome; | |||
data['selfbuy_pay_order'] = this.selfbuyPayOrder; | |||
data['direct_promote_estimated_income'] = this.directPromoteEstimatedIncome; | |||
data['direct_promote_pay_order'] = this.directPromotePayOrder; | |||
data['indirect_promote_estimated_income'] = | |||
this.indirectPromoteEstimatedIncome; | |||
data['indirect_promote_pay_order'] = this.indirectPromotePayOrder; | |||
return data; | |||
} | |||
} |
@@ -72,27 +72,46 @@ class Providers { | |||
} | |||
class DateList { | |||
String isDefault; | |||
String text; | |||
String type; | |||
String textSelectColor; | |||
String textUnselectColor; | |||
String btnImg; | |||
String btnNoColorImg; | |||
String btnColorImg; | |||
DateList( | |||
{this.text, this.textSelectColor, this.textUnselectColor, this.btnImg}); | |||
{this.isDefault, | |||
this.text, | |||
this.type, | |||
this.textSelectColor, | |||
this.textUnselectColor, | |||
this.btnImg, | |||
this.btnNoColorImg, | |||
this.btnColorImg}); | |||
DateList.fromJson(Map<String, dynamic> json) { | |||
isDefault = json['is_default']; | |||
text = json['text']; | |||
type = json['type']; | |||
textSelectColor = json['text_select_color']; | |||
textUnselectColor = json['text_unselect_color']; | |||
btnImg = json['btn_img']; | |||
btnNoColorImg = json['btn_no_color_img']; | |||
btnColorImg = json['btn_color_img']; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['is_default'] = this.isDefault; | |||
data['text'] = this.text; | |||
data['type'] = this.type; | |||
data['text_select_color'] = this.textSelectColor; | |||
data['text_unselect_color'] = this.textUnselectColor; | |||
data['btn_img'] = this.btnImg; | |||
data['btn_no_color_img'] = this.btnNoColorImg; | |||
data['btn_color_img'] = this.btnColorImg; | |||
return data; | |||
} | |||
} | |||
@@ -139,49 +158,62 @@ class ProviderDashbord { | |||
} | |||
class Finish { | |||
String isShow; | |||
String text; | |||
String textColor; | |||
String valueColor; | |||
String vauleKey; | |||
String bgImg; | |||
String tipIcon; | |||
String tipText; | |||
Finish({this.text, this.textColor, this.valueColor, this.bgImg}); | |||
Finish( | |||
{this.isShow, | |||
this.text, | |||
this.textColor, | |||
this.valueColor, | |||
this.vauleKey, | |||
this.bgImg, | |||
this.tipIcon, | |||
this.tipText}); | |||
Finish.fromJson(Map<String, dynamic> json) { | |||
isShow = json['is_show']; | |||
text = json['text']; | |||
textColor = json['text_color']; | |||
valueColor = json['value_color']; | |||
vauleKey = json['vaule_key']; | |||
bgImg = json['bg_img']; | |||
tipIcon = json['tip_icon']; | |||
tipText = json['tip_text']; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['is_show'] = this.isShow; | |||
data['text'] = this.text; | |||
data['text_color'] = this.textColor; | |||
data['value_color'] = this.valueColor; | |||
data['vaule_key'] = this.vauleKey; | |||
data['bg_img'] = this.bgImg; | |||
data['tip_icon'] = this.tipIcon; | |||
data['tip_text'] = this.tipText; | |||
return data; | |||
} | |||
} | |||
class SelfBuy { | |||
String isShow; | |||
String title; | |||
String titleColor; | |||
String leftBgImg; | |||
String rightBgImg; | |||
List<ItemList> itemList; | |||
SelfBuy( | |||
{this.title, | |||
this.titleColor, | |||
this.leftBgImg, | |||
this.rightBgImg, | |||
this.itemList}); | |||
SelfBuy({this.isShow, this.title, this.titleColor, this.itemList}); | |||
SelfBuy.fromJson(Map<String, dynamic> json) { | |||
isShow = json['is_show']; | |||
title = json['title']; | |||
titleColor = json['title_color']; | |||
leftBgImg = json['left_bg_img']; | |||
rightBgImg = json['right_bg_img']; | |||
if (json['list'] != null) { | |||
itemList = new List<ItemList>(); | |||
json['list'].forEach((v) { | |||
@@ -192,10 +224,9 @@ class SelfBuy { | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['is_show'] = this.isShow; | |||
data['title'] = this.title; | |||
data['title_color'] = this.titleColor; | |||
data['left_bg_img'] = this.leftBgImg; | |||
data['right_bg_img'] = this.rightBgImg; | |||
if (this.itemList != null) { | |||
data['list'] = this.itemList.map((v) => v.toJson()).toList(); | |||
} | |||
@@ -204,23 +235,42 @@ class SelfBuy { | |||
} | |||
class ItemList { | |||
String bgImg; | |||
String text; | |||
String textColor; | |||
String vauleKey; | |||
String valueColor; | |||
String tipIcon; | |||
String tipText; | |||
ItemList({this.text, this.textColor, this.valueColor}); | |||
ItemList( | |||
{this.bgImg, | |||
this.text, | |||
this.textColor, | |||
this.vauleKey, | |||
this.valueColor, | |||
this.tipIcon, | |||
this.tipText}); | |||
ItemList.fromJson(Map<String, dynamic> json) { | |||
bgImg = json['bg_img']; | |||
text = json['text']; | |||
textColor = json['text_color']; | |||
vauleKey = json['vaule_key']; | |||
valueColor = json['value_color']; | |||
tipIcon = json['tip_icon']; | |||
tipText = json['tip_text']; | |||
} | |||
Map<String, dynamic> toJson() { | |||
final Map<String, dynamic> data = new Map<String, dynamic>(); | |||
data['bg_img'] = this.bgImg; | |||
data['text'] = this.text; | |||
data['text_color'] = this.textColor; | |||
data['vaule_key'] = this.vauleKey; | |||
data['value_color'] = this.valueColor; | |||
data['tip_icon'] = this.tipIcon; | |||
data['tip_text'] = this.tipText; | |||
return data; | |||
} | |||
} |
@@ -2,9 +2,12 @@ import 'dart:convert'; | |||
import 'package:flutter/cupertino.dart'; | |||
import 'package:flutter/material.dart'; | |||
import 'package:zhiying_base_widget/dialog/tip_dialog/tip_dialog.dart'; | |||
import 'package:zhiying_base_widget/pages/withdraw_page/withdraw_page.dart'; | |||
import 'package:zhiying_base_widget/widgets/home/home_quick_entry/cached_network_image_util.dart'; | |||
import 'package:zhiying_base_widget/widgets/wallet/wallet_detail/model/wallet_detail_data_model.dart'; | |||
import 'package:zhiying_base_widget/widgets/wallet/wallet_detail/model/wallet_detail_model.dart'; | |||
import 'package:zhiying_base_widget/widgets/wallet/wallet_detail/wallet_detail_bloc.dart'; | |||
import 'package:zhiying_base_widget/widgets/wallet/wallet_detail/wallet_detail_sk.dart'; | |||
import 'package:flutter_screenutil/flutter_screenutil.dart'; | |||
import 'package:cached_network_image/cached_network_image.dart'; | |||
@@ -25,7 +28,11 @@ class WalletDetail extends StatefulWidget { | |||
class _WalletDetailState extends State<WalletDetail> | |||
with TickerProviderStateMixin { | |||
WalletDetailModel _model; | |||
TabController _tabController; | |||
WalletDetailBloc _bloc; | |||
@override | |||
void initState() { | |||
if (widget.data != null) { | |||
@@ -33,92 +40,139 @@ class _WalletDetailState extends State<WalletDetail> | |||
_tabController = | |||
TabController(length: _model.providers.length, vsync: this); | |||
} | |||
_bloc = new WalletDetailBloc(); | |||
_bloc.loadData(_model.providers[0].type); | |||
super.initState(); | |||
} | |||
@override | |||
Widget build(BuildContext context) { | |||
return Container( | |||
margin: EdgeInsets.only(left: 12.5, right: 12.5), | |||
child: Column( | |||
children: <Widget>[ | |||
Container( | |||
child: TabBar( | |||
// isScrollable: true, | |||
controller: _tabController, | |||
tabs: _buildTabs()), | |||
), | |||
Container( | |||
height: 75.h, | |||
child: ListView.builder( | |||
padding: EdgeInsets.only(top: 16), | |||
itemCount: _model.dateList.length, | |||
scrollDirection: Axis.horizontal, | |||
itemBuilder: _buildTimeItem), | |||
), | |||
Container( | |||
height: 126.h, | |||
margin: EdgeInsets.only(top: 16), | |||
width: double.infinity, | |||
decoration: BoxDecoration( | |||
image: DecorationImage( | |||
image: CachedNetworkImageProvider( | |||
_model.providerDashbord.finish.bgImg), | |||
fit: BoxFit.fill)), | |||
child: Column( | |||
mainAxisAlignment: MainAxisAlignment.center, | |||
children: <Widget>[ | |||
Row( | |||
return StreamBuilder( | |||
stream: _bloc.outData, | |||
builder: (context, asyn) { | |||
if (_bloc.listDataModel.length == 0) { | |||
///骨架图 | |||
return WalletDetailSkeleton(); | |||
} | |||
return Container( | |||
decoration: BoxDecoration( | |||
color: Colors.white, borderRadius: BorderRadius.circular(8)), | |||
margin: | |||
EdgeInsets.only(left: 12.5, right: 12.5, top: 15.h, bottom: 15.h), | |||
padding: EdgeInsets.only(bottom: 15.h), | |||
child: Column( | |||
children: <Widget>[ | |||
Container( | |||
child: TabBar( | |||
isScrollable: true, | |||
unselectedLabelColor: | |||
HexColor.fromHex(_model.providers[0].unselectColor), | |||
labelColor: | |||
HexColor.fromHex(_model.providers[0].selectColor), | |||
controller: _tabController, | |||
indicatorColor: | |||
HexColor.fromHex(_model.providers[0].selectColor), | |||
indicatorSize: TabBarIndicatorSize.label, | |||
onTap: (index) { | |||
///变更平台 | |||
changeProvider(_model.providers[index].type); | |||
}, | |||
tabs: _buildTabs()), | |||
), | |||
///日期选择 | |||
Container( | |||
height: 75.h, | |||
child: ListView.builder( | |||
padding: EdgeInsets.only(top: 16,left: 16.w), | |||
itemCount: _model.dateList.length, | |||
scrollDirection: Axis.horizontal, | |||
itemBuilder: _buildTimeItem), | |||
), | |||
Container( | |||
height: 126.h, | |||
margin: EdgeInsets.only(top: 16, left: 30.w, right: 30.w), | |||
width: double.infinity, | |||
decoration: BoxDecoration( | |||
image: DecorationImage( | |||
image: CachedNetworkImageProvider( | |||
_model.providerDashbord.finish.bgImg), | |||
fit: BoxFit.fill)), | |||
child: Column( | |||
mainAxisAlignment: MainAxisAlignment.center, | |||
children: <Widget>[ | |||
Text( | |||
"已结算", | |||
style: TextStyle(color: Colors.black, fontSize: 22.sp), | |||
), | |||
InkWell( | |||
child: Padding( | |||
padding: const EdgeInsets.all(8.0), | |||
child: CachedNetworkImage( | |||
imageUrl: "", | |||
width: 20.h, | |||
height: 20.h, | |||
fit: BoxFit.fill, | |||
_model.providerDashbord.finish.isShow == "1" | |||
? Container() | |||
: Padding( | |||
padding: const EdgeInsets.all(8.0), | |||
child: Text( | |||
_model.providerDashbord.finish.text, | |||
style: TextStyle( | |||
fontSize: 28.sp, | |||
color: HexColor.fromHex(_model | |||
.providerDashbord.finish.textColor)), | |||
), | |||
), | |||
Row( | |||
mainAxisAlignment: MainAxisAlignment.center, | |||
children: <Widget>[ | |||
Text( | |||
_model.providerDashbord.finish.text ?? "", | |||
style: | |||
TextStyle(color: Colors.black, fontSize: 22.sp), | |||
), | |||
onTap: () { | |||
///问好 | |||
}) | |||
InkWell( | |||
child: Padding( | |||
padding: const EdgeInsets.all(8.0), | |||
child: CachedNetworkImage( | |||
imageUrl: | |||
_model.providerDashbord.finish.tipIcon ?? | |||
"", | |||
width: 20.h, | |||
height: 20.h, | |||
fit: BoxFit.fill, | |||
), | |||
), | |||
onTap: () { | |||
///显示弹窗 | |||
showTipDialog( | |||
null, _model.providerDashbord.finish.tipText); | |||
}) | |||
], | |||
), | |||
Text( | |||
_bloc.selectDateData.finish ?? "", | |||
style: TextStyle(color: Colors.red, fontSize: 40.sp), | |||
) | |||
], | |||
), | |||
Text( | |||
"158", | |||
style: TextStyle(color: Colors.red, fontSize: 40.sp), | |||
) | |||
], | |||
), | |||
), | |||
Container( | |||
child: ListView.builder( | |||
padding: EdgeInsets.all(0), | |||
itemCount: 3, | |||
shrinkWrap: true, | |||
physics: NeverScrollableScrollPhysics(), | |||
itemBuilder: (context, index) { | |||
return _buildBottomItem( | |||
context, index, _model.providerDashbord); | |||
}), | |||
) | |||
], | |||
), | |||
Container( | |||
child: ListView.builder( | |||
itemCount: 3, | |||
shrinkWrap: true, | |||
physics: NeverScrollableScrollPhysics(), | |||
itemBuilder: (context, index) { | |||
return _buildBottomItem( | |||
context, index, _model.providerDashbord); | |||
}), | |||
) | |||
], | |||
), | |||
); | |||
}, | |||
); | |||
} | |||
///平台选择 | |||
_buildTabs() { | |||
List<Widget> listWidget = List(); | |||
for (var item in _model.providers) { | |||
listWidget.add(Tab( | |||
child: Text( | |||
item.name, | |||
style: TextStyle(color: Colors.grey), | |||
style: TextStyle(fontSize: 28.sp), | |||
), | |||
)); | |||
} | |||
@@ -127,53 +181,173 @@ class _WalletDetailState extends State<WalletDetail> | |||
Widget _buildTimeItem(BuildContext context, int index) { | |||
var item = _model.dateList[index]; | |||
return Container( | |||
margin: EdgeInsets.only(top: 0, left: 8, right: 8), | |||
decoration: BoxDecoration( | |||
color: Colors.grey[200], borderRadius: BorderRadius.circular(50)), | |||
child: Padding( | |||
padding: const EdgeInsets.only(left: 16, right: 16), | |||
child: Center( | |||
child: Text( | |||
item.text, | |||
style: TextStyle(color: Colors.grey), | |||
)), | |||
return InkWell( | |||
child: Container( | |||
margin: EdgeInsets.only(top: 0, left: 8, right: 8), | |||
decoration: BoxDecoration( | |||
image: DecorationImage( | |||
image: CachedNetworkImageProvider( | |||
item.type == _bloc.selectDateData.type | |||
? item.btnImg ?? "" | |||
: item.btnNoColorImg ?? ""), | |||
fit: BoxFit.fitWidth), | |||
), | |||
child: Padding( | |||
padding: const EdgeInsets.only(left: 16, right: 16), | |||
child: Center( | |||
child: Text( | |||
item.text, | |||
style: TextStyle( | |||
fontSize: 22.sp, | |||
color: HexColor.fromHex(item.type == _bloc.selectDateData.type | |||
? item.textSelectColor | |||
: item.textUnselectColor)), | |||
)), | |||
), | |||
), | |||
onTap: () { | |||
for (var select in _bloc.listDataModel) { | |||
if (select.type == item.type) { | |||
_bloc.selectDay = item.type; | |||
_bloc.refresh(); | |||
return; | |||
} | |||
} | |||
}, | |||
); | |||
} | |||
///底部显示 | |||
Widget _buildBottomItem( | |||
BuildContext context, int index, ProviderDashbord dashbord) { | |||
var item = dashbord.selfBuy; | |||
SelfBuy item; | |||
if (index == 0) { | |||
item = dashbord.selfBuy; | |||
} else if (index == 1) { | |||
item = dashbord.directPromote; | |||
} else { | |||
item = dashbord.indirectPromote; | |||
} | |||
var dataMap = _bloc.selectDateData.toJson(); | |||
return Container( | |||
child: Column( | |||
children: <Widget>[ | |||
Text( | |||
item.title, | |||
style: TextStyle(color: HexColor.fromHex(item.titleColor)), | |||
SizedBox( | |||
height: 15.h, | |||
), | |||
item.isShow == "0" | |||
? Container() | |||
: Text( | |||
item.title, | |||
style: TextStyle( | |||
color: HexColor.fromHex(item.titleColor), | |||
fontSize: 28.sp), | |||
), | |||
SizedBox( | |||
height: 15.h, | |||
), | |||
Row( | |||
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |||
children: <Widget>[ | |||
Expanded( | |||
child: Container( | |||
height: 123.h, | |||
margin: EdgeInsets.only(right: 8), | |||
decoration: BoxDecoration( | |||
image: DecorationImage( | |||
image: CachedNetworkImageProvider(item?.leftBgImg ?? ''), | |||
fit: BoxFit.fill)), | |||
child: Center(child: Text("ddd")), | |||
), | |||
height: 123.h, | |||
margin: EdgeInsets.only(right: 8, left: 30.w), | |||
padding: EdgeInsets.only(left: 20.w), | |||
decoration: BoxDecoration( | |||
image: DecorationImage( | |||
image: CachedNetworkImageProvider( | |||
item.itemList[0].bgImg ?? ""), | |||
fit: BoxFit.fill)), | |||
child: Column( | |||
mainAxisAlignment: MainAxisAlignment.center, | |||
crossAxisAlignment: CrossAxisAlignment.start, | |||
children: <Widget>[ | |||
Row( | |||
children: <Widget>[ | |||
Text( | |||
item.itemList[0].text ?? "", | |||
style: TextStyle( | |||
fontSize: 22.sp, | |||
color: HexColor.fromHex( | |||
item.itemList[0].textColor)), | |||
), | |||
InkWell( | |||
child: Padding( | |||
padding: const EdgeInsets.all(8.0), | |||
child: CachedNetworkImage( | |||
imageUrl: item.itemList[0].tipIcon, | |||
width: 20.h, | |||
height: 20.h, | |||
fit: BoxFit.fill, | |||
), | |||
), | |||
onTap: () { | |||
//弹窗 | |||
showTipDialog(null, item.itemList[0].tipText); | |||
}, | |||
) | |||
], | |||
), | |||
Text(dataMap[item.itemList[0].vauleKey], | |||
style: TextStyle( | |||
fontSize: 34.sp, | |||
color: | |||
HexColor.fromHex(item.itemList[1].valueColor), | |||
)) | |||
], | |||
)), | |||
), | |||
Expanded( | |||
child: Container( | |||
height: 123.h, | |||
margin: EdgeInsets.only(left: 8), | |||
height: 123.h, | |||
margin: EdgeInsets.only(left: 8, right: 30.w), | |||
padding: EdgeInsets.only(left: 20.w), | |||
decoration: BoxDecoration( | |||
image: DecorationImage( | |||
image: CachedNetworkImageProvider(item?.rightBgImg ?? ''))), | |||
child: Center(child: Text("dddd")), | |||
image: CachedNetworkImageProvider( | |||
item.itemList[1].bgImg ?? ""), | |||
fit: BoxFit.fill)), | |||
child: Column( | |||
mainAxisAlignment: MainAxisAlignment.center, | |||
crossAxisAlignment: CrossAxisAlignment.start, | |||
children: <Widget>[ | |||
Row( | |||
children: <Widget>[ | |||
Text( | |||
item.itemList[1].text ?? "", | |||
style: TextStyle( | |||
fontSize: 22.sp, | |||
color: | |||
HexColor.fromHex(item.itemList[1].textColor)), | |||
), | |||
InkWell( | |||
child: Padding( | |||
padding: const EdgeInsets.all(8.0), | |||
child: CachedNetworkImage( | |||
imageUrl: item.itemList[1].tipIcon, | |||
width: 20.h, | |||
height: 20.h, | |||
fit: BoxFit.fill, | |||
), | |||
), | |||
onTap: () { | |||
//弹窗 | |||
showTipDialog(null, item.itemList[1].tipText); | |||
}, | |||
) | |||
], | |||
), | |||
Text( | |||
dataMap[item.itemList[1].vauleKey], | |||
style: TextStyle( | |||
fontSize: 34.sp, | |||
color: HexColor.fromHex(item.itemList[1].valueColor)), | |||
) | |||
], | |||
), | |||
)) | |||
], | |||
) | |||
@@ -181,4 +355,14 @@ class _WalletDetailState extends State<WalletDetail> | |||
), | |||
); | |||
} | |||
///变更平台 | |||
void changeProvider(String type) { | |||
_bloc.loadData(type); | |||
} | |||
///显示提示框 | |||
void showTipDialog(String title, String content) { | |||
showDialog(context: context, child: TipDialog(content: content)); | |||
} | |||
} |
@@ -0,0 +1,52 @@ | |||
import 'dart:async'; | |||
import 'dart:convert'; | |||
import 'package:zhiying_comm/util/base_bloc.dart'; | |||
import 'package:zhiying_comm/zhiying_comm.dart'; | |||
import 'model/wallet_detail_data_model.dart'; | |||
class WalletDetailBloc extends BlocBase { | |||
StreamController<WalletDetailDataModel> _dataController = | |||
StreamController<WalletDetailDataModel>(); | |||
Stream<WalletDetailDataModel> get outData => _dataController.stream; | |||
///选中的某一时间的数据 | |||
WalletDetailDataModel selectDateData; | |||
String selectDay = "today"; | |||
List<WalletDetailDataModel> listDataModel = new List(); | |||
@override | |||
void dispose() { | |||
_dataController.close(); | |||
_dataController = null; | |||
} | |||
/// | |||
/// 加载头部数据 | |||
/// | |||
loadData(String type) async { | |||
await NetUtil.request("/api/v1/user/wallet/" + type, onSuccess: (data) { | |||
listDataModel.clear(); | |||
listDataModel.addAll(List.from(data).map((v) { | |||
return WalletDetailDataModel.fromJson(v); | |||
}).toList()); | |||
refresh(); | |||
}); | |||
} | |||
///刷新页面 | |||
refresh() { | |||
for (var item in listDataModel) { | |||
if (selectDay == item.type) { | |||
selectDateData = item; | |||
_dataController.add(selectDateData); | |||
return; | |||
} | |||
} | |||
} | |||
} |
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; | |||
import 'package:shimmer/shimmer.dart'; | |||
class WalletDetailSkeleton extends StatelessWidget { | |||
@override | |||
Widget build(BuildContext context) { | |||
return Container( | |||
@@ -12,23 +13,93 @@ class WalletDetailSkeleton extends StatelessWidget { | |||
child: Shimmer.fromColors( | |||
baseColor: Colors.grey[300], | |||
highlightColor: Colors.grey[100], | |||
child: Row( | |||
child: Column( | |||
children: <Widget>[ | |||
Container( | |||
width: 18, | |||
height: 18, | |||
decoration: BoxDecoration( | |||
borderRadius: BorderRadius.circular(9), | |||
color: Colors.white), | |||
width: double.infinity, | |||
child: _createTab(), | |||
), | |||
Container( | |||
margin: EdgeInsets.only(left: 8), | |||
width: 120, | |||
height: 14, | |||
color: Colors.white, | |||
margin: EdgeInsets.only(top: 6), | |||
width: double.infinity, | |||
child: _createTags(), | |||
), | |||
Container( | |||
margin: EdgeInsets.only(top: 6), | |||
height: 64, | |||
decoration: BoxDecoration( | |||
borderRadius: BorderRadius.circular(7.5), | |||
color: Colors.white), | |||
), | |||
_createDataRow(), | |||
_createDataRow(), | |||
_createDataRow(), | |||
], | |||
)), | |||
); | |||
} | |||
Widget _createTab() { | |||
return Row( | |||
children: List.generate(5, (index) { | |||
return Expanded( | |||
child: Container( | |||
height: 14, | |||
margin: EdgeInsets.only(left: 10, right: 10, top: 4, bottom: 4), | |||
color: Colors.white, | |||
), | |||
); | |||
}), | |||
); | |||
} | |||
Widget _createTags() { | |||
return Row( | |||
children: List.generate(5, (index) { | |||
return Expanded( | |||
child: Container( | |||
height: 20, | |||
margin: EdgeInsets.only(left: 10, right: 10, top: 4, bottom: 4), | |||
decoration: BoxDecoration( | |||
color: Colors.white, borderRadius: BorderRadius.circular(10)), | |||
), | |||
); | |||
}), | |||
); | |||
} | |||
Widget _createDataRow() { | |||
return Column( | |||
children: <Widget>[ | |||
Container( | |||
margin: EdgeInsets.only(top: 8, bottom: 2), | |||
width: 64, | |||
height: 18, | |||
color: Colors.white, | |||
), | |||
Row( | |||
children: <Widget>[ | |||
Expanded( | |||
child: Container( | |||
margin: EdgeInsets.only(top: 6, right: 5), | |||
height: 64, | |||
decoration: BoxDecoration( | |||
borderRadius: BorderRadius.circular(7.5), | |||
color: Colors.white), | |||
), | |||
), | |||
Expanded( | |||
child: Container( | |||
margin: EdgeInsets.only(top: 6, left: 5), | |||
height: 64, | |||
decoration: BoxDecoration( | |||
borderRadius: BorderRadius.circular(7.5), | |||
color: Colors.white), | |||
), | |||
) | |||
], | |||
) | |||
], | |||
); | |||
} | |||
} |
@@ -12,93 +12,23 @@ class WalletIncomeSkeleton extends StatelessWidget { | |||
child: Shimmer.fromColors( | |||
baseColor: Colors.grey[300], | |||
highlightColor: Colors.grey[100], | |||
child: Column( | |||
child: Row( | |||
children: <Widget>[ | |||
Container( | |||
width: double.infinity, | |||
child: _createTab(), | |||
), | |||
Container( | |||
margin: EdgeInsets.only(top: 6), | |||
width: double.infinity, | |||
child: _createTags(), | |||
), | |||
Container( | |||
margin: EdgeInsets.only(top: 6), | |||
height: 64, | |||
width: 18, | |||
height: 18, | |||
decoration: BoxDecoration( | |||
borderRadius: BorderRadius.circular(7.5), | |||
borderRadius: BorderRadius.circular(9), | |||
color: Colors.white), | |||
), | |||
_createDataRow(), | |||
_createDataRow(), | |||
_createDataRow(), | |||
Container( | |||
margin: EdgeInsets.only(left: 8), | |||
width: 120, | |||
height: 14, | |||
color: Colors.white, | |||
), | |||
], | |||
)), | |||
); | |||
} | |||
Widget _createTab() { | |||
return Row( | |||
children: List.generate(5, (index) { | |||
return Expanded( | |||
child: Container( | |||
height: 14, | |||
margin: EdgeInsets.only(left: 10, right: 10, top: 4, bottom: 4), | |||
color: Colors.white, | |||
), | |||
); | |||
}), | |||
); | |||
} | |||
Widget _createTags() { | |||
return Row( | |||
children: List.generate(5, (index) { | |||
return Expanded( | |||
child: Container( | |||
height: 20, | |||
margin: EdgeInsets.only(left: 10, right: 10, top: 4, bottom: 4), | |||
decoration: BoxDecoration( | |||
color: Colors.white, borderRadius: BorderRadius.circular(10)), | |||
), | |||
); | |||
}), | |||
); | |||
} | |||
Widget _createDataRow() { | |||
return Column( | |||
children: <Widget>[ | |||
Container( | |||
margin: EdgeInsets.only(top: 8, bottom: 2), | |||
width: 64, | |||
height: 18, | |||
color: Colors.white, | |||
), | |||
Row( | |||
children: <Widget>[ | |||
Expanded( | |||
child: Container( | |||
margin: EdgeInsets.only(top: 6, right: 5), | |||
height: 64, | |||
decoration: BoxDecoration( | |||
borderRadius: BorderRadius.circular(7.5), | |||
color: Colors.white), | |||
), | |||
), | |||
Expanded( | |||
child: Container( | |||
margin: EdgeInsets.only(top: 6, left: 5), | |||
height: 64, | |||
decoration: BoxDecoration( | |||
borderRadius: BorderRadius.circular(7.5), | |||
color: Colors.white), | |||
), | |||
) | |||
], | |||
) | |||
], | |||
); | |||
} | |||
} |