I made a custom view for my ListView My Custom View extends LinearLayout, It acts as an expandable Item for a normal ListView So the bug I am getting now is really weird, So I have my ListView attributes set to
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
So the height is at wrap_content lets take a note of that, as that will help us understand the issue.
So this is the video of how my ListVIew looks. The first Expandable Item is visible but the others don't fill the screen, I am pretty confident this is because of wrap_content but as soon as I expand one of the item it fill the whole screen. How can I resolve this? My guess is It's because the ListView isn't updating the other items? this is my CustomView code
import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.drawable.ColorDrawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import java.util.ArrayList;
import java.util.List;
public class ExpandableInnerListView extends LinearLayout {
private ListAdapter adapter;
private DataChangeObserver dataChangeObserver;
private View mainView;
private List<View> reusableViews = new ArrayList<>();
private boolean viewsHidden = true;
int mDividerHeight = 1;
public ExpandableInnerListView(Context context) {
this(context, null);
}
public ExpandableInnerListView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ExpandableInnerListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setOrientation(VERTICAL);
}
public void setAdapter(ListAdapter adapter) {
if (this.adapter != null && dataChangeObserver != null) {
this.adapter.unregisterDataSetObserver(dataChangeObserver);
}
this.adapter = adapter;
}
public void setMainView(View mainView) {
this.mainView = mainView;
}
public void toggle() {
viewsHidden = !viewsHidden;
dataChangeObserver.onInvalidated();
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (adapter != null) {
dataChangeObserver = new DataChangeObserver();
adapter.registerDataSetObserver(dataChangeObserver);
setupView();
}
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (adapter != null && dataChangeObserver != null) {
adapter.unregisterDataSetObserver(dataChangeObserver);
dataChangeObserver = null;
}
}
private void setupView() {
this.removeAllViews();
setupMainLayout();
setupInnerView();
}
public void setupMainLayout() {
if (mainView == null) {
throw new NullPointerException("Main View cannot be null!");
}
addView(mainView);
}
public void setupInnerView() {
if (viewsHidden) return;
int reusableCount = reusableViews.size();
int count = adapter.getCount();
for (int i = 0; i < count; i++) {
View converView = null;
if (i < reusableCount) {
converView = reusableViews.get(i);
}
View view = adapter.getView(i, converView, this);
if (i >= reusableCount) {
reusableViews.add(view);
}
if(mDividerHeight > 0) {
View divider = new View(getContext());
divider.setBackground(new ColorDrawable(0xFFCCCCCC));
LinearLayout.LayoutParams dividerLayoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, mDividerHeight);
divider.setLayoutParams(dividerLayoutParams);
addView(divider);
}
addView(view);
}
}
private class DataChangeObserver extends DataSetObserver {
#Override
public void onChanged() {
super.onChanged();
setupView();
}
#Override
public void onInvalidated() {
super.onInvalidated();
setupView();
}
}
}
and this is my whole Fragment View XML
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff">
<include
android:id="#+id/back_button_container"
layout="#layout/kik_back_button" />
<FrameLayout
android:id="#+id/topbar"
android:layout_width="match_parent"
android:layout_height="#dimen/native_topbar_height"
android:layout_alignParentTop="true"
android:layout_toEndOf="#id/back_button_container"
android:layout_toRightOf="#id/back_button_container" />
<include
android:id="#+id/nav_bar_shadow"
layout="#layout/navbar_underline"
android:layout_width="fill_parent"
android:layout_height="#dimen/navbar_underline_height"
android:layout_below="#id/topbar" />
<EditText
android:id="#android:id/edit"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_below="#+id/topbar"
android:layout_centerHorizontal="true"
android:textSize="18sp"
android:layout_marginEnd="15dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginStart="15dp"
android:layout_marginTop="15dp"
android:drawablePadding="15dp"
android:hint="Search Settings"
android:inputType="textNoSuggestions"
android:maxLines="1"
android:paddingEnd="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingStart="16dp"
android:textStyle="normal"
android:typeface="sans" />
<ImageView
android:id="#android:id/icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_alignEnd="#android:id/edit"
android:layout_alignRight="#android:id/edit"
android:layout_alignTop="#android:id/edit"
android:layout_marginEnd="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="12dp"
android:src="#drawable/delete_gray"
android:visibility="gone" />
<View
android:id="#+id/top_divider"
android:layout_width="match_parent"
android:layout_height="1.0px"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="#android:id/edit"
android:layout_marginTop="15dp"
android:background="#color/list_divider_color" />
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="#+id/top_divider"
android:divider="#null"
android:dividerHeight="0dp" />
<View
android:id="#+id/bottom_divider"
android:layout_width="match_parent"
android:layout_below="#android:id/list"
android:layout_height="1.0px"
android:background="#color/list_divider_color" />
<TextView
android:id="#android:id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="No Settings Found"
android:textSize="19.0sp"
android:visibility="gone" />
</RelativeLayout>
Would be really generous if someone can spot where the error happens and how to resolve it, and along side if any other error can happen at certain cases.
Look's like the issue was very minor. I ha to reset the view when I set the mainView
public void setMainView(View mainView) {
this.mainView = mainView;
setupView();
}
Try adapter.notifyDataSetChanged() when new list is updated.
Related
I am working on a student tracker app and I am trying to display dynamic buttons that get created under each of my students. I will paste an image below of what I hope for it to look like.
At the moment, I am hardcoding the buttons for the first image. I am getting the picture of the student and their name from my firbase db. Now my questions is how can I generate the checkBox for each of the student's and make sure it's directly under their picture and name like above.
In my mind, I am thinking the algorithm would be something like
Loop through my Students ArrayList
Generate the checkBox for each student
Place them onto my recyclerView.
I will paste relevant code down below.
daily_grading.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="match_parent"
tools:context=".DailyGrading">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="409dp"
android:layout_height="729dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<CheckBox
android:id="#+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="PASS"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="#+id/recyclerView"
app:layout_constraintHorizontal_bias="0.046"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.499" />
<CheckBox
android:id="#+id/checkBox2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="FAIL"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.261"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.499" />
</androidx.constraintlayout.widget.ConstraintLayout>
student_item.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">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:foreground="?android:attr/selectableItemBackground"
app:cardElevation="2dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</androidx.cardview.widget.CardView>
<RelativeLayout
android:id="#+id/relativeLayout2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="52dp">
<ImageView
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginTop="50dp"
android:paddingTop="20dp"
android:scaleType="centerCrop" />
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/imageView"
android:layout_margin="10dp"
android:textSize="16sp" />
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
DailyGrading.class
public class DailyGrading extends AppCompatActivity{
RecyclerView recyclerView;
Button addStudent;
private DatabaseReference myRef;
public ArrayList<Students> students;
private RecyclerAdapter recyclerAdapter;
private Button orderStudents;
private EditText mEditTextAge;
private EditText mEditTextAssignment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.daily_grading);
recyclerView = findViewById(R.id.recyclerView);
addStudent = findViewById(R.id.addStudentButton);
mEditTextAge = findViewById(R.id.EditTextAge);
mEditTextAssignment = findViewById(R.id.EditTextAssignment);
recyclerView.setLayoutManager(new GridLayoutManager(this, 2));
recyclerView.setHasFixedSize(true);
myRef = FirebaseDatabase.getInstance().getReference();
students = new ArrayList<>();
ClearAll();
GetDataFromFirebase();
}
// fetches images and name from firebase
private void GetDataFromFirebase() {
Query query = myRef.child("student");
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
ClearAll();
for(DataSnapshot snapshot: dataSnapshot.getChildren()) {
Students student = new Students();
if (snapshot.child("url").getValue() == null) {
student.setImageUrl(snapshot.child("imageUrl").getValue().toString());
}
else {
student.setImageUrl(snapshot.child("url").getValue().toString());
}
student.setName(snapshot.child("name").getValue().toString());
students.add(student);
}
recyclerAdapter = new RecyclerAdapter(getApplicationContext(), students);
recyclerView.setAdapter(recyclerAdapter);
recyclerAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
// will clear recyclerAdapter
private void ClearAll() {
if (students != null) {
students.clear();
if(recyclerAdapter != null) {
recyclerAdapter.notifyDataSetChanged();
}
}
students = new ArrayList<>();
}
// method to generate checkboxes dynamically
public void generateButtonsDynamically() {
for(int i = 0; i < students.size(); i++){
}
}
RecyclerAdapter.class
package com.example.studenttracker;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
private OnItemClickListener mListener;
public interface OnItemClickListener {
void onItemClick(int position);
}
public void setOnItemClickListener(OnItemClickListener listener) {
mListener = listener;
}
private static final String Tag = "RecyclerView";
private Context mContext;
private ArrayList<Students> studentsArrayList;
public RecyclerAdapter(Context mContext, ArrayList<Students> studentsArrayList) {
this.mContext = mContext;
this.studentsArrayList = studentsArrayList;
}
#NonNull
#Override
public RecyclerAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.student_item,parent,false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
//TextView
holder.textView.setText(studentsArrayList.get(position).getName());
Glide.with(mContext).load(studentsArrayList.get(position).getImageUrl()).into(holder.imageView);
}
#Override
public int getItemCount() {
return studentsArrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
TextView textView;
public ViewHolder(#NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.imageView);
textView = itemView.findViewById(R.id.textView);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mListener != null) {
int position = getAdapterPosition();
}
}
});
}
}
}
Change the code of your student_item.xml to this :
<?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">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:foreground="?android:attr/selectableItemBackground"
app:cardElevation="2dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</androidx.cardview.widget.CardView>
<RelativeLayout
android:id="#+id/relativeLayout2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="52dp">
<ImageView
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginTop="50dp"
android:paddingTop="20dp"
android:scaleType="centerCrop" />
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/imageView"
android:layout_margin="10dp"
android:textSize="16sp" />
<CheckBox
android:id="#+id/passc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/textView"
android:text="pass" />
<CheckBox
android:id="#+id/failc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/textView"
android:layout_toRightOf="#+id/passc"
android:text="fail" />
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
and control the behaviour of the checkboxes from RecyclerAdapter.class
Try this:
<CheckBox
android:id="#+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="PASS"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="#+id/recyclerView"
app:layout_constraintHorizontal_bias="0.046"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.499"
android:visibility="gone" />
<CheckBox
android:id="#+id/checkBox2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="FAIL"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.261"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.499"
android:visibility="gone" />
and
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
//TextView
holder.textView.setText(studentsArrayList.get(position).getName());
Glide.with(mContext).load(studentsArrayList.get(position).getImageUrl()).into(holder.imageView);
if (studentsArrayList.get(position).displayButtons()) { //check if you need the buttons or not
holder.checkBox.setVisibility(View.VISIBLE);
holder.checkBox2.setVisibility(View.VISIBLE);
} else {
holder.checkBox.setVisibility(View.GONE);
holder.checkBox2.setVisibility(View.GONE);
}
}
Step 1: Add the recyclerview in one xml file.
Step 2: The elements that must be inside a reecyclerview in another xml file (Here add a button that you need).
Step 3: Link these two xml files.
Thus after each insertion dynamically a button will be added.
Hope you will find the solution.
Add Check Boxes in student_item.xml instead daily_grading.xml
here console show ClassCastException but not show error line Number? Any one help me here?
if any one has idea about to find exact errorline number then suggest me plz?
here xml where i used ListView.
i have tried
1) removed Params which set by programatically
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:fitsSystemWindows="true"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/adlayout"
android:background="#color/md_white_0">
<com.os.folder.and.file.locker.files.widget.BGridView
android:id="#+id/hide_view_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:numColumns="3"
android:stretchMode="columnWidth" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/hide_btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="16dp"
android:layout_marginBottom="16dp"
android:background="#color/file_add"
android:onClick="onClick"
android:src="#drawable/ic_action_new" />
<LinearLayout
android:id="#+id/file_bottom_layout_tips"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/unrecord" />
<TextView
android:id="#+id/file_bottom_txt_tips"
android:layout_width="match_parent"
android:layout_height="64dp"
android:gravity="center"
android:text=""
android:textColor="#color/md_black_2"
android:textSize="14sp" />
</LinearLayout>
</RelativeLayout>
<LinearLayout
android:id="#+id/pic_hide_btn_edit"
android:layout_width="match_parent"
android:layout_height="#dimen/title_height"
android:layout_above="#+id/adlayout"
android:layout_alignParentRight="true"
android:background="#color/md_black_1"
android:visibility="visible"
android:weightSum="4">
<LinearLayout
android:id="#+id/pic_hide_img_cancel"
android:layout_width="0dp"
android:layout_height="#dimen/title_height"
android:layout_weight="1"
android:gravity="center"
android:onClick="onClick">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/close" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="#dimen/title_height"
android:layout_weight="1"
android:gravity="center">
<CheckBox
android:id="#+id/item_file_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:button="#drawable/checkbox_selector" />
</LinearLayout>
<LinearLayout
android:id="#+id/pic_hide_img_recovery"
android:layout_width="0dp"
android:layout_height="#dimen/title_height"
android:layout_weight="1"
android:gravity="center"
android:onClick="onClick">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/unlock" />
</LinearLayout>
<LinearLayout
android:id="#+id/pic_hide_img_del"
android:layout_width="0dp"
android:layout_height="#dimen/title_height"
android:layout_weight="1"
android:gravity="center"
android:onClick="onClick">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/delete" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="#+id/adlayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:orientation="horizontal" />
</RelativeLayout>
here Java file, i have implemented from here listView
package com.os.folder.and.file.locker.files.activity;
import android.content.Intent;
import com.os.folder.and.file.locker.R;
import com.os.folder.and.file.locker.data.GroupImage;
import com.os.folder.and.file.locker.data.HideImage;
import com.os.folder.and.file.locker.files.adapter.BaseHideAdapter.OnListener;
import com.os.folder.and.file.locker.files.adapter.PicHideAdapter;
import com.os.folder.and.file.locker.files.entity.HideImageExt;
import com.os.folder.and.file.locker.files.widget.BGridView;
import com.os.folder.and.file.locker.service.GroupImageService;
import com.os.folder.and.file.locker.service.ImageService;
import java.util.List;
public class PicHideActivity extends BaseHideActivity implements OnListener {
protected static final String TAG = "PicHideActivity";
private int itemSize;
protected GroupImageService mGroupImageService;
protected ImageService mImageService;
protected void initUI() {
setContentView((int) R.layout.activity_file_hide_group);
setUI();
setTitleRID(R.string.pic_preview_title, R.string.pic_preview_title_edit);
setGridView();
this.mFile_bottom_txt_tips.setText(R.string.file_hide_txt_add_pic);
this.rid_string_type = R.string.pic_preview;
}
private void setGridView() {
this.itemSize = ((BGridView) findViewById(R.id.hide_view_list)).setGridView(getWindowManager(), 4, 4);
}
void initAdapter() {
BGridView adapterView = findViewById(R.id.hide_view_list);
this.mGroupImageService = new GroupImageService(this);
this.mImageService = new ImageService(this);
this.mBaseHideAdapter = new PicHideAdapter(this, this, this.itemSize);
adapterView.setAdapter(this.mBaseHideAdapter);
}
boolean delFolder() {
return false;
}
void addFolder() {}
public void addFile() {
Intent intent = new Intent(this, PicPreViewActivity.class);
intent.putExtra("beyondGroupId", this.mBaseHideAdapter.getGruopID());
startActivity(intent);
}
protected void recoveryFiles() {
for (Object imageModelView: this.mBaseHideAdapter.getHitFiles()) {
this.mImageService.unHideImage((HideImageExt) imageModelView);
}
}
protected void delFiles() {
for (Object hideImageExt: this.mBaseHideAdapter.getHitFiles()) {
this.mImageService.deleteAudioByPath((HideImageExt)
hideImageExt);
}
}
protected void openHolder(int groupID) {
List < GroupImage > groupList = this.mGroupImageService.getGroupFiles(groupID);
List < HideImage > list = this.mImageService.getHideImages(groupID);
this.mBaseHideAdapter.setHitFiles(groupList, list, groupID);
setHasData(groupList, list);
}
public void openHolder(Object object) {
GroupImage data = (GroupImage) object;
int groupID = -1;
if (data != null) {
groupID = data.getId().intValue();
}
openHolder(groupID);
}
}
and here is adapter code,
package com.os.folder.and.file.locker.files.adapter;
import android.content.Context;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
//import android.widget.AbsListView.LayoutParams;
import android.widget.ImageView;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.DisplayImageOptions.Builder;
import com.nostra13.universalimageloader.core.ImageLoader;
import
com.nostra13.universalimageloader.core.download.ImageDownloader.Scheme;
import com.os.folder.and.file.locker.R;
import com.os.folder.and.file.locker.data.GroupImage;
import com.os.folder.and.file.locker.data.HideImage;
import com.os.folder.and.file.locker.files.activity.PhotoPreViewActivity;
import com.os.folder.and.file.locker.files.entity.GroupImageExt;
import com.os.folder.and.file.locker.files.entity.HideImageExt;
import java.util.ArrayList;
import java.util.List;
public class PicHideAdapter extends BaseHideAdapter {
private static final String TAG = "PicHideAdapter";
protected ImageLoader imageLoader = ImageLoader.getInstance();
DisplayImageOptions options = new Builder().showStubImage(R.drawable.default_picture).showImageForEmptyUri((int) R.drawable.default_picture).showImageOnFail((int) R.drawable.default_picture).cacheInMemory(true).cacheOnDisc(true).build();
private ViewGroup.LayoutParams params;
class PicHolder {
Object mData;
ImageView mImg_pre_preview;
View mItem_file_ok;
View mItem_file_pic;
PicHolder() {}
}
public PicHideAdapter(Context context, OnListener onListern, int itemSize) {
super(context, onListern);
this.params = new ViewGroup.LayoutParams(itemSize, itemSize);
}
public void clear() {
super.clear();
if (this.imageLoader != null) {
this.imageLoader.stop();
this.imageLoader = null;
}
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = this.mInflater.inflate(R.layout.item_file_hide_pic, null);
PicHolder picHolder = new PicHolder();
picHolder.mItem_file_pic = convertView.findViewById(R.id.item_file_pic);
picHolder.mItem_file_ok = convertView.findViewById(R.id.item_file_ok);
picHolder.mImg_pre_preview = (ImageView)
convertView.findViewById(R.id.img_pre_preview);
convertView.setTag(picHolder);
// convertView.setLayoutParams(this.params);
}
initView(convertView, position);
return convertView;
}
protected void initView(View view, final int position) {
int i = 8;
final PicHolder fileHolder = (PicHolder) view.getTag();
fileHolder.mImg_pre_preview.setImageBitmap(null);
Object data = getItem(position);
fileHolder.mData = data;
if (data instanceof HideImageExt) {
final HideImageExt hideImageView = (HideImageExt) data;
this.imageLoader.displayImage(Scheme.THUMBNAIL.wrap(hideImageView.getNewPathUrl()), fileHolder.mImg_pre_preview, this.options);
if (this.edit) {
View view2 = fileHolder.mItem_file_ok;
if (hideImageView.isEnable()) {
i = 0;
}
view2.setVisibility(i);
view.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
boolean z;
int i = 0;
HideImageExt hideImageExt = hideImageView;
if (hideImageView.isEnable()) {
z = false;
} else {
z = true;
}
hideImageExt.setEnable(z);
View view = fileHolder.mItem_file_ok;
if (!hideImageView.isEnable()) {
i = 8;
}
view.setVisibility(i);
PicHideAdapter.this.updateSelect();
}
});
view.setOnLongClickListener(null);
return;
}
fileHolder.mItem_file_ok.setVisibility(8);
view.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent();
intent.setClass(PicHideAdapter.this.context, PhotoPreViewActivity.class);
intent.putParcelableArrayListExtra("list", (ArrayList)
PicHideAdapter.this.mList_HideFile);
intent.putExtra("id", position);
PicHideAdapter.this.context.startActivity(intent);
}
});
view.setOnLongClickListener(new OnLongClickListener() {
public boolean onLongClick(View v) {
PicHideAdapter.this.doVibrator(PicHideAdapter.this.context);
PicHideAdapter.this.mOnListern.onLongClick(hideImageView);
return false;
}
});
} else if (data instanceof GroupImageExt) {
final GroupImageExt groupImageView = (GroupImageExt) data;
fileHolder.mItem_file_ok.setVisibility(8);
fileHolder.mImg_pre_preview.setImageResource(R.drawable.folder);
view.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (PicHideAdapter.this.edit) {
PicHolder fileHolder = (PicHolder) v.getTag();
groupImageView.setEnable(!groupImageView.isEnable());
} else if (PicHideAdapter.this.mOnListern != null) {
PicHideAdapter.this.mOnListern.openHolder(groupImageView);
}
}
});
}
}
public void setHitFiles(List < ?>listGroup, List < ?>listFile, int groupID) {
this.mList_Group = GroupImageExt.transList((List < GroupImage > ) listGroup);
this.mList_HideFile = HideImageExt.transList((List < HideImage > ) listFile);
setGroup(groupID);
notifyDataSetChanged();
}
}
LayoutParams lp = new LayoutParams(-2, -2);
lp.setMargins(margin, margin, margin, margin);
setLayoutParams(lp);
resolved..by removing this param
Within my current Android application, I have a screen that displays an android.support.v4.app.DialogFragment.
This DialogFragment view contains the following UI components
HEADING
== Sub Heading
== NestedScrollView
==== RecyclerView
==== RadioGroup
==== Spinner
==== EditText
==== Action Buttons
The DialogFragment is configured to be Full Screen using Style as follows:-
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NO_TITLE, R.style.AppDialogTheme);
}
My dialog style is
<!-- Define your custom dialog theme here extending from base -->
<style name="AppDialogTheme" parent="Theme.AppCompat.Light.Dialog">
<!-- Define color properties as desired -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#000</item>
<item name="android:textColorHighlight">#color/background_url</item>
<item name="colorAccent">#color/dark_grey</item>
<item name="colorControlNormal">#color/colorPrimaryDark</item>
<!-- Define window properties as desired -->
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowBackground">#android:color/white</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowCloseOnTouchOutside">false</item>
</style>
The reason I employ a NestedScrollView is so that the View will work in both Portrait and Landscape mode.
I wish to limit the height of the RecyclerView
The closest I have got is using the layout below.
<?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="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/headline_literal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:padding="10dp"
android:text="Heading"
android:textSize="20sp"
android:textStyle="bold" />
<View
android:id="#+id/divider"
android:layout_width="fill_parent"
android:layout_height="2dp"
android:layout_marginTop="5dp"
android:background="#c0c0c0" />
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="5"
android:orientation="vertical">
<TextView
android:id="#+id/sub_headline_literal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="10dp"
android:text="Some long texts having a long size so that it takes multiple lines in the view to replicate the real-life app use case. This is important to have 3-4 lines this textview so that we can see if the views are being populated correctly. Hope this sentence is long enough to replicate the real-life scenario of this TextView content. Thank you."
android:textSize="16sp"
android:textStyle="normal" />
<android.support.v7.widget.RecyclerView
android:id="#+id/dummy_rv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_margin="10dp"
android:layout_marginStart="9dp"
android:layout_marginEnd="9dp"
android:layout_weight="1"
android:background="#drawable/rv_border"
android:fadingEdge="horizontal"
android:fadingEdgeLength="10dp"
android:padding="10dp"
android:requiresFadingEdge="vertical" />
<RadioGroup
android:id="#+id/myRadioGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="10dp"
android:checkedButton="#+id/sound">
<RadioButton
android:id="#+id/sound"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sound" />
<RadioButton
android:id="#+id/vibration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Vibration" />
<RadioButton
android:id="#+id/silent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Silent" />
</RadioGroup>
<EditText
android:id="#+id/notes"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Notes" />
<LinearLayout
android:id="#+id/buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp">
<TextView
android:id="#+id/cancel_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="Cancel" />
<TextView
android:id="#+id/submit_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="Submit" />
</LinearLayout>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</LinearLayout>
By using weightSum on the inner LinearLayout of the NestedScrollView I can limit the height of the Recyclerview. However the NestedScrollView height is far too large, with more than half its height being blank.
How can I limit the height of my RecyclerView and get NestedScrollView to wrap_content?
I've tried NestedScrollView with height wrap_content but this has no effect.
How can I achieve the desired UI? Thanks in advance!
Instead of having a NestedRecyclerView, I would like to suggest to have a header and a footer added to your RecyclerView which will nicely place the overall content as far as I have seen your layout. I want to provide you a link to my answer here where you can find how to add a footer and a header along with your RecyclerView.
Hence, I would like to suggest to create a view with headline_literal and the divider and use this as a header whereas the RadioGroup, EditText and the Button will be in the footer. Let me know if you face any problem with it.
I have tried to implement the behavior that you want by myself and let me know if the following implementation works for you. I have added this in Github as well.
Let us first declare an adapter for adding a header and a footer to the RecyclerView.
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
public class RecyclerViewWithHeaderFooterAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int FOOTER_VIEW = 1;
private static final int HEADER_VIEW = 2;
private ArrayList<String> data; // Take any list that matches your requirement.
private Context context;
// Define a constructor
public RecyclerViewWithHeaderFooterAdapter(Context context, ArrayList<String> data) {
this.context = context;
this.data = data;
}
// Define a ViewHolder for Header view
public class HeaderViewHolder extends ViewHolder {
public HeaderViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Do whatever you want on clicking the item
}
});
}
}
// Define a ViewHolder for Footer view
public class FooterViewHolder extends ViewHolder {
public FooterViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Do whatever you want on clicking the item
}
});
}
}
// Now define the ViewHolder for Normal list item
public class NormalViewHolder extends ViewHolder {
public NormalViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Do whatever you want on clicking the normal items
}
});
}
}
// And now in onCreateViewHolder, you have to pass the correct view
// while populating the list item.
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v;
if (viewType == FOOTER_VIEW) {
v = LayoutInflater.from(context).inflate(R.layout.list_item_footer, parent, false);
FooterViewHolder vh = new FooterViewHolder(v);
return vh;
} else if (viewType == HEADER_VIEW) {
v = LayoutInflater.from(context).inflate(R.layout.list_item_header, parent, false);
HeaderViewHolder vh = new HeaderViewHolder(v);
return vh;
}
// Otherwise populate normal views
v = LayoutInflater.from(context).inflate(R.layout.list_item_normal, parent, false);
NormalViewHolder vh = new NormalViewHolder(v);
return vh;
}
// Now bind the ViewHolder in onBindViewHolder
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
try {
if (holder instanceof NormalViewHolder) {
NormalViewHolder vh = (NormalViewHolder) holder;
vh.bindView(position);
} else if (holder instanceof FooterViewHolder) {
FooterViewHolder vh = (FooterViewHolder) holder;
} else if (holder instanceof HeaderViewHolder) {
HeaderViewHolder vh = (HeaderViewHolder) holder;
}
} catch (Exception e) {
e.printStackTrace();
}
}
// Now the critical part. You have return the exact item count of your list
// I've only one footer. So I returned data.size() + 1
// If you've multiple headers and footers, you've to return total count
// like, headers.size() + data.size() + footers.size()
#Override
public int getItemCount() {
if (data == null) {
return 0;
}
if (data.size() == 0) {
// Return 1 here to show nothing
return 1;
}
// Add extra view to show the header view
// Add another extra view to show the footer view
// So there are two extra views need to be populated
return data.size() + 2;
}
// Now define getItemViewType of your own.
#Override
public int getItemViewType(int position) {
if (position == 0) {
// This is where we'll add the header.
return HEADER_VIEW;
} else if (position == data.size() + 1) {
// This is where we'll add a footer.
return FOOTER_VIEW;
}
return super.getItemViewType(position);
}
// So you're done with adding a footer and its action on onClick.
// Now set the default ViewHolder for NormalViewHolder
public class ViewHolder extends RecyclerView.ViewHolder {
// Define elements of a row here
public ViewHolder(View itemView) {
super(itemView);
// Find view by ID and initialize here
}
public void bindView(int position) {
// bindView() method to implement actions
}
}
}
Now let us define the layouts one by one. Here is the list_item_normal.xml.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/normal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="This is a text to be displayed in each item in the RecyclerView"
android:textSize="16sp"
android:textStyle="normal" />
</LinearLayout>
And the list_item_footer.xml should look like the following.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="vertical">
<RadioGroup
android:id="#+id/myRadioGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="10dp"
android:checkedButton="#+id/sound">
<RadioButton
android:id="#+id/sound"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sound" />
<RadioButton
android:id="#+id/vibration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Vibration" />
<RadioButton
android:id="#+id/silent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Silent" />
</RadioGroup>
<EditText
android:id="#+id/notes"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Notes" />
<LinearLayout
android:id="#+id/buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp">
<TextView
android:id="#+id/cancel_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="Cancel" />
<TextView
android:id="#+id/submit_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="Submit" />
</LinearLayout>
</LinearLayout>
Finally, the list_item_header.xml should have the following.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/sub_headline_literal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="10dp"
android:text="Some long texts having a long size so that it takes multiple lines in the view to replicate the real-life app use case. This is important to have 3-4 lines this textview so that we can see if the views are being populated correctly. Hope this sentence is long enough to replicate the real-life scenario of this TextView content. Thank you."
android:textSize="16sp"
android:textStyle="normal" />
</LinearLayout>
Now you have divided the components of your original layout into parts. Hence the main layout should look like the following.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/headline_literal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:padding="10dp"
android:text="Heading"
android:textSize="20sp"
android:textStyle="bold" />
<View
android:id="#+id/divider"
android:layout_width="fill_parent"
android:layout_height="2dp"
android:layout_marginTop="5dp"
android:background="#c0c0c0" />
<android.support.v7.widget.RecyclerView
android:id="#+id/dummy_rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:padding="10dp" />
</LinearLayout>
Hence, I am sharing one sample Activity to run this code which will show the overall implementation.
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private ArrayList<String> data = new ArrayList<String>();
private RecyclerViewWithHeaderFooterAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeData();
initializeRecyclerView();
}
private void initializeRecyclerView() {
mRecyclerView = findViewById(R.id.dummy_rv);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new RecyclerViewWithHeaderFooterAdapter(this, data);
mRecyclerView.setAdapter(adapter);
}
private void initializeData() {
for (int i = 0; i < 10; i++) data.add("Position :" + i);
}
}
Hope that helps!
Customize Recycler view to set maxHeight.
public class MaxHeightRecyclerView extends RecyclerView {
private int mMaxHeight;
public MaxHeightRecyclerView(Context context) {
super(context);
}
public MaxHeightRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(context, attrs);
}
public MaxHeightRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialize(context, attrs);
}
private void initialize(Context context, AttributeSet attrs) {
TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.MaxHeightScrollView);
mMaxHeight = arr.getLayoutDimension(R.styleable.MaxHeightScrollView_maxHeight, mMaxHeight);
arr.recycle();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mMaxHeight > 0) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxHeight, MeasureSpec.AT_MOST);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
n attrs.xml
<declare-styleable name="MaxHeightScrollView">
<attr name="maxHeight" format="dimension" />
</declare-styleable>
set RecyclerView height wrap_content in xml and maxHeight to fixwidth in dp.
The RecyclerView will consume height wrap_content till fixWidth which you set, after reaching to maxHeight, the RecyclerView will scrollable.
If you also need to limit the size of your NestedScrollView by makeing a custom NestedScrollView:
public class CustomNestedScrollView extends NestedScrollView {
private int maxHeight;
private final int defaultHeight = 200;
public CustomNestedScrollView(Context context) {
super(context);
}
public CustomNestedScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
if (!isInEditMode()) {
init(context, attrs);
}
}
public CustomNestedScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
if (!isInEditMode()) {
init(context, attrs);
}
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public CustomNestedScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
if (!isInEditMode()) {
init(context, attrs);
}
}
private void init(Context context, AttributeSet attrs) {
if (attrs != null) {
TypedArray styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.CustomNestedScrollView);
//200 is a defualt value
maxHeight = styledAttrs.getDimensionPixelSize(R.styleable.CustomNestedScrollView_maxHeight, defaultHeight);
styledAttrs.recycle();
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
attr.xml
<declare-styleable name="CustomNestedScrollView">
<attr name="maxHeight" format="dimension" />
</declare-styleable>
example layout for custom NestedScrollView:
<your.package.CustomNestedScrollView
android:layout_weight="1"
app:maxHeight="90dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<!--Child view with RecyclerView here-->
</your.package.CustomNestedScrollView>
Along with this custom NestedScrollView if you apply the customization of your RecyclerView then it will work exactly how you want. I hope this helps!
My Android app is composed of an SQLite database which populates individual ListView items with data user saves. Those items are available for display in activity_main.xml.
I have a class called RecordsListFragment which contains the two problematic methods: onItemClick and onItemLongClick. Here is the class in its entirety:
package com.example.benignfella.projectworkinghoursapplication.Fragment;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import com.example.benignfella.projectworkinghoursapplication.R;
import com.example.benignfella.projectworkinghoursapplication.Adapter.RecordsListAdapter;
import com.example.benignfella.projectworkinghoursapplication.Database.RecordsDAO;
import com.example.benignfella.projectworkinghoursapplication.GetSet.Records;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
public class RecordsListFragment extends Fragment implements OnItemClickListener, OnItemLongClickListener {
public static final String ARGUMENT_ITEM_ID = "records_list";
Activity activity;
ListView recordsListView;
ArrayList<Records> records;
RecordsListAdapter recordsListAdapter;
RecordsDAO recordsDAO;
private GetRecordsTask task;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activity = getActivity();
recordsDAO = new RecordsDAO(activity);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_records_list, container, false);
findViewsById(view);
task = new GetRecordsTask(activity);
task.execute((Void) null);
return view;
}
private void findViewsById(View view) {
recordsListView = (ListView) view.findViewById(R.id.list_records);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Records record = (Records) parent.getItemAtPosition(position);
if (records != null) {
Bundle arguments = new Bundle();
arguments.putParcelable("selectedRecord,", record);
CustomRecordsDialogFragment customRecordsDialogFragment = new CustomRecordsDialogFragment();
customRecordsDialogFragment.setArguments(arguments);
customRecordsDialogFragment.show(getFragmentManager(), CustomRecordsDialogFragment.ARGUMENT_ITEM_ID);
}
}
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
Records records = (Records) parent.getItemAtPosition(position);
recordsDAO.deleteRecord(records);
recordsListAdapter.remove(records);
return true;
}
public class GetRecordsTask extends AsyncTask<Void, Void, ArrayList<Records>> {
private final WeakReference<Activity> activityWeakRef;
public GetRecordsTask(Activity context) {
this.activityWeakRef = new WeakReference<Activity>(context);
}
#Override
protected ArrayList<Records> doInBackground(Void... arg0) {
ArrayList<Records> recordsArrayList = recordsDAO.getRecords();
return recordsArrayList;
}
#Override
protected void onPostExecute(ArrayList<Records> empList) {
if (activityWeakRef.get() != null && !activityWeakRef.get().isFinishing()) {
records = empList;
if (empList != null) {
if (empList.size() != 0) {
recordsListAdapter = new RecordsListAdapter(activity, empList);
recordsListView.setAdapter(recordsListAdapter);
} else {
Toast.makeText(activity, "No Records about records... wait wot m8?",
Toast.LENGTH_LONG).show();
}
}
}
}
}
public void updateView() {
task = new GetRecordsTask(activity);
task.execute((Void) null);
}
public void onResume() {
getActivity().setTitle(R.string.app_name);
getActivity().getActionBar().setTitle(R.string.app_name);
super.onResume();
}
}
Here is activity_main.xml with FrameLayout:
<RelativeLayout
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=".MainActivity">
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
Layout resource file which contains a ListView is called fragment_records_list.xml and here it is:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f9f9f9">
<ListView
android:id="#+id/list_records"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:dividerHeight="10dp"
android:drawSelectorOnTop="true"
android:footerDividersEnabled="false"
android:padding="10dp"
android:scrollbarStyle="outsideOverlay"/>
</RelativeLayout>
Lastly, there is a resource file containing the layout of a single item, list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ededed"
android:descendantFocusability="blocksDescendants">
<RelativeLayout
android:id="#+id/layout_item"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/text_record_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:text="ID"
android:textSize="20dp"/>
<TextView
android:id="#+id/text_record_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/text_record_id"
android:padding="5dp"
android:text="Date"
android:textColor="#00942b"
android:textSize="20dp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/text_record_date"
android:drawableStart="#drawable/ic_date_range_black_24dp"
android:padding="5dp"
/>
<TextView
android:id="#+id/text_record_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/text_record_id"
android:padding="5dp"
android:text="Description"
/>
<TextView
android:id="#+id/text_record_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/text_record_description"
android:padding="5dp"
android:text="17:00"
android:textSize="16dp"
android:textColor="#004561"
/>
<TextView
android:id="#+id/text_record_dash"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/text_record_description"
android:layout_toRightOf="#id/text_record_start"
android:padding="5dp"
android:text="-"
android:textSize="16dp"
/>
<TextView
android:id="#+id/text_record_finish"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/text_record_description"
android:layout_toRightOf="#id/text_record_dash"
android:padding="5dp"
android:text="20:00"
android:textSize="16dp"
android:textColor="#c7002a"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:layout_below="#id/text_record_description"
android:layout_toRightOf="#id/text_record_finish"
android:drawableStart="#drawable/ic_timer_black_24dp"
/>
</RelativeLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="#id/layout_item"
android:background="#000000"
/>
</RelativeLayout>
I haven't found a definite answer to my question, so I'm asking for a bit of help here.
You need set OnItemClickListener and OnLongItemClickListener to ListView, I edited your method in the initializing variable ListView:
private void findViewsById(View view) {
recordsListView = (ListView) view.findViewById(R.id.list_records);
recordsListView.setOnItemClickListener(this);
recordsListView.setOnItemLongClickListener(this);
}
I'm implementing adapter for recycleview in android, but it throws error Resource ID #0x7f0d00aa type #0x12 is not valid.
This is my card layout for client_info_fragment_revision_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="2dp"
android:layout_margin="7dp"
android:clickable="true"
android:focusable="true">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="#+id/revMainLayout">
<!--TOP-->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="#+id/revRelativeTop">
<ImageView android:id="#+id/imagePartRevision"
android:layout_width="28dp"
android:layout_height="28dp"
android:scaleType="fitXY"
android:layout_marginLeft="7dp" android:layout_marginTop="5dp"
android:src="#drawable/ic_indicator_program"/>
<TextView
android:id="#+id/partRevision"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:maxLines="2"
android:padding="10dp"
android:text="Paper"
android:textSize="16sp" android:layout_marginLeft="34dp"/>
<TextView
android:id="#+id/deadlineRevision"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="23-04-2016"
android:textSize="16sp"
android:padding="10dp"
android:layout_marginRight="7dp"/>
</RelativeLayout>
<!--MIDDLE-->
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="#+id/revLinearMiddle">
<View
android:id="#+id/divider1"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#a4b9adba"/>
<ListView
android:layout_width="wrap_content"
android:layout_height="120dp"
android:id="#+id/listViewRevision"/>
<View
android:id="#+id/divider2"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#a4b9adba"/>
</LinearLayout>
<!--BOTTOM-->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="#+id/revRelativeBottom">
<TextView
android:id="#+id/statusRevision"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="#+id/statusRevisionIndicator"
android:maxLines="2"
android:padding="10dp"
android:text="On Progress"
android:textSize="16sp"/>
<ImageView
android:id="#+id/statusRevisionIndicator"
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_alignBottom="#+id/statusRevision"
android:layout_alignParentRight="true"
android:layout_below="#id/divider"
android:layout_marginRight="7dp" android:layout_centerVertical="true"
android:layout_marginBottom="5dp" android:src="#drawable/ic_indicator_not_finished"/>
</RelativeLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
And this is code for my adapter RevisionRecycleCardsAdapter.java:
package com.putraxor.prola.skripsi.client.activity.profileui;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.putraxor.prola.skripsi.R;
import com.putraxor.prola.skripsi.pojo.Revisi;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* Created by Putra on 27/03/2016.
*/
public class RevisionRecycleCardsAdapter extends RecyclerView.Adapter<RevisionRecycleCardsAdapter.CardViewHolder> {
private ArrayList<Revisi> revision_list;
Context context;
public static class CardViewHolder extends RecyclerView.ViewHolder{
ImageView imagePartRevision;
ImageView statusRevisionIndicator;
TextView partRevision;
TextView deadlineRevision;
TextView statusRevision;
ListView listViewRevision;
public CardViewHolder(View itemView) {
super(itemView);
imagePartRevision = (ImageView)itemView.findViewById(R.id.imagePartRevision);
statusRevisionIndicator = (ImageView)itemView.findViewById(R.id.statusRevisionIndicator);
partRevision = (TextView)itemView.findViewById(R.id.partRevision);
deadlineRevision = (TextView)itemView.findViewById(R.id.deadlineRevision);
statusRevision = (TextView)itemView.findViewById(R.id.statusRevision);
listViewRevision = (ListView)itemView.findViewById(R.id.listViewRevision);
}
}
public RevisionRecycleCardsAdapter(ArrayList<Revisi> revision) {
this.revision_list = revision;
}
#Override
public CardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
this.context = parent.getContext();
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.client_info_fragment_revision_layout, parent, false);
CardViewHolder cardViewHolder = new CardViewHolder(view);
return cardViewHolder;
}
#Override
public void onBindViewHolder(final CardViewHolder holder, final int listPosition) {
Revisi rev = revision_list.get(listPosition);
int srcImagePartRevision = rev.getBagian().equalsIgnoreCase("Paper") ? R.drawable.ic_indicator_paper : R.drawable.ic_indicator_program;
int srcStateIndicator = rev.isSelesai() ? R.drawable.ic_indicator_finished : R.drawable.ic_indicator_not_finished;
String status = rev.isSelesai()?"Revisions Finished" : "On Process";
holder.imagePartRevision.setImageResource(srcImagePartRevision);
holder.partRevision.setText(rev.getBagian());
holder.deadlineRevision.setText(rev.getDeadline());
holder.statusRevision.setText(status);
holder.statusRevisionIndicator.setImageResource(srcStateIndicator);
String[] values = rev.getRevisi();
ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < values.length; ++i) {
list.add(values[i]);
}
StableArrayAdapter adapter = new StableArrayAdapter(this.context, R.id.listViewRevision, list);
holder.listViewRevision.setAdapter(adapter);
}
#Override
public int getItemCount() {
return revision_list.size();
}
private class StableArrayAdapter extends ArrayAdapter<String> {
HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();
public StableArrayAdapter(Context context, int textViewResourceId, List<String> objects) {
super(context, textViewResourceId, objects);
for (int i = 0; i < objects.size(); ++i) {
mIdMap.put(objects.get(i), i);
}
}
#Override
public long getItemId(int position) {
String item = getItem(position);
return mIdMap.get(item);
}
#Override
public boolean hasStableIds() {
return true;
}
}
}
Change your code in
#Override
public CardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.R.layout.client_info_fragment_revision_layout, parent, false);
CardViewHolder holder = new CardViewHolder (view);
}
It's just for debug purpose:
If you are using Android studio then open your R.java under folder
build->generated->source->r->debug->yourpackagename->R.java
Then search 0x7f0d00aa in the file; It will be like
public static final int TextView01=0x7f0d00aa;
Search the corresponding ID in xml files under resources folder. Then check the XML content syntax,naming,source etc.