天天看點

OpenHarmony JS UI小型系統自定義控件(4)—textarea多行輸入

一、目标

使用OpenHarmony 小型系統支援的基礎控件實作類似textarea的多行文本輸入框,輸入的文本可以控制動畫的播放時間。

二、背景

在OpenHarmony标準的系統提供了基礎元件:textarea多行文本輸入的文本框。但在小型系統中并沒有類似的元件,目前有個需求在小型系統中實作輸入框功能,支援類似軟鍵盤輸入後顯示相關的資訊,并可以把輸入的資訊緩存,用于操作其他業務使用的資料。

三、環境

裝置:君正x2000開發闆

系統:OpenHarmony 3.0.0.0(LTS)

四、效果

4.1視訊效果

請你移步至:小型系統textarea多行文本輸入框視訊效果

4.2效果截圖
OpenHarmony JS UI小型系統自定義控件(4)—textarea多行輸入
OpenHarmony JS UI小型系統自定義控件(4)—textarea多行輸入

五、實作思路

從效果圖中我們可以看出,textarea多行文本輸入的文本框可以有以下幾個特點:

1、輸入框中可以通過自定義的軟鍵盤輸入單行或多行資料;

2、輸入框有兩種狀态,常态、點選态

  • 常态:未擷取焦點,不顯示軟鍵盤,無法通過軟鍵盤輸入,輸入框背景透明且邊框為白色;
  • 點選态:擷取焦點,顯示軟鍵盤,支援軟鍵盤輸入,輸入框背景灰色且邊框為紅色。

3、點選軟鍵盤非完成按鈕,在輸入框中顯示相關的文本;

4、點選軟鍵盤完成按鈕,清空輸入框中内容,在結果框中顯示使用者輸入的資料,輸入框恢複為常态。

結合幀動畫進行操作

1、在輸入框中輸入數字,點選完成,幀動畫根據使用者輸入的資料設定動畫播放的時長;

分析:小型系統所支援的基礎容器中

1、使用text元件實作文本輸入框,使用onclick監聽點選事件,修改輸入框的狀态,通過動态的設定其屬性:background-color、border-color來實作點選狀态下的背景和邊框顔色;

2、使用input type=‘button’實作軟鍵盤中的按鍵,使用onclick監聽點選事件,根據監聽不同的按鍵執行不同的操作。

幀動畫的實作

1、使用image-animator元件實作幀動畫的加載,通其屬性duration來設定單次動畫播放的時長。

備注:如果你對上面提到的容器API還不熟悉,可以參看以下内容:

  • input API
  • text API
  • image-animator API

缺點:

1、無光标,無法在指定位置後插入資料,目前隻能從最後一位插入資料,當然删除資料也隻能從最後一位開始向前删除;

2、軟鍵盤需要按需實作;

3、輸入框内容超出限制高度則無法顯示超出部分内容。

六、完整代碼

說明:元件的代碼包括三個部分:hml、css、js,因為代碼比較簡單,是以沒有寫注釋,如果有不明白的地方可以留言。

動畫需要的資源在文章底部附件中下載下傳。

<!--textView.hml-->

<div class="container">
    <image src="/common/images/back.png" class="back-img" onclick="onBack"></image>
    <div class="animator_box">
        <image-animator class="animator" images="{{ images }}" duration="{{ animatorDuration }}" ref="animator">
        </image-animator>
    </div>
    <text class="animator-title" onclick="onText">
        動畫單次播放時長{{ animatorDuration }}
    </text>
    <div class="title-content" style="background-color : {{ bg_color }}; border-color : {{ border_color }};">
        <text class="title" onclick="onText">
            {{ curText }}
        </text>
    </div>
    <text class="result">
        您輸入的内容:{{ resultText }}
    </text>
    <div class="key-code" show="{{ isShowKeyCode }}">
        <div class="btn-content">
            <input class="num-btn" type="button" value="1" ref="num-one" onclick="onNumOne"></input>
            <input class="num-btn" type="button" value="2" ref="num-two" onclick="onNumTwo"></input>
            <input class="num-btn" type="button" value="3" ref="num-three" onclick="onNumThree"></input>
            <input class="num-btn" type="button" value="O" ref="en-char" onclick="onEnChar"></input>
            <input class="num-btn" type="button" onclick="onDelete">←</input>
        </div>
        <div class="btn-content">
            <input class="num-btn" type="button" value="#" ref="num-one" onclick="onSpecialSymbol1"></input>
            <input class="num-btn" type="button" value="@" ref="en-char" onclick="onSpecialSymbol2"></input>
            <input class="num-btn" type="button" value="鴻" ref="special-symbol" onclick="onZhChar1"></input>
            <input class="num-btn" type="button" value="蒙" ref="zh-char" onclick="onZhChar2"></input>
            <input class="num-btn" type="button" value="完成" onclick="onFinish"></input>
        </div>
    </div>
</div>

           
/*textView.css*/

.container {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
    background-color: black;
}
.title-content {
    width: 100%;
    height: 220px;
    border-width: 1px;
    padding: 10px;
    margin-bottom: 10px;
    justify-content: flex-start;
    align-items: flex-start;
    text-align: left;
}
.title {
    font-size: 30px;
    width: 95%;
    height: 220px;
}
.result {
    font-size: 22px;
    width: 100%;
    height: 220px;
    text-align: left;
    align-items: flex-start;
    border-width: 1px;
    border-color: white;
    padding: 10px;
}
.btn-content {
    flex-direction: row;
    width: 100%;
    height: 80px;
    margin-top: 5px;
    justify-content: space-between;
}
.num-btn{
    width: 19%;
    text-align: center;
    color: black;
    font-size: 25px;
    border-radius: 5px;
    background-color: white;
    margin: 0 2px;
}
.key-code{
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    width: 100%;
    height: 180px;
    align-items: center;
    margin-top: 10px;
}
.back-img {
    width: 40px;
    height: 40px;
    border-radius: 20px;
    margin: 20px;
}
.animator_box{
    width: 100%;
    height: 240px;
    justify-content: center;
}
.animator {
    width: 100%;
    height: 240px;
}
.animator-title {
    font-size: 30px;
    width: 95%;
    height: 40px;
    color: white;
}

           
// textView.js

import router from '@system.router';
const TEXT_COLOR = {
    NORMAL: '#000',
    CLICK: '#88666666'
};
const BORDER_COLOR = {
    NORMAL: '#fff',
    CLICK: '#c00000'
};
export default {
    data: {
        title: 'World',
        bg_color: TEXT_COLOR.NORMAL,
        isFocus: false,
        curText: '',
        resultText: '',
        isShowKeyCode: false,
        border_color: BORDER_COLOR.NORMAL,
        animatorDuration:'1s',
        images: [
            {
                src: "/common/images/1.png",
            },
            {
                src: "/common/images/2.png",
            },
            {
                src: "/common/images/3.png",
            },
            {
                src: "/common/images/4.png",
            },
            {
                src: "/common/images/5.png",
            },
            {
                src: "/common/images/6.png",
            },
            {
                src: "/common/images/7.png",
            },
            {
                src: "/common/images/8.png",
            },
            {
                src: "/common/images/9.png",
            },
            {
                src: "/common/images/10.png",
            },
            {
                src: "/common/images/11.png",
            },
            {
                src: "/common/images/12.png",
            },
            {
                src: "/common/images/13.png",
            },
            {
                src: "/common/images/14.png",
            },
            {
                src: "/common/images/15.png",
            },
            {
                src: "/common/images/16.png",
            },
            {
                src: "/common/images/17.png",
            },
            {
                src: "/common/images/18.png",
            },
            {
                src: "/common/images/19.png",
            },
            {
                src: "/common/images/20.png",
            },
            {
                src: "/common/images/21.png",
            },
            {
                src: "/common/images/22.png",
            },
            {
                src: "/common/images/23.png",
            },
            {
                src: "/common/images/24.png",
            },
            {
                src: "/common/images/25.png",
            },
            {
                src: "/common/images/26.png",
            },
            {
                src: "/common/images/27.png",
            }
        ],
    },
    onText() {
        this.bg_color = TEXT_COLOR.CLICK;
        this.border_color = BORDER_COLOR.CLICK;
        this.isFocus = true;
        this.isShowKeyCode = true;
        this.resultText = '';
    },
    onNumOne() {
        if (!this.isFocus) {
            return;
        }
        this.curText += '1';
    },
    onNumTwo() {
        if (!this.isFocus) {
            return;
        }
        this.curText += '2';
    },
    onNumThree() {
        if (!this.isFocus) {
            return;
        }
        this.curText += '3';
    },
    onEnChar() {
        if (!this.isFocus) {
            return;
        }
        this.curText += 'O';
    },
    onSpecialSymbol1() {
        if (!this.isFocus) {
            return;
        }
        this.curText += '#';
    },
    onSpecialSymbol2() {
        if (!this.isFocus) {
            return;
        }
        this.curText += '@';
    },
    onZhChar1() {
        if (!this.isFocus) {
            return;
        }
        this.curText += '鴻';
    },
    onZhChar2() {
        if (!this.isFocus) {
            return;
        }
        this.curText += '蒙';
    },
    onFinish() {
        this.resultText = this.curText;
        this.animatorDuration = this.curText+'s';
        this.reset();
    },
    /**
     * 每次點選删除最後一個位元組
     */
    onDelete() {
        if (!this.isFocus) {
            return;
        }
        const len = this.curText.length;
        if (len >= 1) {
            this.curText = this.curText.substring(0, len - 1);
        }
    },
    reset() {
        this.isFocus = false;
        this.curText = '';
        this.bg_color = TEXT_COLOR.NORMAL;
        this.border_color = BORDER_COLOR.NORMAL;
        this.isShowKeyCode = false;
    },
    onBack() {
        router.replace({
            uri: 'pages/index/index'
        });
    },
    onDestroy() {
        this.reset();
    }
}

           

七、感謝

如果您能看到最後,還希望您能動動手指點個贊,一個人能走多遠關鍵在于與誰同行,我用跨越山海的一路相伴,希望得到您的點贊。

附件連結:https://ost.51cto.com/resource/1837

想了解更多關于鴻蒙的内容,請通路:

51CTO和華為官方合作共建的鴻蒙技術社群

https://ost.51cto.com/#bkwz

繼續閱讀