我只是为我准备好此动态布局的第一步,但我无法弄清楚自己在做什么错。
我有以下字符串:
AAA__AB /
_AAAAAA /
_AAABBB /
我应该将上述字符串转换为房间布局,从而:
A-表示可用房间
B-代表已预订的房间
_-表示空格
/-代表新行
我一直在遵循本教程Dynamic bus seats layout来尝试制作一个可以在 RecyclerView 中动态创建公寓房间布局的应用。
我有一个水平方向的recyclerview作为父recyclerView。我有一个适配器和一个来自Web服务器的数据源。
除了应该强制recyclerview添加新行/行以使其余视图可以在新行/行中对齐之外,所有功能都可以正常运行,而NEW_LINE功能除外
请帮助
以下是我得到的
The way my layout looks like as at now
以下是我想要的
The intended layout
Main Activity.java
...rest of the code
//Displaying the rooms and trying to make the layout
private void display_rooms_details(){
ArrayList house_rooms;
house_rooms=new ArrayList<>();
for (int i = 0; i < rooms_list.size(); i++)
{
if(rooms_list.get(i).getType()==0){
house_rooms.add(new Decode_rooms(Decode_rooms.AVAILABLE_ROOMS, rooms_list.get(i).getRoom_type(), rooms_list.get(i).getRoom_number(), rooms_list.get(i).getRoom_name(), rooms_list.get(i).getRoom_symbol(), rooms_list.get(i).getRoom_tenant()));
}
if(rooms_list.get(i).getType()==1){
house_rooms.add(new Decode_rooms(Decode_rooms.BOOKED_ROOMS, rooms_list.get(i).getRoom_type(), rooms_list.get(i).getRoom_number(), rooms_list.get(i).getRoom_name(), rooms_list.get(i).getRoom_symbol(), rooms_list.get(i).getRoom_tenant()));
}
if(rooms_list.get(i).getType()==2){
house_rooms.add(new Decode_rooms(Decode_rooms.NEW_LINE, rooms_list.get(i).getRoom_type(), rooms_list.get(i).getRoom_number(), rooms_list.get(i).getRoom_name(), rooms_list.get(i).getRoom_symbol(), rooms_list.get(i).getRoom_tenant()));
}
if(rooms_list.get(i).getType()==3){
house_rooms.add(new Decode_rooms(Decode_rooms.SPACE, rooms_list.get(i).getRoom_type(), rooms_list.get(i).getRoom_number(), rooms_list.get(i).getRoom_name(), rooms_list.get(i).getRoom_symbol(), rooms_list.get(i).getRoom_tenant()));
}
}
RecyclerView myrv= findViewById(R.id.recycleview_item_list);
Adapter_display_rooms myAdapter= new Adapter_display_rooms(this,house_rooms);
myrv.setLayoutManager(new LinearLayoutManager(this, OrientationHelper.HORIZONTAL,false));
myrv.setItemAnimator(new DefaultItemAnimator());
myrv.setAdapter(myAdapter);
}
Adapter_display_rooms
public class Adapter_display_rooms extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
//Declare context and the class with our list
private static Context mContext;
int total_types;
private static ArrayList<Decode_rooms> rooms_list; //Our data class... this one contains the get and set methods to decode the data for us
//Available rooms layout class
public static class ActualRoomsViewHolder extends RecyclerView.ViewHolder {
CardView cardview;
TextView txtType;
ImageView image;
public ActualRoomsViewHolder(View itemView) {
super(itemView);
this.cardview= itemView.findViewById(R.id.layout_available_rooms);
this.image = itemView.findViewById(R.id.room_icon);
this.txtType = itemView.findViewById(R.id.room_name);
}
}
//New Line layout class
public static class NewLineViewHolder extends RecyclerView.ViewHolder {
LinearLayout linearlayout;
public NewLineViewHolder(View itemView) {
super(itemView);
this.linearlayout = itemView.findViewById(R.id.layout_newline);
}
}
//New Line layout class
public static class AddSpaceViewHolder extends RecyclerView.ViewHolder {
TextView txtType;
public AddSpaceViewHolder(View itemView) {
super(itemView);
this.txtType = itemView.findViewById(R.id.add_space);
}
}
//END OF VIEWHOLDER CLASSES
//The Class Constructor
public Adapter_display_rooms(Context mContext, ArrayList<Decode_rooms> rooms_list) {
this.mContext = mContext;
this.rooms_list = rooms_list;
total_types=rooms_list.size();
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view;
switch (viewType) {
case Decode_rooms.AVAILABLE_ROOMS:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_rooms_layout_listview_rooms, parent, false);
return new ActualRoomsViewHolder(view);
case Decode_rooms.BOOKED_ROOMS:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_rooms_layout_listview_rooms, parent, false);
return new ActualRoomsViewHolder(view);
case Decode_rooms.NEW_LINE:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_rooms_layout_listview_newline, parent, false);
return new NewLineViewHolder(view);
case Decode_rooms.SPACE:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_rooms_layout_listview_space, parent, false);
return new AddSpaceViewHolder(view);
}
return null;
}
@Override
public int getItemViewType(int position) {
switch (rooms_list.get(position).type) {
case 0:
return Decode_rooms.AVAILABLE_ROOMS;
case 1:
return Decode_rooms.BOOKED_ROOMS;
case 2:
return Decode_rooms.NEW_LINE;
case 3:
return Decode_rooms.SPACE;
default:
return -1;
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
final Decode_rooms object = rooms_list.get(position);
if (object != null) {
switch (object.type) {
case Decode_rooms.AVAILABLE_ROOMS:
((ActualRoomsViewHolder) holder).image.setImageResource(R.drawable.ic_seats_book);
((ActualRoomsViewHolder) holder).txtType.setText(object.getRoom_number());
((ActualRoomsViewHolder) holder).cardview.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(mContext, Available_room_details.class);
intent.putExtra("room_number",object.getRoom_number());
intent.putExtra("room_name",object.getRoom_name());
intent.putExtra("room_type",object.getRoom_type());
mContext.startActivity(intent);
}
});
((ActualRoomsViewHolder) holder).cardview.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
//Creating the instance of PopupMenu
PopupMenu popup = new PopupMenu(mContext,v);
//Inflating the Popup using xml file
popup.getMenuInflater()
.inflate(R.menu.menu_available_room_options, popup.getMenu());
//registering popup with OnMenuItemClickListener
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
Toast.makeText(
mContext,
"You Clicked : " + item.getTitle(),
Toast.LENGTH_SHORT
).show();
return true;
}
});
popup.show(); //showing popup menu
return false;
}
});
break;
case Decode_rooms.BOOKED_ROOMS:
((ActualRoomsViewHolder) holder).image.setImageResource(R.drawable.ic_seats_booked);
((ActualRoomsViewHolder) holder).txtType.setText(object.getRoom_number());
((ActualRoomsViewHolder) holder).cardview.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(mContext, Booked_room_details.class);
intent.putExtra("room_number",object.getRoom_number());
intent.putExtra("room_name",object.getRoom_name());
intent.putExtra("room_type",object.getRoom_type());
mContext.startActivity(intent);
}
});
((ActualRoomsViewHolder) holder).cardview.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
//Creating the instance of PopupMenu
PopupMenu popup = new PopupMenu(mContext,v);
//Inflating the Popup using xml file
popup.getMenuInflater()
.inflate(R.menu.menu_booked_room_options, popup.getMenu());
//registering popup with OnMenuItemClickListener
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
Toast.makeText(
mContext,
"You Clicked : " + item.getTitle(),
Toast.LENGTH_SHORT
).show();
return true;
}
});
popup.show(); //showing popup menu
return false;
}
});
break;
case Decode_rooms.NEW_LINE:
break;
case Decode_rooms.SPACE:
((AddSpaceViewHolder) holder).txtType.setText("Space "+object.getRoom_number());
break;
default:
((ActualRoomsViewHolder) holder).txtType.setText("Default "+object.getRoom_number());
break;
}
}
}
@Override
public int getItemCount() {
return rooms_list.size();
}
解码房间java
public class Decode_rooms {
//Aid the custom adapter in inflating different types of layouts
public static final int AVAILABLE_ROOMS = 0;
public static final int BOOKED_ROOMS = 1;
public static final int NEW_LINE = 2;
public static final int SPACE = 3;
String room_type,room_number,room_name,room_symbol,room_tenant;
public int type; //This variable will hold the type of data i.e THE ROOM SYMBOL .. It'll tell the adapter the layout to inflate
public Decode_rooms(int type,String room_type, String room_number, String room_name, String room_symbol, String room_tenant) {
this.type = type;
this.room_type = room_type;
this.room_number = room_number;
this.room_name = room_name;
this.room_symbol = room_symbol;
this.room_tenant = room_tenant;
}
//The setter methods
public void setType(int type) {
this.type = type;
}
public void setRoom_type(String room_type) {
this.room_type = room_type;
}
public void setRoom_number(String room_number) {
this.room_number = room_number;
}
public void setRoom_name(String room_name) {
this.room_name = room_name;
}
public void setRoom_symbol(String room_symbol) {
this.room_symbol = room_symbol;
}
public void setRoom_tenant(String room_tenant) {
this.room_tenant = room_tenant;
}
//The getter methods
public int getType() {
return type;
}
public String getRoom_type() {
return room_type;
}
public String getRoom_number() {
return room_number;
}
public String getRoom_name() {
return room_name;
}
public String getRoom_symbol() {
return room_symbol;
}
public String getRoom_tenant() {
return room_tenant;
}
}
父XML
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/recyclerview" />
</android.support.design.widget.CoordinatorLayout>
回收站视图
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycleview_item_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:background="@color/blue"
android:elevation="2dp"
android:layout_margin="10dp"/>
</android.support.constraint.ConstraintLayout>
“卡片”视图/房间的单个行项
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_available_rooms"
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground"
android:layout_width="@dimen/room_width"
android:layout_height="@dimen/room_height"
android:layout_margin="@dimen/roomGaping"
android:orientation="horizontal"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:cardCornerRadius="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/room_icon"
android:background="@color/black"
android:layout_width="match_parent"
android:layout_height="@dimen/room_width"
android:scaleType="centerCrop"/>
<TextView
android:id="@+id/room_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="#2d2d2d"
android:textSize="13sp"
android:text="Room Name"/>
</LinearLayout>
</android.support.v7.widget.CardView>
新的行布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_newline"
android:layout_width="match_parent"
android:layout_height="@dimen/room_height"
android:background="@color/grey_background"
android:orientation="horizontal">
</LinearLayout>
答案 0 :(得分:0)
您想要的是GridLayoutManager,其列数为所有行的最大长度。 (您可以将其设置为所有输入的长度的lcm)
遍历每个输入并根据需要设置列范围。让我知道是否有任何不清楚的地方。
编辑:添加示例代码
TestActivity.java
public class TestActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
mRecyclerView = findViewById(R.id.recycler_view);
final String[] inputs = new String[3];
inputs[0] = "AAA__AB/";
inputs[1] = "_AAAAAA/";
inputs[2] = "_ABB/";
final StringBuilder sb = new StringBuilder();
for(int i =0; i < inputs.length; i++) {
sb.append(inputs[i]);
}
String[] modifiedInput = sb.toString().split("/");
final int lcm = getLcm(modifiedInput);
GridLayoutManager manager = new GridLayoutManager(getApplicationContext(), lcm);
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int i) {
if(sb.toString().charAt(i) == '/') {
return lcm;
}
else {
int index = 0;
for(int j = 0; j< inputs.length; j++) {
if(i < index+inputs[j].length()) {
if(inputs[j].contains("/")) return lcm / (inputs[j].length()-1);
else return lcm / inputs[j].length();
}
else {
index += inputs[j].length();
}
}
throw new IllegalStateException("Wrong index");
}
}
});
List<String> inputDataList = new ArrayList<>();
String flatInputData = sb.toString();
for(int i = 0; i < flatInputData.length(); i++) {
inputDataList.add(String.valueOf(flatInputData.charAt(i)));
}
Adapter adapter = new Adapter(inputDataList);
mRecyclerView.setAdapter(adapter);
mRecyclerView.setLayoutManager(manager);
}
private int getLcm(String[] modifiedInputs) {
int lcm = modifiedInputs[0].length();
for(int i = 1; i< modifiedInputs.length; i++) {
lcm = lcm(lcm, modifiedInputs[i].length());
}
return lcm;
}
public static int lcm(int a, int b) {
return a/gcd(a,b) * b;
}
public static int gcd(int a, int b){
if (a<b) return gcd(b,a);
if (a%b==0) return b;
else return gcd(b, a%b);
}
}
Adapter.java
public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
public List<String> data;
public Adapter(List<String> data) {
this.data = data;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
return new ViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(android.R.layout.simple_list_item_1, viewGroup, false));
}
@Override
public void onBindViewHolder(@NonNull ViewHolder viewHolder, int i) {
String text = data.get(i);
if(!text.equals("/"))
viewHolder.textView.setText(text);
}
@Override
public int getItemCount() {
if(data == null) {
return 0;
}
else {
return data.size();
}
}
class ViewHolder extends RecyclerView.ViewHolder {
TextView textView;
public ViewHolder(@NonNull View itemView) {
super(itemView);
textView = itemView.findViewById(android.R.id.text1);
}
}
}