You might want to expand the question a bit and be more specific about your custom field. What does it depend on? When should it be updated?
To the general question:
A view-only custom field is just like any other custom field, except that you can't edit it via the GUI. It exists in the database and is displayed just like a 'normal' custom field.
Which hook you need depends on what should cause an update to the custom field value. If for example, it is based on the contact's name then you could use hook_civicrm_post so that your code gets run after the name is created or updated.
For setting the value, you can use the Contact.create API as the field is on a contact. Specify the existing contact id and the new value of the custom field - eg:
$result = civicrm_api3('Contact', 'create', array(
'sequential' => 1,
'id' => 203,
'custom_2' => "M",
));
Your code relates to writing the value of the custom field to the database, not the display of it.
[Update]
Here's a quick demo:
- create a new custom field group for contacts
- add an Integer field 'Set me'
- add a view-only Integer field 'Doubled'
Put the following in an extension and adjust the groupid and fieldids to match your values:
function viewonlydemo_civicrm_custom($op, $groupID, $entityID, &$params) {
$groupid_to_watch = 15;
$fieldid_to_watch = 31; // 'Set me' field
$fieldid_to_set = 32; // 'Doubled' field
if ($groupID == $groupid_to_watch) {
foreach ($params as $cf) {
if ($cf['custom_field_id'] == $fieldid_to_watch) {
civicrm_api3('Contact', 'create', array(
'id' => $entityID,
'custom_' . $fieldid_to_set => $cf['value'] ? $cf['value'] * 2 : "",
));
}
}
}
}
When you change 'Set me' you should see 'Doubled' updated to be twice the value of 'Set me'.
Be aware that the hook will be called when you update 'Set me', and also by the API call in the hook so you need to be careful not to get stuck in a loop.