充填ライブラリをスキップ





常に同じとは限りません。 Android向けのライブラリの作成とその後のこの記事の作成が始まったのは、この考えからでした。 突然誰かが重宝します。 カットの下で、最終的に何が起こったのか。



はじめに



長い冬の夜、友人と私との間で、必要な機能の1つを実装する方法についての議論が始まりました。 *何か*を書くことが必要でした:





最も積極的なので、私は自分の強さを試してみたいと思い、最初の夜にビューを書きました。それは、式ツリーに基づいて式を描きました。 友人はこの問題を見て、より多くの要求を提出しました。





善良な仲間は悲しみ、頭を掻き、座って図書館を書きました。 そして、さらに面白くするために、自分に追加の条件を設定しました。





PS



ライブラリの作成方法と公開方法を段階的に書くことはありません-Habréを含むインターネット上で、これに関する指示が既にあります。 私のロジック、私が遭遇した問題と困難、およびそれらを解決する方法について少しお話します。 これは誰かにとっては当たり障りのないように見えますが、誰かにとっては間違っています。私は正しい判断をするふりをせず、すべてのコメントを考慮します。 この記事またはライブラリが誰かに役立つことを願っています。 githubへのリンクは最後にあります。 リポジトリの説明には、デモライブラリへのリンクとその手順があります。



ステージ1-木を描く



この段階では、最初のデモ、要件、およびすべてがうまくいくとの確固たる信念がありました。 まず最初に、レンダリングを取り上げ、最終的に文字列からツリーへの変換を残すことにしました。



したがって、ツリーのロジックは次のとおりです。



葉は文字のセットです。 たとえば、乗算記号または何らかの数字。 シートは、そのサイズ、その後に誰かがいるかどうか、およびそれ自体に対してどのように配置するかを知っています。 いくつかの種を特定しました。



  1. 安定シート。 これらは、+、-、*、および数字です。 このシートには、内部のテキストに応じた単位の高さと長さがあります。 その背後にあるものはすべて、それと同じ軸上に描画されます。 つまり、Y軸に沿ったこのシートの中心は、その背後にあるすべてのY軸に沿った中心と一致します。



  2. 変更可能なシート。 constableと同じですが、状態が空で塗りつぶされているだけです。 高さは単一ブロックです。 幅は、その内側に従ってではなく、すべての可変および移動されたシートの最も長いテキストに従って取られます。



  3. 可動シート。 それは変更可能なように見えますが、それだけが目に見える、見えない、動く状態です。



  4. パワーシート。 程度の幅があります。 そしてその特徴は、その背後にあるすべてのものが前のシートと同じ軸上にないことです。 後続の領域全体の下端は、前のシートに対してブロックの半分だけオフセットする必要があります。 洗練されたように聞こえますが、数値を学位に入れるだけです。 (22)度は上の半分の線で描かれます。 この程度とは対照的に、私の数では、程度はフォントで減少しません。 このシートは、学位を取得する際に次に誰が、そして学位を取得した後に誰が次にいるかを知っています。 つまり、式(2 ^(1 + 3)-4)では、学位の符号は「1」と「-」について知っています。



  5. 分割シート。 名前が示すように、これは部門を示すシートです。 4段階で描かれます。 中心に線が引かれ、その長さは分子と分母の長さのうち大きい方になります。 分子は、下端で線に押し付けられ、線の全長の中央に位置するように描画されます(分母が長い場合)。 分母は、線の上端で押され、線の全長の中央に位置するように描画されます(分子が長い場合)。 そして最後に、図面は分割後のシートに転送されます。






ロジックが機能するには、各シートで次のことができる必要があります。



  1. 長さと高さを言う
  2. 自分の身長と身長と彼の背後にあるものを言ってください。 次の葉だけでなく、葉全体の枝。 つまり、式2 + 3-4では、「+」記号は「+ 3-4」部分の寸法を知っています。 これは、数式全体のサイズを決定するのに役立ちます。
  3. Y軸に沿って中心からどれだけ移動する必要があるかを言います(ルールはPowerシート専用に導入されました)
  4. 自分自身を描画し、レンダリングの座標をすべての子孫に正しく転送できるようにします。


ステージ2-ブロックとテキストのスケーリング



許可された領域をできるだけ埋めるために、スケーリングの段階は描画の前です。 原理は簡単です。 すべての計算のベースとなる単位ブロックと、スケールを増やす必要がある回数を担当する変数があります。 スケーリングロジックは次のとおりです。式のサイズを取得し、使用可能な領域のサイズと比較し、スケーリング係数を変更します。



そして、小さな問題にぶつかりました。 テキストの幅は、textSize属性に比例して増加しません。 つまり、幅yおよびtextSize xのテキストブロックを作成します。 textSizeを2倍に増やすと、ブロックの幅は2 * yになりません。 この点で、スケーリング値は常に近い値で変動しました。これにより、再描画時に画像が「震えました」。 この問題を解決するために、2つの方法を見ました。



  1. 各ステップの前に、スケーリング値を初期値にリセットすることができました。 しかし、幅のサイズの誤差が大きすぎるため、このオプションは私には向いていませんでした。



  2. スケーリングの各ステップの前に、同じ条件で数式を配置します。 これを行うために、係数0.5に加算して切り上げました。


2番目の方法に続いて、係数がまだ1のときに最初の計算で問題が発生しました。これを解決するために、最初は2番目の方法による計算を2回行いましたが、パフォーマンスに影響しました。 2回目の不必要な計算を避けるために、以前の値を保持し、新しい値と比較することにしました。 それらが同じである場合、2度目にはカウントする意味がありません。 さらに考えて、onSizeChangedメソッドで再集計をレンダリングし、移動用の新しい数式/シートを設定するときにも追加で呼び出しました。



ステージ3-移動



ここではすべてが非常に簡単です。 ちょっとしたトリックが採用されました。 選択したシートを移動する代わりに、非表示にして新しいシートを開始します。onTouchEventがトリガーされると、座標は常に変化します。 MotionEvent.ACTION_DOWNがトリガーされると、タッチが可動シートに当たったかどうかを確認し、それを非表示にして、移動するシートに値をコピーします。 MotionEvent.ACTION_UPがトリガーされると、ツリーを実行して、変更可能なシートと交差するかどうかを確認します。



ステージ4-パーサー



額にはある程度の決定があります。 手始めに、2つのスペシャルが識別されました。 キャラクター。 最初は、変更可能になるブロックを示します。 2番目の文字はペアになっており、内部変換なしで安定または変更可能として定義する必要がある領域を示します(たとえば、分割記号)。 行を取得し、2番目のスペシャルで強調表示された領域に該当しないすべてのスペースを削除します。 シンボル、分割の記号を変換し、文字ごとに読み始めます。 すべてを変換しやすくするために、フォーム2/3の除算記号は/(2)(3)に変換されます。



ステージ5-カスタマイズ



カスタマイズを容易にするために、レンダリングコードまたはパーサーに表示されるほとんどすべての変数は、個別のクラスフィールドに配置されます。 これに関連して、表示されるほとんどすべてを正常に変更できます。



おわりに



判明したように、このライブラリは数学だけでなく、たとえば辞書の単語の知識をテストするための「数式」に非常に適しています。 また、ライブラリを作成することにした人のために、将来のために追加したいと思います-Android Studioでは、ライブラリモジュールの作成があり、ライブラリマニフェストのアプリケーションタグからすべてを削除します。 ご質問があれば、喜んでお答えします。 すべてのコメントと希望を考慮します。



githubのライブラリ



All Articles