首页 > 解决方案 > 如何滑动主布局并强制调整大小?

问题描述

我想创建一个顶部带有选项的文本编辑器(粗体,..)。我也希望能够隐藏这些选项;使用下图所示的确切过渡样式。我的问题是我使用的 EditText 从来没有预期的行为。(例如,在下面的 GIF 中,它在移动后不会调整大小)。

例子


我尝试使用动画(这是图片上显示的内容)。我还尝试了布局动画,结合setVisibility(View.GONE)动画结束的时间(它几乎完美,但对于两者之间的一帧,我们可以看到发生了什么)。我终于尝试设置android:animateLayoutChanges="true"。效果很好,但我无法根据需要为过渡设置动画。

我还尝试以各种方式将这三者结合起来,但从未成功。

爪哇:

public class MainActivity extends AppCompatActivity {
boolean optionVisible = true;
LinearLayout Main;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Main = findViewById(R.id.main);

}

public void show(View v) {
    if (optionVisible) {
        Main.animate().setDuration(300).translationYBy(-Options.getHeight());
    } else {
        Main.animate().setDuration(300).translationYBy(Options.getHeight());
    }
    optionVisible = !optionVisible;
}
}

XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<LinearLayout
    android:id="@+id/options"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:fillAfter="true">

        ... Defining buttons and slider ...

</LinearLayout>

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dp">

       ... Defining Title EditText ...

</RelativeLayout>


 <EditText
     android:id="@+id/writter"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:layout_margin="10dp"
     android:gravity="top"
     android:padding="0dp"
     android:text="azertyuio"
     android:textAlignment="gravity"
     android:textColor="@color/text"
     android:textSize="20sp"
     tools:ignore="HardcodedText"
     android:background="@null"
     />

</LinearLayout>

标签: javaandroidandroid-layout

解决方案


好吧,我终于设法让它正常工作。我仍然觉得解决方案很糟糕,并且很乐意在这里提出另一个建议。

无论如何,我最终所做的是使用动画(而不是动画),并且根据选项的存在与否,基本上将 2 个主视图设置为 GONE 和 VISIBLE。

这是代码(我使用了一个外部类来同步两个EditText)

活动主.xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/main_with_opt"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:visibility="gone">

        <LinearLayout
            android:id="@+id/options"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:fillAfter="true">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">


                <FrameLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <Button
                        style="@style/Widget.AppCompat.Button.Borderless"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center"
                        android:text="@string/underline"/>

                </FrameLayout>

                <FrameLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <Button
                        style="@style/Widget.AppCompat.Button.Borderless"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center"
                        android:text="@string/italic"/>

                </FrameLayout>

                <FrameLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_weight="1">

                    <Button
                        style="@style/Widget.AppCompat.Button.Borderless"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center"
                        android:text="@string/bold"/>

                </FrameLayout>

            </LinearLayout>


            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <TextView
                    android:id="@+id/size"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="aA"
                    android:paddingHorizontal="10dp"
                    android:paddingVertical="5dp"
                    tools:ignore="HardcodedText"
                    android:layout_alignParentStart="true"/>

                <SeekBar
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:layout_toEndOf="@id/size"
                    android:layout_toStartOf="@+id/size_int"/>

                <TextView
                    android:id="@+id/size_int"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@string/text_size"
                    android:paddingHorizontal="10dp"
                    android:paddingVertical="5dp"
                    tools:ignore="HardcodedText"
                    android:layout_alignParentEnd="true"/>

            </RelativeLayout>

        </LinearLayout>

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp">

            <EditText
                android:id="@+id/title_with_opt"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:lines="1"
                android:text="@string/title"
                android:maxLines="1"
                android:textColor="@color/title"
                android:layout_marginStart="10dp"
                android:layout_toStartOf="@+id/arrow_with_opt"/>

            <ImageButton
                style="@style/Widget.AppCompat.Button.Borderless"
                android:id="@+id/arrow_with_opt"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentEnd="true"
                android:layout_centerVertical="true"
                android:src="@drawable/arrow_less"
                android:onClick="show"/>

        </RelativeLayout>


         <com.example.mynotes.SyncEditText
             android:id="@+id/typer_with_opt"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layout_margin="10dp"
             android:gravity="top"
             android:padding="0dp"
             android:textAlignment="gravity"
             android:textColor="@color/text"
             android:textSize="20sp"
             android:background="@null"
             />

    </LinearLayout>

    <LinearLayout
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp">

            <EditText
                android:id="@+id/title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:maxLines="1"
                android:text="@string/title"
                android:textColor="@color/title"
                android:layout_marginStart="10dp"
                android:layout_toStartOf="@+id/arrow"/>

            <ImageButton
                style="@style/Widget.AppCompat.Button.Borderless"
                android:id="@+id/arrow"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentEnd="true"
                android:layout_centerVertical="true"
                android:src="@drawable/arrow_less"
                android:onClick="show"/>

        </RelativeLayout>


        <com.example.mynotes.SyncEditText
            android:id="@+id/typer"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="10dp"
            android:gravity="top"
            android:padding="0dp"
            android:textAlignment="gravity"
            android:textColor="@color/text"
            android:textSize="20sp"
            android:background="@null"
            />

    </LinearLayout>

</FrameLayout>

主要活动.java:

package com.example.mynotes;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.LayoutAnimationController;
import android.widget.LinearLayout;

public class MainActivity extends AppCompatActivity {
    LinearLayout Options;
    boolean optionVisible = false;
    LinearLayout Main;
    LinearLayout Main_with_opt;
    LayoutAnimationController show_lessAnimation;
    LayoutAnimationController show_moreAnimation;
    com.example.mynotes.SyncEditText Typer;
    com.example.mynotes.SyncEditText Typer_with_opt;
    int mSelection;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Main_with_opt = findViewById(R.id.main_with_opt);
        Options = findViewById(R.id.options);

        Main = findViewById(R.id.main);

        Typer = findViewById(R.id.typer);
        Typer_with_opt = findViewById(R.id.typer_with_opt);

        Typer.setDependencies(Typer_with_opt);
        Typer_with_opt.setDependencies(Typer);

        show_lessAnimation = AnimationUtils.loadLayoutAnimation(this, R.anim.show_less_layout);
        show_moreAnimation = AnimationUtils.loadLayoutAnimation(this, R.anim.show_more_layout);
    }

    public void show(View v) {
        if (optionVisible) {
            Main_with_opt.setLayoutAnimationListener(show_lessAnimationListener);
            Main_with_opt.setLayoutAnimation(show_lessAnimation);
            Typer.requestFocus();
            Typer.setSelection(Typer_with_opt.getSelectionStart());
            Typer.scrollTo(Typer_with_opt.getScrollX(), Typer_with_opt.getScrollY());
            Main_with_opt.startLayoutAnimation();
        } else {
            Main_with_opt.setLayoutAnimationListener(show_moreAnimationListener);
            Main_with_opt.setLayoutAnimation(show_moreAnimation);
            Main_with_opt.setVisibility(View.VISIBLE);
            Typer_with_opt.requestFocus();
            Typer_with_opt.setSelection(Typer.getSelectionStart());
            Typer_with_opt.scrollTo(Typer.getScrollX(), Typer.getScrollY());
            Main.setVisibility(View.GONE);
            Main_with_opt.startLayoutAnimation();
        }
        optionVisible = !optionVisible;
    }

    Animation.AnimationListener show_lessAnimationListener = new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {

        }

        @Override
        public void onAnimationEnd(Animation animation) {
            Main.setVisibility(View.VISIBLE);
            Main_with_opt.setVisibility(View.GONE);
        }

        @Override
        public void onAnimationRepeat(Animation animation) {

        }
    };

    Animation.AnimationListener show_moreAnimationListener = new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {
        }

        @Override
        public void onAnimationEnd(Animation animation) {
        }

        @Override
        public void onAnimationRepeat(Animation animation) {

        }
    };

}

和自定义类: SyncEditText.java :

package com.example.mynotes;

import android.content.Context;
import android.support.v7.widget.AppCompatEditText;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;

public class SyncEditText extends AppCompatEditText implements TextWatcher {
    private SyncEditText[] mDependencies;
    private boolean shouldSync = true;

    public SyncEditText(Context context) {
        super(context);
    }

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

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

        // This is to avoid text changed event is called multiple time per character because auto suggestion
        setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);

        addTextChangedListener(this);
    }

    private void addTextChangedListener(SyncEditText syncEditText) {
    }

    public void setDependencies(SyncEditText... dependencies) {
        mDependencies = dependencies;
    }

    public void setText(CharSequence text, boolean syncDependencies) {
        shouldSync = syncDependencies;
        setText(text);

        Log.d("Log", "Text sync: " + text);
    }

    @Override
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { }

    @Override
    public void afterTextChanged(Editable editable) { }

    @Override
    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        if (mDependencies == null)
            return;

        if (!shouldSync) {
            // If this text is sync from other SyncEditText, ignore the change
            shouldSync = true;
            return;
        }

        Log.d("Log", "Text input: " + charSequence);

        // Sync to all dependencies
        for (SyncEditText syncEditText : mDependencies) {
            syncEditText.setText(charSequence, false);
        }
    }
}

推荐阅读