- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 fragment ,用于显示歌曲的歌词,该歌词是根据给定的 id 从房间数据库加载的。
我想在旋转屏幕后保留滚动位置。现在,旋转后,歌曲会再次从数据库加载,并且无论旋转之前的滚动位置如何, View 都位于最顶部。
我认为我可以在onSaveInstanceState
中保存滚动位置,在onCreateView()
中使用命令mSongDisplayScrollView.scrollTo(x, y)
>
fragment 代码:
public class SongDisplayFragment extends Fragment {
private Song mSongToDisplay;
private ScrollView mSongDisplayScrollView;
private TextView mSongTitleTextView;
private RecyclerView mSongLyricsRecyclerView;
private GuitarSongbookViewModel mGuitarSongbookViewModel;
public static final String SONG_ID_KEY = "SONG_ID_KEY";
public SongDisplayFragment() {
}
public static SongDisplayFragment newInstance(Long songId) {
SongDisplayFragment songDisplayFragment = new SongDisplayFragment();
Bundle arguments = new Bundle();
arguments.putLong(SONG_ID_KEY,
songDisplayFragment.setArguments(arguments);
return songDisplayFragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(false);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_song_display, container, false);
mSongDisplayScrollView = view.findViewById(R.id.song_display_scroll_view);
mSongLyricsRecyclerView = view.findViewById(R.id.lyrics_rv_);
mSongTitleTextView = view.findViewById(R.id.
mGuitarSongbookViewModel = ViewModelProviders.of(this).get(GuitarSongbookViewModel.class);
final SongDisplayAdapter songDisplayAdapter = new SongDisplayAdapter(getContext());
Long songId = null;
if (getArguments().containsKey(SONG_ID_KEY)) {
songId = getArguments().getLong(SONG_ID_KEY);
}
if (songId != null) {
final Long finalSongId = songId;
mGuitarSongbookViewModel.getSongById(songId).observe(this, new Observer<Song>() {
@Override
public void onChanged(@Nullable final Song song) {
mSongToDisplay = song;
mSongTitleTextView.setText(mSongToDisplay.getMTitle());
songDisplayAdapter.setSong(song);
}
});
}
mSongLyricsRecyclerView.setAdapter(songDisplayAdapter);
mSongLyricsRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
return view;
}
}
fragment XML:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragments.SongDisplayFragment">
<ScrollView
android:id="@+id/song_display_scroll_view"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/autoscroll_bar"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0"
tools:layout_editor_absoluteX="138dp">
<LinearLayout
android:id="@+id/son_display_linear_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/displayed_song_title_txt_"
style="@style/TitleOfDisplayedSong"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:text="@string/title_placeholder" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/lyrics_rv_"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="8dp"
android:layout_marginBottom="12dp"
android:nestedScrollingEnabled="false" />
</LinearLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
该 fragment 在 textView 和 RecyclerView 中显示歌曲的标题和歌词,适配器类代码为:
package com.example.guitarsongbook.adapters;
import android.content.Context;
import android.graphics.Rect;
import android.text.Html;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.example.guitarsongbook.R;
import com.example.guitarsongbook.daos.SongChordJoinDao;
import com.example.guitarsongbook.model.Chord;
import com.example.guitarsongbook.model.Song;
import java.util.ArrayList;
import java.util.List;
public class SongDisplayAdapter extends RecyclerView.Adapter<SongDisplayAdapter.SongViewHolder> {
private Context context;
private final LayoutInflater mInflater;
private Song mSong;
private ArrayList<String> mLyrics;
public SongDisplayAdapter(Context context) {
this.context = context;
mInflater = LayoutInflater.from(context);
}
@NonNull
@Override
public SongViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = mInflater.inflate(R.layout.song_lyrics_rv_item, parent, false);
return new SongDisplayAdapter.SongViewHolder(itemView);
}
public void setSong(Song song){
mSong = song;
mLyrics = mSong.getMLyrics();
notifyDataSetChanged();
}
@Override
public void onBindViewHolder(@NonNull SongViewHolder holder, int position) {
holder.bindTo(position);
}
@Override
public int getItemCount() {
if (mLyrics != null)
return mLyrics.size();
else return 0;
}
public class SongViewHolder extends RecyclerView.ViewHolder {
private final TextView mLyricsLineTextView;
public SongViewHolder(@NonNull View itemView) {
super(itemView);
mLyricsLineTextView = itemView.findViewById(R.id.song_lyric_line_txt_);
}
public void bindTo(int position) {
if (mSong != null) {
mLyricsLineTextView.setText(Html.fromHtml(mLyrics.get(position)));
} else {
mLyricsLineTextView.setText(context.getString(R.string.no_song_label));
}
}
}
}
RecyclerView 项目 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="wrap_content">
<TextView
android:id="@+id/song_lyric_line_txt_"
style="@style/LyricOfDisplayedSong"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="24dp"
app:layout_constraintEnd_toStartOf="@+id/song_chord_line_txt_"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="placeholder text" />
</androidx.constraintlayout.widget.ConstraintLayout>
我认为问题在于,旋转屏幕后,必须通过观察者的方法 onChange()
再次加载歌曲,因此有一小会儿,scrollView 没有任何内容可显示。我想找到一些解决方案,如何在再次加载歌曲后返回到旧位置。
最佳答案
第一步是通过 Fragment 的 onSaveInstanceState
方法保存对象的值。
我的更多解释将来自每个代码块中的注释,因此您可以更好地理解它是如何工作的。
Values to be persisted: mSongToDisplay and mScrollViewPosition
//new variable introduced
int mScrollViewPosition = 0;
@Override
protected void onSaveInstanceState(Bundle outState) {
//If screen orientation changes, android redraws all views
//and non persistent data would be lost.
//Nevertheless, before this happens android informs the app via this method
//So to prevent state loss we save the data to a temporary storage
outState.putParcelable("song_data", mSongToDisplay);
//save ScrollView current position
outState.putInt("position_data", mSongDisplayScrollView.getScrollY());
//call super to commit your changes
super.onSaveInstanceState(outState);
}
接下来是方向改变完成后恢复数据
在 fragments onCreateView
中添加以下 block ,并确保 if 语句 block
在初始化适配器之后出现
...
//...add adapter initialization block here before checking for saved data
//Check for saved data
if (savedInstanceState != null) {
// Retrieve the data you saved
mSongToDisplay = savedInstanceState.getParcelable("song_data");
mScrollViewPosition = savedInstanceState.getInt("position_data");
//Re-initialize and reload adapter record
mSongToDisplay = song;
mSongTitleTextView.setText(mSongToDisplay.getMTitle());
songDisplayAdapter.setSong(song);
}
else {
//No data to retrieve
//initialize data model here.
}
//Assign the adapter to recyclerView
mSongLyricsRecyclerView.setAdapter(songDisplayAdapter);
mSongLyricsRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
try{
//Finally we set the scrollview position at this point just to make sure
//recyclerview has its data loaded and full length of scrollview is restored
mSongDisplayScrollView.setScrollY(mScrollViewPosition);}
catch(Exception ex){
//position isn't right
}
return view;
此时所需的数据已被保留,并且在每个 screenOrientationChange
上,应用程序会将之前保存的歌曲对象加载到适配器中,以防止错误调用db 或 api
>,并且还会使用保存的整数值mScrollViewPosition
滚动到预期位置。
关于java - 在加载了 LiveDate 对象的 fragment 中旋转屏幕后如何保持 ScrollView 中的滚动位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57315938/
我正在尝试创建一个类似于 BBC 新闻 native 应用程序的布局(使用known.js);一个垂直的ScrollView,其中有许多水平的ScrollView。我已经“工作”到了一切都渲染并且水平
我正在尝试创建一个类似于 BBC 新闻 native 应用程序的布局(使用known.js);一个垂直的ScrollView,其中有许多水平的ScrollView。我已经“工作”到了一切都渲染并且水平
我已经为以下问题寻找了很多答案,但没有找到合适的解决方案(也不是“不可能”)。我不想要双向 ScrollView! 我想要的只是拥有这样的东西: 如果我这样做(具有所需的布局属性),我会得到我的
我想使用 famo.us 标准 Scrollview但是有一个以不同速度滚动的背景图像以产生视差效果。 我想知道是否有一种方法可以连接到事件流,或者以某种方式将 Scrollviews 位置通过管道传
初始化程序中有一个带有 ScrollView(alwaysBounceVertical: false) 的属性,但我似乎找不到它了。 有谁知道如何禁用 SwiftUI ScrollView 上的垂直弹
在你说之前 “Google 说不要这样做” 请阅读我的所有问题!! 布局: ScrollView -> RelativeLayout -> ScrollView -> RelativeLayout 第
我想在 Windows 7 上创建一种体验(使用触摸),我可以在其中拥有一个只能垂直滚动的外部 ScrollViewer(它是屏幕的大小)。在那个 ScrollViewer 中,我将有几个其他的 Sc
我知道 Google 的人要求我们不要将 Scrollable View 放在另一个 Scrollable View 中,但他们是否有任何官方声明指示我们不要这样做? 最佳答案 试试这个 注意:这里
更新Xcode11 beta3后,我发现scrollview内部 View 的阴影会在边界处被切断,但在Xcode11 beta2中还可以。我只是使用底部填充来修复它,但我认为这不是一个好的解决方案。
我的 wpf 应用程序的结构如下: 我的目标是,如果 DataGrid 超过屏幕的高度来使用它自己的 Scrollviewer。目前只使用外部的 S
我在其他应用程序中使用了 ScrollView,只添加了 style={styles.container}与风格。然而,在这个应用程序中,我正在创建我的风格 alignItems:'flex-star
这是我的布局 xml。 ... 我已经尝试过此链接中的解决方案: ScrollView Inside ScrollVie
有没有办法在 nativescript 的 ScrollView 上隐藏滚动指示器?我试过 scrollBars='none' 和 css overflow='hidden' 但它不能同时工作。谢谢
所以我有一个 ScrollView ,里面有一个 TextView 。当文本的String长于屏幕宽度时,它只是在下一行中移动。我想通过在 ScrollView 中添加 HorizontalScr
我正在尝试在 android 的水平 ScrollView 中创建一个水平 ScrollView 。第一个水平 ScrollView 工作正常。当我尝试滚动时,第二个水平 ScrollView 不起作
我在同一布局中创建了两个 ScrollView。你可以说一个平行的 ScrollView 。我想手动滚动一个 ScrollView ,作为响应,另一个 ScrollView 应该以完全相同的方式滚动。
我在 android 中设计 UI,我在另一个 HorizontalScrollView 中有一个 HorizontalScrollView。但是,子 HorizontalScrollVi
我在另一个 ScrollView 中有 ScrollView 。我想滚动内部 ScrollView ,但外部 ScrollView 只滚动。如何解决这个问题? 谢谢。 最佳答案 sv01 =
我有两个 UIScrollView,如果用户在 ScrollView 中滚动,我想让另一个 ScrollView 也滚动。我已经阅读了一个解决方案,涉及将 pangesturerecognizer 从
我以编程方式创建了 UIScrollView 并向其中添加了多个 button。 它运行良好,没有任何问题。 但我需要通过复制先前 ScrollView 的内容来创建另一个 ScrollView 。
我是一名优秀的程序员,十分优秀!