最近、ブロガーがインターネットで何気なく検索していると、下部にあるポップアップ決済ページの実装は、PopupWindow をカスタマイズして実装されていることがほとんどで、複雑なロジックは見たくないという人が多いです。カスタマイズに慣れていないパートナーは、 「カスタマイズ」という3 つの単語を見ると、血圧が下がります。心配しないでください。ブロガーもかつてはあなたと同じでした。カスタマイズをうまくやりたい場合は、 , まだ自分で行う必要があります。カスタマイズに関する本を読んでください。今回、ブロガーは、下部ポップアップ支払いページを作成するための非常に快適で破壊的な伝統的なカスタム方法を推奨しています。非常にフレンドリーな下部ポップアップ支払いを作成したい場合は、ページ、またはその他の豪華なアニメーションのポップアップが表示されるページをクリックすると、この記事が表示されます。この記事は見逃せません。
まずレンダリングを見てください。
ここでの表示効果は下からのポップアップですが、ポップアップ方法は完全にカスタマイズして自分で実装しています。その他の制限はたくさんありますが、このポップアップアニメーションを制限なしにしても問題ありません 。
この章の内容は、GT ライブラリの GT_View パッケージ クラスを使用してカスタム ポップアップ ウィンドウを実装することに重点を置いています。
実際、GT ライブラリには多くのカプセル化されたクラスが提供されています。
これらはすべて GT ライブラリによって提供されるパッケージ化されたクラスであり、今後も随時追加されます。この記事では、GT ライブラリの View パッケージ クラスの使用方法のみを紹介します。
GT ライブラリを使用するには、もちろん、最初に GT ライブラリに依存する必要があります。
この効果がどのように達成されるかを見てみましょう。まずスタイルとリソースを追加しましょう
リソース:
Round_whitelucency_bg13.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#008E8E8E"/>
<!-- 设置圆角 -->
<corners android:radius="1dp"/>
<!-- 设置边框 -->
<stroke
android:width="1dip"
android:color="#6B000000" />
</shape>
Round_whitelucency_bg17.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FFFFFF"/>
<!-- 设置圆角 -->
<corners
android:topRightRadius="15dp"
android:topLeftRadius="15dp"
/>
<!-- 设置边框 -->
<stroke
android:width="1dip"
android:color="#FFFFFF" />
</shape>
スタイル:
<style name="tv_pass">
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">match_parent</item>
<item name="android:layout_weight">1</item>
<item name="android:gravity">center</item>
<item name="android:textColor">#000000</item>
<item name="android:background">#FFFFFF</item>
<item name="android:textStyle">bold</item>
<item name="android:textSize">28sp</item>
<item name="android:layout_marginEnd">2dp</item>
<item name="android:layout_marginBottom">2dp</item>
</style>
<style name="et_pass">
<item name="android:layout_width">50dp</item>
<item name="android:layout_height">50dp</item>
<item name="android:gravity">center</item>
<item name="android:maxLength">1</item>
<item name="android:inputType">numberPassword</item>
<item name="android:layout_marginStart">5dp</item>
<item name="android:background">@drawable/round_whitelucency_bg13</item>
<item name="android:textCursorDrawable">@drawable/color_cursor</item>
</style>
美化スタイルのリソース画像は以上です。添付してください。
カスタム XML レイアウト:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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:id="@+id/cl_filtrate"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="RtlSymmetry,LabelFor,NestedWeights,HardcodedText">
<View
android:id="@+id/view_bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#70000000" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ll_bottom1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="@drawable/round_whitelucency_bg17"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="h,1:1">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:text="请输入二级密码"
android:textColor="#202020"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/view_line"
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_marginTop="15dp"
android:background="#EEEEEE"
app:layout_constraintTop_toBottomOf="@+id/tv_title" />
<!-- 密码框 -->
<LinearLayout
android:id="@+id/ll_pass"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:gravity="center"
android:orientation="horizontal"
app:layout_constraintTop_toBottomOf="@+id/view_line">
<EditText
android:id="@+id/et_1"
style="@style/et_pass"
android:focusable="true" />
<EditText
android:id="@+id/et_2"
style="@style/et_pass" />
<EditText
android:id="@+id/et_3"
style="@style/et_pass" />
<EditText
android:id="@+id/et_4"
style="@style/et_pass" />
<EditText
android:id="@+id/et_5"
style="@style/et_pass" />
<EditText
android:id="@+id/et_6"
style="@style/et_pass" />
</LinearLayout>
<TextView
android:id="@+id/tv_pass"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:padding="10dp"
android:text="忘记密码?请戳我"
android:textColor="#202020"
android:textSize="12sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="@+id/ll_pass"
app:layout_constraintStart_toStartOf="@+id/ll_pass"
app:layout_constraintTop_toBottomOf="@+id/ll_pass" />
<View
android:id="@+id/view_line2"
android:layout_width="match_parent"
android:layout_height="3dp"
android:layout_marginTop="5dp"
android:background="#EEEEEE"
app:layout_constraintTop_toBottomOf="@+id/tv_pass" />
<LinearLayout
android:id="@+id/ll_bottom"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#EEEEEE"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/view_line2">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
style="@style/tv_pass"
android:text="1" />
<TextView
style="@style/tv_pass"
android:text="2" />
<TextView
style="@style/tv_pass"
android:text="3" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
style="@style/tv_pass"
android:text="4" />
<TextView
style="@style/tv_pass"
android:text="5" />
<TextView
style="@style/tv_pass"
android:text="6" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
style="@style/tv_pass"
android:text="7" />
<TextView
style="@style/tv_pass"
android:text="8" />
<TextView
style="@style/tv_pass"
android:text="9" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
style="@style/tv_pass"
android:background="#EEEEEE" />
<TextView
style="@style/tv_pass"
android:text="0" />
<LinearLayout
android:id="@+id/ll_delete"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/ic_delete" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
レイアウトレンダリング:
カスタムの下部ポップアップ ウィンドウのコア コードを見てみましょう。
//加载自定义xml布局
@GT.Annotations.GT_AnnotationView(R.layout.view_pay_pass)
public class PayPassView extends GT.GT_View.AnnotationView {
/**
* 必须写的
* @param context
* @param viewGroup 装入支付弹窗容器(后面会介绍使用的)
*/
public PayPassView(Context context, ViewGroup viewGroup) {
super(context, viewGroup);
}
private View view_bg;
private View ll_bottom1;
//需要重写的初始化方法
@Override
protected void initView(View view) {
super.initView(view);
//获取组件
view_bg = findViewById(R.id.view_bg);
ll_bottom1 = findViewById(R.id.ll_bottom1);
//单击事件
ll_bottom1.setOnClickListener(null);//消耗掉点击密码框的单击事件
view_bg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
hide();//单击上部分 半透明黑背景 进行隐藏动画操作
}
});
}
//显示动画
public void show() {
view_bg.setVisibility(View.VISIBLE);
ll_bottom1.setVisibility(View.VISIBLE);
}
//隐藏动画
private void hide() {
view_bg.setVisibility(View.GONE);
ll_bottom1.setVisibility(View.GONE);
}
}
上記の実装方法を見ると、非常に簡単です。唯一の疑問は、 カスタム xml レイアウトをロードすることです 。このカスタム xml レイアウトのロードは、GTライブラリロード レイアウトを実現するための非常に基本的な方法です。上記は、 GT ライブラリがロードすることを示しています。レイアウト バージョンの2 番目のバージョン。削除されたバージョンはブロガーによって使用されません。使いやすいとは言えませんが、より便利なバージョンがあります。ブロガーは GT ライブラリを使用して、レイアウトの 4 番目のバージョンをロードします。詳細について知りたいGT ライブラリのレイアウトをロードする方法は次のとおりです。
Android——GT-DataBinding ( findViewById を完全に解放) https://blog.csdn.net/qq_39799899/article/details /121270536?spm=1001.2014.3001.5501homeの皆さん、第 4 版を使うのは本当に素晴らしいです。後の記事で第 2 版との比較のために第 4 版を掲載します。
次に、通話支払いポップアップ ページのレイアウトを見てみましょう。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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"
>
<TextView
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始支付"
android:background="@drawable/bg_black_et"
app:layout_constraintVertical_bias="0.28"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:paddingStart="15dp"
android:paddingEnd="15dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<RelativeLayout
android:id="@+id/rl"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout_editor_absoluteX="16dp"
tools:layout_editor_absoluteY="231dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
内部の bg_black_et.xml は GT ライブラリによって提供されており、直接使用できます。
MainActivity.java
public class MainActivity extends AppCompatActivity {
private PayPassView payPassView;
private RelativeLayout rl;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rl = findViewById(R.id.rl);//获取组件容器
//构建 弹窗支付页面 并将构建好的支付页面 添加到 容器 rl 中
payPassView = new PayPassView(this,rl);
findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
payPassView.show();//显示支付页面
}
});
}
}
これは簡単で、作成した支払いポップアップ ウィンドウをコンテナに追加するだけです。ここに書いた後、直接実行して効果を確認できます。
現在のコードの実行効果図:
効果は抜群です。支払いページの追加は非常に簡単だと思いますか。これは完全にカスタマイズされたレイアウト ページです。これらの家族はもうカスタマイズについて心配する必要はありません。
GT ライブラリはシンプルさを追求して誕生しました
これを実行すると、効果は出ていますが、アニメーションが非常に硬いわけではなく、数字や戻るボタンをクリックしても反応しません。それは確かです。コア コードにはロジックがありません。いいえ、それでは次に、ブロガーは残りの論理処理を改善し続けます。まず、第 2 バージョンの読み込みレイアウトを第 4 バージョンに置き換えます。第 4 バージョンには gt-DataBinding 関数を追加する必要があります。
コピーの場合:
//注册 gt-DataBinding 功能
annotationProcessor 'com.github.1079374315:GSLS_Tool:v1.4.2.4'
赤枠内をコピー&ペーストして登録すると、第4バージョンでレイアウトを読み込むことができます
追加して登録した後、コアコードを変更しましょう。
このクラスはコンパイル 後に自動生成されるため、 PayPassViewBinding クラスを継承するときに普及します。
コアコード:
//使用 GT_DataBinding 功能
@GT_DataBinding(setLayout = "view_pay_pass", setBindingType = GT_DataBinding.View)
@GT.Annotations.GT_AnnotationView(R.layout.view_pay_pass)//加载自定义xml布局
public class PayPassView extends PayPassViewBinding {
public PayPassView(Context context, ViewGroup viewGroup) {
super(context, viewGroup);
}
@Override
protected void initView(View view) {
super.initView(view);
ll_bottom1.setOnClickListener(null);//消耗单击密码框事件
hide();//装入容器后直接隐藏
}
//设置单击事件
@GT.Annotations.GT_Click({R.id.view_bg, R.id.tv_pass})
public void onCLick(View view) {
switch (view.getId()) {
case R.id.tv_pass://忘记密码
GT.toast(context, "单击了忘记密码");//吐司
break;
case R.id.view_bg:
hide();//单击上部分 半透明黑背景 进行隐藏动画操作
break;
}
}
//显示动画
public void show() {
view_bg.setVisibility(View.VISIBLE);
ll_bottom1.setVisibility(View.VISIBLE);
}
//隐藏动画
private void hide() {
view_bg.setVisibility(View.GONE);
ll_bottom1.setVisibility(View.GONE);
}
}
元のコアコード:
この比較は前のコードよりもはるかに簡単に感じられますか?
もう一度実行すると、元のバージョンと同じ効果が得られることがわかります。次に、4 番目のバージョンを使用して後続のロジック処理を追加します。
アニメーションを追加したい場合、ブロガーが最初に考えるのは、 GT ライブラリの強力なアニメーション ライブラリは 操作が簡単で、明確な注釈が付いているということです。
コアコードの変更:
//使用 GT_DataBinding 功能
@GT_DataBinding(setLayout = "view_pay_pass", setBindingType = GT_DataBinding.View)
@GT.Annotations.GT_AnnotationView(R.layout.view_pay_pass)//加载自定义xml布局
public class PayPassView extends PayPassViewBinding {
public PayPassView(Context context, ViewGroup viewGroup) {
super(context, viewGroup);
}
@Override
protected void initView(View view) {
super.initView(view);
ll_bottom1.setOnClickListener(null);//消耗单击密码框事件
hide();//装入容器后直接隐藏
}
//设置单击事件
@GT.Annotations.GT_Click({R.id.view_bg, R.id.tv_pass})
public void onCLick(View view) {
switch (view.getId()) {
case R.id.tv_pass://忘记密码
GT.toast(context, "单击了忘记密码");//吐司
break;
case R.id.view_bg:
hide();//单击上部分 半透明黑背景 进行隐藏动画操作
break;
}
}
//构建GT动画库
private static final GT.GT_Animation animation = new GT.GT_Animation();
//定义 必要的计算参数值
private int height;
//显示动画
public void show() {
//获取容器的这个View的宽高,好设置动画的动态数据
height = view_bg.getHeight();
//使用GT库 移动 Y轴(上下) 动画,来给 组件 ll_bottom1 设置移动
animation.translateY_T(height, 0, 300, 0, false, ll_bottom1);
view_bg.setVisibility(View.VISIBLE);//显示半透明黑色背景
}
//隐藏动画
private void hide() {
//获取容器的这个View的宽高,好设置动画的动态数据
height = view_bg.getHeight();
if (height == 0) {//在刚开始创建的时候获取的高会为0,所以直接隐藏支付页
animation.translateY_T(0, 3000, 1, 0, false, ll_bottom1);
}else{//后续就更具动态高度进行动画展示
animation.translateY_T(0, height, 300, 0, false, ll_bottom1);
}
view_bg.setVisibility(View.INVISIBLE);//隐藏半透明黑色背景
}
}
レンダリング:
このとき、実行時に表示支払いページに下部のポップアップ効果が表示されますが、GT アニメーション ライブラリの Y 軸移動アニメーションを使用すると、下部のポップアップ効果を非常にうまく実現でき、非常に使いやすいです。 GT ライブラリのパラメータを知らない友人は、自分で仮パラメータに 1 つずつ注釈を付けてみることができます。また、その注釈も非常に人道的です。
次に、ブロガーはすべてのロジック処理コア コードを直接貼り付けます。あまり説明はしません。
最終的なコアコード:
@GT_DataBinding(setLayout = "view_pay_pass", setBindingType = GT_DataBinding.View)
@GT.Annotations.GT_AnnotationView(R.layout.view_pay_pass)
public class PayPassView extends PayPassViewBinding {
private int height;
private int width;
private List<EditText> editTextList;
private int index;//索引
private static GT.GT_Animation animation = new GT.GT_Animation();
public PayPassView(Context context, ViewGroup viewGroup) {
super(context, viewGroup);
}
@Override
protected void initView(View view) {
super.initView(view);
hide();
ll_bottom1.setOnClickListener(v -> {
});
editTextList = new ArrayList<>();
}
@Override
public void loadData(View view) {
super.loadData(view);
//设置第一个密码框光标
GT.Thread.getInstance(0).execute(() -> {
GT.Thread.sleep(300);
index = 0;
GT.Thread.runAndroid(() -> et_1.requestFocus());
});
//设置每个单独密码的事件
for (int i = 0; i < ll_pass.getChildCount(); i++) {
EditText editText = (EditText) ll_pass.getChildAt(i);
editText.setTag(i);//设置吗每个 EditText 索引
editTextList.add(editText);
int finalI = i;
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
String s1 = editText.getText().toString();
editText.setSelection(s1.length());
if (s1.length() == 0) {//删除的时候
index = Integer.parseInt(editText.getTag().toString());
if (index - 1 >= 0) {
EditText editText1 = editTextList.get(index - 1);
editText1.requestFocus();
}
if (index > 0)
index--;
} else if (s1.length() == 1) {//输入的时候
if (finalI + 1 <= editTextList.size() - 1) {
EditText editText1 = editTextList.get(finalI + 1);
editText1.requestFocus();
index = Integer.parseInt(editText1.getTag().toString());
}
}
transactionPasswordAuthentication();
}
//验证交易密码是否全部输入
private void transactionPasswordAuthentication() {
boolean isOk = true;
String apppwd = "";
for (int i = 0; i < editTextList.size(); i++) {
EditText editText1 = editTextList.get(i);
String s = editText1.getText().toString();
if (s.length() == 0) {
isOk = false;
}
apppwd += s;
}
if (!isOk) return;
// AppUtils.toast("正在支付中...");
for (int i = 0; i < editTextList.size(); i++) {
EditText editText1 = editTextList.get(i);
editText1.setText("");
}
//这里的支付密码可以通过接口返回数据 或者 GT.EventBus 传递消息出去
GT.logt("支付密码:" + apppwd);
GT.toast(context, "支付密码:" + apppwd);
hide();
}
});
}
//单击密码设置
for (int i = 0; i < ll_bottom.getChildCount(); i++) {
View childAt = ll_bottom.getChildAt(i);
if (childAt instanceof ViewGroup) {
ViewGroup vg = (ViewGroup) childAt;
for (int j = 0; j < vg.getChildCount(); j++) {
View childAt1 = vg.getChildAt(j);
//输入密码
if (childAt1 instanceof TextView) {
TextView tv = (TextView) childAt1;
tv.setOnClickListener(v -> {
EditText editText = editTextList.get(index);
editText.setText(tv.getText().toString());
});
}
//删除单个密码框的操作
if (childAt1 instanceof LinearLayout) {
childAt1.setOnClickListener(v -> {
EditText editText = editTextList.get(index);
editText.setText("");
});
}
}
}
}
}
//单击事件
@GT.Annotations.GT_Click({R.id.view_bg, R.id.tv_pass})
public void onCLick(View view) {
switch (view.getId()) {
case R.id.tv_pass://忘记密码
GT.toast(context, "单击了忘记密码");
break;
case R.id.view_bg:
hide();
break;
}
}
//显示动画
public void show() {
//设置第一个密码框光标
GT.Thread.getInstance(0).execute(() -> {
GT.Thread.sleep(300);
index = 0;
GT.Thread.runAndroid(() -> {
if (et_1 != null) et_1.requestFocus();
});
});
height = view_bg.getHeight();
width = view_bg.getWidth();
animation.translateY_T(height, 0, 300, 0, false, ll_bottom1);
view_bg.setVisibility(View.VISIBLE);
GT.Thread.getInstance(0).execute(() -> {
for (float a = 0; a < 1; ) {
if (view_bg == null) break;
a += 0.01;
GT.Thread.sleep(1);
float finalA = a;
GT.Thread.runAndroid(() -> {
if (view_bg != null) {
view_bg.setAlpha(finalA);
}
});
}
});
}
//隐藏动画
private void hide() {
//清空密码框剩余的数据
GT.Thread.getInstance(0).execute(() -> GT.Thread.runAndroid(() -> {
for (int i = 0; i < editTextList.size(); i++) {
EditText editText1 = editTextList.get(i);
if (editText1 == null) return;
editText1.setText("");
}
}));
height = view_bg.getHeight();
width = view_bg.getWidth();
if (height == 0) {
animation.translateY_T(0, 3000, 1, 0, false, ll_bottom1);
view_bg.setAlpha(0);
view_bg.setVisibility(View.INVISIBLE);
} else {
animation.translateY_T(0, height, 300, 0, false, ll_bottom1);
GT.Thread.getInstance(0).execute(() -> {
for (float a = 1; a > 0; ) {
a -= 0.01;
GT.Thread.sleep(1);
float finalA = a;
GT.Thread.runAndroid(() -> {
if (view_bg != null) {
view_bg.setAlpha(finalA);
view_bg.setVisibility(View.INVISIBLE);
}
});
}
});
}
}
}
この記事では、GT_View パッケージング クラスに焦点を当てます。GT_View パッケージング クラスを学習すると、他のポップアップ ウィンドウをすぐにカスタマイズできるようになります。さらに、GT ライブラリのアニメーション ライブラリを上手に使用できるようになり、左、右、右、右などで再生できるようになります。上、下など、拘束されていないアニメーションは実行できません GT ライブラリには Z 軸アニメーションが含まれており、これらのアニメーションを組み合わせることで、直接 3D 効果を生み出すことができます。
この章では、GT_View + GT アニメーション ライブラリで、カスタムの下部支払いポップアップ ウィンドウを実現します。
クリックしてフォローしていいね (〃'▽'〃) し てブロガーの最新リリース ライブラリをフォローしてください: GitHub - 1079374315/GT