主頁 > 移動端開發 > 什么?!!你從來沒用SVG打造過不規則的自定義View?

什么?!!你從來沒用SVG打造過不規則的自定義View?

2021-03-07 15:03:50 移動端開發

目錄

    • SVG概念
    • SVG特性
    • SVG在安卓中能做什么
    • 標準SVG預覽
    • SVG語法介紹
    • SVG圖下載地址
    • 巴鐵!奔跑的小恐龍?(示例開始)
    • 自定義View展示SVG

SVG概念

SVG是一種影像檔案格式,類似于PNG JPG,只不過PNG需要影像引擎加載,SVG則由畫布來加載 它的英文全稱為Scalable
Vector Graphics,意思為可縮放的矢量圖形,可以設計無損失、高解析度的Web圖形頁面,用戶可以直接用代碼來描繪影像,

SVG特性

  • SVG可被非常 多的工具讀取和修改(比如記事本)
  • SVG與JPEG和GIF影像 比起來尺寸更小,且可縮放性更強
  • SVG是可伸縮的
  • SVG影像可在 任何解析度下被高質量地列印
  • SVG可在影像質量不下降地情況下被放大
  • SVG影像中的文本 是可以自定義的可以融入代碼片段
  • SVG檔案是純粹的XML

SVG在安卓中能做什么

  1. APP圖示:在SDK23后,APP的圖示是由SVG來表示
  2. 自定義控制元件:不規則的控制元件,復雜的互動,子控制元件重疊判斷,圖表等都
    可以用SVG來做
  3. 復雜影片:如根據用戶滑動動態顯示影片,路徑影片

是不是很抽象?沒耐心看下去,那就點擊看看這篇博客,就知道它干嘛用了,

Android中使用SVG矢量圖打造多邊形圖形框架

附張圖吧
在這里插入圖片描述

標準SVG預覽

<svg width= 580 height=400"
xmIns= http://www.w3.org/2000/svg>
<title>L ayerl</title>
<line stroke-linecap= undefind stroke linejoin= undefind
ld=svg_1y2=119.4375x2=''412.53211"yl="119.4375"x1='77.5"
Stroke-width= 1.5 stroke- #000" fill= none" />
</svg>

SVG語法介紹

  • M=moveto(M X,Y):將畫筆移動到指定位置
  • L=lineto(L X,Y): 畫直線到指定位置
  • H=horizontal lineto(H X): 畫水平線到指定的X坐標位置
  • V=vertical lineto(VY):畫垂直線到指定的Y坐標位置
  • Q=quadratic Belzier curve(Q X,ENDX,ENDY):二次貝塞爾曲線
  • C=curveto(Q X1,Y1,X2,Y2,ENDX,ENDY):三次貝塞爾曲線
  • S=smooth curveto(S X1,Y1,ENDX,ENDY):平滑過渡
  • Z=closepath(): 閉合路徑

SVG圖下載地址

https://www.amcharts.com/svg-maps/

在這里插入圖片描述
這個網站里面的資源好像挺豐富的,以后有需要可以上來參考看看,

巴鐵!奔跑的小恐龍?(示例開始)

看網上有很多我們大中國的地圖示例了,我就下個巴鐵的地圖,試試能不能給咱巴鐵弄一份,

先按步驟,下載巴基斯坦的svg地圖矢量圖,
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
將下載完成的svg圖片放入專案的raw檔案夾下

在這里插入圖片描述
點開svg圖片,我們就能看到預覽效果
在這里插入圖片描述
再來看看svg檔案中的代碼

<?xml version="1.0" encoding="utf-8"?>
<!-- (c) ammap.com | SVG map of Pakistan - High -->
<svg xmlns="http://www.w3.org/2000/svg"
	xmlns:amcharts="http://amcharts.com/ammap"
	xmlns:xlink="http://www.w3.org/1999/xlink"
	viewBox="0 0 800 700"
	version="1.1">
	<defs>
		<style type="text/css">
			.land
			{
				fill: #CCCCCC;
				fill-opacity: 1;
				stroke:white;
				stroke-opacity: 1;
				stroke-width:0.5;
			}
		</style>

		<amcharts:ammap projection="mercator" leftLongitude="60.896610" topLatitude="37.095717" rightLongitude="77.843840" bottomLatitude="23.705520"></amcharts:ammap>

		<!-- All areas are listed in the line below. You can use this list in your script. -->
		<!--{id:"PK-BA"},{id:"PK-GB"},{id:"PK-IS"},{id:"PK-JK"},{id:"PK-KP"},{id:"PK-PB"},{id:"PK-SD"},{id:"PK-TA"}-->

	</defs>
	<g>
		<!--各省的path-->
		<path />
		<path />
		<path />
		...
	</g>
</svg>

來個中國紅?改屬性:fill: #ff0000;
在這里插入圖片描述
奔跑的小恐龍?

如何能轉成Android專案能使用的VectorDrawable xml檔案呢,步驟如下:

首先需要在svg檔案中加入viewBox屬性(參考上面的svg檔案代碼),然后按下圖操作:在這里插入圖片描述
選中svg檔案,然后確定
在這里插入圖片描述
便能在目標目錄中看到生成好的檔案
在這里插入圖片描述
點擊查看代碼

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="800dp"
    android:height="700dp"
    android:viewportWidth="800"
    android:viewportHeight="700">
    <!--各省份的path的屬性-->
    <path
      android:pathData="balabala"
      android:strokeWidth="0.5"
      android:fillColor="#ff0000"
      android:strokeColor="#ffffff"/>
    <path/>
	...
</vector>

這個時候你就可以指定各省的屬性了,

自定義View展示SVG

這個示例是給巴鐵的各省添加上了點擊事件,點擊的時候展示相應省份的名字,

看看效果

在這里插入圖片描述
附上主要代碼

定義ProvinceItem對應各個省份

public class ProvinceItem {
    private Path path;
    private String name;
    private int drawColor;//板塊顏色
    private PointF clickPoint;//顯示省份資訊

    public ProvinceItem(Path path) {
        this.path = path;
    }

    public Path getPath() {
        return path;
    }

    public void setPath(Path path) {
        this.path = path;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getDrawColor() {
        return drawColor;
    }

    public void setDrawColor(int drawColor) {
        this.drawColor = drawColor;
    }

    public PointF getClickPoint() {
        return clickPoint;
    }

    public void setClickPoint(PointF clickPoint) {
        this.clickPoint = clickPoint;
    }

    void drawItem(Canvas canvas, Paint paint, boolean isSelect) {
        if (isSelect) {
            //繪制內部顏色
            paint.clearShadowLayer();
            paint.setStrokeWidth(1);
            paint.setColor(drawColor);
            paint.setStyle(Paint.Style.FILL);
            canvas.drawPath(path, paint);
            //繪制邊界
            paint.setStyle(Paint.Style.STROKE);
            paint.setColor(0xff0e8ef4);
            canvas.drawPath(path, paint);
        } else {
            paint.setStrokeWidth(2);
            paint.setColor(Color.BLACK);
            paint.setStyle(Paint.Style.FILL);
            paint.setShadowLayer(8, 0, 0, 0xFFFFFF);
            canvas.drawPath(path, paint);

            paint.clearShadowLayer();
            paint.setColor(drawColor);
            paint.setStyle(Paint.Style.FILL);
            canvas.drawPath(path, paint);
        }
    }

    /**
     * 判斷點擊區域是否在當前的省份
     *
     * @param x
     * @param y
     * @return
     */
    public boolean isTouch(float x, float y) {
        //獲取path矩形區域
        RectF recrF = new RectF();
        path.computeBounds(recrF, true);
        Region region = new Region();
        //給定路徑
        region.setPath(path, new Region((int) recrF.left, (int) recrF.top, (int) recrF.right, (int) recrF.bottom));
        return region.contains((int) x, (int) y);
    }
}

自定義View來展示地圖:

public class MapView extends View {
    private int[] colorArray = new int[]{0xFF239BD7, 0xFF30A9E5, 0xFF80CBF1, 0xFF4087A3};
    private List<ProvinceItem> itemList;//所有省份集合
    private Paint paint;
    private ProvinceItem select;//當前選中的省份
    private RectF totalRect;//地圖大小資訊
    private float scale = 1.0f;

    private static final int NONE = 0;
    private static final int DRAG = 1;
    private static final int ZOOM = 2;
    private int mode = NONE;
    // 第一個按下的手指的點
    private PointF startPoint = new PointF();
    // 兩個按下的手指的觸摸點的中點
    private PointF midPoint = new PointF();
    // 初始的兩個手指按下的觸摸點的距離
    private float oriDis = 1f;
    private boolean actionClick = true;
    private float translateX;
    private float translateY;
    private boolean shouldShowText;//是否需要顯示省份名

    public MapView(Context context) {
        super(context);
        init();
    }


    public MapView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MapView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();

    }

    private void init() {
        paint = new Paint();
        paint.setAntiAlias(true);
        itemList = new ArrayList<>();
        loadThread.start();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //獲取當前控制元件的寬高
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        if (totalRect != null) {
            float mapWidth = totalRect.width();
            scale = width / mapWidth;
        }
        setMeasuredDimension(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        float currentScaleCount = 0;//當前縮放系數
        float currentTranslateX = 0;//當前x平移距離
        float currentTranslateY = 0;//當前y平移距離
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                //單點觸控
                startPoint.set(event.getX(), event.getY());
                mode = DRAG;
                actionClick = true;
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                //多點觸控
                Log.e("多點觸控", "多點觸控");
                oriDis = distance(event);
                if (oriDis > 10) {
                    midPoint = midPoint(event);
                    mode = ZOOM;
                }
                actionClick = false;
                break;
            case MotionEvent.ACTION_MOVE:
                //滑動
                Log.e("mode", mode + " ");
                if (mode == DRAG) {
                    //單指拖動
                    if (Math.abs(x - startPoint.x) > 10 || Math.abs(y - startPoint.y) > 10) {
                        currentTranslateX = translateX + x - startPoint.x;
                        currentTranslateY = translateY + y - startPoint.y;
                        translateX = currentTranslateX;
                        translateY = currentTranslateY;
                        startPoint.set(x, y);
                        actionClick = false;
                        invalidate();
                    }
                } else if (mode == ZOOM) {
                    //兩指縮放
                    float newDist = distance(event);//當前兩指距離
                    if (Math.abs(newDist - oriDis) > 10) {
                        float scaleInner = newDist / oriDis;
                        currentScaleCount = scale + (scaleInner - 1);
                        if (currentScaleCount < 1) {
                            scale = 1;
                        } else {
                            scale = currentScaleCount;
                        }
                        oriDis = newDist;
                        invalidate();
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                //單點觸控
                mode = NONE;
                if (actionClick) {
                    handleTouch(x / scale - translateX, y / scale - translateY);
                }
                break;
            case MotionEvent.ACTION_POINTER_UP:
                //多點觸控
                mode = NONE;
                break;
        }
        return true;
    }

    private void handleTouch(float x, float y) {
        shouldShowText = false;
        if (itemList == null) {
            return;
        }
        ProvinceItem selectItem = null;
        for (ProvinceItem provinceItem : itemList) {
            if (provinceItem.isTouch(x, y)) {
                selectItem = provinceItem;
                provinceItem.setClickPoint(new PointF(x, y));
                shouldShowText = true;
            }
        }
        if (selectItem != null) {
            select = selectItem;
            postInvalidate();
        }
    }

    private Thread loadThread = new Thread() {
        @Override
        public void run() {
            InputStream inputStream = getResources().openRawResource(R.raw.pakistan);
            //獲取DocumentBuilderFactory
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            //從DocumentBuilderFactory獲取DocumentBuilder實體
            DocumentBuilder builder;
            try {
                builder = factory.newDocumentBuilder();
                //決議輸入流 獲取Document實體
                Document document = builder.parse(inputStream);
                Element rootElement = document.getDocumentElement();
                //先找到Path
                NodeList path = rootElement.getElementsByTagName("path");
                float left = -1;
                float right = -1;
                float top = -1;
                float bottom = -1;
                List<ProvinceItem> list = new ArrayList<>();
                for (int i = 0; i < path.getLength(); i++) {
                    Element element = (Element) path.item(i);
                    String pathData = element.getAttribute("d");
                    String name = element.getAttribute("title");
                    //將pathData轉成Path
                    @SuppressLint("RestrictedApi") Path path1 = PathParser.createPathFromPathData(pathData);
                    ProvinceItem provinceItem = new ProvinceItem(path1);
                    provinceItem.setName(name);
                    provinceItem.setDrawColor(colorArray[i % 4]);
                    RectF rectF = new RectF();
                    path1.computeBounds(rectF, true);
                    left = left == -1 ? rectF.left : Math.min(left, rectF.left);
                    right = right == -1 ? rectF.right : Math.max(right, rectF.right);
                    top = top == -1 ? rectF.top : Math.min(top, rectF.top);
                    bottom = bottom == -1 ? rectF.bottom : Math.max(bottom, rectF.bottom);
                    list.add(provinceItem);
                }
                itemList = list;
                totalRect = new RectF(left, top, right, bottom);
                //重繪界面
                Handler handler = new Handler(Looper.getMainLooper());
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        requestLayout();
                        invalidate();
                    }
                });
            } catch (ParserConfigurationException e) {
                e.printStackTrace();
            } catch (SAXException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    };

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (itemList != null && itemList.size() > 0) {
            canvas.save();
            canvas.scale(scale, scale);
            canvas.translate(translateX, translateY);
            for (ProvinceItem provinceItem : itemList) {
                if (provinceItem != select) {
                    provinceItem.drawItem(canvas, paint, false);
                } else {
                    provinceItem.drawItem(canvas, paint, true);
                }
            }
            if (shouldShowText) {
                //繪制文本
                paint.setColor(Color.RED);
                paint.setStyle(Paint.Style.FILL);
                paint.setTextSize(40);
                canvas.drawText(select.getName(), select.getClickPoint().x, select.getClickPoint().y, paint);
                canvas.restore();

            }
        }
    }

    /**
     * 計算兩個手指頭之間的中心點的位置
     * x = (x1+x2)/2;
     * y = (y1+y2)/2;
     *
     * @param event 觸摸事件
     * @return 回傳中心點的坐標
     */
    private PointF midPoint(MotionEvent event) {
        float x = (event.getX(0) + event.getX(1)) / 2;
        float y = (event.getY(0) + event.getY(1)) / 2;
        return new PointF(x, y);
    }

    /**
     * 計算兩個手指間的距離
     *
     * @param event 觸摸事件
     * @return 放回兩個手指之間的距離
     */
    private float distance(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return (float) Math.sqrt(x * x + y * y);//兩點間距離公式
    }
}

最后參考即可:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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=".MainActivity">

    <pers.owen.svgmap.MapView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

本文完,Demo下載地址,


About

  • 阿里巴巴矢量圖示庫

UI系列文章一覽

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/267149.html

標籤:其他

上一篇:數學一本通——K. 點與三角形關系(叉積求面積)

下一篇:【Kotlin】let,also,run,apply與with的使用去區別

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more