Yeni bir kullanıcı olduğum için yorum yapamıyorum, ancak yapmaya çalıştığınız NASIL'ın tersine, NE yapmaya çalıştığınızı açıklayabilir misiniz? Sıklıkla, bunun kodlamanın aksine bir tasarım sorunu olduğunu göreceksiniz. Özellikle farklı bir platformdan geliyorsanız (örnek, iOS). Tecrübenizden, iş gereksinimlerinizin ışığında düzeninizi düzgün bir şekilde tasarlamanız durumunda, Android'deki ölçüm ve manuel düzenlerin çoğunlukla gereksiz olduğunu buldum.
DÜZENLEME: Daha önce de belirttiğim gibi bu, bazı tasarım kararları kullanılarak çözülebilir. Düğümler/Liste örneğinizi kullanacağım (bunun gerçek kullanım durumunuz olduğunu umuyorum, ancak çözüm daha genel bir sorun için genişletilebilir).
Bir liste yeterli değil ikidir:
Bu yüzden bir forumda bir açıklama ve yorumunuza yanıt olarak Listesi'nde olarak Üstbilgi düşünecek olursak, aşağıda varsayımı yapabilirsiniz. Listedeki her öğe bir başlık (yorum) veya bir liste öğesi (cevap) olabilir. Her cevap bir yorumdur, ancak tüm yorumlar cevap değildir.
Öğe n'de bunun bir açıklama veya yanıt olup olmadığını (ör. Listenizdeki bir başlık veya öğe) biliyorum.
- Öğe n'de boolean üyeliğim var Vazgeçilmez (varsayılan yanlış; Görünüm.GONE).
Şimdi, aşağıdaki bileşenleri kullanabilirsiniz:
- biri genişletilmiş adaptör sınıfı
- İki Düzen XMLs: Cevabınız için Yorum için One, bir. Sınırsız yorumunuz olabilir ve her yorumun sınırsız yanıtı olabilir. Her ikisi de ihtiyaçlarınızı karşılar.
- Listenizi göstermek/gizlemek için OnItemClickListener'ı uygulayan parça veya etkinlik kapsayıcı sınıfınız.
Hadi bir kod bakalım mı?
İlk olarak, XML dosyaları:
Yorum satır (sizin başlık)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/overall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true">
<TextView
android:id="@+id/comment_row_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
Şimdi cevap sırası (listenizde unsuru)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/overall"
android:layout_width="match_parent"
android:layout_height="wrap_content"> <!-- this is important -->
<TextView
android:id="@+id/reply_row_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"/> <!-- important -->
</RelativeLayout>
Tamam, hemen şimdi adaptör sınıf
public class CommentsListAdapter extends BaseAdapter implements OnClickListener
{
public static String TAG = "CommentsListAdapter";
private final int NORMAL_COMMENT_TYPE = 0;
private final int REPLY_COMMENT_TYPE = 1;
private Context context = null;
private List<Comment> commentEntries = null;
private LayoutInflater inflater = null;
//All replies are comments, but not all comments are replies. The commentsList includes all your data. (Remember that the refresh method allows you to add items to the list at runtime.
public CommentsListAdapter(Context context, List<Comment> commentsList)
{
super();
this.context = context;
this.inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.commentEntries = commentsList;
}
//For our first XML layout file
public static class CommentViewHolder
{
public RelativeLayout overall;
public TextView label;
}
//For our second XML
public static class ReplyViewHolder
{
public RelativeView replyOverall;
public TextView replyLabel;
}
@Override
public int getViewTypeCount()
{
return 2; //Important. We have two views, Comment and reply.
}
//Change the following method to determine if the current item is a header or a list item.
@Override
public int getItemViewType(int position)
{
int type = -1;
if(commentEntries.get(position).getParentKey() == null)
type = NORMAL_COMMENT_TYPE;
else if(commentEntries.get(position).getParentKey() == 0L)
type = NORMAL_COMMENT_TYPE;
else
type = REPLY_COMMENT_TYPE;
return type;
}
@Override
public int getCount()
{
return this.commentEntries.size(); //all data
}
@Override
public Object getItem(int position)
{
return this.commentEntries.get(position);
}
@Override
public long getItemId(int position)
{
return this.commentEntries.indexOf(this.commentEntries.get(position));
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
CommentViewHolder holder = null;
ReplyViewHolder replyHolder = null;
int type = getItemViewType(position);
if(convertView == null)
{
if(type == NORMAL_COMMENT_TYPE)
{
convertView = inflater.inflate(R.layout.row_comment_entry, null);
holder = new CommentViewHolder();
holder.label =(TextView)convertView.findViewById(R.id.comment_row_label);
convertView.setTag(holder);
}
else if(type == REPLY_COMMENT_TYPE)
{
convertView = inflater.inflate(R.layout.row_comment_reply_entry, null);
replyHolder = new ReplyViewHolder();
replyHolder.replyLable = (TextView)convertView.findViewById(R.id.reply_row_label);
convertView.setTag(replyHolder);
}
}
else
{
if(type == NORMAL_COMMENT_TYPE)
{
holder = (CommentViewHolder)convertView.getTag();
}
else if(type == REPLY_COMMENT_TYPE)
{
replyHolder = (ReplyViewHolder)convertView.getTag();
}
}
//Now, set the values of your labels
if(type == NORMAL_COMMENT_TYPE)
{
holder.label.setTag((Integer)position); //Important for onClick handling
//your data model object
Comment entry = (Comment)getItem(position);
holder.label.setText(entry.getLabel());
}
else if(type == REPLY_COMMENT_TYPE)
{
replyHolder = (ReplyViewHolder)convertView.getTag(); //if you want to implement onClick for list items.
//Or another data model if you decide to use multiple Lists
Comment entry = (Comment)getItem(position);
replyHolder.replyLabel.setText(entry.getLabel()));
//This is the key
if(entry.getVisible() == true)
replyHolder.replyLabel.setVisibility(View.VISIBLE);
else
replyHolder.replyLabel.setVisibility(View.GONE);
}
return convertView;
}
//You can use this method to add items to your list. Remember that if you are using two data models, then you will have to send the correct model list here and create another refresh method for the other list.
public void refresh(List<Comment> commentsList)
{
try
{
this.commentEntries = commentsList;
notifyDataSetChanged();
}
catch(Exception e)
{
e.printStackTrace();
Log.d(TAG, "::Error refreshing comments list.");
}
}
//Utility method to show/hide your list items
public void changeVisibility(int position)
{
if(this.commentEntries == null || this.commentEntries.size() == 0)
return;
Comment parent = (Comment)getItem(position);
for(Comment entry : this.commentEntries)
{
if(entry.getParent().isEqual(parent))
entry.setVisible(!entry.getVisible()); //if it's shown, hide it. Show it otherwise.
}
notifyDataSetChanged(); //redraw
}
}
Tamam harika, şimdi gizli çocuklara sahip başlıkların bir listesini görüyoruz (unutmayın, çocukların 'görünmesine' varsayılan görünürlüklerini ayarladık). İstediklerimizi değil, hadi bunu düzeltelim.
Kapsayıcınız sınıfı (fragman veya aktivite) Eğer
<!-- the @null divider means transparent -->
<ListView
android:id="@+id/comments_entries_list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:divider="@null"
android:dividerHeight="5dp" />
aşağıdaki XML tanım olacaktır Ve onCreateView Şimdi
private ListView commentsListView = null;
private List<Comment>comments = null;
private static CommentsListAdapter adapter = null;
....
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
...
//comments list can be null here, and you can use adapter.refresh(data) to set the data
adapter = new CommentsListAdapter(getActivity(), comments);
this.commentsListView.setAdapter(adapter);
this.commentsListView.setOnClickListener(this); //to show your list
}
listenizi göstermek için aşağıdaki OnItemClickListener uygulamak ve olacak zaman sizi Bir öğe c varsa, şimdi bir başlık tıklatın. yaladı ve bu öğe bir ebeveyne sahip (örn. liste öğesi), mevcut durumuna göre gösterilecek/gizlenecektir. kodu hakkında
Bazı yorumlar: Ben kullanışlı bir dev ortamı yok gibi
Ben WordPad bu yazdım. Derleme hataları için özür dilerim.
Bu kod en iyi duruma getirilebilir: Çok büyük bir veri kümeniz varsa, bu kod, değişikliklerin tamamınınVisibility() öğesinin her çağrısında yeniden çizildiğinden yavaş olur. İki listeyi (başlıklar için bir, liste öğeleri için bir tane) ve yalnızca liste öğeleri üzerinde sorgulayabileceğiniz changeVisibility içinde tutabilirsiniz.
Bu tasarım fikrini, bazı tasarım kararlarının hayatınızı çok daha kolaylaştıracağını düşünüyorum. Örneğin, liste öğeleriniz aslında bir etiket listesiyse, özel bir XML dosyanız (başlığınız için) ve bunun içinde View.GONE olarak ayarlayabileceğiniz bir ListView görünümü olabilir. Bu, diğer tüm görüşleri, orada bile olmadığını ve düzeninizin düzgün çalışacağını iddia eder.
Bu yardımcı olur umarım.
Buna nasıl yaklaşacağınız konusunda hiçbir fikrim yok. Şahsen, ben RecyclerView' kapalı çalışırdı. Orada, çocukları dışarıda bırakma çalışması, özel, takılabilir bir yönetici sınıfı tarafından ele alınmaktadır. Daha net bir API var ve problemi nasıl ele alacağınızı görmek için zaten kullanabileceğiniz üçüncü parti yöneticileri var ('recyclerview-v7' içinde üç tane nakliye ile birlikte). – CommonsWare