我的布局顶部有一些视图,应该可以与它们下面的EditText一起滚动。
EditText占用了剩下的空间,占用了所需的空间。
以下是演示它的示例POC布局(此处仅使用了2个EditTexts):
<android.support.v4.widget.NestedScrollView android:id="@+id/nestedScrollView"
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent" android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical">
<EditText
android:id="@+id/titleEditText" android:layout_width="match_parent" android:layout_height="wrap_content"
android:ellipsize="end" android:hint="title" android:imeOptions="actionNext|flagNoExtractUi"
android:inputType="text|textAutoCorrect|textCapSentences" android:maxLines="1"
android:nextFocusDown="@id/contentEditText" android:nextFocusForward="@id/contentEditText"
android:scrollHorizontally="true" android:textColor="#2a2f3b" android:textColorHint="#a3a3a3"
android:textSize="21sp"/>
<EditText
android:id="@+id/contentEditText" android:layout_width="match_parent" android:layout_height="match_parent"
android:gravity="top" android:hint="content" android:background="@android:drawable/alert_light_frame"
android:imeOptions="actionDone|flagNoEnterAction|flagNoExtractUi" android:textSize="18sp"
android:inputType="textMultiLine|textAutoCorrect|textCapSentences"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
我已经设置了一个背景框,可以直观地显示EditText的大小。
我找到了很多我写的解决方案,但实际上没有一个能够很好地处理滚动。
我一直看到的,至少是其中一个问题:
我尝试过这些解决方案:
windowSoftInputMode
值,并尝试在NestedScrollView中设置isNestedScrollingEnabled
。 如何让底层的EditText占用尽可能多的空间,并且仍然可以滚动整个NestedScrollView,而不会出现编辑问题?
编辑:由于原始应用程序有点复杂,底部有一些视图(在工具栏内部),当你没有专注于底部的EditText时自动隐藏,这就得到了答案我发现没有工作。另外,我不小心把赏金给了错误的答案,所以这是一个新的赏金,在更复杂的POC上。问题保持不变。 NestedScrollView应该保留在同一个地方,而不是在关注底部的EditText时滚动。
<LinearLayout
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" android:orientation="vertical">
<View
android:layout_width="0dp" android:layout_height="0dp" android:focusable="true"
android:focusableInTouchMode="true"/>
<android.support.v4.widget.NestedScrollView
android:id="@+id/nestedScrollView" android:layout_width="match_parent" android:layout_height="0px"
android:layout_weight="1" android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical">
<EditText
android:id="@+id/titleEditText" android:layout_width="match_parent" android:layout_height="wrap_content"
android:ellipsize="end" android:hint="title" android:imeOptions="actionNext|flagNoExtractUi"
android:inputType="text|textAutoCorrect|textCapSentences" android:maxLines="1"
android:nextFocusDown="@id/contentEditText" android:nextFocusForward="@id/contentEditText"
android:scrollHorizontally="true" android:textColor="#2a2f3b" android:textColorHint="#a3a3a3"
android:textSize="21sp"/>
<android.support.constraint.ConstraintLayout
android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent"
android:background="@android:drawable/alert_light_frame" android:clickable="true"
android:focusable="false">
<EditText
android:id="@+id/contentEditText" android:layout_width="match_parent"
android:layout_height="wrap_content" android:background="@null" android:gravity="top"
android:hint="content" android:imeOptions="actionDone|flagNoEnterAction|flagNoExtractUi"
android:inputType="textMultiLine|textAutoCorrect|textCapSentences" android:textSize="18sp"/>
</android.support.constraint.ConstraintLayout>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<LinearLayout
android:layout_width="match_parent" android:layout_height="wrap_content" android:animateLayoutChanges="true"
android:orientation="vertical">
<LinearLayout
android:id="@+id/autoHideLayout" android:layout_width="match_parent" android:layout_height="wrap_content"
android:orientation="horizontal" android:visibility="gone" tools:visibility="visible">
<Button
android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="button"/>
<Button
android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="button2"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
container.setOnClickListener {
contentEditText.requestFocus()
contentEditText.setSelection(contentEditText.length())
}
contentEditText.setOnFocusChangeListener { view, hasFocus ->
autoHideLayout.visibility = if (hasFocus) View.VISIBLE else View.GONE
if (hasFocus)
nestedScrollView.scrollTo(0, 0)
}
}
}
答案 0 :(得分:15)
我得到了一些解决方法,通过将底部的EditText包装为可以为其提供焦点的布局。
根本不需要太多代码
<强> activity_main.xml中强>
<android.support.v4.widget.NestedScrollView
android:id="@+id/nestedScrollView" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical">
<EditText
android:id="@+id/titleEditText" android:layout_width="match_parent" android:layout_height="wrap_content"
android:ellipsize="end" android:hint="title" android:imeOptions="actionNext|flagNoExtractUi"
android:inputType="text|textAutoCorrect|textCapSentences" android:maxLines="1"
android:nextFocusDown="@id/contentEditText" android:nextFocusForward="@id/contentEditText"
android:scrollHorizontally="true" android:textColor="#2a2f3b" android:textColorHint="#a3a3a3"
android:textSize="21sp"/>
<android.support.constraint.ConstraintLayout
android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent"
android:background="@android:drawable/alert_light_frame" android:clickable="true" android:focusable="false">
<EditText
android:id="@+id/contentEditText" android:layout_width="match_parent"
android:layout_height="wrap_content" android:background="@null" android:gravity="top"
android:hint="content" android:imeOptions="actionDone|flagNoEnterAction|flagNoExtractUi"
android:inputType="textMultiLine|textAutoCorrect|textCapSentences" android:textSize="18sp"/>
</android.support.constraint.ConstraintLayout>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<强> MainActivity.kt 强>
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
container.setOnClickListener {
contentEditText.requestFocus()
contentEditText.setSelection(contentEditText.length())
}
contentEditText.setOnFocusChangeListener { view, hasFocus ->
if (hasFocus) {
nestedScrollView.scrollTo(0, 0)
}
}
}
}
<强>清单强>
<manifest package="com.example.user.myapplication" xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme">
<activity android:name=".MainActivity" android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
答案 1 :(得分:13)
您应该能够通过根据屏幕高度计算minLines
来实现您想要的效果。请参阅下面的示例活动和布局。
您需要输入相当多的文本来消耗最小的行并超出屏幕的高度以开始滚动行为,但是您可以通过向{添加一些常量行来避免这种情况。 {1}}计算
minLines
这是布局
public class ScrollingActivity extends AppCompatActivity
{
EditText editText2;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scrolling);
editText2 = findViewById(R.id.editText2);
int minHeight = getResources().getDisplayMetrics().heightPixels - editText2.getTop();
float lineHeight = editText2.getPaint().getFontMetrics().bottom - editText2.getPaint().getFontMetrics().top;
int minLines = (int)(minHeight/lineHeight);
editText2.setMinLines(minLines);
}
}
编辑
我重新创建了您的解决方案,您可以通过将此侦听器设置为EditText来纠正焦点问题。它通过在编辑文本获得焦点时覆盖滚动操作来工作,仅滚动到足以使光标可见。
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
android:id="@+id/parentLayout"
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="com.my.package.ScrollingActivity">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000">
<android.support.constraint.ConstraintLayout
android:id="@+id/scrollingLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/editText1"
android:layout_margin="15dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
android:background="#FFFFFF"/>
<EditText
android:id="@+id/editText2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/editText1"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_margin="15dp"
android:background="#FFFFFF"/>
</android.support.constraint.ConstraintLayout>
</ScrollView>
</android.support.constraint.ConstraintLayout>
编辑2
我已经更新了我的回答以反映新奖励的变化,如果我已经正确地理解了这个问题,这应该非常接近你所需要的。
contentEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean hasFocus) {
if(hasFocus){
nestedScrollView.scrollTo(0, 0);
}
}
});
这是新布局
public class ScrollingActivity extends AppCompatActivity
{
ConstraintLayout parentLayout;
EditText contentEditText;
NestedScrollView nestedScrollView;
LinearLayout autoHideLayout;
boolean preventScroll = true;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scrolling);
contentEditText = findViewById(R.id.contentEditText);
nestedScrollView = findViewById(R.id.nestedScrollView);
autoHideLayout = findViewById(R.id.autoHideLayout);
parentLayout = findViewById(R.id.parentLayout);
nestedScrollView.setOverScrollMode(View.OVER_SCROLL_NEVER);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
parentLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int minHeight = autoHideLayout.getTop() - contentEditText.getTop();
float lineHeight = contentEditText.getPaint().getFontMetrics().bottom - contentEditText.getPaint().getFontMetrics().top;
int minLines = (int)(minHeight/lineHeight);
if(minLines != contentEditText.getMinLines()){
contentEditText.setMinLines(minLines);
}
}
});
contentEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean hasFocus) {
ViewGroup.LayoutParams layoutParams = autoHideLayout.getLayoutParams();
if(hasFocus){
nestedScrollView.scrollTo(0,0);
layoutParams.height = ConstraintLayout.LayoutParams.WRAP_CONTENT;
} else{
layoutParams.height = 0;
}
autoHideLayout.setLayoutParams(layoutParams);
}
});
}
}
答案 2 :(得分:3)
您可以通过更改layout.xml和MainActivity来实现预期结果。
更改layout_height
并为layout_weight
添加ConstraintLayout
,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical">
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:focusable="true"
android:focusableInTouchMode="true" />
<android.support.v4.widget.NestedScrollView
android:id="@+id/nestedScrollView"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<EditText
android:id="@+id/titleEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:hint="title"
android:imeOptions="actionNext|flagNoExtractUi"
android:inputType="text|textAutoCorrect|textCapSentences"
android:maxLines="1"
android:nextFocusDown="@id/contentEditText"
android:nextFocusForward="@id/contentEditText"
android:scrollHorizontally="true"
android:textColor="#2a2f3b"
android:textColorHint="#a3a3a3"
android:textSize="21sp" />
<android.support.constraint.ConstraintLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@android:drawable/alert_light_frame"
android:clickable="true"
android:focusable="false"
android:nestedScrollingEnabled="false">
<!-- -->
<EditText
android:id="@+id/contentEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:gravity="top"
android:hint="content"
android:imeOptions="actionDone|flagNoEnterAction|flagNoExtractUi"
android:inputType="textMultiLine|textAutoCorrect|textCapSentences"
android:textSize="18sp" />
</android.support.constraint.ConstraintLayout>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:orientation="vertical">
<LinearLayout
android:id="@+id/autoHideLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="visible"
tools:visibility="visible">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button2" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
Manifest.xml是:
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
记录scrollX&amp;的当前值滚动Y NestedScrollView
并按如下方式调整NestedScrollView
:
<强> MainActivity.java 强>
public class MainActivity extends AppCompatActivity {
private int scrollX;
private int scrollY;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText editText = findViewById(R.id.contentEditText);
final LinearLayout autoHideLayout = findViewById(R.id.autoHideLayout);
ConstraintLayout container = findViewById(R.id.container);
container.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
autoHideLayout.setVisibility(View.VISIBLE);
editText.requestFocus();
editText.setSelection(editText.length());
}
});
final NestedScrollView nestedScrollView = findViewById(R.id.nestedScrollView);
editText.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
scrollX = nestedScrollView.getScrollX();
scrollY = nestedScrollView.getScrollY();
autoHideLayout.setVisibility(View.VISIBLE);
return false;
}
});
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus)
nestedScrollView.scrollTo(scrollX, scrollY);
if (!hasFocus) {
autoHideLayout.setVisibility(View.GONE);
}
}
});
}
}
答案 3 :(得分:1)
我意识到NestedScrollView
在内容离开屏幕之前不会滚动。我做了一个黑客并在输入的文本后放了一些空行,以确保内容将超出当前屏幕。在EditText失去焦点之后,我删除了空行。
public class MainActivity extends AppCompatActivity {
String EMPTY_SPACES = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
EditText mEditText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mEditText = findViewById(R.id.contentEditText);
mEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean hasFocus) {
if (!hasFocus) {
// code to execute when EditText loses focus
mEditText.setText(mEditText.getText().toString().trim());
}
}
});
mEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
int charsThatGuaranteesTextIsOutOfScreen = 400;
if (mEditText.hasFocus() && charSequence.length() < charsThatGuaranteesTextIsOutOfScreen) {
mEditText.setText(String.format(Locale.getDefault(), "%1$s%2$s", charSequence, EMPTY_SPACES));
mEditText.setSelection(i2);
}
}
@Override
public void afterTextChanged(Editable editable) {
}
});
}
@Override
public void onBackPressed() {
if (mEditText.hasFocus()) {
mEditText.clearFocus();
} else {
super.onBackPressed();
}
}
}