简体   繁体   English

自定义textView不能按预期工作

[英]Custom textView not working as expected

I have a custom textview as follows 我有一个自定义的textview如下

public class TaskTitleView extends TextView {
    public static final int NORMAL = 0;
    public static final int DONE = 1;
    public static final int OVERDUE = 2;
    private int mState;

    public TaskTitleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public TaskTitleView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public TaskTitleView(Context context) {
        super(context);
    }

    /**
     * Return the current display state of this view.
     *
     * @return One of {@link #NORMAL}, {@link #DONE}, or {@link #OVERDUE}.
     */
    public int getState() {
        return mState;
    }

    /**
     * Update the text display state of this view.
     * Normal status shows black text. Overdue displays in red.
     * Completed draws a strikethrough line on the text.
     *
     * @param state New state. One of {@link #NORMAL}, {@link #DONE}, or {@link #OVERDUE}.
     */
    public void setState(int state) {
        switch (state) {
            case DONE:
                setPaintFlags(Paint.STRIKE_THRU_TEXT_FLAG);
                Log.i("vvv","vvvv");
                setTextColor(ContextCompat.getColor(getContext(), R.color.black));
            case NORMAL:
                setPaintFlags(0);
                setTextColor(ContextCompat.getColor(getContext(), R.color.black));
                break;
            case OVERDUE:
                setPaintFlags(0);
                setTextColor(ContextCompat.getColor(getContext(), R.color.red));
                break;
            default:
                return;
        }

        mState = state;
    }
}

On the recyclerView adapter, i did something like this 在recyclerView适配器上,我做了这样的事情

public class TaskAdapter extends RecyclerView.Adapter<TaskAdapter.TaskHolder> {

    /* Callback for list item click events */
    public interface OnItemClickListener {
        void onItemClick(View v, int position);

        void onItemToggled(boolean active, int position);
    }

    /* ViewHolder for each task item */
    public class TaskHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        public TaskTitleView nameView;
        public TextView dateView;
        public ImageView priorityView;
        public CheckBox checkBox;

        public TaskHolder(View itemView) {
            super(itemView);

            nameView = (TaskTitleView) itemView.findViewById(R.id.text_description);
            //nameView= new TaskTitleView(mContext);
            dateView = (TextView) itemView.findViewById(R.id.text_date);
            priorityView = (ImageView) itemView.findViewById(R.id.priority);
            checkBox = (CheckBox) itemView.findViewById(R.id.checkbox);

            itemView.setOnClickListener(this);
            checkBox.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            if (v == checkBox) {
                completionToggled(this);
            } else {

                postItemClick(this);
            }
        }
    }

    private Cursor mCursor;
    private OnItemClickListener mOnItemClickListener;
    private Context mContext;

    public TaskAdapter(Cursor cursor, Context context) {
        mCursor = cursor;
        mContext = context;
    }

    public void setOnItemClickListener(OnItemClickListener listener) {
        mOnItemClickListener = listener;
    }

    private void completionToggled(TaskHolder holder) {
        if (mOnItemClickListener != null) {
            mOnItemClickListener.onItemToggled(holder.checkBox.isChecked(),holder.getAdapterPosition());
        }
    }

    private void postItemClick(TaskHolder holder) {
        if (mOnItemClickListener != null) {
            int adapterPosition = holder.getAdapterPosition();
            mCursor.moveToPosition(adapterPosition);
            mOnItemClickListener.onItemClick(holder.itemView, Integer.parseInt(mCursor.getString(mCursor.getColumnIndex(DatabaseContract.TaskColumns._ID))));
            Log.i("rrr",mCursor.getString(mCursor.getColumnIndex(DatabaseContract.TaskColumns._ID)));

        }
    }

    @Override
    public TaskHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        mContext = parent.getContext();
        View itemView = LayoutInflater.from(mContext)
                .inflate(R.layout.list_item_task, parent, false);

        return new TaskHolder(itemView);
    }

    @Override
    public void onBindViewHolder(TaskHolder holder, int position) {

        Log.i("test", String.valueOf(position));
        mCursor.moveToPosition(position);
        holder.nameView.setText(mCursor.getString(mCursor.getColumnIndex(DatabaseContract.TaskColumns.DESCRIPTION)));
        holder.nameView.setState(0);
        if(mCursor.getLong(mCursor.getColumnIndex(DatabaseContract.TaskColumns.DUE_DATE))==Long.MAX_VALUE)
        {

        }
        else {
            CharSequence formatted = DateUtils.getRelativeTimeSpanString(mCursor.getLong(mCursor.getColumnIndex(DatabaseContract.TaskColumns.DUE_DATE)));
            holder.dateView.setText(formatted);
        }

        if(mCursor.getString(mCursor.getColumnIndex(DatabaseContract.TaskColumns.IS_PRIORITY)).equals("0"))
        {

            holder.priorityView.setImageDrawable(mContext.getDrawable(R.drawable.ic_not_priority));
        }
        else
        {
            holder.priorityView.setImageDrawable(mContext.getDrawable(R.drawable.ic_priority));
        }

        if(mCursor.getString(mCursor.getColumnIndex(DatabaseContract.TaskColumns.IS_COMPLETE)).equals("1"))
        {
            holder.nameView.setState(1);
            holder.checkBox.setChecked(true);
        }
        else
        {
            holder.nameView.setState(0);
            holder.checkBox.setChecked(false);
        }
    }

    @Override
    public int getItemCount() {
        return (mCursor != null) ? mCursor.getCount() : 0;
    }

    /**
     * Retrieve a {@link Task} for the data at the given position.
     *
     * @param position Adapter item position.
     *
     * @return A new {@link Task} filled with the position's attributes.
     */
    public Task getItem(int position) {
        if (!mCursor.moveToPosition(position)) {
            throw new IllegalStateException("Invalid item position requested");
        }

        return new Task(mCursor);
    }

    @Override
    public long getItemId(int position) {
        return getItem(position).id;
    }

    public void swapCursor(Cursor cursor) {
        if (mCursor != null) {
            mCursor.close();
        }
        mCursor = cursor;
        notifyDataSetChanged();
    }
}

Whats wrong, when i change the state, it should change. 怎么了,当我改变状态时,它应该改变。 But i'm just seeing nothing. 但是我什么也没看见。 not even a text. 甚至没有文字。 Please help. 请帮忙。 Thanks ........................................................................... ......................................... 谢谢 ................................................. ................................................................. .................

You can add invalidate(); 您可以添加invalidate(); when you set state on your custom TextView . 在自定义TextView上设置状态时。

public void setState(int state) {
    switch (state) {
        case DONE:
            setPaintFlags(Paint.STRIKE_THRU_TEXT_FLAG);
            Log.i("vvv","vvvv");
            setTextColor(ContextCompat.getColor(getContext(), R.color.color_black));
        case NORMAL:
            setPaintFlags(0);
            setTextColor(ContextCompat.getColor(getContext(), R.color.color_blue));
            break;
        case OVERDUE:
            setPaintFlags(0);
            setTextColor(ContextCompat.getColor(getContext(), R.color.color_red));
            break;
        default:
            return;
    }

    mState = state;
    // add here , to update 
    invalidate();
}

Change 更改

@Override
public void onClick(View v) {
    if (v == checkBox) {
        completionToggled(this);
    } else {

        postItemClick(this);
    }
}

to

@Override
public void onClick(View v) {
    switch (v.getId()){
        case R.id.checkbox:
            completionToggled(this);
            break;
        default:
            postItemClick(this);
            break;
    }
}

Try this 尝试这个

 public class Textview_Bold extends TextView {


    public Textview_Bold(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    public Textview_Bold(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public Textview_Bold(Context context) {
        super(context);
        init();
    }

    private void init() {
        if (!isInEditMode()) {
            Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "Lato-Bold.ttf");
            setTypeface(tf);
        }
    }   
}

XML XML格式

<yourpackage name.FontText.Textview_Bold
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="#000"
                    android:text="Create Account"
                    android:layout_marginRight="10dp"
                    android:layout_marginTop="10dp"
                    android:padding="5dp"
                    android:id="@+id/createaccount"
                    android:background="@drawable/buttonselector"
                    android:layout_alignParentTop="true"
                    android:layout_alignParentRight="true"
                    android:layout_alignParentEnd="true" />

You need to change properties in lifecycle of your customView or make your func inside of overrided events. 您需要在customView的生命周期中更改属性,或者将func设置为替代事件的内部。

In your case try to update your view follow next thing: 在您的情况下,请尝试更新您的视图,然后再进行以下操作:

View Update 查看更新

From a view lifecycle diagram you may notices that there are two methods that leads view to redraw itself. 从视图生命周期图中,您可能会注意到有两种方法导致视图重绘自身。 invalidate() and requestLayout() methods will help you to make an interactive custom view, that may change its look on runtime. invalidate()和requestLayout()方法将帮助您创建交互式自定义视图,这可能会更改运行时的外观。 But why there are two of them? 但是为什么有两个呢? invalidate() method used to simple redrawing view. invalidate()方法用于简化重绘视图。 While your view for example updates its text, color or touch interactivity. 例如,在您的视图更新文本,颜色或触摸交互性时。 It means that view will only call onDraw() method once more to update its state. 这意味着视图将仅再次调用onDraw()方法来更新其状态。 requestLayout() method, as you can see will produce view update through its lifecycle just from onMeasure() method. 如您所见,requestLayout()方法将仅通过onMeasure()方法在其生命周期内生成视图更新。 And what it means that you will need it while after your view updates, it changed it's size and you need to measure it once again to draw it depending on new size. 这意味着您需要在视图更新后更改它的大小,并且需要再次对其进行测量以根据新大小绘制它时使用它。

From here: https://medium.com/@romandanylyk96/android-draw-a-custom-view-ef79fe2ff54b 从这里: https : //medium.com/@romandanylyk96/android-draw-a-custom-view-ef79fe2ff54b

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM