Browse Source

1.增加原生androidWebView

2.关于我们增加隐私政策
3.优化我的钱包数据加载
tags/0.0.14+7
“yanghuaxuan” 3 years ago
parent
commit
828cb4ef25
15 changed files with 876 additions and 66 deletions
  1. +6
    -1
      android/build.gradle
  2. +12
    -2
      android/src/main/AndroidManifest.xml
  3. +541
    -0
      android/src/main/java/cn/zhios/zhiying_base_widget/WebViewActivity.java
  4. +79
    -34
      android/src/main/java/cn/zhios/zhiying_base_widget/ZhiyingBaseWidgetPlugin.java
  5. +5
    -0
      android/src/main/res/drawable/ic_baseline_keyboard_arrow_left_24.xml
  6. +5
    -0
      android/src/main/res/drawable/ic_baseline_refresh_24.xml
  7. +67
    -0
      android/src/main/res/layout/activity_web_view.xml
  8. +1
    -0
      android/src/main/res/values/strings.xml
  9. +1
    -1
      example/pubspec.yaml
  10. +49
    -5
      lib/pages/about_us_page/about_us_page.dart
  11. +59
    -21
      lib/pages/about_us_page/model/about_us_model.dart
  12. +15
    -1
      lib/register.dart
  13. +4
    -0
      lib/widgets/wallet/wallet_detail/wallet_detail.dart
  14. +6
    -1
      lib/widgets/wallet/wallet_detail/wallet_detail_bloc.dart
  15. +26
    -0
      lib/zhiying_base_widget.dart

+ 6
- 1
android/build.gradle View File

@@ -25,7 +25,7 @@ android {
compileSdkVersion 28

defaultConfig {
minSdkVersion 16
minSdkVersion 21
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
lintOptions {
@@ -36,3 +36,8 @@ android {

}
}

dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
}

+ 12
- 2
android/src/main/AndroidManifest.xml View File

@@ -1,3 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.zhios.zhiying_base_widget">
</manifest>
package="cn.zhios.zhiying_base_widget">

<application>
<activity
android:name=".WebViewActivity"
android:usesCleartextTraffic="true"
android:hardwareAccelerated="true"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"></activity>
</application>

</manifest>

+ 541
- 0
android/src/main/java/cn/zhios/zhiying_base_widget/WebViewActivity.java View File

@@ -0,0 +1,541 @@
package cn.zhios.zhiying_base_widget;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.webkit.GeolocationPermissions;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;


public class WebViewActivity extends AppCompatActivity {

WebView webview;
ImageView back;
ImageView refresh;

ProgressBar progressBar;

TextView tvTitle;

Boolean isRequestPre = false;
String url;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web_view);
getWindow().setStatusBarColor(Color.TRANSPARENT);
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
url = getIntent().getStringExtra("url");
Log.d("请求连接:", url);
webview = findViewById(R.id.web);

back = findViewById(R.id.iv_back);
refresh = findViewById(R.id.iv_refresh);
progressBar = findViewById(R.id.pg_bar);
tvTitle = findViewById(R.id.tv_title);

back.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
if (webview.canGoBack()) {
webview.goBack();
} else {
isRequestPre = false;
finish();
}
}
}
);


refresh.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
webview.reload();
}
});


WebSettings settings = webview.getSettings();

settings.setJavaScriptEnabled(true);//启用js

settings.setJavaScriptCanOpenWindowsAutomatically(true);//js和android交互

// String cacheDirPath = PathCommonDefines.WEBVIEW_CACHE;
//
// settings.setAppCachePath(cacheDirPath); //设置缓存的指定路径

settings.setAllowFileAccess(true); // 允许访问文件

settings.setAppCacheEnabled(true); //设置H5的缓存打开,默认关闭

settings.setUseWideViewPort(true);//设置webview自适应屏幕大小

settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);//设置,可能的话使所有列的宽度不超过屏幕宽度

settings.setLoadWithOverviewMode(true);//设置webview自适应屏幕大小

settings.setDomStorageEnabled(true);//设置可以使用localStorage

settings.setSupportZoom(false);//关闭zoom按钮

settings.setBuiltInZoomControls(false);//关闭zoom

settings.setGeolocationEnabled(true);

webview.setVerticalScrollBarEnabled(false);
//
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
// webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
//
// }


webview.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.d("WEB重定向", url);
if (WebViewActivity.this.isFinishing()) {
return true;
}
Intent intent2 = new Intent();
intent2.putExtra("url", url);
WebViewActivity.this.setResult(20210501, intent2);

if (url.startsWith("http://") || url.startsWith("https://")) {

} else {
try {
/**
* 统一的scheme协议打开第三方app,若出错说明没有安装该app
* 捕获到错误后不继续加载该url以免加载出错
*/
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
return true;
} catch (Exception e) {

}
}

if (url.startsWith("tel:")) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
return true;
}
if (url.startsWith("bdnetdisk:")) {
return true;
}
if (url.contains("vipshop://")) {//打开唯品会
if (isAvilible(WebViewActivity.this, "com.achievo.vipshop")) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
} else {
Toast.makeText(WebViewActivity.this, "请先安装唯品会app", Toast.LENGTH_SHORT).show();
}
return true;
}
if (url.contains("androidamap://")) {
if (isAvilible(WebViewActivity.this, "com.autonavi.minimap")) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
} else {
Toast.makeText(WebViewActivity.this, "请先安装高德地图app", Toast.LENGTH_SHORT).show();
}
}
if (url.contains("didapinche://")) {
if (isAvilible(WebViewActivity.this, "com.didapinche.booking")) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
} else {
Toast.makeText(WebViewActivity.this, "请先安装滴答出行app", Toast.LENGTH_SHORT).show();
}
return true;
}

if (url.contains("tmast://")) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
} catch (Exception e) {
Toast.makeText(WebViewActivity.this, "请先安装应用宝app", Toast.LENGTH_SHORT).show();
}
return true;
}
if (url.startsWith("http://ditu.amap.com") ||
url.startsWith("https://ditu.amap.com")) {
return true;
}
//品牌店家点击商品,请求接口进行相应的跳转
if (url.contains("h5.m.taobao.com/awp/core/detail") || url.contains("detail.m.tmall.com/item.htm")
|| url.contains("item.m.jd.com/product") || (url.contains("item.m.jd.com/ware/view.action")
|| url.contains("wareId=") || url.contains("h5.m.taobao.com/trip/travel-detail/index/index.htm"))
|| url.contains("detail.tmall.hk/hk") || url.contains("vip.com/product")
|| url.contains("suning.com/product") || url.contains("kaola.com/product")
|| url.contains("yangkeduo.com/goods")) {


}
if (url.contains("tbopen://") || url.contains("tmall://") || url.contains("taobaotravel://")) {
return true;
}
if (url.contains("openapp.jdmobile:")) {
//打开京东app
if (isAvilible(WebViewActivity.this, "com.jingdong.app.mall")) {

}
return true;
}
if (url.contains("pinduoduo://com.xunmeng.pinduoduo")) {
if (isAvilible(WebViewActivity.this, "com.xunmeng.pinduoduo")) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
} else {
Toast.makeText(WebViewActivity.this, "请先安装拼多多app", Toast.LENGTH_SHORT).show();
}
return true;
}
if (url.contains("imeituan://")) {//打开美团
if (isAvilible(WebViewActivity.this, "com.sankuai.meituan")) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} else {
Toast.makeText(WebViewActivity.this, "请先安装美团app", Toast.LENGTH_SHORT).show();
}
return true;
}
if (url.contains("suning://")) {
if (isAvilible(WebViewActivity.this, "com.suning.mobile.ebuy")) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} else {
Toast.makeText(WebViewActivity.this, "请先安装苏宁app", Toast.LENGTH_SHORT).show();
}
return true;
}
if (url.contains("kaola://")) {
if (isAvilible(WebViewActivity.this, "com.kaola")) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} else {
Toast.makeText(WebViewActivity.this, "请先安装考拉app", Toast.LENGTH_SHORT).show();
}
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;
}

if (url.contains("cxcwallet://")) {
if (isAvilible(WebViewActivity.this, "com.cxcblock.wallet")) {//传入指定应用包名
Intent intent = new Intent();
intent.setData(Uri.parse(url));
startActivity(intent);
} else {
Toast.makeText(WebViewActivity.this, "请先安装CXCapp", Toast.LENGTH_SHORT).show();
}
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();
Toast.makeText(WebViewActivity.this, "请先安装微信app", Toast.LENGTH_SHORT).show();
}
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();
Toast.makeText(WebViewActivity.this, "请先安装微信app", Toast.LENGTH_SHORT).show();
}
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#")) {
// String[] split = url.split("navite://save#");
// SDFileHelper sdFileHelper = new SDFileHelper(mActivity);
// sdFileHelper.setOnDownloadFinishListener(new SDFileHelper.OnDownloadFinishListener() {
// @Override
// public void onDownloadFinish(String filePath) {
// ToastUtils.showShort("图片已保存到内存卡根目录" + AppUtil.getAppName() + "文件夹中");
// }
// });
// sdFileHelper.savePicture("we_chat_qr_code" + ".jpg", split[1], true);
// return true;
// }
//不拦截的话绑定淘宝关系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")) {
// AliLoginMethodUtil.AliLoginMethod(new AliLoginMethodUtil.AliLoginListener() {
// @Override
// public void loginSuccess(String s, String s1, Session session) {
//
// }
//
// @Override
// public void LoginFail(int i, String s) {
//
// }
// });
// return true;
// }

if (url.contains("alipays://platformapi")) {
if (checkAliPayInstalled()) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
// finish();
} else {
Toast.makeText(WebViewActivity.this, "请先安装支付宝app", Toast.LENGTH_SHORT).show();
}
return true;
}
if (url.contains("intent://go/ju/webview?")) {
return true;
}

if (url.contains("deterorder")) {
webview.loadUrl(url);
return true;
}
if (getIntent().getBooleanExtra("isSearchEnter", false) && url.contains("sku=")) {

}

return !(url.startsWith("http://") || url.startsWith("https://"));
}

@Override
public void onLoadResource(WebView view, String url) {
}

@Override
public void onPageFinished(WebView view, String url) {
}

});

webview.setWebChromeClient(new WebChromeClient() {
@Override
synchronized public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
callback.invoke(origin, true, false);
// if (!isRequestPre) {
// isRequestPre = true;
// quanxian(WebViewActivity.this);
// }

}

@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
progressBar.setProgress(newProgress);
if (newProgress == 100) {
progressBar.setVisibility(View.GONE);
} else {
progressBar.setVisibility(View.VISIBLE);
}
}

@Override
public void onReceivedTitle(WebView view, String title) {
super.onReceivedTitle(view, title);
if (title != null && title.length() != 0) {
tvTitle.setText(title);
} else {
tvTitle.setText(url);
}

}
});

webview.loadUrl(url);

}

/**
* 检测是否安装支付宝app
*
* @return
*/
public boolean checkAliPayInstalled() {
Uri uri = Uri.parse("alipays://platformapi/startApp");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
ComponentName componentName = intent.resolveActivity(getPackageManager());
return componentName != null;
}


/**
* 检查手机上是否安装了指定的软件
*
* @param context
* @param packageName:应用包名
* @return
*/
private boolean isAvilible(Context context, String packageName) {
//获取packagemanager
final PackageManager packageManager = context.getPackageManager();
//获取所有已安装程序的包信息
List<PackageInfo> packageInfos = packageManager.getInstalledPackages(0);
//用于存储所有已安装程序的包名
List<String> packageNames = new ArrayList<String>();
//从pinfo中将包名字逐一取出,压入pName list中
if (packageInfos != null) {
for (int i = 0; i < packageInfos.size(); i++) {
String packName = packageInfos.get(i).packageName;
packageNames.add(packName);
}
}
//判断packageNames中是否有目标程序的包名,有TRUE,没有FALSE
return packageNames.contains(packageName);
}

/**
* 检查是否安装手机淘宝
*
* @param context
* @return
*/

public static boolean isInstallTaoBao(Context context) {
PackageInfo packageInfo = null;
try {
packageInfo = context.getPackageManager().getPackageInfo("com.taobao.taobao", 0);
} catch (Exception e) {
packageInfo = null;
e.printStackTrace();
}
if (packageInfo == null) {
return false;
} else {
return true;
}
}


///检查并请求定位权限
public void quanxian(final Activity context) {
Log.d("权限请求", "------------");
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
Log.d("权限请求", "无定位权限------------");
ActivityCompat.requestPermissions(context,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 20210422);
}
}
} catch (SecurityException e) {
e.printStackTrace();
}
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (webview.canGoBack()) {
webview.goBack();
return true;
}
isRequestPre = true;
}
return super.onKeyDown(keyCode, event);
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == 20210422) {
Log.d("权限请求", "定位权限回调------------");
webview.clearCache(true);
webview.loadUrl(url);
return;
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}

@Override
protected void onDestroy() {
super.onDestroy();
webview.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
webview.destroy();
}
}

+ 79
- 34
android/src/main/java/cn/zhios/zhiying_base_widget/ZhiyingBaseWidgetPlugin.java View File

@@ -1,45 +1,90 @@
package cn.zhios.zhiying_base_widget;

import android.app.Activity;
import android.content.Intent;

import androidx.annotation.NonNull;

import java.util.HashMap;
import java.util.Map;

import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.Registrar;

/** ZhiyingBaseWidgetPlugin */
public class ZhiyingBaseWidgetPlugin implements FlutterPlugin, MethodCallHandler {
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
final MethodChannel channel = new MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "zhiying_base_widget");
channel.setMethodCallHandler(new ZhiyingBaseWidgetPlugin());
}

// This static function is optional and equivalent to onAttachedToEngine. It supports the old
// pre-Flutter-1.12 Android projects. You are encouraged to continue supporting
// plugin registration via this function while apps migrate to use the new Android APIs
// post-flutter-1.12 via https://flutter.dev/go/android-project-migration.
//
// It is encouraged to share logic between onAttachedToEngine and registerWith to keep
// them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called
// depending on the user's project. onAttachedToEngine or registerWith must both be defined
// in the same class.
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), "zhiying_base_widget");
channel.setMethodCallHandler(new ZhiyingBaseWidgetPlugin());
}

@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
if (call.method.equals("getPlatformVersion")) {
result.success("Android " + android.os.Build.VERSION.RELEASE);
} else {
result.notImplemented();
}
}

@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
}
/**
* ZhiyingBaseWidgetPlugin
*/
public class ZhiyingBaseWidgetPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware, PluginRegistry.ActivityResultListener {

private Activity activity;

private ActivityPluginBinding binding;

private MethodChannel channel;

@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "zhiying_base_widget");
channel.setMethodCallHandler(this);
}


@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
if (call.method.equals("getPlatformVersion")) {
result.success("Android " + android.os.Build.VERSION.RELEASE);
} else if (call.method.equals("loadUrl")) {
String url = (String) ((Map<String, Object>) call.arguments).get("url");
Intent intent = new Intent(activity, WebViewActivity.class);
intent.putExtra("url", url);
activity.startActivityForResult(intent, 20210501);
} else {
result.notImplemented();
}
}

@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
}

@Override
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
activity = binding.getActivity();
binding.addActivityResultListener(this);
}

@Override
public void onDetachedFromActivityForConfigChanges() {
if (binding != null) {
binding.removeActivityResultListener(this);
}
}

@Override
public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {

}

@Override
public void onDetachedFromActivity() {

}

@Override
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 20210501 && resultCode == 20210501) {
HashMap<String, Object> map = new HashMap<>();
map.put("url", data.getStringExtra("url"));
channel.invokeMethod("reload", map);
return true;
}
return false;
}
}

+ 5
- 0
android/src/main/res/drawable/ic_baseline_keyboard_arrow_left_24.xml View File

@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#636363"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M15.41,16.59L10.83,12l4.58,-4.59L14,6l-6,6 6,6 1.41,-1.41z"/>
</vector>

+ 5
- 0
android/src/main/res/drawable/ic_baseline_refresh_24.xml View File

@@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#636363"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z"/>
</vector>

+ 67
- 0
android/src/main/res/layout/activity_web_view.xml View File

@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
android:background="#FFFFFF"
tools:context=".WebViewActivity">

<LinearLayout
android:id="@+id/ly_ll"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="48dp">
<ImageView
android:id="@+id/iv_back"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_alignParentLeft="true"
android:layout_marginLeft="10dp"
android:layout_centerVertical="true"
android:clickable="true"
android:focusable="true"
android:background="@drawable/ic_baseline_keyboard_arrow_left_24"
/>
<TextView
android:id="@+id/tv_title"
android:maxLines="1"
android:maxWidth="200dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text=""
android:textColor="#FF333333"
android:textStyle="bold"
android:textSize="17sp" />
<ImageView
android:id="@+id/iv_refresh"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_alignParentRight="true"
android:layout_marginRight="16dp"
android:layout_centerVertical="true"
android:background="@drawable/ic_baseline_refresh_24"
/>
</RelativeLayout>
<ProgressBar
android:id="@+id/pg_bar"
android:layout_width="match_parent"
android:layout_height="2dp"
style="?android:progressBarStyleHorizontal"
/>
</LinearLayout>
<WebView
android:id="@+id/web"
android:focusable="true"
android:layout_below="@id/ly_ll"
android:layout_width="match_parent"
android:layout_height="match_parent"/>



</RelativeLayout>

+ 1
- 0
android/src/main/res/values/strings.xml View File

@@ -0,0 +1 @@
<resources></resources>

+ 1
- 1
example/pubspec.yaml View File

@@ -36,7 +36,7 @@ dev_dependencies:
path: ../../zhiying_acquisition
zhiying_shopping_mall:
git:
ref: 0.0.4
ref: 0.0.5
url: 'http://192.168.0.138:3000/FnuoOS_ZhiYing/zhiying_shopping_mall.git'
zhiying_credit_card:
path: ../../zhiying_credit_card


+ 49
- 5
lib/pages/about_us_page/about_us_page.dart View File

@@ -11,6 +11,7 @@ import 'bloc/about_us_event.dart';
import 'bloc/about_us_state.dart';
import 'package:zhiying_comm/util/shared_prefe_util.dart';
import 'package:zhiying_comm/util/global_config.dart';

///
/// 关于我们
///
@@ -36,7 +37,7 @@ class _AboutUsPageContainer extends StatefulWidget {

class __AboutUsPageContainerState extends State<_AboutUsPageContainer> {
/// 检查更新
void _onClickCheckUpdate() async{
void _onClickCheckUpdate() async {
Logger.log('点击了更新');
AppUpdateUtil.updateApp(context, needToast: true, mustShowDialog: true);
}
@@ -52,17 +53,18 @@ class __AboutUsPageContainerState extends State<_AboutUsPageContainer> {
_onClickCheckUpdate();
} else if (model.type == 'comment') {
_onClickEvaluation();
}
} else if (model.type == "") {
} else if (model.type == "") {}
}

bool _isiOSReview = false;

@override
void initState() {

_settingIosReview();
super.initState();
}

void _settingIosReview() async {
String is_ios_review = await SharedPreferencesUtil.getStringValue(GlobalConfig.IS_IOS_REVIEW, defaultVal: '0');
setState(() {
@@ -151,12 +153,12 @@ class __AboutUsPageContainerState extends State<_AboutUsPageContainer> {

/// 更新,评价
_isiOSReview ? Container() : _buildListWidget(model),
_buildAgreement(model)
],
),
);
}


/// 列表
Widget _buildListWidget(AboutUsModel model) {
List<Widget> widgets = [];
@@ -165,7 +167,7 @@ class __AboutUsPageContainerState extends State<_AboutUsPageContainer> {
widgets.add(Container());
} else {
model.settings.forEach((element) {
if(element.type == 'comment'){
if (element.type == 'comment') {
return;
}
widgets.add(GestureDetector(
@@ -228,4 +230,46 @@ class __AboutUsPageContainerState extends State<_AboutUsPageContainer> {
elevation: 0,
);
}

_buildAgreement(AboutUsModel model) {
List<Widget> widgets = [];
int length = model?.articles?.length ?? 0;
if (length == 0) {
widgets.add(Container());
} else {
model.articles.forEach((element) {
widgets.add(GestureDetector(
onTap: () => _onClickAgreementItem(element),
behavior: HitTestBehavior.opaque,
child: Container(
margin: const EdgeInsets.symmetric(vertical: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
element?.title ?? '',
style: TextStyle(color: HexColor.fromHex('#333333'), fontSize: 13, fontWeight: FontWeight.bold),
),
Icon(
Icons.arrow_forward_ios,
color: HexColor.fromHex('#999999'),
size: 14,
)
],
),
),
));
});
return Column(
children: widgets,
);
}
}

_onClickAgreementItem(Articles element) {
if (element.link != null) {
RouterUtil.openWebview(element.link, context);
}
}

}

+ 59
- 21
lib/pages/about_us_page/model/about_us_model.dart View File

@@ -9,25 +9,25 @@ class AboutUsModel {
String appVersionColor;
List<String> dataKeys;
List<Settings> settings;
List<Articles> articles;
String bottomName;
String bottomNameColor;
String appVerison;

AboutUsModel({
this.appBarName,
this.appBarNameColor,
this.appBarBgColor,
this.bgColor,
this.settingsBgColor,
this.appLogo,
this.appVersionText,
this.appVersionColor,
this.dataKeys,
this.settings,
this.bottomName,
this.bottomNameColor,
this.appVerison,
});
AboutUsModel(
{this.appBarName,
this.appBarNameColor,
this.appBarBgColor,
this.bgColor,
this.settingsBgColor,
this.appLogo,
this.appVersionText,
this.appVersionColor,
this.dataKeys,
this.settings,
this.articles,
this.bottomName,
this.bottomNameColor});

AboutUsModel.fromJson(Map<String, dynamic> json) {
appBarName = json['app_bar_name'];
@@ -38,7 +38,6 @@ class AboutUsModel {
appLogo = json['app_logo'];
appVersionText = json['app_version_text'];
appVersionColor = json['app_version_color'];
appVerison = json['appVerison'];
dataKeys = json['data_keys'].cast<String>();
if (json['settings'] != null) {
settings = new List<Settings>();
@@ -46,6 +45,12 @@ class AboutUsModel {
settings.add(new Settings.fromJson(v));
});
}
if (json['articles'] != null) {
articles = new List<Articles>();
json['articles'].forEach((v) {
articles.add(new Articles.fromJson(v));
});
}
bottomName = json['bottom_name'];
bottomNameColor = json['bottom_name_color'];
}
@@ -64,16 +69,18 @@ class AboutUsModel {
if (this.settings != null) {
data['settings'] = this.settings.map((v) => v.toJson()).toList();
}
if (this.articles != null) {
data['articles'] = this.articles.map((v) => v.toJson()).toList();
}
data['bottom_name'] = this.bottomName;
data['bottom_name_color'] = this.bottomNameColor;
data['appVerison'] = this.appVerison;
return data;
}
}

class Settings {
List<String> dataKeys;
String type;
List<String> dataKeys;
String name;
String subName;
String nameColor;
@@ -82,12 +89,21 @@ class Settings {
String descColor;
String skipIdentifier;

Settings({this.dataKeys, this.name, this.subName, this.nameColor, this.subNameColor, this.descText, this.descColor, this.skipIdentifier});
Settings(
{this.type,
this.dataKeys,
this.name,
this.subName,
this.nameColor,
this.subNameColor,
this.descText,
this.descColor,
this.skipIdentifier});

Settings.fromJson(Map<String, dynamic> json) {
type = json['type'];
dataKeys = json['data_keys'].cast<String>();
name = json['name'];
type = json['type'];
subName = json['sub_name'];
nameColor = json['name_color'];
subNameColor = json['sub_name_color'];
@@ -98,8 +114,8 @@ class Settings {

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['type'] = this.type;
data['data_keys'] = this.dataKeys;
data['type'] = this.type;
data['name'] = this.name;
data['sub_name'] = this.subName;
data['name_color'] = this.nameColor;
@@ -110,3 +126,25 @@ class Settings {
return data;
}
}

class Articles {
String type;
String title;
String link;

Articles({this.type, this.title, this.link});

Articles.fromJson(Map<String, dynamic> json) {
type = json['type'];
title = json['title'];
link = json['link'];
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['type'] = this.type;
data['title'] = this.title;
data['link'] = this.link;
return data;
}
}

+ 15
- 1
lib/register.dart View File

@@ -1,8 +1,10 @@
import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_user_agent/flutter_user_agent.dart';
import 'package:jdsdk/jdsdk.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:sharesdk_plugin/sharesdk_interface.dart';
import 'package:sharesdk_plugin/sharesdk_register.dart';
import 'package:zhiying_base_widget/models/app_config_model.dart';
@@ -131,7 +133,8 @@ class BaseWidgetRegister {
register.setupWechat(config.keys?.weixin?.appId ?? '', config.keys?.weixin?.secret ?? '', config.keys?.weixin?.universalLink ?? '');

//================ Weibo
register.setupSinaWeibo(config.keys?.weibo?.appkey ?? '', config.keys?.weibo?.secret ?? '', config.keys?.weibo?.redirectUrl ?? '', config.keys?.weibo?.universalLink ?? 'templink');
register.setupSinaWeibo(
config.keys?.weibo?.appkey ?? '', config.keys?.weibo?.secret ?? '', config.keys?.weibo?.redirectUrl ?? '', config.keys?.weibo?.universalLink ?? 'templink');

// ================ QQ
register.setupQQ(config.keys?.qq?.appId ?? '', config.keys?.qq?.appkey ?? '');
@@ -201,6 +204,17 @@ class BaseWidgetRegister {
Application.addMethod(() async {
// return Future.delayed(Duration(seconds: 1));
});

Application.addStringParamsMethod(
type: "openUrl",
method: (data) async {
if (!EmptyUtil.isEmpty(data)) {
if (!await Permission.location.isGranted) {
await showDialog(context: navigatorKey.currentState.overlay.context, child: NotificationSettingDialogNew([NotificationSettingDialogNew.locationPermissModel]));
}
ZhiyingBaseWidget.loadUrl(data['url']);
}
});
}

// 注册页面


+ 4
- 0
lib/widgets/wallet/wallet_detail/wallet_detail.dart View File

@@ -3,6 +3,7 @@ import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:tab_indicator_styler/tab_indicator_styler.dart';
import 'package:zhiying_base_widget/dialog/loading/loading.dart';
import 'package:zhiying_base_widget/dialog/tip_dialog/tip_dialog.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';
@@ -70,6 +71,7 @@ class _WalletDetailState extends State<WalletDetail> with TickerProviderStateMix
///骨架图
return WalletDetailSkeleton();
}
Loading.dismiss();
return Container(
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)),
margin: EdgeInsets.only(left: 12.5, right: 12.5, top: 7.5, bottom: 7.5),
@@ -98,6 +100,7 @@ class _WalletDetailState extends State<WalletDetail> with TickerProviderStateMix
indicatorSize: TabBarIndicatorSize.label,
onTap: (index) {
///变更平台
Loading.show(context);
changeProvider(_model.providers[index].type);
},
tabs: _buildTabs()),
@@ -212,6 +215,7 @@ class _WalletDetailState extends State<WalletDetail> with TickerProviderStateMix
),
),
onTap: () {
Loading.show(context);
_bloc.selectDay = item.type;
_bloc.loadData(_bloc.currentType, _bloc.selectDay);
},


+ 6
- 1
lib/widgets/wallet/wallet_detail/wallet_detail_bloc.dart View File

@@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:convert';

import 'package:zhiying_base_widget/dialog/loading/loading.dart';
import 'package:zhiying_comm/util/base_bloc.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

@@ -42,7 +43,11 @@ class WalletDetailBloc extends BlocBase {
currentWalletDetailDataModel = listDataModel[0];
refresh();
}
});
Loading.dismiss();
}, onError: (e) {
Fluttertoast.showToast(msg: "加载数据出了小差");
Loading.dismiss();
}, timeOut: 60000);
}

///刷新页面


+ 26
- 0
lib/zhiying_base_widget.dart View File

@@ -1,5 +1,7 @@
library zhiying_base_widget;

import 'package:flutter/services.dart';

export 'dialog/loading/loading.dart';
export 'package:flutter_swiper/flutter_swiper.dart';
export 'package:zhiying_base_widget/pages/main_page/model/background_model.dart';
@@ -11,3 +13,27 @@ export 'package:amap_flutter_location/amap_flutter_location.dart';
export 'package:amap_flutter_location/amap_location_option.dart';
export 'package:tab_indicator_styler/tab_indicator_styler.dart';
export 'package:zhiying_base_widget/dialog/global_dialog/notification_setting_dialog/notification_setting_dialog.dart';

class ZhiyingBaseWidget {
static const MethodChannel _channel = const MethodChannel('zhiying_base_widget');

///监听重定向的方法
static addListener(Function(String) reload) {
_channel.setMethodCallHandler((call) {
if (call.method == "reload") {
reload(call.arguments['url']);
}
return null;
});
}

///打开原生webView
static loadUrl(String url) async {
await _channel.invokeMethod("loadUrl", {"url": url});
}

static Future<String> get platformVersion async {
final String version = await _channel.invokeMethod('getPlatformVersion');
return version;
}
}

Loading…
Cancel
Save