[英]Android RecyclerView not drawing custom View; onDraw is not called
I have tried all sorts of things and sifted through lots of questions on this site.我已经尝试了各种各样的事情,并在这个网站上筛选了很多问题。 None of it is working.
它都不起作用。 I followed this tutorial:https://developer.android.com/guide/topics/ui/custom-components and it does not work with RecyclerViews.
我遵循了本教程:https://developer.android.com/guide/topics/ui/custom-components ,它不适用于 RecyclerViews。
The RecyclerView adds the custom view and it has a non zero size confirmed via the layout inspector, but it is transparent. RecyclerView 添加了自定义视图,并且通过布局检查器确认了它的非零大小,但它是透明的。 I have tried the setWillNotDraw() and invalidate() solutions.
我已经尝试了 setWillNotDraw() 和 invalidate() 解决方案。 Nothing.
没有什么。 onDraw() is not called.
不调用 onDraw()。
Here is the custom View:这是自定义视图:
public class FunctionView extends View {
Paint color = new Paint(Paint.ANTI_ALIAS_FLAG);
float height = 0;
float width = 0;
private int minY = 0;
private int maxY = 1;
private float[] dataF = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
public FunctionView(Context context) {
super(context);
}
public FunctionView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// Account for padding
float xpad = (float)(getPaddingLeft() + getPaddingRight());
float ypad = (float)(getPaddingTop() + getPaddingBottom());
width = (float)w - xpad;
height = (float)h - ypad;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
color.setColor(Color.GREEN);
if(NativeMethods.isFloat()){
double xScale = ((double)width)/((double)dataF.length);
double yScale = ((double)height)/((double)(maxY-minY));
for(int i = 0; i < dataF.length; i+=2){
canvas.drawLine((float)(((double)i)*xScale), (float)(((double)dataF[i])*yScale),
(float)(((double)(i+1))*xScale), (float)(((double)dataF[(i+1)])*yScale),
color);
}
}
}
void setData(double miny, double maxy, float[] values){
this.minY = minY;
this.maxY = maxY;
this.dataF = values;
}
}
Here is the Activity containing the RecylcerView这是包含 RecyclerView 的 Activity
public class MainActivity extends AppCompatActivity {
private RecyclerView ampRecyclerView;
private RecyclerView.Adapter ampAdapter;
private RecyclerView.LayoutManager ampLayoutManager;
private RecyclerView freqRecyclerView;
private RecyclerView.Adapter freqAdapter;
private RecyclerView.LayoutManager freqLayoutManager;
List<FunctionView> myDataset = new ArrayList<FunctionView>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setUpRecyclerView();
}
private void setUpRecyclerView() {
ampRecyclerView = (RecyclerView) findViewById(R.id.AmpRecyclerView);
freqRecyclerView = (RecyclerView) findViewById(R.id.FreqRecyclerView);
// use a linear layout manager
ampLayoutManager = new LinearLayoutManager(this);
freqLayoutManager = new LinearLayoutManager(this);
ampRecyclerView.setLayoutManager(ampLayoutManager);
freqRecyclerView.setLayoutManager(freqLayoutManager);
myDataset.add(new FunctionView(this));
// specify an adapter (see also next example)
ampAdapter = new MainActivityAdapter(myDataset);
ampRecyclerView.setAdapter(ampAdapter);
freqAdapter = new MainActivityAdapter(myDataset);
freqRecyclerView.setAdapter(freqAdapter);
}
}
Here is the adapter:这是适配器:
class MainActivityAdapter extends RecyclerView.Adapter<MainActivityAdapter.FunctionViewHolder> {
private List<FunctionView> views = new ArrayList<FunctionView>();
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class FunctionViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public FunctionView functionView;
public FunctionViewHolder(FunctionView v) {
super(v);
functionView = v;
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MainActivityAdapter(List<FunctionView> myDataset) {
views = myDataset;
}
// Create new views (invoked by the layout manager)
@Override
public MainActivityAdapter.FunctionViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
FunctionView v = (FunctionView) LayoutInflater.from(parent.getContext())
.inflate(R.layout.function_holder, parent, false);
MainActivityAdapter.FunctionViewHolder vh = new MainActivityAdapter.FunctionViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(MainActivityAdapter.FunctionViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
//TODO set the data
holder.functionView = views.get(position);
holder.functionView.invalidate();
holder.functionView.requestLayout();
}
// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
return views.size();
}
}
Here is the xml of the custom view:这是自定义视图的 xml:
<?xml version="1.0" encoding="utf-8"?>
<com.example.hellooboe.FunctionView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/function_view_holder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
Here is the layout for the main page:这是主页面的布局:
<?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:id="@+id/main_ll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/AmpRecyclerView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/FreqRecyclerView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
Why won't a RecyclerView call onDraw for a custom View created from directions in the Developer's Guide?为什么 RecyclerView 不会为根据开发人员指南中的说明创建的自定义视图调用 onDraw? When I used a plain TextView in the tutorial for a RecylerView, it worked just fine and drew the TextView, so why won't it draw the custom view?
当我在 RecylerView 的教程中使用普通的 TextView 时,它工作得很好并绘制了 TextView,那么为什么它不绘制自定义视图呢? I literally copied the code from the RecyclerView guide and replaced the TextView with my custom View.
我从 RecyclerView 指南中复制了代码,并用我的自定义视图替换了 TextView。 Is there something I am missing from the guides?
指南中有我遗漏的东西吗? Are they incompatible?
它们不兼容吗?
The problem is that the RecyclerViews have a width of 0dp.问题是 RecyclerViews 的宽度为 0dp。 Using wrap_content or match_parent fixes the issue.
使用 wrap_content 或 match_parent 解决了这个问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.