我正在创建自定义LinearLayouts以用作RecyclerView中的行项目。有两个片段使用两个带有两个适配器的RecyclerView,使用XML定义的一个布局。在调整行项目大小时,这两个片段都显示相同的异常行为,但可以理解,因为它们使用相同的布局文件和几乎相同的略微修改的适配器/片段代码。
这是布局文件pool_layout.xml:
void create_borders(char **map, int nb_elem)
{
printf("nb_elem : %d\n", nb_elem);
for (int i = 0 ; i < nb_elem ; i++) //THIS dosnt work and stop once i = 1
// int i = 0; //ALL the commentes are part of the other
// int j = 0; //solution that i found which is working
// while (j < nb_elem)
{
int newx = -1;
int newy = -1;
while (newx <= letter_infos[i].width + 1 ||
newy <= letter_infos[i].height + 1)
{
if (letter_infos[i].square_p1.y - 1 >= 0 &&
newx <= letter_infos[i].width + 1)
map[letter_infos[i].square_p1.y - 1][letter_infos[i].square_p1.x + newx] = '@';
if (letter_infos[i].square_p1.x - 1 >= 0 &&
newy <= letter_infos[i].height + 1)
map[letter_infos[i].square_p1.y +
newy][letter_infos[i].square_p1.x - 1] = '@';
if (letter_infos[i].square_p2.y + 1 < strlen (map[0]) &&
newx <= letter_infos[i].width + 1)
map[letter_infos[i].square_p2.y + 1][letter_infos[i].square_p2.x - newx] = '@';
if (letter_infos[i].square_p2.x + 1 < my_tablen (map) &&
newy <= letter_infos[i].height + 1)
map[letter_infos[i].square_p2.y - newy][letter_infos[i].square_p2.x + 1] = '@';
newx++;
newy++;
}
printf ("i = %d\n", i);
i++;
//j++;
}
}
包含LinearLayout的高度设置为100dp,宽度设置为match_parent,但RecyclerView显示的视图具有不同的宽度,每次重绘视图时都会更改。
这里是LinearLayout的父级,即XML定义的片段的RecyclerView:
<?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:layout_width="match_parent"
android:layout_height="100dp"
android:orientation="vertical"
android:paddingLeft="@dimen/betPool_padding_horizontal"
android:paddingRight="@dimen/betPool_padding_horizontal"
android:paddingTop="@dimen/betPool_padding_vertical"
android:layout_margin="@dimen/courseRace_margin"
android:id="@+id/stakepool_background">
<TextView
android:id="@+id/stakepool_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
<TextView
android:id="@+id/stakepool_name"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="@dimen/betPool_text_size"
/>
</LinearLayout>
此宽度也设置为match_parent,并且它的父(未包含)由具有相对布局的main_activity XML定义,因此视图宽度应的大小为main_activity中定义的片段减去边距等,但它不是。
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/pools_frag"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/brb_cyan"
tools:context="com.ineda.terminal.fragments.pools.PoolsFragment">
<!-- TODO: Update blank fragment layout -->
<android.support.v7.widget.RecyclerView
android:id="@+id/pools_recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical" />
<TextView
android:id="@+id/overlay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0.5"
android:background="@color/md_grey_200"
android:clickable="true"
android:gravity="center"
android:textColor="@color/md_white_1000"
android:visibility="gone" />
</FrameLayout>
片段代码,如果你认为它是相关的,但我怀疑它不是。
适配器代码:
public class PoolsFragment extends Fragment {
public static final String POOL_SELECTED = "com.ineda.terminal.fragments.ppol.POOL_SELECTED";
private Context context;
private RecyclerView mRecyclerView;
private PoolsAdapter mAdapter;
private List<Pool> poolList = new ArrayList<>();
private Pool currentPool;
private TextView overlay;
private Pool previousSelection;
public PoolsFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
context = getContext();
// Inflate the layout for this fragment
return inflater.inflate(R.layout.pools_fragment, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mAdapter = new PoolsAdapter(poolList, context);
overlay = view.findViewById(R.id.overlay);
overlay.setOnClickListener(new View.OnClickListener() {
mRecyclerView = (RecyclerView) view.findViewById(R.id.pools_recyclerView);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setAdapter(mAdapter);
}
我强制布局在适配器级别调整自身大小,因为这是一种让它至少看起来很好的hacky方式,但这不会长期工作,特别是如果应用程序要进入多个设备或需要这是通过LinearLayout.LayoutParams完成的,它在布局膨胀后强制布局宽度为wrap_content。如果我然后转到XML并使自定义布局的高度更小,则包含在其中的文本不会缩小以匹配,这意味着事物是不合适的。
这里最后是Custom LinearLayout本身,虽然如果问题我会感到惊讶:
public class PoolsAdapter extends RecyclerView.Adapter<PoolsAdapter.holder> {
private static OnPoolClickListener OnPoolClickListener;
private List<Pool> pools;
private Context context;
private View previousSelectedPool;
private Pool currentPool;
private boolean initialised;
public PoolsAdapter(List<Pool> list, Context context) {
this.pools = list;
this.context = context;
}
@Override
public holder onCreateViewHolder(ViewGroup parent, int viewType) {
return new holder(new StakePoolButton(context));
}
@Override
public void onBindViewHolder(final holder holder, final int position) {
currentPool = pools.get(position);
holder.button.getButtonText().setText(pools.get(position).code);
if (!initialised) {
if (position == 0) {
OnPoolClickListener.onPoolClick(currentPool);
}
initialised = true;
}
if(currentPool.getStates() == null){
currentPool.setStates(ButtonStates.UNSELECTED);
}
switch (currentPool.getStates()){
case UNSELECTED:
holder.button.colourAsDeselected();
break;
case SELECTED:
holder.button.colourAsSelected();
break;
}
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
holder.button.setLayoutParams(params);
}
public class holder extends RecyclerView.ViewHolder implements View.OnClickListener {
StakePoolButton button;
public holder(StakePoolButton view) {
super(view);
view.setOnClickListener(this);
button = view;
}
我有其他自定义LinearLayouts可以正常工作,并且可以通过更改包含布局的宽度和高度值来正确调整,但是这个不适用于任何原因。
编辑:在左边我们有预期的行为,这是通过在通胀后设置LayoutParams来强制的。在右边,我们有行为,当它没有被迫通胀后。宽度都是可变的,并且每次重新加载视图时都会更改。
答案 0 :(得分:1)
我认为这种宽度变化的问题是因为您必须再添加一个设置到您的Recyclerview。
所以在你的PoolsFragment中
添加此
mRecyclerView.setHasFixedSize(true);
这段代码之后
mRecyclerView.setLayoutManager(layoutManager);
编辑2
根据Drew在this中的答案,似乎最好像这样手动给予参数
所以你的适配器类
//update this according to the answer I linked
@Override
public holder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemview=new StakePoolButton(parent.getContext());
RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, //width
ViewGroup.LayoutParams.WRAP_CONTENT);//height
itemView.setLayoutParams(lp);//override default layout params
return new holder(itemview);
}
如您所见,高度为wrap_content,但您可以将其更改为100dp,宽度应保持match_parent